X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fmdt%2Fmdt_som.c;h=8636c6144edc40239a5e963807c2b5c94e8f4baa;hb=36ba989752c62cc76b06089373fcd6cec6da9008;hp=ed47a53d552313c2b206d811373b246888e1265c;hpb=5999c0b881e8d9f2b431c842bdd1717115a82b7c;p=fs%2Flustre-release.git diff --git a/lustre/mdt/mdt_som.c b/lustre/mdt/mdt_som.c index ed47a53..8636c61 100644 --- a/lustre/mdt/mdt_som.c +++ b/lustre/mdt/mdt_som.c @@ -28,70 +28,256 @@ * Size on MDS revival * * Author: Jinshan Xiong + * Author: Yingjin Qian */ #define DEBUG_SUBSYSTEM S_MDS #include "mdt_internal.h" +/* + * Swab and extract SOM attributes from on-disk xattr. + * + * \param buf - is a buffer containing the on-disk LSOM extended attribute. + * \param rc - is the SOM xattr stored in \a buf + * \param ms - is the md_som structure where to extract SOM attributes. + */ +int lustre_buf2som(void *buf, int rc, struct md_som *ms) +{ + struct lustre_som_attrs *attrs = (struct lustre_som_attrs *)buf; + ENTRY; + + if (rc == 0 || rc == -ENODATA) + /* no LSOM attributes */ + RETURN(-ENODATA); + + if (rc < 0) + /* error hit while fetching xattr */ + RETURN(rc); + + /* unpack LSOM attributes */ + lustre_som_swab(attrs); + + /* fill in-memory md_som structure */ + ms->ms_valid = attrs->lsa_valid; + ms->ms_size = attrs->lsa_size; + ms->ms_blocks = attrs->lsa_blocks; + + RETURN(0); +} + int mdt_get_som(struct mdt_thread_info *info, struct mdt_object *obj, - struct lu_attr *attr) + struct md_attr *ma) { struct lu_buf *buf = &info->mti_buf; - struct lustre_som_attrs *som; + struct lu_attr *attr = &ma->ma_attr; int rc; - som = buf->lb_buf = info->mti_xattr_buf; + buf->lb_buf = info->mti_xattr_buf; buf->lb_len = sizeof(info->mti_xattr_buf); + CLASSERT(sizeof(struct lustre_som_attrs) <= + sizeof(info->mti_xattr_buf)); rc = mo_xattr_get(info->mti_env, mdt_object_child(obj), buf, XATTR_NAME_SOM); - if (rc >= (int)sizeof(*som) && (som->lsa_valid & LSOM_FL_VALID)) { - attr->la_valid |= LA_SIZE | LA_BLOCKS; - attr->la_size = som->lsa_size; - attr->la_blocks = som->lsa_blocks; - - /* Size on MDS is valid and could be returned to client */ - info->mti_som_valid = 1; - - CDEBUG(D_INODE, DFID": Reading som attrs: " - "valid: %x, size: %lld, blocks: %lld, rc: %d.\n", - PFID(mdt_object_fid(obj)), som->lsa_valid, - som->lsa_size, som->lsa_blocks, rc); + rc = lustre_buf2som(info->mti_xattr_buf, rc, &ma->ma_som); + if (rc == 0) { + struct md_som *som = &ma->ma_som; + + ma->ma_valid |= MA_SOM; + + if ((som->ms_valid & SOM_FL_STRICT)) { + attr->la_valid |= LA_SIZE | LA_BLOCKS; + attr->la_size = som->ms_size; + attr->la_blocks = som->ms_blocks; + + /* + * Size on MDS is valid and could be returned + * to client. + */ + info->mti_som_valid = 1; + + CDEBUG(D_INODE, DFID": Reading som attrs: " + "valid: %x, size: %lld, blocks: %lld\n", + PFID(mdt_object_fid(obj)), som->ms_valid, + som->ms_size, som->ms_blocks); + } + } else if (rc == -ENODATA) { + rc = 0; } - return (rc > 0 || rc == -ENODATA) ? 0 : rc; + return rc; } +/** + * Update SOM on-disk attributes. + */ int mdt_set_som(struct mdt_thread_info *info, struct mdt_object *obj, - struct lu_attr *attr) + enum lustre_som_flags flag, __u64 size, __u64 blocks) { struct md_object *next = mdt_object_child(obj); struct lu_buf *buf = &info->mti_buf; struct lustre_som_attrs *som; int rc; + ENTRY; - buf->lb_buf = info->mti_xattr_buf; - buf->lb_len = sizeof(info->mti_xattr_buf); - rc = mo_xattr_get(info->mti_env, next, buf, XATTR_NAME_SOM); - if (rc < 0 && rc != -ENODATA) - RETURN(rc); + CDEBUG(D_INODE, + DFID": Set SOM attrs S/B/F: %lld/%lld/%x.\n", + PFID(mdt_object_fid(obj)), size, blocks, flag); - som = buf->lb_buf; + som = (struct lustre_som_attrs *)info->mti_xattr_buf; + CLASSERT(sizeof(info->mti_xattr_buf) >= sizeof(*som)); - CDEBUG(D_INODE, - DFID": Set som attrs: S/B: %lld/%lld to %lld/%lld, rc: %d\n", - PFID(mdt_object_fid(obj)), som->lsa_size, som->lsa_blocks, - attr->la_size, attr->la_blocks, rc); - - if (rc == -ENODATA) - memset(som, 0, sizeof(*som)); - if (attr->la_valid & (LA_SIZE | LA_BLOCKS)) { - som->lsa_valid |= LSOM_FL_VALID; - som->lsa_size = attr->la_size; - som->lsa_blocks = attr->la_blocks; - } + som->lsa_valid = flag; + som->lsa_size = size; + som->lsa_blocks = blocks; + memset(&som->lsa_reserved, 0, sizeof(som->lsa_reserved)); + lustre_som_swab(som); + + /* update SOM attributes */ + buf->lb_buf = som; buf->lb_len = sizeof(*som); rc = mo_xattr_set(info->mti_env, next, buf, XATTR_NAME_SOM, 0); + + RETURN(rc); +} + +/** + * SOM state transition from STRICT to STALE, + */ +int mdt_lsom_downgrade(struct mdt_thread_info *info, struct mdt_object *o) +{ + struct md_attr *tmp_ma; + int rc; + + ENTRY; + + mutex_lock(&o->mot_som_mutex); + tmp_ma = &info->mti_u.som.attr; + tmp_ma->ma_need = MA_SOM; + tmp_ma->ma_valid = 0; + + rc = mdt_get_som(info, o, tmp_ma); + if (rc < 0) + GOTO(out_lock, rc); + + if (tmp_ma->ma_valid & MA_SOM) { + struct md_som *som = &tmp_ma->ma_som; + + info->mti_som_valid = 0; + /* The size and blocks info should be still correct. */ + if (som->ms_valid & SOM_FL_STRICT) + rc = mdt_set_som(info, o, SOM_FL_STALE, + som->ms_size, som->ms_blocks); + } +out_lock: + mutex_unlock(&o->mot_som_mutex); + RETURN(rc); +} + +int mdt_lsom_update(struct mdt_thread_info *info, + struct mdt_object *o, bool truncate) +{ + struct md_attr *ma, *tmp_ma; + struct lu_attr *la; + int rc = 0; + + ENTRY; + + ma = &info->mti_attr; + la = &ma->ma_attr; + + mutex_lock(&o->mot_som_mutex); + tmp_ma = &info->mti_u.som.attr; + tmp_ma->ma_need = MA_INODE | MA_SOM; + tmp_ma->ma_valid = 0; + + rc = mdt_attr_get_complex(info, o, tmp_ma); + if (rc) + GOTO(out_lock, rc); + + rc = mo_xattr_get(info->mti_env, mdt_object_child(o), &LU_BUF_NULL, + XATTR_NAME_LOV); + if (rc < 0 && rc != -ENODATA) + GOTO(out_lock, rc); + else if (rc > 0) /* has LOV EA*/ + tmp_ma->ma_valid |= MA_LOV; + + rc = 0; + /** + * Check if a Lazy Size-on-MDS update is needed. Skip the + * file with no LOV EA or unlink files. + * MDS only updates LSOM of the file if the size or block + * size is being increased or the file is being truncated. + */ + if ((tmp_ma->ma_valid & MA_LOV) && + !(tmp_ma->ma_valid & MA_INODE && + tmp_ma->ma_attr.la_nlink == 0)) { + __u64 size; + __u64 blocks; + bool changed = false; + struct md_som *som = &tmp_ma->ma_som; + + if (truncate) { + size = la->la_size; + if (size == 0) { + blocks = 0; + } else if (!(tmp_ma->ma_valid & MA_SOM) || + size < som->ms_size) { + /* We cannot rely to blocks after + * truncate especially for spare file, + * and the truncate operation is usually + * followed with a close, so just set blocks + * to 1 here, and the following close will + * update it accordingly. + */ + blocks = 1; + } else { + blocks = som->ms_blocks; + } + } else { + if (!(tmp_ma->ma_valid & MA_SOM)) { + /* Only set initial SOM Xattr data when both + * size and blocks are valid. + */ + if (la->la_valid & (LA_SIZE | LA_LSIZE) && + la->la_valid & (LA_BLOCKS | LA_LBLOCKS)) { + changed = true; + size = la->la_size; + blocks = la->la_blocks; + } + } else { + /* Double check whether it is already set + * to SOM_FL_STRICT in mdt_mfd_close. + * If file is in SOM_FL_STALE state, and + * the close indicates there is no data + * modified, skip to transimit to LAZY + * state. + */ + if (som->ms_valid & SOM_FL_STRICT || + (som->ms_valid & SOM_FL_STALE && + !(ma->ma_attr_flags & MDS_DATA_MODIFIED))) + GOTO(out_lock, rc); + + size = som->ms_size; + blocks = som->ms_blocks; + if (la->la_valid & (LA_SIZE | LA_LSIZE) && + la->la_size > som->ms_size) { + changed = true; + size = la->la_size; + } + if (la->la_valid & (LA_BLOCKS | LA_LBLOCKS) && + la->la_blocks > som->ms_blocks) { + changed = true; + blocks = la->la_blocks; + } + } + } + if (truncate || changed) + rc = mdt_set_som(info, o, SOM_FL_LAZY, size, blocks); + } + +out_lock: + mutex_unlock(&o->mot_som_mutex); RETURN(rc); }