retry:
if (op_data->op_flags & MF_GETATTR_BY_FID) {
- /* getattr by FID, replace fid1 with stripe FID */
+ /* getattr by FID, replace fid1 with stripe FID,
+ * NB, don't replace if name is "/", because it may be a subtree
+ * mount, and if it's a striped directory, fid1 will be replaced
+ * to stripe FID by hash, while fid2 is master object FID, which
+ * will be treated as a remote object if the two FIDs are
+ * located on different MDTs, and LOOKUP lock can't be fetched.
+ */
LASSERT(op_data->op_name);
- tgt = lmv_locate_tgt(lmv, op_data);
- if (IS_ERR(tgt))
- RETURN(PTR_ERR(tgt));
+ if (op_data->op_namelen != 1 ||
+ strncmp(op_data->op_name, "/", 1) != 0) {
+ tgt = lmv_locate_tgt(lmv, op_data);
+ if (IS_ERR(tgt))
+ RETURN(PTR_ERR(tgt));
+ }
/* name is used to locate stripe target, clear it here
* to avoid packing name in request, so that MDS knows
{
struct mdt_device *mdt = info->mti_mdt;
struct lu_name *lname = &info->mti_name;
+ const char *start = fileset;
char *filename = info->mti_filename;
struct mdt_object *parent;
u32 mode;
*/
*fid = mdt->mdt_md_root_fid;
- while (rc == 0 && fileset != NULL && *fileset != '\0') {
- const char *s1 = fileset;
+ while (rc == 0 && start != NULL && *start != '\0') {
+ const char *s1 = start;
const char *s2;
while (*++s1 == '/')
if (s2 == s1)
break;
- fileset = s2;
+ start = s2;
lname->ln_namelen = s2 - s1;
if (lname->ln_namelen > NAME_MAX) {
rc = PTR_ERR(parent);
else {
mode = lu_object_attr(&parent->mot_obj);
- mdt_object_put(info->mti_env, parent);
- if (!S_ISDIR(mode))
+ if (!S_ISDIR(mode)) {
rc = -ENOTDIR;
+ } else if (mdt_is_remote_object(info, parent, parent)) {
+ if (!mdt->mdt_enable_remote_subdir_mount) {
+ rc = -EREMOTE;
+ LCONSOLE_WARN("%s: subdir mount '%s' refused because 'enable_remote_subdir_mount=0': rc = %d\n",
+ mdt_obd_name(mdt),
+ fileset, rc);
+ } else {
+ LCONSOLE_INFO("%s: subdir mount '%s' is remote and may be slow\n",
+ mdt_obd_name(mdt),
+ fileset);
+ }
+ }
+ mdt_object_put(info->mti_env, parent);
}
}
m->mdt_enable_chprojid_gid = 0;
m->mdt_enable_remote_rename = 1;
m->mdt_dir_restripe_nsonly = 1;
+ m->mdt_enable_remote_subdir_mount = 1;
atomic_set(&m->mdt_mds_mds_conns, 0);
atomic_set(&m->mdt_async_commit_count, 0);
mdt_skip_lfsck:1,
mdt_readonly:1,
/* dir restripe migrate dirent only */
- mdt_dir_restripe_nsonly:1;
+ mdt_dir_restripe_nsonly:1,
+ /* subdirectory mount of remote dir */
+ mdt_enable_remote_subdir_mount:1;
/* user with gid can create remote/striped
* dir, and set default dir stripe */
}
LUSTRE_RW_ATTR(dir_restripe_nsonly);
+static ssize_t enable_remote_subdir_mount_show(struct kobject *kobj,
+ struct attribute *attr,
+ char *buf)
+{
+ struct obd_device *obd = container_of(kobj, struct obd_device,
+ obd_kset.kobj);
+ struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n",
+ mdt->mdt_enable_remote_subdir_mount);
+}
+
+static ssize_t enable_remote_subdir_mount_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *buffer,
+ size_t count)
+{
+ struct obd_device *obd = container_of(kobj, struct obd_device,
+ obd_kset.kobj);
+ struct mdt_device *mdt = mdt_dev(obd->obd_lu_dev);
+ bool val;
+ int rc;
+
+ rc = kstrtobool(buffer, &val);
+ if (rc)
+ return rc;
+
+ mdt->mdt_enable_remote_subdir_mount = val;
+ return count;
+}
+LUSTRE_RW_ATTR(enable_remote_subdir_mount);
+
/**
* Show if the OFD enforces T10PI checksum.
*
&lustre_attr_dir_split_delta.attr,
&lustre_attr_dir_restripe_nsonly.attr,
&lustre_attr_checksum_t10pi_enforce.attr,
+ &lustre_attr_enable_remote_subdir_mount.attr,
NULL,
};
[ $MDSCOUNT -lt 2 ] && skip_env "needs >= 2 MDTs"
[ $MDS1_VERSION -lt $(version_code 2.13.52) ] &&
skip "Need at least version 2.13.52"
+ [ $CLIENT_VERSION -lt $(version_code 2.14.50) ] &&
+ skip "Need at least version 2.14.50"
lctl get_param -n mdc.$FSNAME-MDT0000*.import |
grep -q subtree ||
skip "Fileset feature is not supported"
$LFS mkdir -i $((MDSCOUNT - 1)) $DIR/$tdir/remote ||
error "mkdir remote failed"
mkdir $DIR/$tdir/remote/subdir || error "mkdir remote/subdir failed"
- $LFS mkdir -c $MDSCOUNT $DIR/$tdir/striped ||
+ $LFS mkdir -i 0 -c $MDSCOUNT $DIR/$tdir/striped ||
error "mkdir striped failed"
mkdir $DIR/$tdir/striped/subdir || error "mkdir striped/subdir failed"
local submount=${MOUNT}_$tdir
mkdir -p $submount || error "mkdir $submount failed"
+ stack_trap "rmdir $submount"
local dir
+ local stat
local fileset=$FILESET
+ local mdts=$(comma_list $(mdts_nodes))
+
+ stat=$(do_facet mds1 $LCTL get_param -n \
+ mdt.*MDT0000.enable_remote_subdir_mount)
+ stack_trap "do_nodes $mdts $LCTL set_param \
+ mdt.*.enable_remote_subdir_mount=$stat"
- for dir in $tdir/remote $tdir/remote/subdir \
- $tdir/striped $tdir/striped/subdir $tdir/striped/. ; do
+ do_nodes $mdts "$LCTL set_param mdt.*.enable_remote_subdir_mount=0"
+ stack_trap "umount_client $submount"
+ FILESET="$fileset/$tdir/remote" mount_client $submount &&
+ error "mount remote dir $dir should fail"
+
+ for dir in $tdir/remote/subdir $tdir/striped $tdir/striped/subdir \
+ $tdir/striped/. ; do
FILESET="$fileset/$dir" mount_client $submount ||
error "mount $dir failed"
umount_client $submount
done
+
+ do_nodes $mdts "$LCTL set_param mdt.*.enable_remote_subdir_mount=1"
+ FILESET="$fileset/$tdir/remote" mount_client $submount ||
+ error "mount $tdir/remote failed"
}
run_test 247f "mount striped or remote directory as fileset"
+test_247g() {
+ [ $MDSCOUNT -lt 4 ] && skip_env "needs >= 4 MDTs"
+ [ $CLIENT_VERSION -lt $(version_code 2.14.50) ] &&
+ skip "Need at least version 2.14.50"
+
+ $LFS mkdir -i 0 -c 4 -H fnv_1a_64 $DIR/$tdir ||
+ error "mkdir $tdir failed"
+ touch $DIR/$tdir/$tfile || error "touch $tfile failed"
+
+ local submount=${MOUNT}_$tdir
+
+ mkdir -p $submount || error "mkdir $submount failed"
+ stack_trap "rmdir $submount"
+
+ FILESET="$fileset/$tdir" mount_client $submount ||
+ error "mount $dir failed"
+ stack_trap "umount $submount"
+
+ local mdts=$(comma_list $(mdts_nodes))
+
+ local nrpcs
+
+ stat $submount > /dev/null
+ cancel_lru_locks $MDC
+ stat $submount > /dev/null
+ stat $submount/$tfile > /dev/null
+ do_nodes $mdts "$LCTL set_param mdt.*.md_stats=clear > /dev/null"
+ stat $submount/$tfile > /dev/null
+ nrpcs=$(do_nodes $mdts "lctl get_param -n mdt.*.md_stats" |
+ awk '/getattr/ {sum += $2} END {print sum}')
+
+ [ -z "$nrpcs" ] || error "$nrpcs extra getattr sent"
+}
+run_test 247g "mount striped directory as fileset caches ROOT lookup lock"
+
test_248a() {
local fast_read_sav=$($LCTL get_param -n llite.*.fast_read 2>/dev/null)
[ -z "$fast_read_sav" ] && skip "no fast read support"