Print usage message.
.TP
.BR \-H ", " \-\-mdt-hash
-Only show the hash function being used for this directory.
+Only show the hash function being used for this directory. Also shows hash
+flags, such as overstriping (>1 stripe per MDT).
.TP
.BR --hex-idx
Print MDT indexes in hexademical rather than decimal.
.SH NAME
lfs setdirstripe, mkdir \- set striping pattern of a directory.
.SH SYNOPSIS
-.B lfs setdirstripe [\fR-cdDhHioTxX\fR] \fIDIR\fR...
+.B lfs setdirstripe [\fR-cCdDhHioTxX\fR] \fIDIR\fR...
.br
.SH DESCRIPTION
Create a striped directory with specified striping pattern. This
.I COUNT
MDTs.
.TP
+.B -C\fR, \fB--overstripe-count \fISTRIPE_COUNT\fR
+The number of stripes to create, creating > 1 stripe MDT if \fISTRIPE_COUNT\fR
+exceeds the number of MDTs in the file system. \fB0 \fRmeans to use the
+filesystem-wide default stripe count (default 1), and \fB-1 \fRmeans to stripe
+over all available MDTs. Max of 5 stripes/MDT.
+.TP
.BR \-h ", " \-\-help
Print usage message.
.TP
void *cbid_arg; /* additional arg */
};
-/** Maximum number of locks to fit into reply state */
-#define RS_MAX_LOCKS 8
+/** Maximum number of locks to fit into reply state, migrating directory max
+ * stripe count is 2 * LMV_MAX_STRIPES_PER_MDT, plus source parent, target
+ * parent, source and target master object:
+ * 2 * LMV_MAX_STRIPES_PER_MDT + 4
+ */
+#define RS_MAX_LOCKS 14
#define RS_DEBUG 0
/**
/** Handles of locks awaiting client reply ACK */
struct lustre_handle rs_locks[RS_MAX_LOCKS];
- /** Lock modes of locks in \a rs_locks */
- enum ldlm_mode rs_modes[RS_MAX_LOCKS];
};
struct ptlrpc_thread;
* @{
*/
void ptlrpc_save_lock(struct ptlrpc_request *req, struct lustre_handle *lock,
- int mode, bool no_ack);
+ bool no_ack);
void ptlrpc_commit_replies(struct obd_export *exp);
void ptlrpc_dispatch_difficult_reply(struct ptlrpc_reply_state *rs);
void ptlrpc_schedule_difficult_reply(struct ptlrpc_reply_state *rs);
#define LMV_HASH_FLAG_LAYOUT_CHANGE \
(LMV_HASH_FLAG_MIGRATION | LMV_HASH_FLAG_SPLIT | LMV_HASH_FLAG_MERGE)
-#define LMV_HASH_FLAG_KNOWN 0xbe000000
+#define LMV_HASH_FLAG_KNOWN 0xbf000000
/* migration failure may leave hash type as
* LMV_HASH_TYPE_UNKNOWN|LMV_HASH_FLAG_BAD_TYPE, which should be treated as
* (max buffer size - lmv+rpc header) / sizeof(struct lmv_user_mds_data)
*/
#define LMV_MAX_STRIPE_COUNT 2000 /* ((12 * 4096 - 256) / 24) */
+#define LMV_MAX_STRIPES_PER_MDT 5 /* (RS_MAX_LOCKS - 4) / 2 */
#define lmv_user_md lmv_user_md_v1
struct lmv_user_md_v1 {
__u32 lum_magic; /* must be the first field */
LMV_INHERIT_DEFAULT_PLAIN = LMV_INHERIT_UNLIMITED,
/* not inherit any more */
LMV_INHERIT_END = 1,
- /* for multiple stripes, the default lum_max_inherit is 3 */
+ /* for overstriped dirs, the default limit is 1 level of inheritance */
+ LMV_INHERIT_DEFAULT_OVERSTRIPED = 2,
+ /* for multiple stripes, the default limit is 2 levels of inheritance*/
LMV_INHERIT_DEFAULT_STRIPED = 3,
/* max inherit depth */
LMV_INHERIT_MAX = 250,
bool already_allocated = false;
__u32 k;
- CDEBUG(D_INFO, "try idx %d, mdt cnt %u, allocated %u\n",
- idx, lod->lod_remote_mdt_count + 1, stripe_idx);
+ CDEBUG(D_INFO,
+ "try idx %d, mdt cnt %u, allocated %u, specific %d count %hu offset %d hash %#X\n",
+ idx, lod->lod_remote_mdt_count + 1, stripe_idx,
+ is_specific, lo->ldo_dir_stripe_count,
+ (int)lo->ldo_dir_stripe_offset,
+ lo->ldo_dir_hash_type);
if (likely(!is_specific &&
- !CFS_FAIL_CHECK(OBD_FAIL_LARGE_STRIPE))) {
+ !CFS_FAIL_CHECK(OBD_FAIL_LARGE_STRIPE) &&
+ !(lo->ldo_dir_hash_type &
+ LMV_HASH_FLAG_OVERSTRIPED))) {
/* check whether the idx already exists
* in current allocated array */
for (k = 0; k < stripe_idx; k++) {
struct dt_object **stripes;
struct lu_object_conf conf = { .loc_flags = LOC_F_NEW };
struct lu_fid fid = { 0 };
+ int mdt_count = lod->lod_remote_mdt_count + 1;
__u32 stripe_count;
int i;
int rc = 0;
le32_to_cpu(lum->lum_magic) == LMV_USER_MAGIC_SPECIFIC);
stripe_count = lo->ldo_dir_stripe_count;
+ if (!(lo->ldo_dir_hash_type & LMV_HASH_FLAG_OVERSTRIPED) &&
+ stripe_count > mdt_count)
+ RETURN(-E2BIG);
+
+ if ((lo->ldo_dir_hash_type & LMV_HASH_FLAG_OVERSTRIPED) &&
+ (stripe_count > mdt_count * LMV_MAX_STRIPES_PER_MDT ||
+ /* a single MDT doesn't initialize the infrastructure for striped
+ * directories, so we just don't support overstriping in that case
+ */
+ mdt_count == 1))
+ RETURN(-E2BIG);
OBD_ALLOC_PTR_ARRAY(stripes, stripe_count);
if (!stripes)
GOTO(out, rc = -ENOMEM);
if (le32_to_cpu(lum->lum_magic) == LMV_USER_MAGIC_SPECIFIC) {
+ int stripes_per_mdt;
+ int mdt;
+
is_specific = true;
+
+ /* Verify we do not exceed the stripes per MDT limit */
+ for (mdt = 0; mdt < mdt_count + 1; mdt++) {
+ stripes_per_mdt = 0;
+ for (i = 0; i < stripe_count; i++) {
+ if (mdt == le32_to_cpu(
+ lum->lum_objects[i].lum_mds))
+ stripes_per_mdt++;
+ }
+ if (stripes_per_mdt > LMV_MAX_STRIPES_PER_MDT)
+ GOTO(out_free, rc = -EINVAL);
+ }
+
for (i = 0; i < stripe_count; i++)
idx_array[i] =
le32_to_cpu(lum->lum_objects[i].lum_mds);
lu_site2seq(lod2lu_dev(lod)->ld_site)->ss_node_id;
rc = lod_mdt_alloc_specific(env, lo, stripes, idx_array,
is_specific);
+out_free:
OBD_FREE_PTR_ARRAY(idx_array, stripe_count);
}
if (S_ISDIR(child_mode)) {
const struct lmv_user_md_v1 *lum1 = ah->dah_eadata;
+ int max_stripe_count;
/* other default values are 0 */
lc->ldo_dir_stripe_offset = LMV_OFFSET_DEFAULT;
d->lod_max_mdt_stripecount)
lc->ldo_dir_stripe_count = d->lod_max_mdt_stripecount;
- /* shrink the stripe_count to the avaible MDT count */
- if (lc->ldo_dir_stripe_count > d->lod_remote_mdt_count + 1 &&
+ max_stripe_count = d->lod_remote_mdt_count + 1;
+ if (lc->ldo_dir_hash_type & LMV_HASH_FLAG_OVERSTRIPED)
+ max_stripe_count =
+ max_stripe_count * LMV_MAX_STRIPES_PER_MDT;
+
+ /* shrink the stripe_count to max stripe count */
+ if (lc->ldo_dir_stripe_count > max_stripe_count &&
!CFS_FAIL_CHECK(OBD_FAIL_LARGE_STRIPE)) {
- lc->ldo_dir_stripe_count = d->lod_remote_mdt_count + 1;
+ lc->ldo_dir_stripe_count = max_stripe_count;
if (lc->ldo_dir_stripe_count == 1)
lc->ldo_dir_stripe_count = 0;
}
lc->ldo_def_striping = lds;
}
- CDEBUG(D_INFO, "final dir stripe_count=%hu offset=%d hash=%u\n",
+ CDEBUG(D_INFO, "final dir stripe_count=%hu offset=%d hash=%x\n",
lc->ldo_dir_stripe_count,
(int)lc->ldo_dir_stripe_offset, lc->ldo_dir_hash_type);
struct dt_object_format *dof = &info->lti_format;
struct lmv_user_md_v1 *lum = mlc->mlc_spec->u.sp_ea.eadata;
struct dt_object **stripes;
+ int mdt_count = lod->lod_remote_mdt_count + 1;
u32 stripe_count;
u32 saved_count;
int i;
if (stripe_count <= saved_count)
RETURN(-EINVAL);
+ /* if the split target is overstriped, we need to put that flag in the
+ * current layout so it can allocate the larger number of stripes
+ *
+ * Note we need to pick up any hash *flags* which affect allocation
+ * *before* allocation, so they're used in allocating the directory,
+ * rather than after when we finalize directory setup (at the end of
+ * this function).
+ */
+ if (le32_to_cpu(lum->lum_hash_type) & LMV_HASH_FLAG_OVERSTRIPED)
+ lo->ldo_dir_hash_type |= LMV_HASH_FLAG_OVERSTRIPED;
+
+ if (!(lo->ldo_dir_hash_type & LMV_HASH_FLAG_OVERSTRIPED) &&
+ stripe_count > mdt_count) {
+ RETURN(-E2BIG);
+ } else if ((lo->ldo_dir_hash_type & LMV_HASH_FLAG_OVERSTRIPED) &&
+ (stripe_count > mdt_count * LMV_MAX_STRIPES_PER_MDT ||
+ /* a single MDT doesn't initialize the infrastructure for striped
+ * directories, so we just don't support overstriping in that case
+ */
+ mdt_count == 1)) {
+ RETURN(-E2BIG);
+ }
+
dof->dof_type = DFT_DIR;
OBD_ALLOC(stripes, sizeof(*stripes) * stripe_count);
stripes[i] = lo->ldo_stripe[i];
lod_qos_statfs_update(env, lod, &lod->lod_mdt_descs);
+
rc = lod_mdt_alloc_qos(env, lo, stripes, saved_count, stripe_count);
if (rc == -EAGAIN)
rc = lod_mdt_alloc_rr(env, lo, stripes, saved_count,
struct lu_tgt_descs *ltd = &lod->lod_mdt_descs;
struct lu_tgt_pool *pool;
struct lu_qos_rr *lqr;
- struct lu_tgt_desc *mdt;
struct lu_object_conf conf = { .loc_flags = LOC_F_NEW };
struct lu_fid fid = { 0 };
struct dt_object *dto;
unsigned int pool_idx;
unsigned int i;
u32 saved_idx = stripe_idx;
+ int stripes_per_mdt = 1;
u32 mdt_idx;
bool use_degraded = false;
+ bool overstriped = false;
int tgt_connecting = 0;
int rc;
if (rc)
RETURN(rc);
+ overstriped = lo->ldo_dir_hash_type & LMV_HASH_FLAG_OVERSTRIPED;
+
+ if (stripe_count > lod->lod_remote_mdt_count + 1 && !overstriped)
+ RETURN(-E2BIG);
+
+ if (lo->ldo_dir_hash_type & LMV_HASH_FLAG_OVERSTRIPED)
+ stripes_per_mdt = stripe_count / (pool->op_count + 1);
+
rc = lod_qos_mdt_in_use_init(env, ltd, stripe_idx, stripe_count, pool,
stripes);
if (rc)
} else if (atomic_read(&lqr->lqr_start_idx) >= pool->op_count) {
/* If we have allocated from all of the tgts, slowly
* precess the next start if the tgt/stripe count isn't
- * already doing this for us. */
+ * already doing this for us.
+ */
atomic_sub(pool->op_count, &lqr->lqr_start_idx);
if (stripe_count - 1 > 1 &&
(pool->op_count % (stripe_count - 1)) != 1)
spin_unlock(&lqr->lqr_alloc);
repeat_find:
- CDEBUG(D_OTHER, "want=%d start_idx=%d start_count=%d offset=%d active=%d count=%d\n",
+ CDEBUG(D_OTHER,
+ "want=%d start_idx=%d start_count=%d offset=%d active=%d count=%d\n",
stripe_count - 1, atomic_read(&lqr->lqr_start_idx),
- lqr->lqr_start_count, lqr->lqr_offset_idx, pool->op_count,
- pool->op_count);
-
- for (i = 0; i < pool->op_count && stripe_idx < stripe_count; i++) {
+ lqr->lqr_start_count, lqr->lqr_offset_idx,
+ /* if we're overstriped, the local MDT is available and is
+ * included in the count
+ */
+ pool->op_count + overstriped,
+ lqr->lqr_pool.op_count + overstriped);
+
+ for (i = 0; i < (pool->op_count + overstriped) * stripes_per_mdt &&
+ stripe_idx < stripe_count; i++) {
+ struct lu_tgt_desc *mdt = NULL;
+ struct dt_device *mdt_tgt;
+ bool local_alloc = false;
int idx;
idx = atomic_inc_return(&lqr->lqr_start_idx);
pool_idx = (idx + lqr->lqr_offset_idx) %
- pool->op_count;
- mdt_idx = lqr->lqr_pool.op_array[pool_idx];
- mdt = LTD_TGT(ltd, mdt_idx);
+ (pool->op_count + overstriped);
+ /* in the overstriped case, we must be able to allocate a stripe
+ * to the local MDT, ie, the one doing the allocation
+ */
+ if (pool_idx == pool->op_count) {
+ LASSERT(overstriped);
+ /* because there is already a stripe on the local MDT,
+ * do not allocate from the local MDT until we've
+ * allocated at least as many stripes as we have MDTs
+ */
+ if (stripe_idx < (pool->op_count + 1)) {
+ CDEBUG(D_OTHER,
+ "Skipping local alloc, not enough stripes yet\n");
+ continue;
+ }
+ CDEBUG(D_OTHER, "Attempting to allocate locally\n");
+ local_alloc = true;
+ mdt_tgt = lod->lod_child;
+ rc = lodname2mdt_index(lod2obd(lod)->obd_name,
+ &mdt_idx);
+ /* this parsing can't fail here because we're working
+ * with a known-good MDT
+ */
+ LASSERT(!rc);
+ } else {
+ mdt_idx = lqr->lqr_pool.op_array[pool_idx];
+ mdt = LTD_TGT(ltd, mdt_idx);
+ mdt_tgt = mdt->ltd_tgt;
+ }
CDEBUG(D_OTHER, "#%d strt %d act %d strp %d ary %d idx %d\n",
i, idx, /* XXX: active*/ 0,
stripe_idx, pool_idx, mdt_idx);
- if (mdt_idx == LOV_QOS_EMPTY ||
- !test_bit(mdt_idx, ltd->ltd_tgt_bitmap))
- continue;
-
- /* do not put >1 objects on one MDT */
- if (lod_qos_is_tgt_used(env, mdt_idx, stripe_idx))
- continue;
-
- if (mdt->ltd_discon) {
- tgt_connecting = 1;
+ if (!local_alloc && (mdt_idx == LOV_QOS_EMPTY ||
+ !test_bit(mdt_idx, ltd->ltd_tgt_bitmap))) {
+ CDEBUG(D_OTHER, "mdt_idx not found %d\n", mdt_idx);
continue;
}
- if (lod_statfs_check(ltd, mdt))
- continue;
+ /* do not put >1 objects on one MDT, except for overstriping */
+ if (!local_alloc) {
+ if (lo->ldo_dir_hash_type & LMV_HASH_FLAG_OVERSTRIPED) {
+ CDEBUG(D_OTHER, "overstriped\n");
+ } else if (lod_qos_is_tgt_used(env, mdt_idx,
+ stripe_idx)) {
+ CDEBUG(D_OTHER, "#%d: already used\n", mdt_idx);
+ continue;
+ }
+ }
- if (mdt->ltd_statfs.os_state & OS_STATFS_NOCREATE)
- continue;
+ /* we know the local MDT is usable */
+ if (!local_alloc) {
+ if (mdt->ltd_discon) {
+ tgt_connecting = 1;
+ CDEBUG(D_OTHER, "#%d: unusable\n", mdt_idx);
+ continue;
+ }
+ if (lod_statfs_check(ltd, mdt))
+ continue;
+ if (mdt->ltd_statfs.os_state & OS_STATFS_NOCREATE)
+ continue;
+ }
/* try to use another OSP if this one is degraded */
- if (mdt->ltd_statfs.os_state & OS_STATFS_DEGRADED &&
- !use_degraded) {
+ if (!local_alloc && !use_degraded &&
+ mdt->ltd_statfs.os_state & OS_STATFS_DEGRADED) {
CDEBUG(D_OTHER, "#%d: degraded\n", mdt_idx);
continue;
}
- rc = dt_fid_alloc(env, mdt->ltd_tgt, &fid, NULL, NULL);
+ rc = dt_fid_alloc(env, mdt_tgt, &fid, NULL, NULL);
if (rc < 0) {
CDEBUG(D_OTHER, "#%d: alloc FID failed: %dl\n", mdt_idx, rc);
continue;
}
- dto = dt_locate_at(env, mdt->ltd_tgt, &fid,
+ dto = dt_locate_at(env, mdt_tgt, &fid,
lo->ldo_obj.do_lu.lo_dev->ld_site->ls_top_dev,
&conf);
if (IS_ERR(dto)) {
CDEBUG(D_OTHER, "can't alloc stripe on #%u: %d\n",
- mdt->ltd_index, (int) PTR_ERR(dto));
+ mdt_idx, (int) PTR_ERR(dto));
- if (mdt->ltd_discon)
+ if (!local_alloc && mdt->ltd_discon)
tgt_connecting = 1;
continue;
}
}
up_read(<d->ltd_qos.lq_rw_sem);
- if (stripe_idx > saved_idx)
+ if (stripe_idx > saved_idx) {
+ /* If there are enough MDTs, we will not actually do
+ * overstriping, and the hash flags should reflect this.
+ */
+ if (!overstriped)
+ lo->ldo_dir_hash_type &= ~LMV_HASH_FLAG_OVERSTRIPED;
/* at least one stripe is allocated */
RETURN(stripe_idx);
+ }
/* nobody provided us with a single object */
if (tgt_connecting)
if (stripe_idx == stripe_count)
RETURN(stripe_count);
+ /* we do not use qos for overstriping, since it will always use all the
+ * MDTs. So we check if it's truly needed, falling back to rr if it is,
+ * and otherwise we remove the flag and continue
+ */
+ if (lo->ldo_dir_hash_type & LMV_HASH_FLAG_OVERSTRIPED) {
+ if (stripe_count > lod->lod_remote_mdt_count + 1)
+ RETURN(-EAGAIN);
+ lo->ldo_dir_hash_type &= ~LMV_HASH_FLAG_OVERSTRIPED;
+ }
+
/* use MDT pool in @ltd, once MDT pool is supported in the future, it
* can be passed in as argument like OST object allocation.
*/
if (req->rq_export->exp_disconnected)
mdt_fid_unlock(h, mode);
else
- ptlrpc_save_lock(req, h, mode, no_ack);
+ ptlrpc_save_lock(req, h, no_ack);
} else {
mdt_fid_unlock(h, mode);
}
spin_lock(&rs->rs_lock);
for (i = 0; i < rs->rs_nlocks; i++)
- ptlrpc_save_lock(req, &rs->rs_locks[i],
- rs->rs_modes[i], rs->rs_no_ack);
+ ptlrpc_save_lock(req, &rs->rs_locks[i], rs->rs_no_ack);
rs->rs_nlocks = 0;
DEBUG_REQ(D_HA, req, "stole locks for");
rs = req->rq_reply_state;
for (i = 0; i < rs->rs_nlocks; i++)
- ldlm_lock_decref(&rs->rs_locks[i], rs->rs_modes[i]);
+ ldlm_lock_decref(&rs->rs_locks[i], LCK_TXN);
rs->rs_nlocks = 0;
}
* directory.
*/
- if (lum_stripe_count > 1 && lmu->lum_hash_type &&
- lmu->lum_hash_type !=
+ if (lum_stripe_count > 1 &&
+ (lmu->lum_hash_type & cpu_to_le32(LMV_HASH_TYPE_MASK)) &&
+ (lmu->lum_hash_type & cpu_to_le32(LMV_HASH_TYPE_MASK)) !=
(lmv->lmv_hash_type & cpu_to_le32(LMV_HASH_TYPE_MASK))) {
- CERROR("%s: "DFID" migrate mdt hash mismatch %u != %u\n",
+ CERROR("%s: "DFID" migrate mdt hash mismatch %x != %x\n",
mdt_obd_name(info->mti_mdt), PFID(rr->rr_fid1),
lmv->lmv_hash_type, lmu->lum_hash_type);
GOTO(unlock_obj, rc = -EINVAL);
nrs->rs_no_ack = rs->rs_no_ack;
for (i = 0; i < rs->rs_nlocks; i++) {
nrs->rs_locks[i] = rs->rs_locks[i];
- nrs->rs_modes[i] = rs->rs_modes[i];
nrs->rs_nlocks++;
}
rs->rs_nlocks = 0;
* Puts a lock and its mode into reply state assotiated to request reply.
*/
void ptlrpc_save_lock(struct ptlrpc_request *req, struct lustre_handle *lock,
- int mode, bool no_ack)
+ bool no_ack)
{
struct ptlrpc_reply_state *rs = req->rq_reply_state;
int idx;
LASSERT(rs != NULL);
+ CDEBUG(D_RPCTRACE, "nlocks %d\n", rs->rs_nlocks);
LASSERT(rs->rs_nlocks < RS_MAX_LOCKS);
idx = rs->rs_nlocks++;
rs->rs_locks[idx] = *lock;
- rs->rs_modes[idx] = mode;
rs->rs_difficult = 1;
rs->rs_no_ack = no_ack;
}
}
while (nlocks-- > 0)
- ldlm_lock_decref(&rs->rs_locks[nlocks],
- rs->rs_modes[nlocks]);
+ ldlm_lock_decref(&rs->rs_locks[nlocks], LCK_TXN);
spin_lock(&rs->rs_lock);
}
trap 0
umask $SAVE_UMASK
}
+
test_striped_dir() {
local mdt_index=$1
- local stripe_count
+ local stripe_count=$2
+ local overstriping=$3
local stripe_index
+ local getstripe_count
mkdir -p $DIR/$tdir
SAVE_UMASK=$(umask)
trap cleanup_test_300 RETURN EXIT
- $LFS setdirstripe -i $mdt_index -c 2 -H all_char -o 755 \
- $DIR/$tdir/striped_dir ||
- error "set striped dir error"
+ if [ -z $overstriping ]; then
+ $LFS setdirstripe -i $mdt_index -c $stripe_count -H all_char \
+ -o 755 $DIR/$tdir/striped_dir ||
+ error "set striped dir error"
+ else
+ $LFS setdirstripe -i $mdt_index -C $stripe_count -H all_char \
+ -o 755 $DIR/$tdir/striped_dir ||
+ error "set striped dir error"
+ fi
local mode=$(stat -c%a $DIR/$tdir/striped_dir)
[ "$mode" = "755" ] || error "expect 755 got $mode"
$LFS getdirstripe $DIR/$tdir/striped_dir > /dev/null 2>&1 ||
error "getdirstripe failed"
- stripe_count=$($LFS getdirstripe -c $DIR/$tdir/striped_dir)
- if [ "$stripe_count" != "2" ]; then
- error "1:stripe_count is $stripe_count, expect 2"
+ getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/striped_dir)
+ if [ "$getstripe_count" != "$stripe_count" ]; then
+ error "1:stripe_count is $getstripe_count, expect $stripe_count"
fi
- stripe_count=$($LFS getdirstripe -T $DIR/$tdir/striped_dir)
- if [ "$stripe_count" != "2" ]; then
- error "2:stripe_count is $stripe_count, expect 2"
+ getstripe_count=$($LFS getdirstripe -T $DIR/$tdir/striped_dir)
+ if [ "$getstripe_count" != "$stripe_count" ]; then
+ error "2:stripe_count is $getstripe_count, expect $stripe_count"
fi
stripe_index=$($LFS getdirstripe -i $DIR/$tdir/striped_dir)
[ $PARALLEL == "yes" ] && skip "skip parallel run"
[ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
- test_striped_dir 0 || error "failed on striped dir on MDT0"
- test_striped_dir 1 || error "failed on striped dir on MDT0"
+ test_striped_dir 0 2 || error "failed on striped dir on MDT0"
+ test_striped_dir 1 2 || error "failed on striped dir on MDT0"
}
run_test 300a "basic striped dir sanity test"
}
run_test 300t "test max_mdt_stripecount"
+MDT_OVSTRP_VER="2.15.60"
+# 300u family tests MDT overstriping
+test_300ua() {
+ (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
+
+ local setcount=$((MDSCOUNT * 2))
+
+ local expected_count
+
+ mkdir $DIR/$tdir
+ $LFS setdirstripe -C $setcount $DIR/$tdir/${tdir}.0 ||
+ error "(0) failed basic overstriped dir creation test"
+ local getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/${tdir}.0)
+
+ # This does a basic interop test - if the MDS does not support mdt
+ # overstriping, we should get stripes == number of MDTs
+ if (( $MDS1_VERSION < $(version_code $MDT_OVSTRP_VER) )); then
+ expected_count=$MDSCOUNT
+ else
+ expected_count=$setcount
+ fi
+ (( getstripe_count == expected_count )) ||
+ error "(1) incorrect stripe count for simple overstriped dir"
+
+ rm -rf $DIR/$tdir/${tdir}.0 ||
+ error "(2) unable to rm overstriped dir"
+
+ # Tests after this require overstriping support
+ (( MDS1_VERSION >= $(version_code $MDT_OVSTRP_VER) )) ||
+ { echo "skipped for MDS < $MDT_OVSTRP_VER"; return 0; }
+
+ test_striped_dir 0 $setcount true ||
+ error "(3)failed on overstriped dir"
+ test_striped_dir 1 $setcount true ||
+ error "(4)failed on overstriped dir"
+
+ local setcount=$((MDSCOUNT * $LMV_MAX_STRIPES_PER_MDT))
+
+ test_striped_dir 0 $setcount true ||
+ error "(5)failed on overstriped dir"
+}
+run_test 300ua "basic overstriped dir sanity test"
+
+test_300ub() {
+ (( MDS1_VERSION >= $(version_code $MDT_OVSTRP_VER) )) ||
+ skip "skipped for MDS < $MDT_OVSTRP_VER"
+ (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
+
+ mkdir $DIR/$tdir
+
+ echo "Testing invalid stripe count, failure expected"
+ local setcount=$((MDSCOUNT * 2))
+
+ $LFS setdirstripe -c $setcount $DIR/$tdir/${tdir}.0
+ local getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/${tdir}.0)
+
+ (( getstripe_count <= MDSCOUNT )) ||
+ error "(0)stripe count ($setcount) > MDT count ($MDSCOUNT) succeeded with -c"
+
+ # When a user requests > LMV_MAX_STRIPES_PER_MDT, we reduce to that
+ setcount=$((MDSCOUNT * 2 * LMV_MAX_STRIPES_PER_MDT))
+ $LFS setdirstripe -C $setcount $DIR/$tdir/${tdir}.1
+
+ local maxcount=$((MDSCOUNT * LMV_MAX_STRIPES_PER_MDT))
+
+ getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/${tdir}.1)
+ (( getstripe_count == maxcount )) ||
+ error "(1)stripe_count is $getstripe_count, expect $maxcount"
+
+ # Test specific striping with -i
+ $LFS setdirstripe -i 0,0,0,0 $DIR/$tdir/${tdir}.2
+
+ getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/${tdir}.2)
+ (( getstripe_count == 4 )) ||
+ error "(2)stripe_count is $getstripe_count, expect 4"
+
+ local nonzeroindices=$($LFS getdirstripe $DIR/$tdir/${tdir}.2 | grep "\[" | \
+ grep -v mdtidx | awk '{print $1}' | grep -c -v 0)
+
+ [[ -n "$nonzeroindices" ]] ||
+ error "(3) stripes indices not all 0: $nonzeroindices"
+
+ # Test specific striping with too many stripes on one MDT
+ echo "Testing invalid striping, failure expected"
+ $LFS setdirstripe -i 0,1,0,1,0,1,0,1,0,1,0 $DIR/$tdir/${tdir}.3
+ $LFS getdirstripe $DIR/$tdir/${tdir}.3
+ getstripe_count=$($LFS getdirstripe $DIR/$tdir/${tdir}.3 | grep "\[" | \
+ grep -v mdtidx | awk '{print $1}' | grep -c '0')
+ echo "stripes on MDT0: $getstripe_count"
+ (( getstripe_count <= LMV_MAX_STRIPES_PER_MDT )) ||
+ error "(4) setstripe with too many stripes on MDT0 succeeded"
+
+ setcount=$((MDSCOUNT * 2))
+ $LFS setdirstripe -C $setcount -H all_char $DIR/${tdir}.4 ||
+ error "(5) can't setdirstripe with manually set hash function"
+
+ getstripe_count=$($LFS getdirstripe -c $DIR/${tdir}.4)
+ (( getstripe_count == setcount )) ||
+ error "(6)stripe_count is $getstripe_count, expect $setcount"
+
+ setcount=$((MDSCOUNT * 2))
+ mkdir $DIR/${tdir}.5
+ $LFS setdirstripe -C $setcount -D -H crush $DIR/${tdir}.5 ||
+ error "(7) can't setdirstripe with manually set hash function"
+ mkdir $DIR/${tdir}.5/${tdir}.6
+
+ getstripe_count=$($LFS getdirstripe -c $DIR/${tdir}.5/${tdir}.6)
+ (( getstripe_count == setcount )) ||
+ error "(8)stripe_count is $getstripe_count, expect $setcount"
+}
+run_test 300ub "test MDT overstriping interface & limits"
+
+test_300uc() {
+ (( MDS1_VERSION >= $(version_code $MDT_OVSTRP_VER) )) ||
+ skip "skipped for MDS < $MDT_OVSTRP_VER"
+ (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
+
+ mkdir $DIR/$tdir
+
+ local setcount=$((MDSCOUNT * 2))
+
+ $LFS setdirstripe -D -C $setcount $DIR/$tdir
+
+ mkdir $DIR/$tdir/${tdir}.1
+
+ local getstripe_count=$($LFS getdirstripe -c $DIR/$tdir/${tdir}.1)
+
+ (( getstripe_count == setcount )) ||
+ error "(0)stripe_count is $getstripe_count, expect $setcount"
+
+ mkdir $DIR/$tdir/${tdir}.1/${tdir}.2
+
+ local getstripe_count=$($LFS getdirstripe -c \
+ $DIR/$tdir/${tdir}.1/${tdir}.2)
+
+ (( getstripe_count == setcount )) ||
+ error "(1)stripe_count is $getstripe_count, expect $setcount"
+}
+run_test 300uc "test MDT overstriping as default & inheritance"
+
+test_300ud() {
+ (( MDS1_VERSION >= $(version_code $MDT_OVSTRP_VER) )) ||
+ skip "skipped for MDS < $MDT_OVSTRP_VER"
+ (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
+
+ local mdts=$(comma_list $(mdts_nodes))
+ local timeout=100
+
+ local restripe_status
+ local delta
+ local i
+
+ [[ $mds1_FSTYPE == zfs ]] && timeout=300
+
+ # in case "crush" hash type is not set
+ do_nodes $mdts "$LCTL set_param lod.*.mdt_hash=crush"
+
+ restripe_status=$(do_facet mds1 $LCTL get_param -n \
+ mdt.*MDT0000.enable_dir_restripe)
+ do_nodes $mdts "$LCTL set_param mdt.*.enable_dir_restripe=1"
+ stack_trap "do_nodes $mdts $LCTL set_param \
+ mdt.*.enable_dir_restripe=$restripe_status"
+
+ mkdir $DIR/$tdir
+ createmany -m $DIR/$tdir/f $((50 * MDSCOUNT)) ||
+ error "create files under remote dir failed $i"
+ createmany -d $DIR/$tdir/d $((50 * MDSCOUNT)) ||
+ error "create dirs under remote dir failed $i"
+
+ local setcount=$((MDSCOUNT * $LMV_MAX_STRIPES_PER_MDT))
+
+ (( setcount < 13 )) || setcount=12
+ for i in $(seq 2 $setcount); do
+ do_nodes $mdts "$LCTL set_param mdt.*.md_stats=clear >/dev/null"
+ $LFS setdirstripe -C $i $DIR/$tdir ||
+ error "split -C $i $tdir failed"
+ wait_update $HOSTNAME \
+ "$LFS getdirstripe -H $DIR/$tdir" "crush" $timeout ||
+ error "dir split not finished"
+ delta=$(do_nodes $mdts "lctl get_param -n mdt.*MDT*.md_stats" |
+ awk '/migrate/ {sum += $2} END { print sum }')
+ echo "$delta migrated when dir split $((i - 1)) to $i stripes"
+ # delta is around total_files/stripe_count, deviation 3%
+ (( delta < 100 * MDSCOUNT / i + 3 * MDSCOUNT )) ||
+ error "$delta files migrated >= $((100 * MDSCOUNT / i + 3 * MDSCOUNT))"
+ done
+}
+run_test 300ud "dir split"
+
+test_300ue() {
+ (( MDS1_VERSION >= $(version_code $MDT_OVSTRP_VER) )) ||
+ skip "skipped for MDS < $MDT_OVSTRP_VER"
+ (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
+
+ local mdts=$(comma_list $(mdts_nodes))
+ local timeout=100
+
+ local restripe_status
+ local delta
+ local c
+
+ [[ $mds1_FSTYPE == zfs ]] && timeout=300
+
+ do_nodes $mdts "$LCTL set_param lod.*.mdt_hash=crush"
+
+ restripe_status=$(do_facet mds1 $LCTL get_param -n \
+ mdt.*MDT0000.enable_dir_restripe)
+ do_nodes $mdts "$LCTL set_param mdt.*.enable_dir_restripe=1"
+ stack_trap "do_nodes $mdts $LCTL set_param \
+ mdt.*.enable_dir_restripe=$restripe_status"
+
+ local setcount=$((MDSCOUNT * $LMV_MAX_STRIPES_PER_MDT))
+
+ (( setcount < 13 )) || setcount=12
+ test_mkdir -C $setcount -H crush $DIR/$tdir
+ createmany -m $DIR/$tdir/f $((50 * MDSCOUNT)) ||
+ error "create files under remote dir failed"
+ createmany -d $DIR/$tdir/d $((50 * MDSCOUNT)) ||
+ error "create dirs under remote dir failed"
+
+ for c in $(seq $((setcount - 1)) -1 1); do
+ do_nodes $mdts "$LCTL set_param mdt.*.md_stats=clear >/dev/null"
+ $LFS setdirstripe -C $c $DIR/$tdir ||
+ error "split -C $c $tdir failed"
+ wait_update $HOSTNAME \
+ "$LFS getdirstripe -H $DIR/$tdir" "crush,fixed" $timeout ||
+ error "dir merge not finished"
+ delta=$(do_nodes $mdts "lctl get_param -n mdt.*MDT*.md_stats" |
+ awk '/migrate/ {sum += $2} END { print sum }')
+ echo "$delta migrated when dir merge $((c + 1)) to $c stripes"
+ # delta is around total_files/stripe_count, deviation 3%
+ (( delta < 100 * MDSCOUNT / c + 3 * MDSCOUNT )) ||
+ error "$delta files migrated >= $((100 * MDSCOUNT / c + 3 * MDSCOUNT))"
+ done
+}
+run_test 300ue "dir merge"
+
+test_300uf() {
+ (( MDS1_VERSION >= $(version_code $MDT_OVSTRP_VER) )) ||
+ skip "skipped for MDS < $MDT_OVSTRP_VER"
+ (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
+
+ # maximum amount of local locks:
+ # parent striped dir - 2 locks
+ # new stripe in parent to migrate to - 1 lock
+ # source and target - 2 locks
+ # Total 5 locks for regular file
+ #
+ # NB: Overstriping should add several extra local locks
+ # FIXME: Remove this once understood
+ #lctl set_param *debug=-1 debug_mb=10000
+ lctl clear
+ lctl mark "touch/create"
+ mkdir -p $DIR/$tdir
+ local setcount=$((MDSCOUNT * $LMV_MAX_STRIPES_PER_MDT))
+ local setcount=$((MDSCOUNT * 5))
+
+ $LFS mkdir -i1 -C $setcount $DIR/$tdir/dir1
+ touch $DIR/$tdir/dir1/eee
+
+ lctl mark "hardlinks"
+ # create 4 hardlink for 4 more locks
+ # Total: 9 locks > RS_MAX_LOCKS (8)
+ $LFS mkdir -i1 -c1 $DIR/$tdir/dir2
+ $LFS mkdir -i1 -c1 $DIR/$tdir/dir3
+ $LFS mkdir -i1 -c1 $DIR/$tdir/dir4
+ $LFS mkdir -i1 -c1 $DIR/$tdir/dir5
+ ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir2/eee
+ ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir3/eee
+ ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir4/eee
+ ln $DIR/$tdir/dir1/eee $DIR/$tdir/dir5/eee
+
+ lctl mark "cancel lru"
+ cancel_lru_locks mdc
+
+ lctl mark "migrate"
+ $LFS migrate -m1 -c1 $DIR/$tdir/dir1 ||
+ error "migrate dir fails"
+
+ rm -rf $DIR/$tdir || error "rm dir failed after migration"
+}
+run_test 300uf "migrate with too many local locks"
+
+test_300ug() {
+ (( MDS1_VERSION >= $(version_code $MDT_OVSTRP_VER) )) ||
+ skip "skipped for MDS < $MDT_OVSTRP_VER"
+ (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
+
+ mkdir -p $DIR/$tdir
+ local migrate_dir=$DIR/$tdir/migrate_dir
+ local setcount=$((MDSCOUNT * $LMV_MAX_STRIPES_PER_MDT))
+ local setcount2=$((setcount - 2))
+
+ $LFS setdirstripe -c 2 $migrate_dir ||
+ error "(0) failed to create striped directory"
+
+ $LFS migrate -m 0 -C $setcount $migrate_dir ||
+ error "(1)failed to migrate to overstriped directory"
+ local getstripe_count=$($LFS getdirstripe -c $migrate_dir)
+
+ (( getstripe_count == setcount )) ||
+ error "(2)stripe_count is $getstripe_count, expect $setcount"
+ touch $DIR/$tdir/migrate_dir/$tfile ||
+ error "(3)failed to create file in overstriped directory"
+ $LFS migrate -m 0 -C $setcount2 $migrate_dir ||
+ error "(4)failed to migrate overstriped directory"
+ # Check stripe count after migration
+ $LFS getdirstripe $migrate_dir
+ getstripe_count=$($LFS getdirstripe -c $migrate_dir)
+ (( getstripe_count == setcount2 )) ||
+ error "(5)stripe_count is $getstripe_count, expect $setcount2"
+
+ rm -rf $migrate_dir || error "(6) unable to rm overstriped dir"
+}
+run_test 300ug "migrate overstriped dirs"
+
prepare_remote_file() {
mkdir $DIR/$tdir/src_dir ||
error "create remote source failed"
# Constants used in more than one test script
export LOV_MAX_STRIPE_COUNT=2000
+ export LMV_MAX_STRIPES_PER_MDT=5
export DELETE_OLD_POOLS=${DELETE_OLD_POOLS:-false}
export KEEP_POOLS=${KEEP_POOLS:-false}
export PARALLEL=${PARALLEL:-"no"}
local dirstripe_count=${DIRSTRIPE_COUNT:-"2"}
local dirstripe_index=${DIRSTRIPE_INDEX:-$((base % $MDSCOUNT))}
local OPTIND=1
+ local overstripe_count
+ local stripe_command="-c"
(( $MDS1_VERSION > $(version_code 2.15.0) )) &&
hash_name+=("crush2")
- while getopts "c:H:i:p" opt; do
+ while getopts "c:C:H:i:p" opt; do
case $opt in
c) dirstripe_count=$OPTARG;;
+ C) overstripe_count=$OPTARG;;
H) hash_type=$OPTARG;;
i) dirstripe_index=$OPTARG;;
p) p_option="-p";;
fi
fi
+ if [[ -n "$overstripe_count" ]]; then
+ stripe_command="-C"
+ dirstripe_count=$overstripe_count
+ fi
+
if [ $MDSCOUNT -le 1 ] || ! is_lustre ${parent}; then
mkdir $path || error "mkdir '$path' failed"
else
dirstripe_count=1
fi
- echo "striped dir -i$mdt_index -c$dirstripe_count -H $hash_type $path"
- $LFS mkdir -i$mdt_index -c$dirstripe_count -H $hash_type $path ||
- error "mkdir -i $mdt_index -c$dirstripe_count -H $hash_type $path failed"
+ echo "striped dir -i$mdt_index $stripe_command$dirstripe_count -H $hash_type $path"
+ $LFS mkdir -i$mdt_index $stripe_command$dirstripe_count -H $hash_type $path ||
+ error "mkdir -i $mdt_index $stripe_command$dirstripe_count -H $hash_type $path failed"
fi
}
" [--mdt-count|-c stripe_count>\n" \
" [--help|-h] [--mdt-hash|-H mdt_hash]\n" \
" [--mdt-index|-i mdt_index[,mdt_index,...]\n" \
+ " [--mdt-overcount|-C stripe_count>\n" \
" [--default|-D] [--mode|-o mode]\n" \
" [--max-inherit|-X max_inherit]\n" \
" [--max-inherit-rr max_inherit_rr] <dir>\n" \
"usage: swap_layouts <path1> <path2>"},
{"migrate", lfs_setstripe_migrate, 0,
"migrate directories and their inodes between MDTs.\n"
- "usage: migrate [--mdt-count|-c STRIPE_COUNT] [--directory|-d]\n"
- " [--mdt-hash|-H HASH_TYPE]\n"
+ "usage: migrate [--mdt-count|-c STRIPE_COUNT]\n"
+ " [--mdt-overcount|-C OVERSTRIPE_COUNT\n"
+ " [--directory|-d] [--mdt-hash|-H HASH_TYPE]\n"
" [--mdt-index|-m START_MDT_INDEX] [--verbose|-v]\n"
" DIRECTORY\n"
"\n"
* \param[in] size size of \a tgts array
* \param[in] offset starting index in \a tgts
* \param[in] arg string containing OST index list
- * \param[in/out] overstriping index list may contain duplicates
+ * \param[out] duplicates tell caller list contains duplicates
*
* \retval positive number of indices in \a tgts
* \retval -EINVAL unable to parse \a arg
*/
static int parse_targets(__u32 *tgts, int size, int offset, char *arg,
- unsigned long long *pattern)
+ bool *duplicates)
{
int rc;
int nr = offset;
int slots = size - offset;
char *ptr = NULL;
- bool overstriped = false;
bool end_of_loop;
if (!arg)
for (i = start_index; i <= end_index && slots > 0; i++) {
int j;
- /* remove duplicate */
+ /* note presence of duplicates */
for (j = 0; j < offset; j++) {
- if (tgts[j] == i && pattern &&
- *pattern == LLAPI_LAYOUT_OVERSTRIPING)
- overstriped = true;
- else if (tgts[j] == i)
- return -EINVAL;
+ if (tgts[j] == i)
+ *duplicates = true;
}
j = offset;
if (!end_of_loop && ptr)
*ptr = ',';
- if (!overstriped && pattern)
- *pattern = LLAPI_LAYOUT_DEFAULT;
-
return rc < 0 ? rc : nr;
}
char *template = NULL;
bool foreign_mode = false;
char *xattr = NULL;
+ bool overstriped = false;
uint32_t type = LU_FOREIGN_TYPE_NONE, flags = 0;
char *mode_opt = NULL;
mode_t previous_umask = 0;
{ .val = 'c', .name = "mdt-count", .has_arg = required_argument},
{ .val = 'C', .name = "overstripe-count",
.has_arg = required_argument},
+ { .val = 'C', .name = "mdt-overcount",
+ .has_arg = required_argument},
{ .val = 'd', .name = "delete", .has_arg = no_argument},
{ .val = 'd', .name = "destroy", .has_arg = no_argument},
/* used with "lfs migrate -m" */
progname, argv[0]);
goto usage_error;
}
- lsa.lsa_pattern = LLAPI_LAYOUT_OVERSTRIPING;
+ if (migrate_mode)
+ overstriped = true;
+ else
+ lsa.lsa_pattern = LLAPI_LAYOUT_OVERSTRIPING;
fallthrough;
case 'c':
errno = 0;
}
migrate_mdt_mode = true;
lsa.lsa_nr_tgts = parse_targets(tgts,
- sizeof(tgts) / sizeof(__u32),
- lsa.lsa_nr_tgts, optarg, NULL);
+ sizeof(tgts) / sizeof(__u32),
+ lsa.lsa_nr_tgts, optarg,
+ &overstriped);
if (lsa.lsa_nr_tgts < 0) {
fprintf(stderr,
"%s: invalid MDT target(s) '%s'\n",
* parse_targets is shared with MDT striping, which
* does not allow duplicates
*/
- lsa.lsa_pattern = LLAPI_LAYOUT_OVERSTRIPING;
lsa.lsa_nr_tgts = parse_targets(tgts,
sizeof(tgts) / sizeof(__u32),
lsa.lsa_nr_tgts, optarg,
- &lsa.lsa_pattern);
+ &overstriped);
if (lsa.lsa_nr_tgts < 0) {
fprintf(stderr,
"%s %s: invalid OST target(s) '%s'\n",
goto usage_error;
}
+ if (overstriped)
+ lsa.lsa_pattern = LLAPI_LAYOUT_OVERSTRIPING;
+
lsa.lsa_tgts = tgts;
if (lsa.lsa_stripe_off == LLAPI_LAYOUT_DEFAULT)
lsa.lsa_stripe_off = tgts[0];
goto usage_error;
}
lmu->lum_stripe_offset = lsa.lsa_stripe_off;
+
if (lsa.lsa_pattern != LLAPI_LAYOUT_RAID0)
lmu->lum_hash_type = lsa.lsa_pattern;
else
lmu->lum_hash_type = LMV_HASH_TYPE_UNKNOWN;
+
+ if (overstriped)
+ lmu->lum_hash_type |= LMV_HASH_FLAG_OVERSTRIPED;
+
if (lsa.lsa_pool_name) {
strncpy(lmu->lum_pool_name, lsa.lsa_pool_name,
sizeof(lmu->lum_pool_name) - 1);
bool delete = false;
bool foreign_mode = false;
bool mdt_count_set = false;
+ bool overstriped = false;
mode_t mode = S_IRWXU | S_IRWXG | S_IRWXO;
mode_t previous_mode = 0;
char *xattr = NULL;
struct option long_opts[] = {
{ .val = 'c', .name = "count", .has_arg = required_argument },
{ .val = 'c', .name = "mdt-count", .has_arg = required_argument },
+ { .val = 'C', .name = "mdt-overcount", .has_arg = required_argument },
{ .val = 'd', .name = "delete", .has_arg = no_argument },
{ .val = 'D', .name = "default", .has_arg = no_argument },
{ .val = 'D', .name = "default_stripe", .has_arg = no_argument },
setstripe_args_init(&lsa);
- while ((c = getopt_long(argc, argv, "c:dDi:hH:m:o:t:T:x:X:",
+ while ((c = getopt_long(argc, argv, "c:C:dDi:hH:m:o:t:T:x:X:",
long_opts, NULL)) >= 0) {
switch (c) {
case 0:
/* Long options. */
break;
+ case 'C':
+ overstriped = true;
+ fallthrough;
case 'c':
+ fallthrough;
case 'T':
errno = 0;
lsa.lsa_stripe_count = strtoul(optarg, &end, 0);
#endif
lsa.lsa_nr_tgts = parse_targets(mdts,
sizeof(mdts) / sizeof(__u32),
- lsa.lsa_nr_tgts, optarg, NULL);
+ lsa.lsa_nr_tgts, optarg,
+ &overstriped);
if (lsa.lsa_nr_tgts < 0) {
fprintf(stderr,
"%s %s: invalid MDT target(s) '%s'\n",
param->lsp_stripe_offset = LMV_OFFSET_DEFAULT;
else
param->lsp_stripe_offset = lsa.lsa_stripe_off;
+
if (lsa.lsa_pattern != LLAPI_LAYOUT_RAID0)
param->lsp_stripe_pattern = lsa.lsa_pattern;
else
param->lsp_stripe_pattern = LMV_HASH_TYPE_UNKNOWN;
+
+ if (overstriped) {
+ param->lsp_stripe_pattern |= LMV_HASH_FLAG_OVERSTRIPED;
+ max_inherit = LMV_INHERIT_DEFAULT_OVERSTRIPED;
+ }
+
param->lsp_pool = lsa.lsa_pool_name;
param->lsp_is_specific = false;
llapi_printf(LLAPI_MSG_NORMAL, ",lost_lmv");
if (flags & LMV_HASH_FLAG_FIXED)
llapi_printf(LLAPI_MSG_NORMAL, ",fixed");
- /* NB: OVERSTRIPED is not in KNOWN until implementation patch
- * is landed, but we do recognize it
- */
- if (flags & ~(LMV_HASH_FLAG_KNOWN|LMV_HASH_FLAG_OVERSTRIPED))
+ if (flags & ~LMV_HASH_FLAG_KNOWN)
llapi_printf(LLAPI_MSG_NORMAL, ",unknown_%04x",
flags & ~LMV_HASH_FLAG_KNOWN);