Whamcloud - gitweb
LU-4843 mdt: disallow old clients access striped dir 56/9956/11
authorwang di <di.wang@intel.com>
Fri, 18 Apr 2014 08:31:17 +0000 (01:31 -0700)
committerOleg Drokin <oleg.drokin@intel.com>
Fri, 23 May 2014 05:24:33 +0000 (05:24 +0000)
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 <di.wang@intel.com>
Change-Id: I20c0b04c7e1d9a0cab4241dc39d0648f5631f2f4
Reviewed-on: http://review.whamcloud.com/9956
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Fan Yong <fan.yong@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
lustre/mdt/mdt_handler.c
lustre/mdt/mdt_internal.h
lustre/mdt/mdt_reint.c
lustre/tests/conf-sanity.sh
lustre/tests/recovery-small.sh
lustre/tests/test-framework.sh
lustre/utils/lfs.c

index 298e9d8..8ae3794 100644 (file)
@@ -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.*/
 
        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))
                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;
 
                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) {
                         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) {
                        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);
                        LASSERT(S_ISDIR(la->la_mode));
                        repbody->eadatasize = ma->ma_lmv_size;
                        repbody->valid |= (OBD_MD_FLDIREA|OBD_MD_DEFAULT_MEA);
index d1a3b66..de5bd8f 100644 (file)
@@ -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. */
 
 /* 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);
 }
 
 {
        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);
 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);
index 23d7079..8cb8cb7 100644 (file)
@@ -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.
 /*
  * 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 (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,
                 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))
                       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);
 
                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));
 
        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)) {
        /* 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);
        }
 
                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);
        /* 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);
index 85b9307..e58f466 100644 (file)
@@ -1694,6 +1694,10 @@ t32_test() {
                        error_noexit "mount mdt1 failed"
                        return 1
                }
                        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
 
                shall_cleanup_mdt1=true
        fi
 
index ed7fae3..cf7a5ae 100755 (executable)
@@ -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
        [ $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" ||
 
        mkdir -p $DIR/$tdir
        drop_request "$LFS mkdir -i $MDTIDX -c2 $remote_dir" ||
index 816078a..d26cb56 100755 (executable)
@@ -1183,12 +1183,19 @@ start() {
         eval export ${facet}failover_dev=$device
     fi
 
         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() {
 }
 
 stop() {
@@ -3857,6 +3864,13 @@ check_and_setup_lustre() {
                set_flavor_all $SEC
        fi
 
                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
        if [ "$ONLY" == "setup" ]; then
                exit 0
        fi
index 3e42beb..cb684a1 100644 (file)
@@ -156,7 +156,9 @@ command_t cmdlist[] = {
         "[--default_stripe|-D ] <dir>\n"
         "\tstripe_count: stripe count of the striped directory\n"
         "\tmdt_index:  MDT index of first stripe\n"
         "[--default_stripe|-D ] <dir>\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"
         "\tdefault_stripe: set default dirstripe of the directory\n"},
        {"getdirstripe", lfs_getdirstripe, 0,
         "To list the striping info for a given directory\n"