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>
.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>]
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);
}
#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)
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;
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)
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:
{
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;
}
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) {
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;
}
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;
}
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
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,
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: ",
*ptr = '\0';
++ptr;
- if (strlen(ptr) == 0) {
+ if (ptr[0] == '\0') {
fprintf(stderr, "poolname is empty\n");
rc = -EINVAL;
goto err;
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: