.IR FILE " ..."
.br
.B lfs migrate -m \fISTART_MDT_INDEX
-.RB [ -cHv ]
+.RB [ -cdHv ]
.I DIRECTORY
.br
.SH DESCRIPTION
values must match
.IR COUNT .
.TP
+.BR -d , --directory
+Only migrate the specified \fIDIRECTORY\fR and the non-directory inodes that are
+directly located within it.
+Similar to '\fBls -d\fR' and '\fBlfs getstripe -d\fR'.
+.TP
.BR -H , --mdt-hash=\fIHASH_TYPE\fR
Use
.I HASH_TYPE
.B testremote
directory and all of its subdirectories will be striped across both MDTs.
.TP
+.B $ lfs migrate -m 0,2 -d ./testremote
+Move ./testremote and the first level of sub files from their current MDT
+to the MDT with index 0 and 2. Different from above case, the layout of
+subdirectories under ./testremote won't be changed.
+.TP
.B # lfs setstripe -E 256M -c 1 -E 16G -c 4 -E eof -c 40 topdir
Set a default PFL layout (without any DoM component) on the directory
.BR topdir ,
/* setstripe create only, don't restripe if target exists */
MDS_SETSTRIPE_CREATE = 1 << 21,
MDS_FID_OP = 1 << 22,
+ /* migrate dirent only */
+ MDS_MIGRATE_NSONLY = 1 << 23,
};
#define MDS_CLOSE_INTENT (MDS_HSM_RELEASE | MDS_CLOSE_LAYOUT_SWAP | \
int len;
char *filename;
int namelen = 0;
+ __u32 flags;
int rc;
rc = obd_ioctl_getdata(&data, &len, (void __user *)arg);
filename = data->ioc_inlbuf1;
namelen = data->ioc_inllen1;
+ flags = data->ioc_type;
if (namelen < 1 || namelen != strlen(filename) + 1) {
CDEBUG(D_INFO, "IOC_MDC_LOOKUP missing filename\n");
GOTO(migrate_free, rc);
}
- rc = ll_migrate(inode, file, lum, filename);
+ rc = ll_migrate(inode, file, lum, filename, flags);
migrate_free:
OBD_FREE_LARGE(data, len);
}
int ll_migrate(struct inode *parent, struct file *file, struct lmv_user_md *lum,
- const char *name)
+ const char *name, __u32 flags)
{
struct dentry *dchild = NULL;
struct inode *child_inode = NULL;
op_data->op_data = lum;
op_data->op_data_size = lumlen;
+ /* migrate dirent only for subdirs if MDS_MIGRATE_NSONLY set */
+ if (S_ISDIR(child_inode->i_mode) && (flags & MDS_MIGRATE_NSONLY) &&
+ lmv_dir_layout_changing(ll_i2info(parent)->lli_lsm_md))
+ op_data->op_bias |= MDS_MIGRATE_NSONLY;
+
again:
if (S_ISREG(child_inode->i_mode)) {
och = ll_lease_open(child_inode, NULL, FMODE_WRITE, 0);
}
int ll_migrate(struct inode *parent, struct file *file,
- struct lmv_user_md *lum, const char *name);
+ struct lmv_user_md *lum, const char *name, __u32 flags);
int ll_get_fid_by_name(struct inode *parent, const char *name,
int namelen, struct lu_fid *fid, struct inode **inode);
int ll_inode_permission(struct inode *inode, int mask);
tp_tgt = lmv_tgt(lmv, oinfo->lmo_mds);
if (!tp_tgt)
RETURN(-ENODEV);
+
+ /* parent unchanged and update namespace only */
+ if (lu_fid_eq(&op_data->op_fid4, &op_data->op_fid2) &&
+ op_data->op_bias & MDS_MIGRATE_NSONLY)
+ RETURN(-EALREADY);
}
} else {
sp_tgt = parent_tgt;
} else {
spec->sp_migrate_close = 0;
}
- spec->sp_migrate_nsonly = 0;
+
+ spec->sp_migrate_nsonly = !!(rec->rn_bias & MDS_MIGRATE_NSONLY);
/* lustre version > 2.11 migration packs lum */
if (req_capsule_has_field(pill, &RMF_EADATA, RCL_CLIENT)) {
(unsigned)MDS_PCC_ATTACH);
LASSERTF(MDS_CLOSE_UPDATE_TIMES == 0x00100000UL, "found 0x%.8xUL\n",
(unsigned)MDS_CLOSE_UPDATE_TIMES);
+ LASSERTF(MDS_SETSTRIPE_CREATE == 0x00200000UL, "found 0x%.8xUL\n",
+ (unsigned)MDS_SETSTRIPE_CREATE);
+ LASSERTF(MDS_FID_OP == 0x00400000UL, "found 0x%.8xUL\n",
+ (unsigned)MDS_FID_OP);
+ LASSERTF(MDS_MIGRATE_NSONLY == 0x00800000UL, "found 0x%.8xUL\n",
+ (unsigned)MDS_MIGRATE_NSONLY);
/* Checks for struct mdt_body */
LASSERTF((int)sizeof(struct mdt_body) == 216, "found %lld\n",
}
run_test 230v "subdir migrated to the MDT where its parent is located"
+test_230w() {
+ (( MDSCOUNT > 1 )) || skip "needs >= 2 MDTs"
+ (( MDS1_VERSION >= $(version_code 2.14.53) )) ||
+ skip "Need MDS version at least 2.14.53"
+
+ mkdir -p $DIR/$tdir/sub || error "mkdir failed"
+
+ $LFS migrate -m 1 -c $MDSCOUNT -d $DIR/$tdir ||
+ error "migrate failed"
+
+ (( $($LFS getdirstripe -c $DIR/$tdir) == MDSCOUNT )) ||
+ error "$tdir stripe count mismatch"
+
+ (( $($LFS getdirstripe -c $DIR/$tdir/sub) == 0 )) ||
+ error "$tdir/sub is striped"
+}
+run_test 230w "non-recursive mode dir migration"
+
test_231a()
{
# For simplicity this test assumes that max_pages_per_rpc
local file
local pid
+ mkdir_on_mdt0 $DIR1/$tdir
mkdir -p $DIR1/$tdir/dir
createmany -o $DIR1/$tdir/dir/f 10 ||
error "create files under remote dir failed $i"
"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]\n"
+ "usage: migrate [--mdt-count|-c STRIPE_COUNT] [--directory|-d]\n"
" [--mdt-hash|-H HASH_TYPE]\n"
" [--mdt-index|-m START_MDT_INDEX] [--verbose|-v]\n"
" DIRECTORY\n"
.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" */
+ { .val = 'd', .name = "directory", .has_arg = no_argument},
/* --non-direct is only valid in migrate mode */
{ .val = 'D', .name = "non-direct", .has_arg = no_argument },
{ .val = 'E', .name = "comp-end", .has_arg = required_argument},
{ .val = 'p', .name = "pool", .has_arg = required_argument },
/* find { .val = 'P', .name = "print", .has_arg = no_argument }, */
/* getstripe { .val = 'q', .name = "quiet", .has_arg = no_argument }, */
-/* getstripe { .val = 'r', .name = "recursive", .has_arg = no_argument }, */
/* getstripe { .val = 'R', .name = "raw", .has_arg = no_argument }, */
{ .val = 'S', .name = "stripe-size", .has_arg = required_argument },
{ .val = 'S', .name = "stripe_size", .has_arg = required_argument },
lsa.lsa_stripe_count = LLAPI_LAYOUT_WIDE;
break;
case 'd':
- /* delete the default striping pattern */
- delete = 1;
- if (opc == SO_MIRROR_SPLIT) {
- if (has_m_file) {
- fprintf(stderr,
- "%s %s: -d cannot used with -f\n",
- progname, argv[0]);
- goto usage_error;
+ if (migrate_mode) {
+ migrate_mdt_param.fp_max_depth = 1;
+ } else {
+ /* delete the default striping pattern */
+ delete = 1;
+ if (opc == SO_MIRROR_SPLIT) {
+ if (has_m_file) {
+ fprintf(stderr,
+ "%s %s: -d cannot used with -f\n",
+ progname, argv[0]);
+ goto usage_error;
+ }
+ mirror_flags |= MF_DESTROY;
}
- mirror_flags |= MF_DESTROY;
}
break;
case 'D':
data.ioc_inlbuf2 = (char *)lmu;
data.ioc_inllen2 = lmv_user_md_size(lmu->lum_stripe_count,
lmu->lum_magic);
+ /* reach bottom? */
+ if (param->fp_depth == param->fp_max_depth)
+ data.ioc_type = MDS_MIGRATE_NSONLY;
ret = llapi_ioctl_pack(&data, &rawbuf, sizeof(raw));
if (ret != 0) {
llapi_error(LLAPI_MSG_ERROR, ret,
}
out:
+ /* Do not get down anymore? */
+ if (param->fp_depth == param->fp_max_depth)
+ ret = 1;
+ param->fp_depth++;
+
if (dp != NULL) {
/*
* If the directory is being migration, we need
CHECK_VALUE_X(MDS_TRUNC_KEEP_LEASE);
CHECK_VALUE_X(MDS_PCC_ATTACH);
CHECK_VALUE_X(MDS_CLOSE_UPDATE_TIMES);
+ CHECK_VALUE_X(MDS_SETSTRIPE_CREATE);
+ CHECK_VALUE_X(MDS_FID_OP);
+ CHECK_VALUE_X(MDS_MIGRATE_NSONLY);
}
static void
(unsigned)MDS_PCC_ATTACH);
LASSERTF(MDS_CLOSE_UPDATE_TIMES == 0x00100000UL, "found 0x%.8xUL\n",
(unsigned)MDS_CLOSE_UPDATE_TIMES);
+ LASSERTF(MDS_SETSTRIPE_CREATE == 0x00200000UL, "found 0x%.8xUL\n",
+ (unsigned)MDS_SETSTRIPE_CREATE);
+ LASSERTF(MDS_FID_OP == 0x00400000UL, "found 0x%.8xUL\n",
+ (unsigned)MDS_FID_OP);
+ LASSERTF(MDS_MIGRATE_NSONLY == 0x00800000UL, "found 0x%.8xUL\n",
+ (unsigned)MDS_MIGRATE_NSONLY);
/* Checks for struct mdt_body */
LASSERTF((int)sizeof(struct mdt_body) == 216, "found %lld\n",