From: wang di Date: Tue, 14 Jul 2015 15:51:56 +0000 (-0700) Subject: LU-6341 llite: Use ll_dir_getstripe to get default LMVEA X-Git-Tag: 2.7.58~55 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=29d18f84e80b6f11d1e435c370ea962162851432 LU-6341 llite: Use ll_dir_getstripe to get default LMVEA Use ll_dir_getstripe to get default stripeEA in ll_new_node(), Because ll_getxattr_common requires admin rights for retrieving default LMVEA (because of trusted- prefix), which might cause mkdir (from normal user) failure. If parent does not have default stripeEA, then child should always be in the same MDT for mkdir. Otherwise MDT should return -EREMOTE, then client will refresh the default stripe index, and recreate the object. Signed-off-by: wang di Change-Id: I0d8884b78fbc8b8d1930b1133150686e65d20c54 Reviewed-on: http://review.whamcloud.com/13990 Tested-by: Jenkins Reviewed-by: John L. Hammond Tested-by: Maloo Reviewed-by: James Simmons Reviewed-by: Oleg Drokin --- diff --git a/lustre/include/obd_support.h b/lustre/include/obd_support.h index e0f3be1..a2fc1a8 100644 --- a/lustre/include/obd_support.h +++ b/lustre/include/obd_support.h @@ -244,6 +244,7 @@ extern char obd_jobid_var[]; #define OBD_FAIL_MDS_RENAME3 0x155 #define OBD_FAIL_MDS_RENAME4 0x156 #define OBD_FAIL_MDS_LDLM_REPLY_NET 0x157 +#define OBD_FAIL_MDS_STALE_DIR_LAYOUT 0x158 /* layout lock */ #define OBD_FAIL_MDS_NO_LL_GETATTR 0x170 diff --git a/lustre/llite/namei.c b/lustre/llite/namei.c index 483ca43..d7c28c3 100644 --- a/lustre/llite/namei.c +++ b/lustre/llite/namei.c @@ -936,40 +936,40 @@ again: from_kgid(&init_user_ns, current_fsgid()), cfs_curproc_cap_pack(), rdev, &request); ll_finish_md_op_data(op_data); - if (err) { - /* If the client doesn't know where to create a subdirectory (or - * in case of a race that sends the RPC to the wrong MDS), the - * MDS will return -EREMOTE and the client will fetch the layout - * for the directory, either from the local xattr cache or the - * MDS, then create the directory on the right MDT. */ - if (err == -EREMOTE) { - struct lmv_user_md *lum; - int rc; - - ptlrpc_req_finished(request); - request = NULL; - - OBD_ALLOC_PTR(lum); - if (lum == NULL) - GOTO(err_exit, err = -ENOMEM); - - rc = ll_getxattr_common(dir, XATTR_NAME_DEFAULT_LMV, - lum, sizeof(*lum), - OBD_MD_FLXATTR); - if (rc < 0) { - OBD_FREE_PTR(lum); - if (rc == -ENODATA) - GOTO(err_exit, err); - else - GOTO(err_exit, rc); - } + if (err < 0 && err != -EREMOTE) + GOTO(err_exit, err); - ll_i2info(dir)->lli_def_stripe_offset = - le32_to_cpu(lum->lum_stripe_offset); - OBD_FREE_PTR(lum); - goto again; + /* If the client doesn't know where to create a subdirectory (or + * in case of a race that sends the RPC to the wrong MDS), the + * MDS will return -EREMOTE and the client will fetch the layout + * of the directory, then create the directory on the right MDT. */ + if (unlikely(err == -EREMOTE)) { + struct ll_inode_info *lli = ll_i2info(dir); + struct lmv_user_md *lum; + int lumsize; + int err2; + + ptlrpc_req_finished(request); + request = NULL; + + err2 = ll_dir_getstripe(dir, (void **)&lum, &lumsize, &request, + OBD_MD_DEFAULT_MEA); + if (err2 == 0) { + /* Update stripe_offset and retry */ + lli->lli_def_stripe_offset = lum->lum_stripe_offset; + } else if (err2 == -ENODATA && + lli->lli_def_stripe_offset != -1) { + /* If there are no default stripe EA on the MDT, but the + * client has default stripe, then it probably means + * default stripe EA has just been deleted. */ + lli->lli_def_stripe_offset = -1; + } else { + GOTO(err_exit, err); } - GOTO(err_exit, err); + + ptlrpc_req_finished(request); + request = NULL; + goto again; } ll_update_times(request, dir); diff --git a/lustre/lod/lod_object.c b/lustre/lod/lod_object.c index f191742..95b5982 100644 --- a/lustre/lod/lod_object.c +++ b/lustre/lod/lod_object.c @@ -3108,17 +3108,8 @@ static void lod_ah_init(const struct lu_env *env, LASSERT(lc->ldo_stripenr == 0); LASSERT(lc->ldo_stripe == NULL); - /* - * local object may want some hints - * in case of late striping creation, ->ah_init() - * can be called with local object existing - */ - if (!dt_object_exists(nextc) || dt_object_remote(nextc)) { - struct dt_object *obj; - - obj = (nextp != NULL && dt_object_remote(nextp)) ? NULL : nextp; - nextc->do_ops->do_ah_init(env, ah, obj, nextc, child_mode); - } + if (!dt_object_exists(nextc)) + nextc->do_ops->do_ah_init(env, ah, nextp, nextc, child_mode); if (S_ISDIR(child_mode)) { if (lc->ldo_dir_stripe == NULL) { @@ -3460,10 +3451,20 @@ static int lod_declare_object_create(const struct lu_env *env, * Note: if dah_eadata != NULL, it means creating the * striped directory with specified stripeEA, then it * should ignore the default stripeEA */ - if ((hint == NULL || hint->dah_eadata == NULL) && - lo->ldo_dir_stripe_offset != -1 && - lo->ldo_dir_stripe_offset != ss->ss_node_id) - GOTO(out, rc = -EREMOTE); + if (hint != NULL && hint->dah_eadata == NULL) { + if (OBD_FAIL_CHECK(OBD_FAIL_MDS_STALE_DIR_LAYOUT)) + GOTO(out, rc = -EREMOTE); + + if (lo->ldo_dir_stripe_offset == -1) { + /* child and parent should be in the same MDT */ + if (hint->dah_parent != NULL && + dt_object_remote(hint->dah_parent)) + GOTO(out, rc = -EREMOTE); + } else if (lo->ldo_dir_stripe_offset != + ss->ss_node_id) { + GOTO(out, rc = -EREMOTE); + } + } /* Orphan object (like migrating object) does not have * lod_dir_stripe, see lod_ah_init */ diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c index dc190b9..e5401f6 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c @@ -1898,8 +1898,9 @@ static int osd_mkfile(struct osd_thread_info *info, struct osd_object *obj, oth = container_of(th, struct osd_thandle, ot_super); LASSERT(oth->ot_handle->h_transaction != NULL); - if (hint && hint->dah_parent) - parent = hint->dah_parent; + if (hint != NULL && hint->dah_parent != NULL && + !dt_object_remote(hint->dah_parent)) + parent = hint->dah_parent; inode = ldiskfs_create_inode(oth->ot_handle, parent ? osd_dt_obj(parent)->oo_inode : diff --git a/lustre/osd-zfs/osd_object.c b/lustre/osd-zfs/osd_object.c index 2279df0..51b218d 100644 --- a/lustre/osd-zfs/osd_object.c +++ b/lustre/osd-zfs/osd_object.c @@ -1440,7 +1440,8 @@ static int osd_object_create(const struct lu_env *env, struct dt_object *dt, /* to follow ZFS on-disk format we need * to initialize parent dnode properly */ zapid = 0; - if (hint && hint->dah_parent) + if (hint != NULL && hint->dah_parent != NULL && + !dt_object_remote(hint->dah_parent)) zapid = osd_dt_obj(hint->dah_parent)->oo_db->db_object; db = osd_create_type_f(dof->dof_type)(env, obj, attr, zapid, oh); diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 1eabf32..4ea2ade 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -13557,6 +13557,27 @@ test_300k() { } run_test 300k "test large striped directory" +test_300l() { + [ $PARALLEL == "yes" ] && skip "skip parallel run" && return + [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return + local stripe_index + + test_mkdir -p $DIR/$tdir/striped_dir + chown $RUNAS_ID $DIR/$tdir/striped_dir || + error "chown $RUNAS_ID failed" + $LFS setdirstripe -i 1 -D $DIR/$tdir/striped_dir || + error "set default striped dir failed" + + #define OBD_FAIL_MDS_STALE_DIR_LAYOUT 0x158 + $LCTL set_param fail_loc=0x80000158 + $RUNAS mkdir $DIR/$tdir/striped_dir/test_dir || error "create dir fails" + + stripe_index=$($LFS getdirstripe -i $DIR/$tdir/striped_dir/test_dir) + [ $stripe_index -eq 1 ] || + error "expect 1 get $stripe_index for $dir" +} +run_test 300l "non-root user to create dir under striped dir with stale layout" + prepare_remote_file() { mkdir $DIR/$tdir/src_dir || error "create remote source failed"