Whamcloud - gitweb
LU-15707 lod: force creation of a component without a pool 77/49477/2
authorEtienne AUJAMES <etienne.aujames@cea.fr>
Wed, 30 Mar 2022 16:43:44 +0000 (18:43 +0200)
committerOleg Drokin <green@whamcloud.com>
Mon, 13 Nov 2023 02:07:11 +0000 (02:07 +0000)
This patch add the pool option "lfs setstripe -p ignore" to force
the creation of component without a pool set by inheritance (from
parent or root).

e.g:
$ lfs setstripe -p pool tdir
$ lfs setstripe -E1M -p ignore -E-1 -p '' -c2 -S2M tdir/tfile
$ lfs getstripe -I1 -p tdir/tfile
(no pool set)
$ lfs getstripe -I2 -p tdir/tfile
pool
(inherited from tdir)

This patch add the test "ost-pools test_32" to verify this behavior.

The poorly-named "-p none" keyword, which indicates the pool name
should be inherited from the root or parent dir layout, will be
eventually replaced by the new "-p inherit" keyword.

Lustre-change: https://review.whamcloud.com/46955
Lustre-commit: 6b69d22e4cb738f4f9ff5454a6f9ae17a3a2d6fa

Test-Parameters: serverdistro=el7.9 serverversion=2.12.8 testlist=ost-pools env=ONLY=32,ONLY_REPEAT=50
Test-Parameters: testlist=ost-pools env=ONLY=32,ONLY_REPEAT=50
Signed-off-by: Etienne AUJAMES <eaujames@ddn.com>
Change-Id: I782cbafe209cff6857162303a4650f5e3b438be5
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Jian Yu <yujian@whamcloud.com>
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/49477
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
12 files changed:
lustre/doc/lfs-setstripe.1
lustre/include/obd_class.h
lustre/include/uapi/linux/lustre/lustre_user.h
lustre/lod/lod_object.c
lustre/lod/lod_pool.c
lustre/lod/lod_qos.c
lustre/mdd/mdd_lproc.c
lustre/mgs/mgs_handler.c
lustre/tests/ost-pools.sh
lustre/utils/lfs.c
lustre/utils/liblustreapi.c
lustre/utils/obd.c

index b9a144a..4212d1a 100644 (file)
@@ -247,10 +247,14 @@ plain
 .B raid0
 layouts, or the first component of a composite file).
 Use
-.BR pool_name='' ,
+.BR pool_name=ignore
+to force a component without a pool set (no inheritance from last component,
+root or parent).
+Use
+.BR pool_name=''
 or
-.BR pool_name=none
-(since Lustre 2.11) to force a component to inherit the pool from the parent
+.BR pool_name=inherit
+(since Lustre 2.15) to force a component to inherit the pool from the parent
 or root directory instead of the previous component.
 .TP
 .B --foreign \fR[<\fIforeign_type\fR>]
index 8d93466..1cf5d39 100644 (file)
@@ -940,6 +940,10 @@ static inline int obd_pool_new(struct obd_device *obd, char *poolname)
                RETURN(-EOPNOTSUPP);
        }
 
+       /* Check poolname validity */
+       if (!poolname || poolname[0] == '\0' || lov_pool_is_reserved(poolname))
+               RETURN(-EINVAL);
+
         rc = OBP(obd, pool_new)(obd, poolname);
         RETURN(rc);
 }
index 25fa6ad..7c807e2 100644 (file)
@@ -746,6 +746,30 @@ static inline bool lov_pattern_supported_normal_comp(__u32 pattern)
 
 #define LOV_MAXPOOLNAME 15
 #define LOV_POOLNAMEF "%.15s"
