From 7936ec229c7f62cfbf5a0e4ff5933149967e7c8f Mon Sep 17 00:00:00 2001 From: wang di Date: Fri, 18 Apr 2014 01:31:17 -0700 Subject: [PATCH] LU-4843 mdt: disallow old clients access striped dir 1. When old clients access striped directory, it should return -ENOTSUPP. 2. After we send create remote directory to the MDT where child is reside, we need check whether the parent is resided on MDT0. 3. add hash_type description. Signed-off-by: wang di Change-Id: I20c0b04c7e1d9a0cab4241dc39d0648f5631f2f4 Reviewed-on: http://review.whamcloud.com/9956 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Fan Yong Reviewed-by: Andreas Dilger --- lustre/mdt/mdt_handler.c | 11 +++- lustre/mdt/mdt_internal.h | 9 +++- lustre/mdt/mdt_reint.c | 118 +++++++++++++++++++++++++++++------------ lustre/tests/conf-sanity.sh | 4 ++ lustre/tests/recovery-small.sh | 8 +++ lustre/tests/test-framework.sh | 26 ++++++--- lustre/utils/lfs.c | 4 +- 7 files changed, 136 insertions(+), 44 deletions(-) diff --git a/lustre/mdt/mdt_handler.c b/lustre/mdt/mdt_handler.c index 298e9d8d..8ae3794 100644 --- a/lustre/mdt/mdt_handler.c +++ b/lustre/mdt/mdt_handler.c @@ -785,9 +785,9 @@ static int mdt_getattr_internal(struct mdt_thread_info *info, if (mdt_object_remote(o)) { /* This object is located on remote node.*/ - /* Return -EIO for old client */ + /* Return -ENOTSUPP for old client */ if (!mdt_is_dne_client(req->rq_export)) - GOTO(out, rc = -EIO); + GOTO(out, rc = -ENOTSUPP); repbody->fid1 = *mdt_object_fid(o); repbody->valid = OBD_MD_FLID | OBD_MD_MDS; @@ -897,12 +897,19 @@ static int mdt_getattr_internal(struct mdt_thread_info *info, mdt_dump_lmm(D_INFO, ma->ma_lmm, repbody->valid); } if (ma->ma_valid & MA_LMV) { + /* Return -ENOTSUPP for old client */ + if (!mdt_is_striped_client(req->rq_export)) + RETURN(-ENOTSUPP); + LASSERT(S_ISDIR(la->la_mode)); mdt_dump_lmv(D_INFO, ma->ma_lmv); repbody->eadatasize = ma->ma_lmv_size; repbody->valid |= (OBD_MD_FLDIREA|OBD_MD_MEA); } if (ma->ma_valid & MA_LMV_DEF) { + /* Return -ENOTSUPP for old client */ + if (!mdt_is_striped_client(req->rq_export)) + RETURN(-ENOTSUPP); LASSERT(S_ISDIR(la->la_mode)); repbody->eadatasize = ma->ma_lmv_size; repbody->valid |= (OBD_MD_FLDIREA|OBD_MD_DEFAULT_MEA); diff --git a/lustre/mdt/mdt_internal.h b/lustre/mdt/mdt_internal.h index d1a3b66..de5bd8f 100644 --- a/lustre/mdt/mdt_internal.h +++ b/lustre/mdt/mdt_internal.h @@ -589,11 +589,18 @@ static inline void mdt_export_evict(struct obd_export *exp) /* Here we use LVB_TYPE to check dne client, because it is * also landed on 2.4. */ -static inline int mdt_is_dne_client(struct obd_export *exp) +static inline bool mdt_is_dne_client(struct obd_export *exp) { return !!(exp_connect_flags(exp) & OBD_CONNECT_LVB_TYPE); } +/* Here we use OBD_CONNECT_DISP_STRIPE to check the client who support + * striped directory, because it is also landed on 2.6 */ +static inline bool mdt_is_striped_client(struct obd_export *exp) +{ + return exp_connect_flags(exp) & OBD_CONNECT_DISP_STRIPE; +} + int mdt_get_disposition(struct ldlm_reply *rep, int flag); void mdt_set_disposition(struct mdt_thread_info *info, struct ldlm_reply *rep, int flag); diff --git a/lustre/mdt/mdt_reint.c b/lustre/mdt/mdt_reint.c index 23d7079..8cb8cb7 100644 --- a/lustre/mdt/mdt_reint.c +++ b/lustre/mdt/mdt_reint.c @@ -245,6 +245,79 @@ int mdt_lookup_version_check(struct mdt_thread_info *info, } +/** + * mdt_remote_permission: Check whether the remote operation is permitted, + * + * Before we implement async cross-MDT updates (DNE phase 2). There are a few + * limitations here: + * + * 1.Only sysadmin can create remote directory and striped directory and + * migrate directory now, unless + * lctl set_param mdt.*.enable_remote_dir_gid=allow_gid. + * 2.Remote directory can only be created on MDT0, unless + * lctl set_param mdt.*.enable_remote_dir = 1 + * 3.Only new clients can access remote dir( >= 2.4) and striped dir(>= 2.6), + * old client will return -ENOTSUPP. + * + * XXX these check are only needed for remote synchronization, once async + * update is supported, these check will be removed. + * + * param[in]info: execution environment. + * param[in]parent: the directory of this operation. + * param[in]child: the child of this operation. + * + * retval = 0 remote operation is allowed. + * < 0 remote operation is denied. + */ +static int mdt_remote_permission(struct mdt_thread_info *info, + struct mdt_object *parent, + struct mdt_object *child) +{ + struct mdt_device *mdt = info->mti_mdt; + struct lu_ucred *uc = mdt_ucred(info); + struct md_op_spec *spec = &info->mti_spec; + struct lu_attr *attr = &info->mti_attr.ma_attr; + struct obd_export *exp = mdt_info_req(info)->rq_export; + + /* Only check create remote directory, striped directory and + * migration */ + if (mdt_object_remote(parent) == 0 && mdt_object_remote(child) == 0 && + !(S_ISDIR(attr->la_mode) && spec->u.sp_ea.eadata != NULL && + spec->u.sp_ea.eadatalen != 0) && + info->mti_rr.rr_opcode != REINT_MIGRATE) + return 0; + + if (!md_capable(uc, CFS_CAP_SYS_ADMIN)) { + if (uc->uc_gid != mdt->mdt_enable_remote_dir_gid && + mdt->mdt_enable_remote_dir_gid != -1) + return -EPERM; + } + + if (mdt->mdt_enable_remote_dir == 0) { + struct seq_server_site *ss = mdt_seq_site(mdt); + struct lu_seq_range range = { 0 }; + int rc; + + fld_range_set_type(&range, LU_SEQ_RANGE_MDT); + rc = fld_server_lookup(info->mti_env, ss->ss_server_fld, + fid_seq(mdt_object_fid(parent)), &range); + if (rc != 0) + return rc; + + if (range.lsr_index != 0) + return -EPERM; + } + + if (!mdt_is_dne_client(exp)) + return -ENOTSUPP; + + if (S_ISDIR(attr->la_mode) && spec->u.sp_ea.eadata != NULL && + spec->u.sp_ea.eadatalen != 0 && !mdt_is_striped_client(exp)) + return -ENOTSUPP; + + return 0; +} + /* * VBR: we save three versions in reply: * 0 - parent. Check that parent version is the same during replay. @@ -314,39 +387,11 @@ static int mdt_md_create(struct mdt_thread_info *info) if (likely(!IS_ERR(child))) { struct md_object *next = mdt_object_child(parent); - if (mdt_object_remote(child)) { - struct seq_server_site *ss; - struct lu_ucred *uc = mdt_ucred(info); - - if (!md_capable(uc, CFS_CAP_SYS_ADMIN)) { - if (uc->uc_gid != - mdt->mdt_enable_remote_dir_gid && - mdt->mdt_enable_remote_dir_gid != -1) { - CERROR("%s: Creating remote dir is only" - " permitted for administrator or" - " set mdt_enable_remote_dir_gid:" - " rc = %d\n", - mdt_obd_name(mdt), -EPERM); - GOTO(out_put_child, rc = -EPERM); - } - } - - ss = mdt_seq_site(mdt); - if (ss->ss_node_id != 0 && - mdt->mdt_enable_remote_dir == 0) { - CERROR("%s: remote dir is only permitted on" - " MDT0 or set_param" - " mdt.*.enable_remote_dir=1\n", - mdt_obd_name(mdt)); - GOTO(out_put_child, rc = -EPERM); - } - if (!mdt_is_dne_client(mdt_info_req(info)->rq_export)) { - /* Return -EIO for old client */ - GOTO(out_put_child, rc = -EIO); - } + rc = mdt_remote_permission(info, parent, child); + if (rc != 0) + GOTO(out_put_child, rc); - } - ma->ma_need = MA_INODE; + ma->ma_need = MA_INODE; ma->ma_valid = 0; /* capa for cross-ref will be stored here */ ma->ma_capa = req_capsule_server_get(info->mti_pill, @@ -910,8 +955,8 @@ static int mdt_reint_unlink(struct mdt_thread_info *info, PNAME(&rr->rr_name), PFID(mdt_object_fid(mc))); if (!mdt_is_dne_client(req->rq_export)) - /* Return -EIO for old client */ - GOTO(put_child, rc = -EIO); + /* Return -ENOTSUPP for old client */ + GOTO(put_child, rc = -ENOTSUPP); if (info->mti_spec.sp_rm_entry) { struct lu_ucred *uc = mdt_ucred(info); @@ -1413,6 +1458,7 @@ static int mdt_reint_migrate_internal(struct mdt_thread_info *info, CDEBUG(D_INODE, "migrate "DFID"/"DNAME" to "DFID"\n", PFID(rr->rr_fid1), PNAME(&rr->rr_name), PFID(rr->rr_fid2)); + /* 1: lock the source dir. */ msrcdir = mdt_object_find(info->mti_env, info->mti_mdt, rr->rr_fid1); if (IS_ERR(msrcdir)) { @@ -1467,6 +1513,10 @@ static int mdt_reint_migrate_internal(struct mdt_thread_info *info, GOTO(out_put_child, rc = -EPERM); } + rc = mdt_remote_permission(info, msrcdir, mold); + if (rc != 0) + GOTO(out_put_child, rc); + /* 3: iterate the linkea of the object and lock all of the objects */ CFS_INIT_LIST_HEAD(&lock_list); rc = mdt_lock_objects_in_linkea(info, mold, msrcdir, &lock_list); diff --git a/lustre/tests/conf-sanity.sh b/lustre/tests/conf-sanity.sh index 85b9307..e58f466 100644 --- a/lustre/tests/conf-sanity.sh +++ b/lustre/tests/conf-sanity.sh @@ -1694,6 +1694,10 @@ t32_test() { error_noexit "mount mdt1 failed" return 1 } + + $r $LCTL set_param -n mdt.${fsname}*.enable_remote_dir=1 || + error_noexit "enable remote dir create failed" + shall_cleanup_mdt1=true fi diff --git a/lustre/tests/recovery-small.sh b/lustre/tests/recovery-small.sh index ed7fae3..cf7a5ae 100755 --- a/lustre/tests/recovery-small.sh +++ b/lustre/tests/recovery-small.sh @@ -1685,6 +1685,14 @@ test_110a () { [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return 0 local remote_dir=$DIR/$tdir/remote_dir local MDTIDX=1 + local num + + #prepare for 110 test, which need set striped dir on remote MDT. + for num in $(seq $MDSCOUNT); do + do_facet mds$num \ + lctl set_param -n mdt.${FSNAME}*.enable_remote_dir=1 \ + 2>/dev/null + done mkdir -p $DIR/$tdir drop_request "$LFS mkdir -i $MDTIDX -c2 $remote_dir" || diff --git a/lustre/tests/test-framework.sh b/lustre/tests/test-framework.sh index 816078a..d26cb56 100755 --- a/lustre/tests/test-framework.sh +++ b/lustre/tests/test-framework.sh @@ -1183,12 +1183,19 @@ start() { eval export ${facet}failover_dev=$device fi - local mntpt=$(facet_mntpt $facet) - do_facet ${facet} mkdir -p $mntpt - eval export ${facet}_MOUNT=$mntpt - mount_facet ${facet} - RC=$? - return $RC + local mntpt=$(facet_mntpt $facet) + do_facet ${facet} mkdir -p $mntpt + eval export ${facet}_MOUNT=$mntpt + mount_facet ${facet} + RC=$? + + if [[ $facet == mds* ]]; then + do_facet $facet \ + lctl set_param -n mdt.${FSNAME}*.enable_remote_dir=1 \ + 2>/dev/null + fi + + return $RC } stop() { @@ -3857,6 +3864,13 @@ check_and_setup_lustre() { set_flavor_all $SEC fi + #Enable remote MDT create for testing + for num in $(seq $MDSCOUNT); do + do_facet mds$num \ + lctl set_param -n mdt.${FSNAME}*.enable_remote_dir=1 \ + 2>/dev/null + done + if [ "$ONLY" == "setup" ]; then exit 0 fi diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 3e42beb..cb684a1 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -156,7 +156,9 @@ command_t cmdlist[] = { "[--default_stripe|-D ] \n" "\tstripe_count: stripe count of the striped directory\n" "\tmdt_index: MDT index of first stripe\n" - "\thash_type: hash type of the striped directory\n" + "\thash_type: hash type of the striped directory. Hash types:\n" + " -t fnv_1a_64 FNV-1a hash algorithm(default)\n" + " -t all_char sum of characters % MDT_COUNT. (not recommended)\n" "\tdefault_stripe: set default dirstripe of the directory\n"}, {"getdirstripe", lfs_getdirstripe, 0, "To list the striping info for a given directory\n" -- 1.8.3.1