Whamcloud - gitweb
LU-6341 llite: Use ll_dir_getstripe to get default LMVEA 90/13990/11
authorwang di <di.wang@intel.com>
Tue, 14 Jul 2015 15:51:56 +0000 (08:51 -0700)
committerOleg Drokin <oleg.drokin@intel.com>
Wed, 29 Jul 2015 15:44:05 +0000 (15:44 +0000)
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 <di.wang@intel.com>
Change-Id: I0d8884b78fbc8b8d1930b1133150686e65d20c54
Reviewed-on: http://review.whamcloud.com/13990
Tested-by: Jenkins
Reviewed-by: John L. Hammond <john.hammond@intel.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: James Simmons <uja.ornl@yahoo.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/include/obd_support.h
lustre/llite/namei.c
lustre/lod/lod_object.c
lustre/osd-ldiskfs/osd_handler.c
lustre/osd-zfs/osd_object.c
lustre/tests/sanity.sh

index e0f3be1..a2fc1a8 100644 (file)
@@ -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_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
 
 /* layout lock */
 #define OBD_FAIL_MDS_NO_LL_GETATTR      0x170
index 483ca43..d7c28c3 100644 (file)
@@ -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);
                        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);
        }
 
         ll_update_times(request, dir);
index f191742..95b5982 100644 (file)
@@ -3108,17 +3108,8 @@ static void lod_ah_init(const struct lu_env *env,
        LASSERT(lc->ldo_stripenr == 0);
        LASSERT(lc->ldo_stripe == NULL);
 
        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) {
 
        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 */
                 * 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 */
 
                /* Orphan object (like migrating object) does not have
                 * lod_dir_stripe, see lod_ah_init */
index dc190b9..e5401f6 100644 (file)
@@ -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);
 
         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 :
 
         inode = ldiskfs_create_inode(oth->ot_handle,
                                      parent ? osd_dt_obj(parent)->oo_inode :
index 2279df0..51b218d 100644 (file)
@@ -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;
        /* 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);
                zapid = osd_dt_obj(hint->dah_parent)->oo_db->db_object;
 
        db = osd_create_type_f(dof->dof_type)(env, obj, attr, zapid, oh);
index 1eabf32..4ea2ade 100644 (file)
@@ -13557,6 +13557,27 @@ test_300k() {
 }
 run_test 300k "test large striped directory"
 
 }
 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"
 prepare_remote_file() {
        mkdir $DIR/$tdir/src_dir ||
                error "create remote source failed"