+/* The poolname "ignore" is used to force a component creation without pool */
+#define LOV_POOL_IGNORE "ignore"
+/* The poolname "inherit" is used to force a component to inherit the pool from
+ * parent or root directory
+ */
+#define LOV_POOL_INHERIT "inherit"
+/* The poolname "none" is deprecated in 2.15 (same behavior as "inherit") */
+#define LOV_POOL_NONE "none"
+
+static inline bool lov_pool_is_ignored(const char *pool)
+{
+       return pool && strncmp(pool, LOV_POOL_IGNORE, LOV_MAXPOOLNAME) == 0;
+}
+
+static inline bool lov_pool_is_inherited(const char *pool)
+{
+       return pool && (strncmp(pool, LOV_POOL_INHERIT, LOV_MAXPOOLNAME) == 0 ||
+                       strncmp(pool, LOV_POOL_NONE, LOV_MAXPOOLNAME) == 0);
+}
+
+static inline bool lov_pool_is_reserved(const char *pool)
+{
+       return lov_pool_is_ignored(pool) || lov_pool_is_inherited(pool);
+}
 
 #define LOV_MIN_STRIPE_BITS 16   /* maximum PAGE_SIZE (ia64), power of 2 */
 #define LOV_MIN_STRIPE_SIZE (1 << LOV_MIN_STRIPE_BITS)
