Whamcloud - gitweb
LU-14366 mdt: lfs mkdir should return -EEXIST if exists 29/41329/6
authorLai Siyao <lai.siyao@whamcloud.com>
Sat, 23 Jan 2021 10:28:26 +0000 (18:28 +0800)
committerOleg Drokin <green@whamcloud.com>
Thu, 15 Apr 2021 06:30:28 +0000 (06:30 +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.

Signed-off-by: Lai Siyao <lai.siyao@whamcloud.com>
Change-Id: I7b7ed04ee0b150253ff4d13bbdf1fe847d8f577c
Reviewed-on: https://review.whamcloud.com/41329
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Yingjin Qian <qian@ddn.com>
Reviewed-by: Oleg Drokin <green@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 d731aee..d057fc1 100644 (file)
@@ -130,6 +130,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 0970619..1218328 100644 (file)
@@ -1954,6 +1954,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 7657dd5..bb483bd 100644 (file)
@@ -399,7 +399,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;
@@ -505,6 +506,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()),
@@ -1410,12 +1414,13 @@ out_free:
        }
        case LL_IOC_LMV_SETSTRIPE: {
                struct lmv_user_md  *lum;
-               char            *filename;
-               int              namelen = 0;
-               int              lumlen = 0;
-               umode_t          mode;
-               int              len;
-               int              rc;
+               char *filename;
+               int namelen = 0;
+               int lumlen = 0;
+               umode_t mode;
+               bool createonly = false;
+               int len;
+               int rc;
 
                rc = obd_ioctl_getdata(&data, &len, (void __user *)arg);
                if (rc)
@@ -1457,7 +1462,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(data, len);
                RETURN(rc);
index a1a1d22..753ea83 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 6760847..670beef 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 82d0f76..817ed77 100755 (executable)
@@ -19059,6 +19059,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 2ad1dc0..ca8304f 100644 (file)
@@ -6602,6 +6602,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 0f85d29..40a6ee7 100644 (file)
@@ -1086,6 +1086,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,