From fab54100cb822e8b471b0df92ce24f41bd0fd94c Mon Sep 17 00:00:00 2001 From: Etienne AUJAMES Date: Wed, 30 Mar 2022 18:43:44 +0200 Subject: [PATCH] LU-15707 lod: force creation of a component without a pool 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 Change-Id: I782cbafe209cff6857162303a4650f5e3b438be5 Reviewed-by: Andreas Dilger Reviewed-by: Jian Yu Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/49477 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin --- lustre/doc/lfs-setstripe.1 | 10 ++++-- lustre/include/obd_class.h | 4 +++ lustre/include/uapi/linux/lustre/lustre_user.h | 24 ++++++++++++++ lustre/lod/lod_object.c | 11 +++--- lustre/lod/lod_pool.c | 31 ++++++++--------- lustre/lod/lod_qos.c | 5 ++- lustre/mdd/mdd_lproc.c | 22 ++++-------- lustre/mgs/mgs_handler.c | 3 ++ lustre/tests/ost-pools.sh | 46 ++++++++++++++++++++++++++ lustre/utils/lfs.c | 7 ++-- lustre/utils/liblustreapi.c | 3 +- lustre/utils/obd.c | 6 ++-- 12 files changed, 126 insertions(+), 46 deletions(-) diff --git a/lustre/doc/lfs-setstripe.1 b/lustre/doc/lfs-setstripe.1 index b9a144a..4212d1a 100644 --- a/lustre/doc/lfs-setstripe.1 +++ b/lustre/doc/lfs-setstripe.1 @@ -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>] diff --git a/lustre/include/obd_class.h b/lustre/include/obd_class.h index 8d93466..1cf5d39 100644 --- a/lustre/include/obd_class.h +++ b/lustre/include/obd_class.h @@ -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); } diff --git a/lustre/include/uapi/linux/lustre/lustre_user.h b/lustre/include/uapi/linux/lustre/lustre_user.h index 25fa6ad..7c807e2 100644 --- a/lustre/include/uapi/linux/lustre/lustre_user.h +++ b/lustre/include/uapi/linux/lustre/lustre_user.h @@ -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) diff --git a/lustre/lod/lod_object.c b/lustre/lod/lod_object.c index 982ccec..de4b6fa 100644 --- a/lustre/lod/lod_object.c +++ b/lustre/lod/lod_object.c @@ -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: diff --git a/lustre/lod/lod_pool.c b/lustre/lod/lod_pool.c index 47e3618..c6cc5a6 100644 --- a/lustre/lod/lod_pool.c +++ b/lustre/lod/lod_pool.c @@ -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; } diff --git a/lustre/lod/lod_qos.c b/lustre/lod/lod_qos.c index 6447dd9..4d816b6 100644 --- a/lustre/lod/lod_qos.c +++ b/lustre/lod/lod_qos.c @@ -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) { diff --git a/lustre/mdd/mdd_lproc.c b/lustre/mdd/mdd_lproc.c index e0ce2cb..c3a926a 100644 --- a/lustre/mdd/mdd_lproc.c +++ b/lustre/mdd/mdd_lproc.c @@ -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; } diff --git a/lustre/mgs/mgs_handler.c b/lustre/mgs/mgs_handler.c index 688b538..d49e51c 100644 --- a/lustre/mgs/mgs_handler.c +++ b/lustre/mgs/mgs_handler.c @@ -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; diff --git a/lustre/tests/ost-pools.sh b/lustre/tests/ost-pools.sh index 950d8fe..be8fc3a 100755 --- a/lustre/tests/ost-pools.sh +++ b/lustre/tests/ost-pools.sh @@ -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 diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 7946d9e..425df77 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -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, diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index a3c819f..f897ab61 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -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: ", diff --git a/lustre/utils/obd.c b/lustre/utils/obd.c index ceb7aa7..92143fc 100644 --- a/lustre/utils/obd.c +++ b/lustre/utils/obd.c @@ -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: -- 1.8.3.1