index 982ccec..de4b6fa 100644 (file)
@@ -2731,7 +2731,6 @@ static int lod_declare_layout_add(const struct lu_env *env,
        struct dt_object *next = dt_object_child(dt);
        struct lov_desc *desc = &d->lod_ost_descs.ltd_lov_desc;
        struct lod_object *lo = lod_dt_obj(dt);
-       struct lov_user_md_v3 *v3;
        struct lov_comp_md_v1 *comp_v1 = buf->lb_buf;
        __u32 magic;
        int i, rc, array_cnt, old_array_cnt;
@@ -2787,8 +2786,10 @@ static int lod_declare_layout_add(const struct lu_env *env,
                lod_adjust_stripe_info(lod_comp, desc, 0);
 
                if (v1->lmm_magic == LOV_USER_MAGIC_V3) {
-                       v3 = (struct lov_user_md_v3 *) v1;
-                       if (v3->lmm_pool_name[0] != '\0') {
+                       struct lov_user_md_v3 *v3 = (typeof(*v3) *) v1;
+
+                       if (v3->lmm_pool_name[0] != '\0' &&
+                           !lov_pool_is_ignored(v3->lmm_pool_name)) {
                                rc = lod_set_pool(&lod_comp->llc_pool,
                                                  v3->lmm_pool_name);
                                if (rc)
@@ -3897,7 +3898,9 @@ static int lod_xattr_set_lov_on_dir(const struct lu_env *env,
        case LOV_USER_MAGIC_SPECIFIC:
        case LOV_USER_MAGIC_V3:
                v3 = buf->lb_buf;
-               if (v3->lmm_pool_name[0] != '\0')
+               if (lov_pool_is_reserved(v3->lmm_pool_name))
+                       memset(v3->lmm_pool_name, 0, sizeof(v3->lmm_pool_name));
+               else if (v3->lmm_pool_name[0] != '\0')
                        pool_name = v3->lmm_pool_name;
                fallthrough;
        case LOV_USER_MAGIC_V1:
index 47e3618..c6cc5a6 100644 (file)
@@ -711,22 +711,23 @@ struct pool_desc *lod_find_pool(struct lod_device *lod, char *poolname)
 {
        struct pool_desc *pool;
 
-       pool = NULL;
-       if (poolname[0] != '\0') {
-               pool = lod_pool_find(lod, poolname);
-               if (!pool)
-                       CDEBUG(D_CONFIG,
-                              "%s: request for an unknown pool (" LOV_POOLNAMEF ")\n",
-                              lod->lod_child_exp->exp_obd->obd_name, poolname);
-               if (pool != NULL && pool_tgt_count(pool) == 0) {
-                       CDEBUG(D_CONFIG, "%s: request for an empty pool ("
-                              LOV_POOLNAMEF")\n",
-                              lod->lod_child_exp->exp_obd->obd_name, poolname);
-                       /* pool is ignored, so we remove ref on it */
-                       lod_pool_putref(pool);
-                       pool = NULL;
-               }
+       if (poolname[0] == '\0' || lov_pool_is_reserved(poolname))
+               return NULL;
+
+       pool = lod_pool_find(lod, poolname);
+       if (!pool)
+               CDEBUG(D_CONFIG,
+                      "%s: request for an unknown pool (" LOV_POOLNAMEF ")\n",
+                      lod->lod_child_exp->exp_obd->obd_name, poolname);
+       if (pool != NULL && pool_tgt_count(pool) == 0) {
+               CDEBUG(D_CONFIG, "%s: request for an empty pool ("
+                      LOV_POOLNAMEF")\n",
+                      lod->lod_child_exp->exp_obd->obd_name, poolname);
+               /* pool is ignored, so we remove ref on it */
+               lod_pool_putref(pool);
+               pool = NULL;
        }
+
        return pool;
 }
 
index 6447dd9..4d816b6 100644 (file)
@@ -2300,7 +2300,10 @@ int lod_qos_parse_config(const struct lu_env *env, struct lod_object *lo,
                    v1->lmm_magic == LOV_USER_MAGIC_SPECIFIC) {
                        v3 = (struct lov_user_md_v3 *)v1;
 
-                       if (v3->lmm_pool_name[0] != '\0')
+                       if (lov_pool_is_ignored(v3->lmm_pool_name))
+                               pool_name = NULL;
+                       else if (v3->lmm_pool_name[0] != '\0' &&
+                                !lov_pool_is_inherited(v3->lmm_pool_name))
                                pool_name = v3->lmm_pool_name;
 
                        if (v3->lmm_magic == LOV_USER_MAGIC_SPECIFIC) {
index e0ce2cb..c3a926a 100644 (file)
@@ -695,24 +695,16 @@ static ssize_t append_pool_store(struct kobject *kobj, struct attribute *attr,
        struct mdd_device *mdd = container_of(kobj, struct mdd_device,
                                              mdd_kobj);
 
-       if (!count || count > LOV_MAXPOOLNAME + 1)
+       if (!count || count > LOV_MAXPOOLNAME + 1 || buffer[0]  == '\n')
                return -EINVAL;
 
-       /* clear previous value */
-       memset(mdd->mdd_append_pool, 0, LOV_MAXPOOLNAME + 1);
+       strlcpy(mdd->mdd_append_pool, buffer, LOV_MAXPOOLNAME + 1);
+       if (mdd->mdd_append_pool[count - 1] == '\n')
+               mdd->mdd_append_pool[count - 1] = '\0';
 
-       /* entering "none" clears the pool, otherwise copy the new pool */
-       if (strncmp("none", buffer, 4)) {
-               memcpy(mdd->mdd_append_pool, buffer, count);
-
-               /* Trim the trailing '\n' if any */
-               if (mdd->mdd_append_pool[count - 1] == '\n') {
-                       /* Don't echo just a newline */
-                       if (count == 1)
-                               return -EINVAL;
-                       mdd->mdd_append_pool[count - 1] = 0;
-               }
-       }
+       /* clears the pool for "none", "inherit" or "ignore" */
+       if (lov_pool_is_reserved(mdd->mdd_append_pool))
+               memset(mdd->mdd_append_pool, 0, LOV_MAXPOOLNAME + 1);
 
        return count;
 }
index 688b538..d49e51c 100644 (file)
@@ -716,6 +716,9 @@ static int mgs_extract_fs_pool(char *arg, char *fsname, char *poolname)
                return -EINVAL;
        ptr++;
 
+       /* Check pool name validity. */
+       if (ptr[0] == '\0' || lov_pool_is_reserved(ptr))
+               return -EINVAL;
        /* Also make sure poolname is not to long. */
        if (strlen(ptr) > LOV_MAXPOOLNAME)
                return -ENAMETOOLONG;
index 950d8fe..be8fc3a 100755 (executable)
@@ -1805,6 +1805,52 @@ test_31() {
 }
 run_test 31 "OST pool spilling chained"
 
+test_32() { # LU-15707
+       (( OSTCOUNT >= 2 )) || skip "Need at least 2 OST"
+
+       local pool=$TESTNAME
+       pool_add $pool || error "add $pool failed"
+       pool_add_targets $pool 0 ||
+               error "add targets to $pool failed"
+
+       test_mkdir $DIR/$tdir
+       $LFS setstripe -p $pool $DIR/$tdir ||
+               error "setstripe fail on $DIR/$tdir"
+
+       ( $LFS getstripe -p $DIR/$tdir | grep -q $pool ) ||
+               error "fail to set pool on $DIR/$tdir"
+
+       $LFS setstripe -p ignore $DIR/$tdir/$tfile ||
+               error "setstripe fail on $DIR/$tdir/$tfile"
+
+       ! ( $LFS getstripe -p $DIR/$tdir/$tfile | egrep -q "[^ ]+" ) ||
+               error "fail to create $DIR/$tdir/$tfile without pool"
+
+       # Test with start index
+       local got idx
+       for ((idx = 0; idx < OSTCOUNT; idx++)); do
+               $LFS setstripe -p ignore -i $idx $DIR/$tdir/$tfile.$idx ||
+                       error "setstripe -i fail on $DIR/$tdir/$tfile.$idx"
+
+               got=$($LFS getstripe -i $DIR/$tdir/$tfile.$idx)
+               (( got == idx )) ||
+                       error "file $tfile.$idx on OST $got != $idx"
+       done
+
+       # Test with ost list
+       $LFS setstripe -p ignore -o 1,0 $DIR/$tdir/$tfile.1_0 ||
+               error "setstripe --ost fail on $DIR/$tdir/$tfile.1_0"
+
+       got=$($LFS getstripe -i $DIR/$tdir/$tfile.1_0)
+       (( got == 1 )) ||
+               error "file $tfile.1_0 (ostlist) start on OST $got != 1"
+
+       got=$($LFS getstripe -c $DIR/$tdir/$tfile.1_0)
+       (( got == 2 )) ||
+               error "file $tfile.1_0 (ostlist) has stripe count $got != 2"
+}
+run_test 32 "force to create a file without pool (no inheritance)"
+
 cd $ORIG_PWD
 
 complete $SECONDS
index 7946d9e..425df77 100644 (file)
@@ -3940,12 +3940,11 @@ static int lfs_setstripe_internal(int argc, char **argv,
                case 'p':
                        if (!optarg)
                                goto usage_error;
-                       lsa.lsa_pool_name = optarg;
 
-                       if (strlen(lsa.lsa_pool_name) == 0 ||
-                           strncmp(lsa.lsa_pool_name, "none",
-                                   LOV_MAXPOOLNAME) == 0)
+                       if (optarg[0] == '\0' || lov_pool_is_inherited(optarg))
                                lsa.lsa_pool_name = NULL;
+                       else
+                               lsa.lsa_pool_name = optarg;
                        break;
                case 'S':
                        result = llapi_parse_size(optarg, &lsa.lsa_stripe_size,
index a3c819f..f897ab6 100644 (file)
@@ -3178,7 +3178,8 @@ static void lov_dump_user_lmm_header(struct lov_user_md *lum, char *path,
                        separator = "\n";
        }
 
-       if ((verbose & VERBOSE_POOL) && pool_name && (pool_name[0] != '\0')) {
+       if ((verbose & VERBOSE_POOL) && pool_name && (pool_name[0] != '\0') &&
+           (!lov_pool_is_ignored(pool_name) || is_raw)) {
                llapi_printf(LLAPI_MSG_NORMAL, "%s", separator);
                if (verbose & ~VERBOSE_POOL)
                        llapi_printf(LLAPI_MSG_NORMAL, "%s%spool:          ",
index ceb7aa7..92143fc 100644 (file)
@@ -5099,7 +5099,7 @@ static int extract_fsname_poolname(char **argv, char *fsname,
        *ptr = '\0';
        ++ptr;
 
-       if (strlen(ptr) == 0) {
+       if (ptr[0] == '\0') {
                fprintf(stderr, "poolname is empty\n");
                rc = -EINVAL;
                goto err;
@@ -5108,8 +5108,8 @@ static int extract_fsname_poolname(char **argv, char *fsname,
        strncpy(poolname, ptr, LOV_MAXPOOLNAME);
        poolname[LOV_MAXPOOLNAME] = '\0';
 
-       if (strncmp(poolname, "none", LOV_MAXPOOLNAME) == 0) {
-               fprintf(stderr, "poolname cannot be 'none'\n");
+       if (lov_pool_is_reserved(poolname)) {
+               fprintf(stderr, "poolname cannot be '%s'\n", poolname);
                return -EINVAL;
        }
 out: