Whamcloud - gitweb
LU-14366 mdt: lfs mkdir should return -EEXIST if exists
authorLai Siyao <lai.siyao@whamcloud.com>
Sat, 23 Jan 2021 10:28:26 +0000 (18:28 +0800)
committerAndreas Dilger <adilger@whamcloud.com>
Wed, 5 May 2021 03:56:55 +0000 (03:56 +0000)
'lfs setdirstripe' will try restripe if target exists, however
it's confusing to get -ENOTSUPP or -EALREADY for 'lfs mkdir', while
the latter invokes the same function as 'lfs setdirstripe'.

Pack MDS_OPEN_CREAT flag in request for 'lfs mkdir', and MDT won't
try restripe if it's set.

Add sanity 230s.

Lustre-change: https://review.whamcloud.com/41329
Lustre-commit: 65e3e4050ec5bb371c1c343fca49a605286a086e

Signed-off-by: Lai Siyao <lai.siyao@whamcloud.com>
Change-Id: I7b7ed04ee0b150253ff4d13bbdf1fe847d8f577c
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Yingjin Qian <qian@ddn.com>
Reviewed-on: https://review.whamcloud.com/43428
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
lustre/include/lustre/lustreapi.h
lustre/include/uapi/linux/lustre/lustre_idl.h
lustre/llite/dir.c
lustre/mdc/mdc_lib.c
lustre/mdt/mdt_reint.c
lustre/tests/sanity.sh
lustre/utils/lfs.c
lustre/utils/liblustreapi.c

index 49cc02a..be4c892 100644 (file)
@@ -131,6 +131,7 @@ struct llapi_stripe_param {
        /* Number of stripes. Size of lsp_osts[] if lsp_specific is true.*/
        int                     lsp_stripe_count;
        bool                    lsp_is_specific;
+       bool                    lsp_is_create;
        __u32                   lsp_osts[0];
 };
 
index 85db043..b932907 100644 (file)
@@ -1972,6 +1972,8 @@ enum mds_op_bias {
        MDS_TRUNC_KEEP_LEASE    = 1 << 18,
        MDS_PCC_ATTACH          = 1 << 19,
        MDS_CLOSE_UPDATE_TIMES  = 1 << 20,
+       /* setstripe create only, don't restripe if target exists */
+       MDS_SETSTRIPE_CREATE    = 1 << 21,
 };
 
 #define MDS_CLOSE_INTENT (MDS_HSM_RELEASE | MDS_CLOSE_LAYOUT_SWAP |         \
index 0e73a9d..4329254 100644 (file)
@@ -402,7 +402,8 @@ out:
  *                      <0 if the creation is failed.
  */
 static int ll_dir_setdirstripe(struct dentry *dparent, struct lmv_user_md *lump,
-                              size_t len, const char *dirname, umode_t mode)
+                              size_t len, const char *dirname, umode_t mode,
+                              bool createonly)
 {
        struct inode *parent = dparent->d_inode;
        struct ptlrpc_request *request = NULL;
@@ -508,6 +509,9 @@ static int ll_dir_setdirstripe(struct dentry *dparent, struct lmv_user_md *lump,
        }
 
        op_data->op_cli_flags |= CLI_SET_MEA;
+       if (createonly)
+               op_data->op_bias |= MDS_SETSTRIPE_CREATE;
+
        err = md_create(sbi->ll_md_exp, op_data, lump, len, mode,
                        from_kuid(&init_user_ns, current_fsuid()),
                        from_kgid(&init_user_ns, current_fsgid()),
@@ -1412,17 +1416,18 @@ static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                }
 out_free:
                OBD_FREE_LARGE(buf, len);
-                return rc;
-        }
+               return rc;
+       }
        case LL_IOC_LMV_SETSTRIPE: {
                struct lmv_user_md  *lum;
-               char            *buf = NULL;
-               char            *filename;
-               int              namelen = 0;
-               int              lumlen = 0;
-               umode_t          mode;
-               int              len;
-               int              rc;
+               char *buf = NULL;
+               char *filename;
+               int namelen = 0;
+               int lumlen = 0;
+               umode_t mode;
+               bool createonly = false;
+               int len;
+               int rc;
 
                rc = obd_ioctl_getdata(&buf, &len, (void __user *)arg);
                if (rc)
@@ -1465,7 +1470,9 @@ out_free:
                }
 
                mode = data->ioc_type;
