Add an option "-d|--directory" option for "lfs migrate -m" to
migrate specified directory only, which is similar to "ls -d".
Add sanity 230w.
Signed-off-by: Lai Siyao <lai.siyao@whamcloud.com>
Change-Id: Ib97949e3840a3b49f7074b16e259582a9bf16e3b
Reviewed-on: https://review.whamcloud.com/44802
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Yingjin Qian <qian@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
14 files changed:
.IR FILE " ..."
.br
.B lfs migrate -m \fISTART_MDT_INDEX
.IR FILE " ..."
.br
.B lfs migrate -m \fISTART_MDT_INDEX
.I DIRECTORY
.br
.SH DESCRIPTION
.I DIRECTORY
.br
.SH DESCRIPTION
values must match
.IR COUNT .
.TP
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
.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 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 ,
.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,
/* 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 | \
};
#define MDS_CLOSE_INTENT (MDS_HSM_RELEASE | MDS_CLOSE_LAYOUT_SWAP | \
int len;
char *filename;
int namelen = 0;
int len;
char *filename;
int namelen = 0;
int rc;
rc = obd_ioctl_getdata(&data, &len, (void __user *)arg);
int rc;
rc = obd_ioctl_getdata(&data, &len, (void __user *)arg);
filename = data->ioc_inlbuf1;
namelen = data->ioc_inllen1;
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");
if (namelen < 1 || namelen != strlen(filename) + 1) {
CDEBUG(D_INFO, "IOC_MDC_LOOKUP missing filename\n");
GOTO(migrate_free, rc);
}
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);
migrate_free:
OBD_FREE_LARGE(data, len);
}
int ll_migrate(struct inode *parent, struct file *file, struct lmv_user_md *lum,
}
int ll_migrate(struct inode *parent, struct file *file, struct lmv_user_md *lum,
+ const char *name, __u32 flags)
{
struct dentry *dchild = NULL;
struct inode *child_inode = NULL;
{
struct dentry *dchild = NULL;
struct inode *child_inode = NULL;
op_data->op_data = lum;
op_data->op_data_size = lumlen;
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);
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,
}
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);
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);
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 {
sp_tgt = parent_tgt;
} else {
spec->sp_migrate_close = 0;
}
} 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)) {
/* 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);
(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",
/* 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"
}
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
test_231a()
{
# For simplicity this test assumes that max_pages_per_rpc
+ 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"
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: 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"
" [--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},
.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},
/* --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 }, */
{ .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 },
/* 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':
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;
data.ioc_inlbuf2 = (char *)lmu;
data.ioc_inllen2 = lmv_user_md_size(lmu->lum_stripe_count,
lmu->lum_magic);
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,
ret = llapi_ioctl_pack(&data, &rawbuf, sizeof(raw));
if (ret != 0) {
llapi_error(LLAPI_MSG_ERROR, ret,
+ /* 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
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_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);
(unsigned)MDS_PCC_ATTACH);
LASSERTF(MDS_CLOSE_UPDATE_TIMES == 0x00100000UL, "found 0x%.8xUL\n",
(unsigned)MDS_CLOSE_UPDATE_TIMES);
(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",
/* Checks for struct mdt_body */
LASSERTF((int)sizeof(struct mdt_body) == 216, "found %lld\n",