return rc;
}
+/* mkdir by QoS upon 'lfs mkdir -i -1'.
+ *
+ * NB, mkdir by QoS only if parent is not striped, this is to avoid remote
+ * directories under striped directory.
+ */
static inline bool lmv_op_user_qos_mkdir(const struct md_op_data *op_data)
{
const struct lmv_user_md *lum = op_data->op_data;
+ if (op_data->op_code != LUSTRE_OPC_MKDIR)
+ return false;
+
+ if (lmv_dir_striped(op_data->op_mea1))
+ return false;
+
return (op_data->op_cli_flags & CLI_SET_MEA) && lum &&
le32_to_cpu(lum->lum_magic) == LMV_USER_MAGIC &&
le32_to_cpu(lum->lum_stripe_offset) == LMV_OFFSET_DEFAULT;
}
+/* mkdir by QoS if either ROOT or parent default LMV is space balanced. */
static inline bool lmv_op_default_qos_mkdir(const struct md_op_data *op_data)
{
const struct lmv_stripe_md *lsm = op_data->op_default_mea1;
- return (op_data->op_flags & MF_QOS_MKDIR) ||
- (lsm && lsm->lsm_md_master_mdt_index == LMV_OFFSET_DEFAULT);
-}
-
-/* mkdir by QoS in three cases:
- * 1. ROOT default LMV is space balanced.
- * 2. 'lfs mkdir -i -1'
- * 3. parent default LMV master_mdt_index is -1
- *
- * NB, mkdir by QoS only if parent is not striped, this is to avoid remote
- * directories under striped directory.
- */
-static inline bool lmv_op_qos_mkdir(const struct md_op_data *op_data)
-{
if (op_data->op_code != LUSTRE_OPC_MKDIR)
return false;
if (lmv_dir_striped(op_data->op_mea1))
return false;
- if (lmv_op_user_qos_mkdir(op_data))
- return true;
-
- if (lmv_op_default_qos_mkdir(op_data))
- return true;
-
- return false;
+ return (op_data->op_flags & MF_QOS_MKDIR) ||
+ (lsm && lsm->lsm_md_master_mdt_index == LMV_OFFSET_DEFAULT);
}
/* if parent default LMV is space balanced, and
LMV_OFFSET_DEFAULT;
}
+/* locate MDT by space usage */
+static struct lu_tgt_desc *lmv_locate_tgt_by_space(struct lmv_obd *lmv,
+ struct md_op_data *op_data,
+ struct lmv_tgt_desc *tgt)
+{
+ struct lmv_tgt_desc *tmp = tgt;
+
+ tgt = lmv_locate_tgt_qos(lmv, op_data->op_mds, op_data->op_dir_depth);
+ if (tgt == ERR_PTR(-EAGAIN)) {
+ if (ltd_qos_is_balanced(&lmv->lmv_mdt_descs) &&
+ !lmv_op_default_rr_mkdir(op_data) &&
+ !lmv_op_user_qos_mkdir(op_data))
+ /* if not necessary, don't create remote directory. */
+ tgt = tmp;
+ else
+ tgt = lmv_locate_tgt_rr(lmv);
+ }
+
+ /*
+ * only update statfs after QoS mkdir, this means the cached statfs may
+ * be stale, and current mkdir may not follow QoS accurately, but it's
+ * not serious, and avoids periodic statfs when client doesn't mkdir by
+ * QoS.
+ */
+ if (!IS_ERR(tgt)) {
+ op_data->op_mds = tgt->ltd_index;
+ lmv_statfs_check_update(lmv2obd_dev(lmv), tgt);
+ }
+
+ return tgt;
+}
+
int lmv_create(struct obd_export *exp, struct md_op_data *op_data,
const void *data, size_t datalen, umode_t mode, uid_t uid,
gid_t gid, kernel_cap_t cap_effective, __u64 rdev,
if (IS_ERR(tgt))
RETURN(PTR_ERR(tgt));
+ /* the order to apply policy in mkdir:
+ * 1. is "lfs mkdir -i N"? mkdir on MDT N.
+ * 2. is "lfs mkdir -i -1"? mkdir by space usage.
+ * 3. is starting MDT specified in default LMV? mkdir on MDT N.
+ * 4. is default LMV space balanced? mkdir by space usage.
+ */
if (lmv_op_user_specific_mkdir(op_data)) {
struct lmv_user_md *lum = op_data->op_data;
tgt = lmv_tgt(lmv, op_data->op_mds);
if (!tgt)
RETURN(-ENODEV);
+ } else if (lmv_op_user_qos_mkdir(op_data)) {
+ tgt = lmv_locate_tgt_by_space(lmv, op_data, tgt);
+ if (IS_ERR(tgt))
+ RETURN(PTR_ERR(tgt));
} else if (lmv_op_default_specific_mkdir(op_data)) {
op_data->op_mds =
op_data->op_default_mea1->lsm_md_master_mdt_index;
tgt = lmv_tgt(lmv, op_data->op_mds);
if (!tgt)
RETURN(-ENODEV);
- } else if (lmv_op_qos_mkdir(op_data)) {
- struct lmv_tgt_desc *tmp = tgt;
-
- tgt = lmv_locate_tgt_qos(lmv, op_data->op_mds,
- op_data->op_dir_depth);
- if (tgt == ERR_PTR(-EAGAIN)) {
- if (ltd_qos_is_balanced(&lmv->lmv_mdt_descs) &&
- !lmv_op_default_rr_mkdir(op_data) &&
- !lmv_op_user_qos_mkdir(op_data))
- /* if it's not necessary, don't create remote
- * directory.
- */
- tgt = tmp;
- else
- tgt = lmv_locate_tgt_rr(lmv);
- }
+ } else if (lmv_op_default_qos_mkdir(op_data)) {
+ tgt = lmv_locate_tgt_by_space(lmv, op_data, tgt);
if (IS_ERR(tgt))
RETURN(PTR_ERR(tgt));
-
- op_data->op_mds = tgt->ltd_index;
- /*
- * only update statfs after QoS mkdir, this means the cached
- * statfs may be stale, and current mkdir may not follow QoS
- * accurately, but it's not serious, and avoids periodic statfs
- * when client doesn't mkdir by QoS.
- */
- lmv_statfs_check_update(obd, tgt);
}
retry:
RETURN(rc);
}
+ /* ldo_def_striping is not allocated, clear after use, in case directory
+ * layout is changed later.
+ */
+ if (!declare)
+ lo->ldo_def_striping = NULL;
+
RETURN(0);
}
RETURN_EXIT;
}
- /*
- * If parent object is not root directory,
- * then get default striping from parent object.
- */
- if (likely(lp != NULL)) {
+ if (likely(lp != NULL))
lod_get_default_striping(env, lp, lds);
- /* inherit default striping except ROOT */
- if ((lds->lds_def_striping_set ||
- lds->lds_dir_def_striping_set) &&
- !fid_is_root(lod_object_fid(lp)))
- lc->ldo_def_striping = lds;
- }
/* It should always honour the specified stripes */
/* Note: old client (< 2.7)might also do lfs mkdir, whose EA
lc->ldo_dir_stripe_count,
(int)lc->ldo_dir_stripe_offset,
lc->ldo_dir_hash_type);
+
+ if (d->lod_mdt_descs.ltd_lmv_desc.ld_active_tgt_count &&
+ lc->ldo_dir_stripe_count < 2 &&
+ lum1->lum_max_inherit != LMV_INHERIT_NONE) {
+ /* when filesystem-wide default LMV is set, dirs
+ * will be created on MDT by space usage, but if
+ * dir is created with "lfs mkdir -c 1 ...", its
+ * subdirs should be kept on the same MDT. To
+ * guarantee this, set default LMV for such dir.
+ */
+ lds->lds_dir_def_stripe_count =
+ le32_to_cpu(lum1->lum_stripe_count);
+ /* if "-1" stripe offset is set, save current
+ * MDT index in default LMV.
+ */
+ if (le32_to_cpu(lum1->lum_stripe_offset) ==
+ LMV_OFFSET_DEFAULT)
+ lds->lds_dir_def_stripe_offset =
+ lod2lu_dev(d)->ld_site->ld_seq_site->ss_node_id;
+ else
+ lds->lds_dir_def_stripe_offset =
+ le32_to_cpu(lum1->lum_stripe_offset);
+ lds->lds_dir_def_hash_type =
+ le32_to_cpu(lum1->lum_hash_type);
+ lds->lds_dir_def_max_inherit =
+ lum1->lum_max_inherit;
+ /* it will be decreased by 1 later in setting */
+ if (lum1->lum_max_inherit >= LMV_INHERIT_END &&
+ lum1->lum_max_inherit < LMV_INHERIT_MAX)
+ lds->lds_dir_def_max_inherit++;
+ lds->lds_dir_def_max_inherit_rr =
+ lum1->lum_max_inherit_rr;
+ lds->lds_dir_def_striping_set = 1;
+ /* don't inherit LOV from ROOT */
+ if (lds->lds_def_striping_set &&
+ fid_is_root(lod_object_fid(lp)))
+ lds->lds_def_striping_set = 0;
+ lc->ldo_def_striping = lds;
+ } else if (lds->lds_def_striping_set &&
+ !fid_is_root(lod_object_fid(lp))) {
+ /* don't inherit default LMV for "lfs mkdir" */
+ lds->lds_dir_def_striping_set = 0;
+ lc->ldo_def_striping = lds;
+ }
} else {
+ /* inherit default striping except ROOT */
+ if ((lds->lds_def_striping_set ||
+ lds->lds_dir_def_striping_set) &&
+ !fid_is_root(lod_object_fid(lp)))
+ lc->ldo_def_striping = lds;
+
/* transfer defaults LMV to new directory */
lod_striping_from_default(lc, lds, child_mode);
lu_buf_free(&xattrs->mx_namebuf);
}
-/* read xattrs into buf, but ignore LMA, LMV, and LINKEA if 'skip_linkea' is
- * set.
+/* read xattrs into buf, but skip LMA, LMV, LINKEA if 'skip_linkea' is
+ * set, and DMV if 'skip_dmv" is set.
*/
static int mdd_xattrs_migrate_prep(const struct lu_env *env,
struct mdd_xattrs *xattrs,
struct mdd_object *sobj,
- bool skip_linkea)
+ bool skip_linkea,
+ bool skip_dmv)
{
struct mdd_xattr_entry *entry;
char *xname;
strcmp(XATTR_NAME_LINK, xname) == 0)
continue;
+ if (skip_dmv &&
+ strcmp(XATTR_NAME_DEFAULT_LMV, xname) == 0)
+ continue;
+
xsize = mdo_xattr_get(env, sobj, &LU_BUF_NULL, xname);
if (xsize == -ENODATA)
continue;
* RPCs inside transaction.
*/
if (!spec->sp_migrate_nsonly) {
- rc = mdd_xattrs_migrate_prep(env, &xattrs, sobj, false);
+ rc = mdd_xattrs_migrate_prep(env, &xattrs, sobj, true, true);
if (rc)
GOTO(out, rc);
}
}
if (!lmv_is_fixed(lmv))
- rc = mdd_xattrs_migrate_prep(env, &xattrs, obj, true);
+ rc = mdd_xattrs_migrate_prep(env, &xattrs, obj, false,
+ false);
}
handle = mdd_trans_create(env, mdd);
count = lum->lum_stripe_count;
lum->lum_stripe_count = 0;
+ /* don't set default LMV since it will become a striped dir */
+ lum->lum_max_inherit = LMV_INHERIT_NONE;
mdd_object_make_hint(env, pobj, tobj, mlc->mlc_attr, mlc->mlc_spec,
hint);
rc = mdd_declare_create(env, mdo2mdd(&pobj->mod_obj), pobj, tobj,
mdd_xattrs_init(&xattrs);
if (is_plain)
- rc = mdd_xattrs_migrate_prep(env, &xattrs, obj, true);
+ rc = mdd_xattrs_migrate_prep(env, &xattrs, obj, true, true);
handle = mdd_trans_create(env, mdd);
if (IS_ERR(handle))
run_test 411 "Slab allocation error with cgroup does not LBUG"
test_412() {
- [ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
- if [ $MDS1_VERSION -lt $(version_code 2.10.55) ]; then
+ (( $MDSCOUNT > 1 )) || skip_env "needs >= 2 MDTs"
+ (( $MDS1_VERSION >= $(version_code 2.10.55) )) ||
skip "Need server version at least 2.10.55"
- fi
$LFS mkdir -i $((MDSCOUNT - 1)),$((MDSCOUNT - 2)) $DIR/$tdir ||
error "mkdir failed"
local stripe_count=$($LFS getdirstripe -T $DIR/$tdir)
[ $stripe_count -eq 2 ] ||
error "expect 2 get $stripe_count"
+
+ (( $MDS1_VERSION >= $(version_code 2.14.55) )) || return 0
+
+ local index
+ local index2
+
+ # subdirs should be on the same MDT as parent
+ for i in $(seq 0 $((MDSCOUNT - 1))); do
+ $LFS mkdir -i $i $DIR/$tdir/mdt$i || error "mkdir mdt$i failed"
+ mkdir $DIR/$tdir/mdt$i/sub || error "mkdir sub failed"
+ index=$($LFS getstripe -m $DIR/$tdir/mdt$i/sub)
+ (( index == i )) || error "mdt$i/sub on MDT$index"
+ done
+
+ # stripe offset -1, ditto
+ for i in {1..10}; do
+ $LFS mkdir -i -1 $DIR/$tdir/qos$i || error "mkdir qos$i failed"
+ index=$($LFS getstripe -m $DIR/$tdir/qos$i)
+ mkdir $DIR/$tdir/qos$i/sub || error "mkdir sub failed"
+ index2=$($LFS getstripe -m $DIR/$tdir/qos$i/sub)
+ (( index == index2 )) ||
+ error "qos$i on MDT$index, sub on MDT$index2"
+ done
+
+ local testdir=$DIR/$tdir/inherit
+
+ $LFS mkdir -i 1 --max-inherit=3 $testdir || error "mkdir inherit failed"
+ # inherit 2 levels
+ for i in 1 2; do
+ testdir=$testdir/s$i
+ mkdir $testdir || error "mkdir $testdir failed"
+ index=$($LFS getstripe -m $testdir)
+ (( index == 1 )) ||
+ error "$testdir on MDT$index"
+ done
+
+ # not inherit any more
+ testdir=$testdir/s3
+ mkdir $testdir || error "mkdir $testdir failed"
+ getfattr -d -m dmv $testdir | grep dmv &&
+ error "default LMV set on $testdir" || true
}
run_test 412 "mkdir on specific MDTs"
shift $((OPTIND - 1))
$LFS mkdir -i $mdt -c 1 $*
- # setting default LMV in non-DNE system will cause sanity-quota 41 fail
- ((MDSCOUNT < 2)) || $LFS setdirstripe -D -i $mdt -c 1 $*
}
mkdir_on_mdt0() {
xattr = optarg;
break;
case 'X':
- if (!default_stripe) {
- fprintf(stderr,
- "%s %s: '--max-inherit' must be specified with '-D'\n",
- progname, argv[0]);
- return CMD_HELP;
- }
errno = 0;
max_inherit = strtol(optarg, &end, 10);
if (errno != 0 || *end != '\0' || max_inherit < -2) {
param->lsp_stripe_pattern = LMV_HASH_TYPE_UNKNOWN;
param->lsp_pool = lsa.lsa_pool_name;
param->lsp_is_specific = false;
+ if (max_inherit == LAYOUT_INHERIT_UNSET)
+ max_inherit = LMV_INHERIT_DEFAULT;
+ param->lsp_max_inherit = max_inherit;
if (default_stripe) {
- if (max_inherit == LAYOUT_INHERIT_UNSET)
- max_inherit = LMV_INHERIT_DEFAULT;
if (max_inherit_rr == LAYOUT_INHERIT_UNSET)
max_inherit_rr = LMV_INHERIT_RR_DEFAULT;
- param->lsp_max_inherit = max_inherit;
param->lsp_max_inherit_rr = max_inherit_rr;
}
if (strcmp(argv[0], "mkdir") == 0)