From ae828cd3b092a38adbc86a4da320dd9d3a0fc80c Mon Sep 17 00:00:00 2001 From: Lai Siyao Date: Fri, 20 Jul 2018 12:26:41 +0800 Subject: [PATCH] LU-4684 llite: add lock for dir layout data Directory layout data should be accessed with lock, because directory migration may change it, if it's accessed without lock, it may cause crash. Introduce an rw_semaphore 'lli_lsm_sem', any MD operation that uses directory layout data will take read lock, and ll_update_lsm_md() will take write lock when setting lsm. Signed-off-by: Lai Siyao Change-Id: Ice3b15c90eefd6c9dbefbea87cd65f436bec96b1 Reviewed-on: https://review.whamcloud.com/32946 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Mike Pershin Reviewed-by: Oleg Drokin --- lustre/include/lustre_lmv.h | 17 +++++ lustre/include/obd.h | 2 + lustre/llite/dir.c | 25 ++++--- lustre/llite/file.c | 5 +- lustre/llite/llite_internal.h | 3 + lustre/llite/llite_lib.c | 170 ++++++++++++++++++++---------------------- lustre/llite/namei.c | 2 + lustre/llite/statahead.c | 164 +++++++++++++++++++++------------------- lustre/lmv/lmv_obd.c | 2 - 9 files changed, 209 insertions(+), 181 deletions(-) diff --git a/lustre/include/lustre_lmv.h b/lustre/include/lustre_lmv.h index ff91ff1..d5fb751 100644 --- a/lustre/include/lustre_lmv.h +++ b/lustre/include/lustre_lmv.h @@ -82,6 +82,23 @@ lsm_md_eq(const struct lmv_stripe_md *lsm1, const struct lmv_stripe_md *lsm2) return true; } + +static inline void lsm_md_dump(int mask, const struct lmv_stripe_md *lsm) +{ + int i; + + CDEBUG(mask, "magic %#x stripe count %d master mdt %d hash type %#x " + "version %d migrate offset %d migrate hash %#x pool %s\n", + lsm->lsm_md_magic, lsm->lsm_md_stripe_count, + lsm->lsm_md_master_mdt_index, lsm->lsm_md_hash_type, + lsm->lsm_md_layout_version, lsm->lsm_md_migrate_offset, + lsm->lsm_md_migrate_hash, lsm->lsm_md_pool_name); + + for (i = 0; i < lsm->lsm_md_stripe_count; i++) + CDEBUG(mask, "stripe[%d] "DFID"\n", + i, PFID(&lsm->lsm_md_oinfo[i].lmo_fid)); +} + union lmv_mds_md; void lmv_free_memmd(struct lmv_stripe_md *lsm); diff --git a/lustre/include/obd.h b/lustre/include/obd.h index 78cb375..d005aec 100644 --- a/lustre/include/obd.h +++ b/lustre/include/obd.h @@ -843,6 +843,8 @@ struct md_op_data { s64 op_mod_time; const char *op_name; size_t op_namelen; + struct rw_semaphore *op_mea1_sem; + struct rw_semaphore *op_mea2_sem; struct lmv_stripe_md *op_mea1; struct lmv_stripe_md *op_mea2; __u32 op_suppgids[2]; diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index 9e07036..e85e975 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -321,6 +321,7 @@ static int ll_readdir(struct file *filp, void *cookie, filldir_t filldir) int hash64 = sbi->ll_flags & LL_SBI_64BIT_HASH; int api32 = ll_need_32bit_api(sbi); struct md_op_data *op_data; + struct lu_fid pfid = { 0 }; __u64 pos; int rc; ENTRY; @@ -340,12 +341,7 @@ static int ll_readdir(struct file *filp, void *cookie, filldir_t filldir) */ GOTO(out, rc = 0); - op_data = ll_prep_md_op_data(NULL, inode, inode, NULL, 0, 0, - LUSTRE_OPC_ANY, inode); - if (IS_ERR(op_data)) - GOTO(out, rc = PTR_ERR(op_data)); - - if (unlikely(op_data->op_mea1 != NULL)) { + if (unlikely(ll_i2info(inode)->lli_lsm_md != NULL)) { /* This is only needed for striped dir to fill .., * see lmv_read_entry */ if (file_dentry(filp)->d_parent != NULL && @@ -355,19 +351,24 @@ static int ll_readdir(struct file *filp, void *cookie, filldir_t filldir) file_dentry(filp)->d_parent->d_inode; if (ll_have_md_lock(parent, &ibits, LCK_MINMODE)) - op_data->op_fid3 = *ll_inode2fid(parent); + pfid = *ll_inode2fid(parent); } /* If it can not find in cache, do lookup .. on the master * object */ - if (fid_is_zero(&op_data->op_fid3)) { - rc = ll_dir_get_parent_fid(inode, &op_data->op_fid3); - if (rc != 0) { - ll_finish_md_op_data(op_data); + if (fid_is_zero(&pfid)) { + rc = ll_dir_get_parent_fid(inode, &pfid); + if (rc != 0) RETURN(rc); - } } } + + op_data = ll_prep_md_op_data(NULL, inode, inode, NULL, 0, 0, + LUSTRE_OPC_ANY, inode); + if (IS_ERR(op_data)) + GOTO(out, rc = PTR_ERR(op_data)); + op_data->op_fid3 = pfid; + #ifdef HAVE_DIR_CONTEXT ctx->pos = pos; rc = ll_dir_read(inode, &pos, op_data, ctx); diff --git a/lustre/llite/file.c b/lustre/llite/file.c index a1b43b6..157bd4b 100644 --- a/lustre/llite/file.c +++ b/lustre/llite/file.c @@ -4428,12 +4428,15 @@ out: static int ll_merge_md_attr(struct inode *inode) { + struct ll_inode_info *lli = ll_i2info(inode); struct cl_attr attr = { 0 }; int rc; - LASSERT(ll_i2info(inode)->lli_lsm_md != NULL); + LASSERT(lli->lli_lsm_md != NULL); + down_read(&lli->lli_lsm_sem); rc = md_merge_attr(ll_i2mdexp(inode), ll_i2info(inode)->lli_lsm_md, &attr, ll_md_blocking_ast); + up_read(&lli->lli_lsm_sem); if (rc != 0) RETURN(rc); diff --git a/lustre/llite/llite_internal.h b/lustre/llite/llite_internal.h index a9a7d96..45cf1a0 100644 --- a/lustre/llite/llite_internal.h +++ b/lustre/llite/llite_internal.h @@ -166,6 +166,8 @@ struct ll_inode_info { unsigned int lli_sa_enabled:1; /* generation for statahead */ unsigned int lli_sa_generation; + /* rw lock protects lli_lsm_md */ + struct rw_semaphore lli_lsm_sem; /* directory stripe information */ struct lmv_stripe_md *lli_lsm_md; /* default directory stripe offset. This is extracted @@ -978,6 +980,7 @@ enum { LUSTRE_OPC_ANY = 5, }; +void ll_unlock_md_op_lsm(struct md_op_data *op_data); struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, struct inode *i1, struct inode *i2, const char *name, size_t namelen, diff --git a/lustre/llite/llite_lib.c b/lustre/llite/llite_lib.c index 28acbb6..654c874 100644 --- a/lustre/llite/llite_lib.c +++ b/lustre/llite/llite_lib.c @@ -953,6 +953,7 @@ void ll_lli_init(struct ll_inode_info *lli) lli->lli_opendir_pid = 0; lli->lli_sa_enabled = 0; lli->lli_def_stripe_offset = -1; + init_rwsem(&lli->lli_lsm_sem); } else { mutex_init(&lli->lli_size_mutex); lli->lli_symlink_name = NULL; @@ -1308,9 +1309,16 @@ static int ll_init_lsm_md(struct inode *inode, struct lustre_md *md) { struct lu_fid *fid; struct lmv_stripe_md *lsm = md->lmv; + struct ll_inode_info *lli = ll_i2info(inode); int i; LASSERT(lsm != NULL); + + CDEBUG(D_INODE, "%s: "DFID" set dir layout:\n", + ll_get_fsname(inode->i_sb, NULL, 0), + PFID(&lli->lli_fid)); + lsm_md_dump(D_INODE, lsm); + /* XXX sigh, this lsm_root initialization should be in * LMV layer, but it needs ll_iget right now, so we * put this here right now. */ @@ -1327,10 +1335,16 @@ static int ll_init_lsm_md(struct inode *inode, struct lustre_md *md) int rc = PTR_ERR(lsm->lsm_md_oinfo[i].lmo_root); lsm->lsm_md_oinfo[i].lmo_root = NULL; + while (i-- > 0) { + iput(lsm->lsm_md_oinfo[i].lmo_root); + lsm->lsm_md_oinfo[i].lmo_root = NULL; + } return rc; } } + lli->lli_lsm_md = lsm; + return 0; } @@ -1338,7 +1352,8 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) { struct ll_inode_info *lli = ll_i2info(inode); struct lmv_stripe_md *lsm = md->lmv; - int rc; + int rc = 0; + ENTRY; LASSERT(S_ISDIR(inode->i_mode)); @@ -1352,75 +1367,65 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) if (!lsm) RETURN(0); - /* Compare the old and new stripe information */ + /* + * normally dir layout doesn't change, only take read lock to check + * that to avoid blocking other MD operations. + */ + if (lli->lli_lsm_md) + down_read(&lli->lli_lsm_sem); + else + down_write(&lli->lli_lsm_sem); + + /* + * if dir layout mismatch, check whether version is increased, which + * means layout is changed, this happens in dir migration and lfsck. + */ if (lli->lli_lsm_md && !lsm_md_eq(lli->lli_lsm_md, lsm)) { - struct lmv_stripe_md *old_lsm = lli->lli_lsm_md; - int idx; - bool layout_changed = lsm->lsm_md_layout_version > - old_lsm->lsm_md_layout_version; - - int mask = layout_changed ? D_INODE : D_ERROR; - - CDEBUG(mask, - "%s: inode@%p "DFID" lmv layout %s magic %#x/%#x " - "stripe count %d/%d master_mdt %d/%d " - "hash_type %#x/%#x version %d/%d migrate offset %d/%d " - "migrate hash %#x/%#x pool %s/%s\n", - ll_get_fsname(inode->i_sb, NULL, 0), inode, - PFID(&lli->lli_fid), - layout_changed ? "changed" : "mismatch", - lsm->lsm_md_magic, old_lsm->lsm_md_magic, - lsm->lsm_md_stripe_count, - old_lsm->lsm_md_stripe_count, - lsm->lsm_md_master_mdt_index, - old_lsm->lsm_md_master_mdt_index, - lsm->lsm_md_hash_type, old_lsm->lsm_md_hash_type, - lsm->lsm_md_layout_version, - old_lsm->lsm_md_layout_version, - lsm->lsm_md_migrate_offset, - old_lsm->lsm_md_migrate_offset, - lsm->lsm_md_migrate_hash, - old_lsm->lsm_md_migrate_hash, - lsm->lsm_md_pool_name, - old_lsm->lsm_md_pool_name); - - for (idx = 0; idx < old_lsm->lsm_md_stripe_count; idx++) - CDEBUG(mask, "old stripe[%d] "DFID"\n", - idx, PFID(&old_lsm->lsm_md_oinfo[idx].lmo_fid)); - - for (idx = 0; idx < lsm->lsm_md_stripe_count; idx++) - CDEBUG(mask, "new stripe[%d] "DFID"\n", - idx, PFID(&lsm->lsm_md_oinfo[idx].lmo_fid)); - - if (!layout_changed) - RETURN(-EINVAL); + if (lsm->lsm_md_layout_version <= + lli->lli_lsm_md->lsm_md_layout_version) { + CERROR("%s: "DFID" dir layout mismatch:\n", + ll_get_fsname(inode->i_sb, NULL, 0), + PFID(&lli->lli_fid)); + lsm_md_dump(D_ERROR, lli->lli_lsm_md); + lsm_md_dump(D_ERROR, lsm); + GOTO(unlock, rc = -EINVAL); + } + /* layout changed, switch to write lock */ + up_read(&lli->lli_lsm_sem); + down_write(&lli->lli_lsm_sem); ll_dir_clear_lsm_md(inode); } - /* set the directory layout */ + /* set directory layout */ if (!lli->lli_lsm_md) { struct cl_attr *attr; rc = ll_init_lsm_md(inode, md); + up_write(&lli->lli_lsm_sem); if (rc != 0) RETURN(rc); /* set md->lmv to NULL, so the following free lustre_md * will not free this lsm */ md->lmv = NULL; - lli->lli_lsm_md = lsm; + + /* + * md_merge_attr() may take long, since lsm is already set, + * switch to read lock. + */ + down_read(&lli->lli_lsm_sem); OBD_ALLOC_PTR(attr); if (attr == NULL) - RETURN(-ENOMEM); + GOTO(unlock, rc = -ENOMEM); /* validate the lsm */ rc = md_merge_attr(ll_i2mdexp(inode), lsm, attr, ll_md_blocking_ast); if (rc != 0) { OBD_FREE_PTR(attr); - RETURN(rc); + GOTO(unlock, rc); } if (md->body->mbo_valid & OBD_MD_FLNLINK) @@ -1435,49 +1440,11 @@ static int ll_update_lsm_md(struct inode *inode, struct lustre_md *md) md->body->mbo_mtime = attr->cat_mtime; OBD_FREE_PTR(attr); - - CDEBUG(D_INODE, "Set lsm %p magic %x to "DFID"\n", lsm, - lsm->lsm_md_magic, PFID(ll_inode2fid(inode))); - RETURN(0); - } - - /* Compare the old and new stripe information */ - if (!lsm_md_eq(lli->lli_lsm_md, lsm)) { - struct lmv_stripe_md *old_lsm = lli->lli_lsm_md; - int idx; - - CERROR("%s: inode "DFID"(%p)'s lmv layout mismatch (%p)/(%p)" - "magic:0x%x/0x%x stripe count: %d/%d master_mdt: %d/%d" - "hash_type:0x%x/0x%x layout: 0x%x/0x%x pool:%s/%s\n", - ll_get_fsname(inode->i_sb, NULL, 0), PFID(&lli->lli_fid), - inode, lsm, old_lsm, - lsm->lsm_md_magic, old_lsm->lsm_md_magic, - lsm->lsm_md_stripe_count, - old_lsm->lsm_md_stripe_count, - lsm->lsm_md_master_mdt_index, - old_lsm->lsm_md_master_mdt_index, - lsm->lsm_md_hash_type, old_lsm->lsm_md_hash_type, - lsm->lsm_md_layout_version, - old_lsm->lsm_md_layout_version, - lsm->lsm_md_pool_name, - old_lsm->lsm_md_pool_name); - - for (idx = 0; idx < old_lsm->lsm_md_stripe_count; idx++) { - CERROR("%s: sub FIDs in old lsm idx %d, old: "DFID"\n", - ll_get_fsname(inode->i_sb, NULL, 0), idx, - PFID(&old_lsm->lsm_md_oinfo[idx].lmo_fid)); - } - - for (idx = 0; idx < lsm->lsm_md_stripe_count; idx++) { - CERROR("%s: sub FIDs in new lsm idx %d, new: "DFID"\n", - ll_get_fsname(inode->i_sb, NULL, 0), idx, - PFID(&lsm->lsm_md_oinfo[idx].lmo_fid)); - } - - RETURN(-EIO); } +unlock: + up_read(&lli->lli_lsm_sem); - RETURN(0); + RETURN(rc); } void ll_clear_inode(struct inode *inode) @@ -2502,6 +2469,23 @@ out_statfs: return rc; } +/* + * this is normally called in ll_fini_md_op_data(), but sometimes it needs to + * be called early to avoid deadlock. + */ +void ll_unlock_md_op_lsm(struct md_op_data *op_data) +{ + if (op_data->op_mea2_sem) { + up_read(op_data->op_mea2_sem); + op_data->op_mea2_sem = NULL; + } + + if (op_data->op_mea1_sem) { + up_read(op_data->op_mea1_sem); + op_data->op_mea1_sem = NULL; + } +} + /* this function prepares md_op_data hint for passing it down to MD stack. */ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, struct inode *i1, struct inode *i2, @@ -2531,7 +2515,10 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, ll_i2gids(op_data->op_suppgids, i1, i2); op_data->op_fid1 = *ll_inode2fid(i1); op_data->op_default_stripe_offset = -1; + if (S_ISDIR(i1->i_mode)) { + down_read(&ll_i2info(i1)->lli_lsm_sem); + op_data->op_mea1_sem = &ll_i2info(i1)->lli_lsm_sem; op_data->op_mea1 = ll_i2info(i1)->lli_lsm_md; if (opc == LUSTRE_OPC_MKDIR) op_data->op_default_stripe_offset = @@ -2540,8 +2527,14 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, if (i2) { op_data->op_fid2 = *ll_inode2fid(i2); - if (S_ISDIR(i2->i_mode)) + if (S_ISDIR(i2->i_mode)) { + if (i2 != i1) { + down_read(&ll_i2info(i2)->lli_lsm_sem); + op_data->op_mea2_sem = + &ll_i2info(i2)->lli_lsm_sem; + } op_data->op_mea2 = ll_i2info(i2)->lli_lsm_md; + } } else { fid_zero(&op_data->op_fid2); } @@ -2571,6 +2564,7 @@ struct md_op_data *ll_prep_md_op_data(struct md_op_data *op_data, void ll_finish_md_op_data(struct md_op_data *op_data) { + ll_unlock_md_op_lsm(op_data); security_release_secctx(op_data->op_file_secctx, op_data->op_file_secctx_size); OBD_FREE_PTR(op_data); diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 8abf542..3c63e23 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -775,6 +775,8 @@ static struct dentry *ll_lookup_it(struct inode *parent, struct dentry *dentry, if (rc < 0) GOTO(out, retval = ERR_PTR(rc)); + /* dir layout may change */ + ll_unlock_md_op_lsm(op_data); rc = ll_lookup_it_finish(req, it, parent, &dentry); if (rc != 0) { ll_intent_release(it); diff --git a/lustre/llite/statahead.c b/lustre/llite/statahead.c index 22203ce..3977129 100644 --- a/lustre/llite/statahead.c +++ b/lustre/llite/statahead.c @@ -330,6 +330,58 @@ __sa_make_ready(struct ll_statahead_info *sai, struct sa_entry *entry, int ret) return (index == sai->sai_index_wait); } +/* finish async stat RPC arguments */ +static void sa_fini_data(struct md_enqueue_info *minfo) +{ + ll_unlock_md_op_lsm(&minfo->mi_data); + iput(minfo->mi_dir); + OBD_FREE_PTR(minfo); +} + +static int ll_statahead_interpret(struct ptlrpc_request *req, + struct md_enqueue_info *minfo, int rc); + +/* + * prepare arguments for async stat RPC. + */ +static struct md_enqueue_info * +sa_prep_data(struct inode *dir, struct inode *child, struct sa_entry *entry) +{ + struct md_enqueue_info *minfo; + struct ldlm_enqueue_info *einfo; + struct md_op_data *op_data; + + OBD_ALLOC_PTR(minfo); + if (minfo == NULL) + return ERR_PTR(-ENOMEM); + + op_data = ll_prep_md_op_data(&minfo->mi_data, dir, child, + entry->se_qstr.name, entry->se_qstr.len, 0, + LUSTRE_OPC_ANY, NULL); + if (IS_ERR(op_data)) { + OBD_FREE_PTR(minfo); + return (struct md_enqueue_info *)op_data; + } + + if (child == NULL) + op_data->op_fid2 = entry->se_fid; + + minfo->mi_it.it_op = IT_GETATTR; + minfo->mi_dir = igrab(dir); + minfo->mi_cb = ll_statahead_interpret; + minfo->mi_cbdata = entry; + + einfo = &minfo->mi_einfo; + einfo->ei_type = LDLM_IBITS; + einfo->ei_mode = it_to_lock_mode(&minfo->mi_it); + einfo->ei_cb_bl = ll_md_blocking_ast; + einfo->ei_cb_cp = ldlm_completion_ast; + einfo->ei_cb_gl = NULL; + einfo->ei_cbdata = NULL; + + return minfo; +} + /* * release resources used in async stat RPC, update entry state and wakeup if * scanner process it waiting on this entry. @@ -346,8 +398,7 @@ sa_make_ready(struct ll_statahead_info *sai, struct sa_entry *entry, int ret) if (minfo) { entry->se_minfo = NULL; ll_intent_release(&minfo->mi_it); - iput(minfo->mi_dir); - OBD_FREE_PTR(minfo); + sa_fini_data(minfo); } if (req) { @@ -582,14 +633,14 @@ static void sa_instantiate(struct ll_statahead_info *sai, int rc = 0; ENTRY; - LASSERT(entry->se_handle != 0); + LASSERT(entry->se_handle != 0); - minfo = entry->se_minfo; - it = &minfo->mi_it; - req = entry->se_req; - body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); - if (body == NULL) - GOTO(out, rc = -EFAULT); + minfo = entry->se_minfo; + it = &minfo->mi_it; + req = entry->se_req; + body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY); + if (body == NULL) + GOTO(out, rc = -EFAULT); child = entry->se_inode; if (child != NULL) { @@ -604,25 +655,25 @@ static void sa_instantiate(struct ll_statahead_info *sai, it->it_lock_handle = entry->se_handle; rc = md_revalidate_lock(ll_i2mdexp(dir), it, ll_inode2fid(dir), NULL); - if (rc != 1) - GOTO(out, rc = -EAGAIN); + if (rc != 1) + GOTO(out, rc = -EAGAIN); - rc = ll_prep_inode(&child, req, dir->i_sb, it); - if (rc) - GOTO(out, rc); + rc = ll_prep_inode(&child, req, dir->i_sb, it); + if (rc) + GOTO(out, rc); CDEBUG(D_READA, "%s: setting %.*s"DFID" l_data to inode %p\n", ll_get_fsname(child->i_sb, NULL, 0), entry->se_qstr.len, entry->se_qstr.name, PFID(ll_inode2fid(child)), child); - ll_set_lock_data(ll_i2sbi(dir)->ll_md_exp, child, it, NULL); + ll_set_lock_data(ll_i2sbi(dir)->ll_md_exp, child, it, NULL); - entry->se_inode = child; + entry->se_inode = child; - if (agl_should_run(sai, child)) - ll_agl_add(sai, child, entry->se_index); + if (agl_should_run(sai, child)) + ll_agl_add(sai, child, entry->se_index); - EXIT; + EXIT; out: /* sa_make_ready() will drop ldlm ibits lock refcount by calling @@ -686,8 +737,7 @@ static int ll_statahead_interpret(struct ptlrpc_request *req, if (rc != 0) { ll_intent_release(it); - iput(dir); - OBD_FREE_PTR(minfo); + sa_fini_data(minfo); } else { /* release ibits lock ASAP to avoid deadlock when statahead * thread enqueues lock on parent in readdir and another @@ -695,6 +745,7 @@ static int ll_statahead_interpret(struct ptlrpc_request *req, * unlink. */ handle = it->it_lock_handle; ll_intent_drop_lock(it); + ll_unlock_md_op_lsm(&minfo->mi_data); } spin_lock(&lli->lli_sa_lock); @@ -724,54 +775,6 @@ static int ll_statahead_interpret(struct ptlrpc_request *req, RETURN(rc); } -/* finish async stat RPC arguments */ -static void sa_fini_data(struct md_enqueue_info *minfo) -{ - iput(minfo->mi_dir); - OBD_FREE_PTR(minfo); -} - -/* - * prepare arguments for async stat RPC. - */ -static struct md_enqueue_info * -sa_prep_data(struct inode *dir, struct inode *child, struct sa_entry *entry) -{ - struct md_enqueue_info *minfo; - struct ldlm_enqueue_info *einfo; - struct md_op_data *op_data; - - OBD_ALLOC_PTR(minfo); - if (minfo == NULL) - return ERR_PTR(-ENOMEM); - - op_data = ll_prep_md_op_data(&minfo->mi_data, dir, child, - entry->se_qstr.name, entry->se_qstr.len, 0, - LUSTRE_OPC_ANY, NULL); - if (IS_ERR(op_data)) { - OBD_FREE_PTR(minfo); - return (struct md_enqueue_info *)op_data; - } - - if (child == NULL) - op_data->op_fid2 = entry->se_fid; - - minfo->mi_it.it_op = IT_GETATTR; - minfo->mi_dir = igrab(dir); - minfo->mi_cb = ll_statahead_interpret; - minfo->mi_cbdata = entry; - - einfo = &minfo->mi_einfo; - einfo->ei_type = LDLM_IBITS; - einfo->ei_mode = it_to_lock_mode(&minfo->mi_it); - einfo->ei_cb_bl = ll_md_blocking_ast; - einfo->ei_cb_cp = ldlm_completion_ast; - einfo->ei_cb_gl = NULL; - einfo->ei_cbdata = NULL; - - return minfo; -} - /* async stat for file not found in dcache */ static int sa_lookup(struct inode *dir, struct sa_entry *entry) { @@ -813,22 +816,20 @@ static int sa_revalidate(struct inode *dir, struct sa_entry *entry, if (d_mountpoint(dentry)) RETURN(1); + minfo = sa_prep_data(dir, inode, entry); + if (IS_ERR(minfo)) + RETURN(PTR_ERR(minfo)); + entry->se_inode = igrab(inode); rc = md_revalidate_lock(ll_i2mdexp(dir), &it, ll_inode2fid(inode), NULL); if (rc == 1) { entry->se_handle = it.it_lock_handle; ll_intent_release(&it); + sa_fini_data(minfo); RETURN(1); } - minfo = sa_prep_data(dir, inode, entry); - if (IS_ERR(minfo)) { - entry->se_inode = NULL; - iput(inode); - RETURN(PTR_ERR(minfo)); - } - rc = md_intent_getattr_async(ll_i2mdexp(dir), minfo); if (rc < 0) { entry->se_inode = NULL; @@ -1003,8 +1004,7 @@ static int ll_statahead_thread(void *arg) CDEBUG(D_READA, "statahead thread starting: sai %p, parent %.*s\n", sai, parent->d_name.len, parent->d_name.name); - op_data = ll_prep_md_op_data(NULL, dir, dir, NULL, 0, 0, - LUSTRE_OPC_ANY, dir); + OBD_ALLOC_PTR(op_data); if (IS_ERR(op_data)) GOTO(out, rc = PTR_ERR(op_data)); @@ -1026,8 +1026,16 @@ static int ll_statahead_thread(void *arg) struct lu_dirpage *dp; struct lu_dirent *ent; + op_data = ll_prep_md_op_data(op_data, dir, dir, NULL, 0, 0, + LUSTRE_OPC_ANY, dir); + if (IS_ERR(op_data)) { + rc = PTR_ERR(op_data); + break; + } + sai->sai_in_readpage = 1; page = ll_get_dir_page(dir, op_data, pos, &chain); + ll_unlock_md_op_lsm(op_data); sai->sai_in_readpage = 0; if (IS_ERR(page)) { rc = PTR_ERR(page); diff --git a/lustre/lmv/lmv_obd.c b/lustre/lmv/lmv_obd.c index f2db29f..090f3b1 100644 --- a/lustre/lmv/lmv_obd.c +++ b/lustre/lmv/lmv_obd.c @@ -1937,8 +1937,6 @@ static int lmv_migrate(struct obd_export *exp, struct md_op_data *op_data, ENTRY; LASSERT(op_data->op_cli_flags & CLI_MIGRATE); - LASSERTF(fid_is_sane(&op_data->op_fid3), "invalid FID "DFID"\n", - PFID(&op_data->op_fid3)); CDEBUG(D_INODE, "MIGRATE "DFID"/%.*s\n", PFID(&op_data->op_fid1), (int)namelen, name); -- 1.8.3.1