From 65e3e4050ec5bb371c1c343fca49a605286a086e Mon Sep 17 00:00:00 2001 From: Lai Siyao Date: Sat, 23 Jan 2021 18:28:26 +0800 Subject: [PATCH] LU-14366 mdt: lfs mkdir should return -EEXIST if exists '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 Change-Id: I7b7ed04ee0b150253ff4d13bbdf1fe847d8f577c Reviewed-on: https://review.whamcloud.com/41329 Tested-by: jenkins Reviewed-by: Andreas Dilger Tested-by: Maloo Reviewed-by: Yingjin Qian Reviewed-by: Oleg Drokin --- lustre/include/lustre/lustreapi.h | 1 + lustre/include/uapi/linux/lustre/lustre_idl.h | 2 ++ lustre/llite/dir.c | 23 +++++++++++++++-------- lustre/mdc/mdc_lib.c | 5 +++++ lustre/mdt/mdt_reint.c | 8 ++++++-- lustre/tests/sanity.sh | 22 ++++++++++++++++++++++ lustre/utils/lfs.c | 2 ++ lustre/utils/liblustreapi.c | 3 +++ 8 files changed, 56 insertions(+), 10 deletions(-) diff --git a/lustre/include/lustre/lustreapi.h b/lustre/include/lustre/lustreapi.h index d731aee..d057fc1 100644 --- a/lustre/include/lustre/lustreapi.h +++ b/lustre/include/lustre/lustreapi.h @@ -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]; }; diff --git a/lustre/include/uapi/linux/lustre/lustre_idl.h b/lustre/include/uapi/linux/lustre/lustre_idl.h index 0970619..1218328 100644 --- a/lustre/include/uapi/linux/lustre/lustre_idl.h +++ b/lustre/include/uapi/linux/lustre/lustre_idl.h @@ -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 | \ diff --git a/lustre/llite/dir.c b/lustre/llite/dir.c index 7657dd5..bb483bd 100644 --- a/lustre/llite/dir.c +++ b/lustre/llite/dir.c @@ -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); diff --git a/lustre/mdc/mdc_lib.c b/lustre/mdc/mdc_lib.c index a1a1d22..753ea83 100644 --- a/lustre/mdc/mdc_lib.c +++ b/lustre/mdc/mdc_lib.c @@ -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(); diff --git a/lustre/mdt/mdt_reint.c b/lustre/mdt/mdt_reint.c index 6760847..670beef 100644 --- a/lustre/mdt/mdt_reint.c +++ b/lustre/mdt/mdt_reint.c @@ -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; } diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 82d0f76..817ed77 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -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 diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 2ad1dc0..ca8304f 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -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 && diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index 0f85d29..40a6ee7 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -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, -- 1.8.3.1