-               rc = ll_dir_setdirstripe(dentry, lum, lumlen, filename, mode);
+               createonly = data->ioc_obdo1.o_flags & OBD_FL_OBDMDEXISTS;
+               rc = ll_dir_setdirstripe(dentry, lum, lumlen, filename, mode,
+                                        createonly);
 lmv_out_free:
                OBD_FREE_LARGE(buf, len);
                RETURN(rc);
index b44bc0f..09f4e7c 100644 (file)
@@ -219,6 +219,11 @@ void mdc_create_pack(struct ptlrpc_request *req, struct md_op_data *op_data,
        flags = 0;
        if (op_data->op_bias & MDS_CREATE_VOLATILE)
                flags |= MDS_OPEN_VOLATILE;
+       if (op_data->op_bias & MDS_SETSTRIPE_CREATE)
+               /* borrow MDS_OPEN_CREATE flag to indicate current setstripe
+                * create only, and don't restripe if object exists.
+                */
+               flags |= MDS_OPEN_CREAT;
        set_mrc_cr_flags(rec, flags);
        rec->cr_bias     = op_data->op_bias;
        rec->cr_umask    = current_umask();
index c14b84a..c29422b 100644 (file)
@@ -531,8 +531,12 @@ static int mdt_create(struct mdt_thread_info *info)
                    mdt->mdt_enable_remote_dir_gid != -1)
                        RETURN(-EPERM);
 
-               /* restripe if later found dir exists */
-               if (le32_to_cpu(lum->lum_stripe_offset) == LMV_OFFSET_DEFAULT)
+               /* restripe if later found dir exists, MDS_OPEN_CREAT means
+                * this is create only, don't try restripe.
+                */
+               if (mdt->mdt_enable_dir_restripe &&
+                   le32_to_cpu(lum->lum_stripe_offset) == LMV_OFFSET_DEFAULT &&
+                   !(spec->sp_cr_flags & MDS_OPEN_CREAT))
                        restripe = true;
        }
 
index 442bbb0..190910e 100755 (executable)
@@ -18733,6 +18733,28 @@ test_230r() {
 }
 run_test 230r "migrate with too many local locks"
 
+test_230s() {
+       [ $MDS1_VERSION -ge $(version_code 2.13.57) ] ||
+               skip "Need MDS version at least 2.13.57"
+
+       local mdts=$(comma_list $(mdts_nodes))
+       local restripe_status=$(do_facet mds1 $LCTL get_param -n \
+                               mdt.*MDT0000.enable_dir_restripe)
+
+       stack_trap "do_nodes $mdts $LCTL set_param \
+                   mdt.*.enable_dir_restripe=$restripe_status"
+
+       local st
+       for st in 0 1; do
+               do_nodes $mdts "$LCTL set_param mdt.*.enable_dir_restripe=$st"
+               test_mkdir $DIR/$tdir
+               $LFS mkdir $DIR/$tdir |& grep "File exists" ||
+                       error "$LFS mkdir doesn't return -EEXIST if target exists"
+               rmdir $DIR/$tdir
+       done
+}
+run_test 230s "lfs mkdir should return -EEXIST if target exists"
+
 test_231a()
 {
        # For simplicity this test assumes that max_pages_per_rpc
index eff36a7..43a81a4 100644 (file)
@@ -6337,6 +6337,8 @@ static int lfs_setdirstripe(int argc, char **argv)
                param->lsp_stripe_pattern = LMV_HASH_TYPE_UNKNOWN;
        param->lsp_pool = lsa.lsa_pool_name;
        param->lsp_is_specific = false;
+       if (strcmp(argv[0], "mkdir") == 0)
+               param->lsp_is_create = true;
        if (lsa.lsa_nr_tgts > 1) {
                if (lsa.lsa_stripe_count > 0 &&
                    lsa.lsa_stripe_count != LLAPI_LAYOUT_DEFAULT &&
index d03ea43..469dbc9 100644 (file)
@@ -1097,6 +1097,9 @@ int llapi_dir_create(const char *name, mode_t mode,
        data.ioc_inlbuf2 = (char *)lmu;
        data.ioc_inllen2 = lmu_size;
        data.ioc_type = mode;
+       if (param->lsp_is_create)
+               /* borrow obdo1.o_flags to store this flag */
+               data.ioc_obdo1.o_flags = OBD_FL_OBDMDEXISTS;
        rc = llapi_ioctl_pack(&data, &buf, sizeof(rawbuf));
        if (rc) {
                llapi_error(LLAPI_MSG_ERROR, rc,