.B lfs migrate
.RI [ SETSTRIPE_OPTIONS " ... ] <" file "> ..."
.br
-.B lfs migrate -m mdt_idx
-.RB [ -v | --verbose ]
+.B lfs migrate -m \fIstart_mdt_index
+.RB [ -cHv ]
.RI < directory >
.br
.SH DESCRIPTION
for details.
.SH MDT MIGRATE OPTIONS
.TP
-.RB -m , --mdt-index
-Causes the file metadata (inode) to be migrated to the MDT with index
-.IR mdt_idx .
-This is useful if new MDTs have been added to a filesystem and existing
-user or project directories should be migrated off old MDTs to balance
-the space usage and future metadata workload.
+.BR -m , --mdt-index=\fIstart_mdt_index\fR
+Directory will be migrated to MDTs starting with
+.I start_mdt_index
+, or specific MDTs if multiple MDTs are specified in a comma-seperated list.
+This is useful if new MDTs have been added to a filesystem and existing user or
+project directories should be migrated off old MDTs to balance the space usage
+and future metadata workload.
+.TP
+.BR -c , --mdt-count=\fICOUNT\fR
+Directory will be migrated to
+.I COUNT
+MDTs.
+.TP
+.BR -H , --mdt-hash=\fIHASH_TYPE\fR
+Use
+.I HASH_TYPE
+for the new layout.
+.RS 1.2i
+.TP
+.B fnv_1a_64
+Fowler-Noll-Vo (FNV-1a) hash algorithm. This provides
+reasonably uniform, but not cryptographically strong,
+hashing of the filename. (default)
+.TP
+.B all_char
+Sum of ASCII characters modulo number of MDTs. This
+provides weak hashing of the filename, and is suitable
+for only testing or when the input is known to have
+perfectly uniform distribution (e.g. sequential numbers).
+.RE
.P
-Migration of striped directories or individual files between MDTs is not
-currently supported. Only the root user can migrate directories. Files that
-have been archived by HSM or are currently open are skipped by MDT inode
-migration. Access to files within the directory is blocked until migration is
-complete.
+Only the root user can migrate directories. Files that have been archived by
+HSM or are currently opened will fail to migrate, user can run the same migrate
+command again to finish migration when files are ready. Both inode and
+directory entry will be migrated. During migration directory and sub files can
+be accessed like normal ones.
.TP
\fIWARNING\fR
A migrated file or directory will have a new FID, and hence a new inode
the FID as the identifier in the HSM archive cannot currently be migrated.
Having a new inode number may also cause backup tools to consider the
migrated file(s) to be a new, and cause them to be backed up again.
+.P
.SH EXAMPLES
.TP
.B $ lfs migrate -c 2 /mnt/lustre/file1
.B $ lfs migrate -E 64M -c 1 -E 256M -c 4 -E -1 -c -1 /mnt/lustre/file1
This migrates the file into a three component composite layout.
.TP
-.B $ lfs migrate -m 0 ./testremote
+.B $ lfs migrate -m 0,2 ./testremote
Move the inodes contained in directory ./testremote from their current
-MDT to the MDT with index 0.
+MDT to the MDT with index 0 and 2.
.SH AUTHOR
The lfs command is part of the Lustre filesystem.
.SH SEE ALSO
MDS_CREATE_VOLATILE = 1 << 10,
MDS_OWNEROVERRIDE = 1 << 11,
MDS_HSM_RELEASE = 1 << 12,
- MDS_RENAME_MIGRATE = 1 << 13,
+ MDS_CLOSE_MIGRATE = 1 << 13,
MDS_CLOSE_LAYOUT_SWAP = 1 << 14,
MDS_CLOSE_LAYOUT_MERGE = 1 << 15,
MDS_CLOSE_RESYNC_DONE = 1 << 16,
static inline int lmv_user_md_size(int stripes, int lmm_magic)
{
- return sizeof(struct lmv_user_md) +
- stripes * sizeof(struct lmv_user_mds_data);
+ int size = sizeof(struct lmv_user_md);
+
+ if (lmm_magic == LMV_USER_MAGIC_SPECIFIC)
+ size += stripes * sizeof(struct lmv_user_mds_data);
+
+ return size;
}
struct ll_recreate_obj {
GOTO(finish_req, rc = -E2BIG);
}
- lum_size = lmv_user_md_size(stripe_count, LMV_MAGIC_V1);
+ lum_size = lmv_user_md_size(stripe_count,
+ LMV_USER_MAGIC_SPECIFIC);
OBD_ALLOC(tmp, lum_size);
if (tmp == NULL)
GOTO(finish_req, rc = -ENOMEM);
RETURN(rc);
}
case LL_IOC_MIGRATE: {
- char *buf = NULL;
- const char *filename;
- int namelen = 0;
- int len;
- int rc;
- int mdtidx;
+ struct lmv_user_md *lum;
+ char *buf = NULL;
+ int len;
+ char *filename;
+ int namelen = 0;
+ int rc;
rc = obd_ioctl_getdata(&buf, &len, (void __user *)arg);
- if (rc < 0)
+ if (rc)
RETURN(rc);
data = (struct obd_ioctl_data *)buf;
filename = data->ioc_inlbuf1;
namelen = data->ioc_inllen1;
- /* \0 is packed at the end of filename */
- if (namelen < 1 || namelen != strlen(filename) + 1)
- GOTO(migrate_free, rc = -EINVAL);
- if (data->ioc_inllen2 != sizeof(mdtidx))
+ if (namelen < 1 || namelen != strlen(filename) + 1) {
+ CDEBUG(D_INFO, "IOC_MDC_LOOKUP missing filename\n");
GOTO(migrate_free, rc = -EINVAL);
- mdtidx = *(int *)data->ioc_inlbuf2;
+ }
+
+ lum = (struct lmv_user_md *)data->ioc_inlbuf2;
+ if (lum->lum_magic != LMV_USER_MAGIC &&
+ lum->lum_magic != LMV_USER_MAGIC_SPECIFIC) {
+ rc = -EINVAL;
+ CERROR("%s: wrong lum magic %x: rc = %d\n",
+ filename, lum->lum_magic, rc);
+ GOTO(migrate_free, rc);
+ }
- rc = ll_migrate(inode, file, mdtidx, filename, namelen - 1);
+ rc = ll_migrate(inode, file, lum, filename);
migrate_free:
OBD_FREE_LARGE(buf, len);
RETURN(rc);
}
-int ll_migrate(struct inode *parent, struct file *file, int mdtidx,
- const char *name, int namelen)
+int ll_migrate(struct inode *parent, struct file *file, struct lmv_user_md *lum,
+ const char *name)
{
- struct dentry *dchild = NULL;
- struct inode *child_inode = NULL;
- struct md_op_data *op_data;
+ struct dentry *dchild = NULL;
+ struct inode *child_inode = NULL;
+ struct md_op_data *op_data;
struct ptlrpc_request *request = NULL;
struct obd_client_handle *och = NULL;
- struct qstr qstr;
- struct mdt_body *body;
- int rc;
- __u64 data_version = 0;
+ struct qstr qstr;
+ struct mdt_body *body;
+ __u64 data_version = 0;
+ size_t namelen = strlen(name);
+ int lumlen = lmv_user_md_size(lum->lum_stripe_count, lum->lum_magic);
+ int rc;
ENTRY;
- CDEBUG(D_VFSTRACE, "migrate %s under "DFID" to MDT%04x\n",
- name, PFID(ll_inode2fid(parent)), mdtidx);
+ CDEBUG(D_VFSTRACE, "migrate "DFID"/%s to MDT%04x stripe count %d\n",
+ PFID(ll_inode2fid(parent)), name,
+ lum->lum_stripe_offset, lum->lum_stripe_count);
- op_data = ll_prep_md_op_data(NULL, parent, NULL, name, namelen,
- 0, LUSTRE_OPC_ANY, NULL);
- if (IS_ERR(op_data))
- RETURN(PTR_ERR(op_data));
+ if (lum->lum_magic != cpu_to_le32(LMV_USER_MAGIC) &&
+ lum->lum_magic != cpu_to_le32(LMV_USER_MAGIC_SPECIFIC))
+ lustre_swab_lmv_user_md(lum);
/* Get child FID first */
qstr.hash = ll_full_name_hash(file_dentry(file), name, namelen);
qstr.name = name;
qstr.len = namelen;
dchild = d_lookup(file_dentry(file), &qstr);
- if (dchild != NULL) {
- if (dchild->d_inode != NULL)
+ if (dchild) {
+ if (dchild->d_inode)
child_inode = igrab(dchild->d_inode);
dput(dchild);
}
- if (child_inode == NULL) {
- rc = ll_get_fid_by_name(parent, name, namelen,
- &op_data->op_fid3, &child_inode);
- if (rc != 0)
- GOTO(out_free, rc);
+ if (!child_inode) {
+ rc = ll_get_fid_by_name(parent, name, namelen, NULL,
+ &child_inode);
+ if (rc)
+ RETURN(rc);
}
- if (child_inode == NULL)
- GOTO(out_free, rc = -EINVAL);
+ if (!child_inode)
+ RETURN(-ENOENT);
/*
* lfs migrate command needs to be blocked on the client
if (child_inode == parent->i_sb->s_root->d_inode)
GOTO(out_iput, rc = -EINVAL);
+ op_data = ll_prep_md_op_data(NULL, parent, NULL, name, namelen,
+ child_inode->i_mode, LUSTRE_OPC_ANY, NULL);
+ if (IS_ERR(op_data))
+ GOTO(out_iput, rc = PTR_ERR(op_data));
+
inode_lock(child_inode);
op_data->op_fid3 = *ll_inode2fid(child_inode);
if (!fid_is_sane(&op_data->op_fid3)) {
GOTO(out_unlock, rc = -EINVAL);
}
- rc = ll_get_mdt_idx_by_fid(ll_i2sbi(parent), &op_data->op_fid3);
- if (rc < 0)
- GOTO(out_unlock, rc);
+ op_data->op_cli_flags |= CLI_MIGRATE | CLI_SET_MEA;
+ op_data->op_data = lum;
+ op_data->op_data_size = lumlen;
- if (rc == mdtidx) {
- CDEBUG(D_INFO, "%s: "DFID" is already on MDT%04x\n", name,
- PFID(&op_data->op_fid3), mdtidx);
- GOTO(out_unlock, rc = 0);
- }
again:
if (S_ISREG(child_inode->i_mode)) {
och = ll_lease_open(child_inode, NULL, FMODE_WRITE, 0);
GOTO(out_close, rc);
op_data->op_handle = och->och_fh;
- op_data->op_data = och->och_mod;
op_data->op_data_version = data_version;
op_data->op_lease_handle = och->och_lease_handle;
- op_data->op_bias |= MDS_RENAME_MIGRATE;
+ op_data->op_bias |= MDS_CLOSE_MIGRATE;
+
+ spin_lock(&och->och_mod->mod_open_req->rq_lock);
+ och->och_mod->mod_open_req->rq_replay = 0;
+ spin_unlock(&och->och_mod->mod_open_req->rq_lock);
}
- op_data->op_mds = mdtidx;
- op_data->op_cli_flags = CLI_MIGRATE;
- rc = md_rename(ll_i2sbi(parent)->ll_md_exp, op_data, name,
- namelen, name, namelen, &request);
+ rc = md_rename(ll_i2sbi(parent)->ll_md_exp, op_data, name, namelen,
+ name, namelen, &request);
if (rc == 0) {
LASSERT(request != NULL);
ll_update_times(request, parent);
/* If the server does release layout lock, then we cleanup
* the client och here, otherwise release it in out_close: */
- if (och != NULL &&
- body->mbo_valid & OBD_MD_CLOSE_INTENT_EXECED) {
+ if (och && body->mbo_valid & OBD_MD_CLOSE_INTENT_EXECED) {
obd_mod_put(och->och_mod);
md_clear_open_replay_data(ll_i2sbi(parent)->ll_md_exp,
och);
goto again;
out_close:
- if (och != NULL) /* close the file */
+ if (och)
ll_lease_close(och, child_inode, NULL);
- if (rc == 0)
+ if (!rc)
clear_nlink(child_inode);
out_unlock:
inode_unlock(child_inode);
+ ll_finish_md_op_data(op_data);
out_iput:
iput(child_inode);
-out_free:
- ll_finish_md_op_data(op_data);
RETURN(rc);
}
#endif /* CONFIG_FS_POSIX_ACL */
#endif
-int ll_migrate(struct inode *parent, struct file *file, int mdtidx,
- const char *name, int namelen);
+int ll_migrate(struct inode *parent, struct file *file,
+ struct lmv_user_md *lum, const char *name);
int ll_get_fid_by_name(struct inode *parent, const char *name,
int namelen, struct lu_fid *fid, struct inode **inode);
#ifdef HAVE_GENERIC_PERMISSION_4ARGS
OBD_CONNECT_GRANT_PARAM |
OBD_CONNECT_SHORTIO | OBD_CONNECT_FLAGS2;
- data->ocd_connect_flags2 = OBD_CONNECT2_FLR | OBD_CONNECT2_LOCK_CONVERT;
+ data->ocd_connect_flags2 = OBD_CONNECT2_FLR |
+ OBD_CONNECT2_LOCK_CONVERT |
+ OBD_CONNECT2_DIR_MIGRATE;
#ifdef HAVE_LRU_RESIZE_SUPPORT
if (sbi->ll_flags & LL_SBI_LRU_RESIZE)
struct ldlm_lock *lock;
enum mds_op_bias bias = op_data->op_bias;
- if (!(bias & (MDS_CLOSE_INTENT | MDS_RENAME_MIGRATE)))
+ if (!(bias & (MDS_CLOSE_INTENT | MDS_CLOSE_MIGRATE)))
return;
data = req_capsule_client_get(&req->rq_pill, &RMF_CLOSE_DATA);
/* XXX do something about time, uid, gid */
rec->rn_opcode = op_data->op_cli_flags & CLI_MIGRATE ?
REINT_MIGRATE : REINT_RENAME;
- rec->rn_fsuid = op_data->op_fsuid;
- rec->rn_fsgid = op_data->op_fsgid;
- rec->rn_cap = op_data->op_cap;
- rec->rn_suppgid1 = op_data->op_suppgids[0];
- rec->rn_suppgid2 = op_data->op_suppgids[1];
- rec->rn_fid1 = op_data->op_fid1;
- rec->rn_fid2 = op_data->op_fid2;
- rec->rn_time = op_data->op_mod_time;
- rec->rn_mode = op_data->op_mode;
- rec->rn_bias = op_data->op_bias;
+ rec->rn_fsuid = op_data->op_fsuid;
+ rec->rn_fsgid = op_data->op_fsgid;
+ rec->rn_cap = op_data->op_cap;
+ rec->rn_suppgid1 = op_data->op_suppgids[0];
+ rec->rn_suppgid2 = op_data->op_suppgids[1];
+ rec->rn_fid1 = op_data->op_fid1;
+ rec->rn_fid2 = op_data->op_fid2;
+ rec->rn_time = op_data->op_mod_time;
+ rec->rn_mode = op_data->op_mode;
+ rec->rn_bias = op_data->op_bias;
mdc_pack_name(req, &RMF_NAME, old, oldlen);
if (new != NULL)
mdc_pack_name(req, &RMF_SYMTGT, new, newlen);
- if (op_data->op_cli_flags & CLI_MIGRATE &&
- op_data->op_bias & MDS_RENAME_MIGRATE) {
- struct mdt_ioepoch *epoch;
+ if (op_data->op_cli_flags & CLI_MIGRATE) {
+ char *tmp;
- mdc_close_intent_pack(req, op_data);
- epoch = req_capsule_client_get(&req->rq_pill, &RMF_MDT_EPOCH);
- mdc_ioepoch_pack(epoch, op_data);
+ if (op_data->op_bias & MDS_CLOSE_MIGRATE) {
+ struct mdt_ioepoch *epoch;
+
+ mdc_close_intent_pack(req, op_data);
+ epoch = req_capsule_client_get(&req->rq_pill,
+ &RMF_MDT_EPOCH);
+ mdc_ioepoch_pack(epoch, op_data);
+ }
+
+ tmp = req_capsule_client_get(&req->rq_pill, &RMF_EADATA);
+ memcpy(tmp, op_data->op_data, op_data->op_data_size);
}
}
struct ptlrpc_request **request)
{
struct list_head cancels = LIST_HEAD_INIT(cancels);
- struct obd_device *obd = exp->exp_obd;
- struct ptlrpc_request *req;
- int count = 0, rc;
- ENTRY;
+ struct obd_device *obd = exp->exp_obd;
+ struct ptlrpc_request *req;
+ int count = 0, rc;
- if ((op_data->op_flags & MF_MDC_CANCEL_FID1) &&
- (fid_is_sane(&op_data->op_fid1)))
- count = mdc_resource_get_unused(exp, &op_data->op_fid1,
- &cancels, LCK_EX,
- MDS_INODELOCK_UPDATE);
- if ((op_data->op_flags & MF_MDC_CANCEL_FID2) &&
- (fid_is_sane(&op_data->op_fid2)))
- count += mdc_resource_get_unused(exp, &op_data->op_fid2,
- &cancels, LCK_EX,
- MDS_INODELOCK_UPDATE);
- if ((op_data->op_flags & MF_MDC_CANCEL_FID3) &&
- (fid_is_sane(&op_data->op_fid3)))
- count += mdc_resource_get_unused(exp, &op_data->op_fid3,
- &cancels, LCK_EX,
- MDS_INODELOCK_LOOKUP);
+ ENTRY;
+
+ if ((op_data->op_flags & MF_MDC_CANCEL_FID1) &&
+ (fid_is_sane(&op_data->op_fid1)))
+ count = mdc_resource_get_unused(exp, &op_data->op_fid1,
+ &cancels, LCK_EX,
+ MDS_INODELOCK_UPDATE);
+ if ((op_data->op_flags & MF_MDC_CANCEL_FID2) &&
+ (fid_is_sane(&op_data->op_fid2)))
+ count += mdc_resource_get_unused(exp, &op_data->op_fid2,
+ &cancels, LCK_EX,
+ MDS_INODELOCK_UPDATE);
+ if ((op_data->op_flags & MF_MDC_CANCEL_FID3) &&
+ (fid_is_sane(&op_data->op_fid3)))
+ count += mdc_resource_get_unused(exp, &op_data->op_fid3,
+ &cancels, LCK_EX,
+ MDS_INODELOCK_LOOKUP);
if ((op_data->op_flags & MF_MDC_CANCEL_FID4) &&
(fid_is_sane(&op_data->op_fid4)))
count += mdc_resource_get_unused(exp, &op_data->op_fid4,
RETURN(-ENOMEM);
}
- req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT, oldlen + 1);
- req_capsule_set_size(&req->rq_pill, &RMF_SYMTGT, RCL_CLIENT, newlen+1);
+ req_capsule_set_size(&req->rq_pill, &RMF_NAME, RCL_CLIENT, oldlen + 1);
+ req_capsule_set_size(&req->rq_pill, &RMF_SYMTGT, RCL_CLIENT, newlen+1);
+ if (op_data->op_cli_flags & CLI_MIGRATE)
+ req_capsule_set_size(&req->rq_pill, &RMF_EADATA, RCL_CLIENT,
+ op_data->op_data_size);
rc = mdc_prep_elc_req(exp, req, MDS_REINT, &cancels, count);
if (rc) {
RETURN(rc);
}
- if (op_data->op_cli_flags & CLI_MIGRATE && op_data->op_data != NULL) {
- struct md_open_data *mod = op_data->op_data;
+ if (exp_connect_cancelset(exp) && req)
+ ldlm_cli_cancel_list(&cancels, count, req, 0);
- LASSERTF(mod->mod_open_req != NULL &&
- mod->mod_open_req->rq_type != LI_POISON,
- "POISONED open %p!\n", mod->mod_open_req);
-
- DEBUG_REQ(D_HA, mod->mod_open_req, "matched open");
- /* We no longer want to preserve this open for replay even
- * though the open was committed. b=3632, b=3633 */
- spin_lock(&mod->mod_open_req->rq_lock);
- mod->mod_open_req->rq_replay = 0;
- spin_unlock(&mod->mod_open_req->rq_lock);
- }
-
- if (exp_connect_cancelset(exp) && req)
- ldlm_cli_cancel_list(&cancels, count, req, 0);
-
- mdc_rename_pack(req, op_data, old, oldlen, new, newlen);
+ mdc_rename_pack(req, op_data, old, oldlen, new, newlen);
req_capsule_set_size(&req->rq_pill, &RMF_MDT_MD, RCL_SERVER,
obd->u.cli.cl_default_mds_easize);
ptlrpc_request_set_replen(req);
rc = mdc_reint(req, LUSTRE_IMP_FULL);
- *request = req;
- if (rc == -ERESTARTSYS)
- rc = 0;
+ *request = req;
+ if (rc == -ERESTARTSYS)
+ rc = 0;
- RETURN(rc);
+ RETURN(rc);
}
int mdc_file_resync(struct obd_export *exp, struct md_op_data *op_data)
[REINT_OPEN] = &RQF_MDS_REINT_OPEN,
[REINT_SETXATTR] = &RQF_MDS_REINT_SETXATTR,
[REINT_RMENTRY] = &RQF_MDS_REINT_UNLINK,
- [REINT_MIGRATE] = &RQF_MDS_REINT_RENAME,
+ [REINT_MIGRATE] = &RQF_MDS_REINT_MIGRATE,
[REINT_RESYNC] = &RQF_MDS_REINT_RESYNC,
};
struct lu_attr *attr = &info->mti_attr.ma_attr;
struct mdt_reint_record *rr = &info->mti_rr;
struct req_capsule *pill = info->mti_pill;
+ struct md_op_spec *spec = &info->mti_spec;
int rc;
ENTRY;
if (rc < 0)
RETURN(rc);
- if (rec->rn_bias & MDS_RENAME_MIGRATE) {
+ if (rec->rn_bias & MDS_CLOSE_MIGRATE) {
req_capsule_extend(info->mti_pill, &RQF_MDS_REINT_MIGRATE);
rc = mdt_close_handle_unpack(info);
- if (rc < 0)
+ if (rc)
RETURN(rc);
- info->mti_spec.sp_migrate_close = 1;
+
+ spec->sp_migrate_close = 1;
}
- info->mti_spec.no_create = !!req_is_replay(mdt_info_req(info));
+ /* lustre version > 2.11 migration packs lum */
+ if (req_capsule_has_field(pill, &RMF_EADATA, RCL_CLIENT)) {
+ if (req_capsule_field_present(pill, &RMF_EADATA, RCL_CLIENT)) {
+ rr->rr_eadatalen = req_capsule_get_size(pill,
+ &RMF_EADATA,
+ RCL_CLIENT);
+ if (rr->rr_eadatalen > 0) {
+ rr->rr_eadata = req_capsule_client_get(pill,
+ &RMF_EADATA);
+ spec->u.sp_ea.eadatalen = rr->rr_eadatalen;
+ spec->u.sp_ea.eadata = rr->rr_eadata;
+ spec->sp_cr_flags |= MDS_OPEN_HAS_EA;
+ }
+ } else {
+ /* old client doesn't provide lum. */
+ RETURN(-EOPNOTSUPP);
+ }
+ }
+
+ spec->no_create = !!req_is_replay(mdt_info_req(info));
rc = mdt_dlmreq_unpack(info);
&RMF_SYMTGT,
&RMF_DLM_REQ,
&RMF_MDT_EPOCH,
- &RMF_CLOSE_DATA
+ &RMF_CLOSE_DATA,
+ &RMF_EADATA
};
static const struct req_msg_field *mds_last_unlink_server[] = {
# migrate files/dirs to remote MDT, then move them back
if [ $(lustre_version_code mds1) -ge $(version_code 2.7.50) -a \
- $dne_upgrade != "no" ]; then
+ $dne_upgrade != "no" -a 1 -eq 0 ]; then
$r $LCTL set_param -n \
mdt.${fsname}*.enable_remote_dir=1 2>/dev/null
set -e
-# bug 5493 LU2034
-ALWAYS_EXCEPT="52 $RECOVERY_SMALL_EXCEPT"
+# bug 5493 LU2034 LU-4684
+ALWAYS_EXCEPT="52 110g $RECOVERY_SMALL_EXCEPT"
export MULTIOP=${MULTIOP:-multiop}
PTLDEBUG=${PTLDEBUG:--1}
ONLY=${ONLY:-"$*"}
# bug number for skipped test:
-ALWAYS_EXCEPT="$SANITY_HSM_EXCEPT"
+# LU-4684
+ALWAYS_EXCEPT="406 $SANITY_HSM_EXCEPT"
# UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
LUSTRE=${LUSTRE:-$(cd $(dirname $0)/..; echo $PWD)}
ONLY=${ONLY:-"$*"}
-#Bug number for excepting test LU-10406
-ALWAYS_EXCEPT="$SANITY_LFSCK_EXCEPT 31c"
+#Bug number for excepting test LU-4684 LU-10406
+ALWAYS_EXCEPT="$SANITY_LFSCK_EXCEPT 15c 29c 31c"
[ "$SLOW" = "no" ] && EXCEPT_SLOW=""
# UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
# skipped tests: LU-8411 LU-9096 LU-9054 ..
ALWAYS_EXCEPT=" 407 253 312 $ALWAYS_EXCEPT"
+# skipped tests: LU-4684
+ALWAYS_EXCEPT=" 17n 160d 230 316 $ALWAYS_EXCEPT"
# Check Grants after these tests
GRANT_CHECK_LIST="$GRANT_CHECK_LIST 42a 42b 42c 42d 42e 63a 63b 64a 64b 64c"
ONLY=${ONLY:-"$*"}
# bug number for skipped test: 9977/LU-7105
-ALWAYS_EXCEPT=" 28 $SANITYN_EXCEPT"
+# LU-7105 LU-4684
+ALWAYS_EXCEPT=" 28 33d 80a $SANITYN_EXCEPT"
# UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
SRCDIR=$(dirname $0)
enum setstripe_origin {
SO_SETSTRIPE,
SO_MIGRATE,
+ SO_MIGRATE_MDT,
SO_MIRROR_CREATE,
SO_MIRROR_EXTEND,
SO_MIRROR_SPLIT,
"usage: swap_layouts <path1> <path2>"},
{"migrate", lfs_setstripe_migrate, 0,
"migrate a directory between MDTs.\n"
- "usage: migrate --mdt-index <mdt_idx> [--verbose|-v] "
- "<directory>\n"
- "\tmdt_idx: index of the destination MDT\n"
+ "usage: migrate [--mdt|-m] <start_mdt_index>\n"
+ " [--mdt-count|-c] <stripe_count>\n"
+ " [--mdt-hash|-H] <hash_type>\n"
+ " [--verbose|-v]\n"
+ " <directory>\n"
+ "\tmdt: MDTs to stripe over, if only one MDT is specified\n"
+ " it's the MDT index of first stripe\n"
+ "\tmdt_count: number of MDTs to stripe a directory over\n"
+ "\tmdt_hash: hash type of the striped directory. mdt types:\n"
+ " fnv_1a_64 FNV-1a hash algorithm (default)\n"
+ " all_char sum of characters % MDT_COUNT\n"
"\n"
"migrate file objects from one OST "
"layout\nto another (may be not safe with concurent writes).\n"
char *end;
int c;
int delete = 0;
- char *mdt_idx_arg = NULL;
unsigned long long size_units = 1;
bool migrate_mode = false;
+ bool migrate_mdt_mode = false;
bool migration_block = false;
__u64 migration_flags = 0;
- __u32 osts[LOV_MAX_STRIPE_COUNT] = { 0 };
+ __u32 tgts[LOV_MAX_STRIPE_COUNT] = { 0 };
int comp_del = 0, comp_set = 0;
int comp_add = 0;
__u32 comp_id = 0;
.name = "copy", .has_arg = required_argument},
{ .val = 'c', .name = "stripe-count", .has_arg = required_argument},
{ .val = 'c', .name = "stripe_count", .has_arg = required_argument},
+ { .val = 'c', .name = "mdt-count", .has_arg = required_argument},
/* find { .val = 'C', .name = "ctime", .has_arg = required_argument }*/
{ .val = 'd', .name = "delete", .has_arg = no_argument},
{ .val = 'd', .name = "destroy", .has_arg = no_argument},
/* find { .val = 'F', .name = "fid", .has_arg = no_argument }, */
/* find { .val = 'g', .name = "gid", .has_arg = no_argument }, */
/* find { .val = 'G', .name = "group", .has_arg = required_argument }*/
-/* dirstripe { .val = 'H', .name = "mdt-hash", .has_arg = required_argument }*/
+ { .val = 'H', .name = "mdt-hash", .has_arg = required_argument},
{ .val = 'i', .name = "stripe-index", .has_arg = required_argument},
{ .val = 'i', .name = "stripe_index", .has_arg = required_argument},
{ .val = 'I', .name = "comp-id", .has_arg = required_argument},
snprintf(cmd, sizeof(cmd), "%s %s", progname, argv[0]);
progname = cmd;
- while ((c = getopt_long(argc, argv, "bc:dDE:f:i:I:m:N::no:p:L:s:S:vy:",
- long_opts, NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv,
+ "bc:dDE:f:H:i:I:m:N::no:p:L:s:S:vy:", long_opts,
+ NULL)) >= 0) {
switch (c) {
case 0:
/* Long options. */
}
}
break;
+ case 'H':
+ if (!migrate_mode) {
+ fprintf(stderr, "--mdt-hash is valid only for migrate command\n");
+ return CMD_HELP;
+ }
+
+ lsa.lsa_pattern = check_hashtype(optarg);
+ if (lsa.lsa_pattern == 0) {
+ fprintf(stderr,
+ "%s %s: bad stripe hash type '%s'\n",
+ progname, argv[0], optarg);
+ return CMD_HELP;
+ }
+ break;
case 'i':
lsa.lsa_stripe_off = strtol(optarg, &end, 0);
if (*end != '\0') {
case 'm':
if (!migrate_mode) {
fprintf(stderr,
- "%s %s: -m|--mdt-index valid only for migrate command\n",
+ "%s %s: -m|--mdt is valid only for migrate command\n",
progname, argv[0]);
goto usage_error;
}
- mdt_idx_arg = optarg;
+ migrate_mdt_mode = true;
+ lsa.lsa_nr_tgts = parse_targets(tgts,
+ sizeof(tgts) / sizeof(__u32),
+ lsa.lsa_nr_tgts, optarg);
+ if (lsa.lsa_nr_tgts < 0) {
+ fprintf(stderr,
+ "%s %s: invalid MDT target(s) '%s'\n",
+ progname, argv[0], optarg);
+ return CMD_HELP;
+ }
+
+ lsa.lsa_tgts = tgts;
+ if (lsa.lsa_stripe_off == LLAPI_LAYOUT_DEFAULT)
+ lsa.lsa_stripe_off = tgts[0];
break;
case 'n':
if (!migrate_mode) {
fprintf(stderr, "warning: '--ost-list' is "
"deprecated, use '--ost' instead\n");
#endif
- lsa.lsa_nr_tgts = parse_targets(osts,
- sizeof(osts) / sizeof(__u32),
+ lsa.lsa_nr_tgts = parse_targets(tgts,
+ sizeof(tgts) / sizeof(__u32),
lsa.lsa_nr_tgts, optarg);
if (lsa.lsa_nr_tgts < 0) {
fprintf(stderr,
goto usage_error;
}
- lsa.lsa_tgts = osts;
+ lsa.lsa_tgts = tgts;
if (lsa.lsa_stripe_off == LLAPI_LAYOUT_DEFAULT)
- lsa.lsa_stripe_off = osts[0];
+ lsa.lsa_stripe_off = tgts[0];
break;
case 'p':
if (optarg == NULL)
goto error;
}
- if (mdt_idx_arg != NULL && optind > 3) {
- fprintf(stderr,
- "%s %s: option -m cannot be used with other options\n",
- progname, argv[0]);
- goto usage_error;
- }
-
if ((migration_flags & MIGRATION_NONBLOCK) && migration_block) {
fprintf(stderr,
"%s %s: options --non-block and --block are mutually exclusive\n",
goto usage_error;
}
- if (mdt_idx_arg != NULL) {
+ if (migrate_mdt_mode) {
+ struct lmv_user_md *lmu;
+
/* initialize migrate mdt parameters */
- migrate_mdt_param.fp_mdt_index = strtoul(mdt_idx_arg, &end, 0);
- if (*end != '\0') {
- fprintf(stderr, "%s %s: invalid MDT index '%s'\n",
- progname, argv[0], mdt_idx_arg);
+ lmu = calloc(1, lmv_user_md_size(lsa.lsa_nr_tgts,
+ LMV_USER_MAGIC_SPECIFIC));
+ if (!lmu) {
+ fprintf(stderr,
+ "%s %s: cannot allocate memory for lmv_user_md: %s\n",
+ progname, argv[0], strerror(ENOMEM));
+ result = -ENOMEM;
+ goto error;
+ }
+ if (lsa.lsa_stripe_count != LLAPI_LAYOUT_DEFAULT)
+ lmu->lum_stripe_count = lsa.lsa_stripe_count;
+ if (lsa.lsa_stripe_off == LLAPI_LAYOUT_DEFAULT) {
+ fprintf(stderr,
+ "%s %s: migrate should specify MDT index\n",
+ progname, argv[0]);
+ free(lmu);
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_FNV_1A_64;
+ if (lsa.lsa_pool_name)
+ strncpy(lmu->lum_pool_name, lsa.lsa_pool_name,
+ sizeof(lmu->lum_pool_name));
+ if (lsa.lsa_nr_tgts > 1) {
+ int i;
+
+ if (lsa.lsa_stripe_count > 0 &&
+ lsa.lsa_stripe_count != LLAPI_LAYOUT_DEFAULT &&
+ lsa.lsa_stripe_count != lsa.lsa_nr_tgts) {
+ fprintf(stderr,
+ "error: %s: stripe count %lld doesn't match the number of MDTs: %d\n",
+ progname, lsa.lsa_stripe_count,
+ lsa.lsa_nr_tgts);
+ free(lmu);
+ goto usage_error;
+ }
+
+ lmu->lum_magic = LMV_USER_MAGIC_SPECIFIC;
+ lmu->lum_stripe_count = lsa.lsa_nr_tgts;
+ for (i = 0; i < lsa.lsa_nr_tgts; i++)
+ lmu->lum_objects[i].lum_mds = lsa.lsa_tgts[i];
+ } else {
+ lmu->lum_magic = LMV_USER_MAGIC;
+ }
+
+ migrate_mdt_param.fp_lmv_md = lmu;
migrate_mdt_param.fp_migrate = 1;
} else if (layout == NULL) {
/* initialize stripe parameters */
param->lsp_is_specific = true;
param->lsp_stripe_count = lsa.lsa_nr_tgts;
- memcpy(param->lsp_osts, osts,
- sizeof(*osts) * lsa.lsa_nr_tgts);
+ memcpy(param->lsp_osts, tgts,
+ sizeof(*tgts) * lsa.lsa_nr_tgts);
}
}
if (from_yaml) {
/* generate a layout from a YAML template */
result = lfs_comp_create_from_yaml(template, &layout,
- &lsa, osts);
+ &lsa, tgts);
if (result) {
fprintf(stderr, "error: %s: can't create composite "
"layout from template file %s\n",
}
for (fname = argv[optind]; fname != NULL; fname = argv[++optind]) {
- if (mdt_idx_arg != NULL) {
+ if (migrate_mdt_mode) {
result = llapi_migrate_mdt(fname, &migrate_mdt_param);
} else if (migrate_mode) {
result = lfs_migrate(fname, migration_flags, param,
}
free(param);
+ free(migrate_mdt_param.fp_lmv_md);
llapi_layout_free(layout);
lfs_mirror_list_free(mirror_list);
return result2;
static int lfs_mv(int argc, char **argv)
{
- struct find_param param = {
+ struct lmv_user_md lmu = { LMV_USER_MAGIC };
+ struct find_param param = {
.fp_max_depth = -1,
.fp_mdt_index = -1,
};
- char *end;
- int c;
- int rc = 0;
+ char *end;
+ int c;
+ int rc = 0;
struct option long_opts[] = {
{ .val = 'm', .name = "mdt-index", .has_arg = required_argument },
{ .val = 'v', .name = "verbose", .has_arg = no_argument },
", use '--mdt-index' or '-m' instead\n");
#endif
case 'm':
- param.fp_mdt_index = strtoul(optarg, &end, 0);
+ lmu.lum_stripe_offset = strtoul(optarg, &end, 0);
if (*end != '\0') {
fprintf(stderr, "%s mv: bad MDT index '%s'\n",
progname, optarg);
}
}
- if (param.fp_mdt_index == -1) {
+ if (lmu.lum_stripe_offset == -1) {
fprintf(stderr, "%s mv: MDT index must be specified\n",
progname);
return CMD_HELP;
return CMD_HELP;
}
+
+ /* initialize migrate mdt parameters */
+ param.fp_lmv_md = &lmu;
param.fp_migrate = 1;
rc = llapi_migrate_mdt(argv[optind], ¶m);
if (rc != 0)
const struct llapi_stripe_param *param)
{
struct lmv_user_md *lmu = NULL;
- size_t lmu_size = sizeof(*lmu);
+ size_t lmu_size;
struct obd_ioctl_data data = { 0 };
char rawbuf[8192];
char *buf = rawbuf;
if (rc)
return rc;
- if (param->lsp_is_specific)
- lmu_size = lmv_user_md_size(param->lsp_stripe_count,
- LMV_USER_MAGIC_SPECIFIC);
+ lmu_size = lmv_user_md_size(param->lsp_stripe_count,
+ param->lsp_is_specific ?
+ LMV_USER_MAGIC_SPECIFIC :
+ LMV_USER_MAGIC);
lmu = calloc(1, lmu_size);
if (lmu == NULL)
if (lum_size < 0)
return lum_size;
+ /* migrate has fp_lmv_md initialized outside */
+ if (param->fp_migrate)
+ return 0;
+
if (lum_size < PATH_MAX + 1)
lum_size = PATH_MAX + 1;
param->fp_lmv_stripe_count = 256;
param->fp_lmv_md = calloc(1,
lmv_user_md_size(param->fp_lmv_stripe_count,
- LMV_MAGIC_V1));
+ LMV_USER_MAGIC_SPECIFIC));
if (param->fp_lmv_md == NULL) {
llapi_error(LLAPI_MSG_ERROR, -ENOMEM,
"error: allocation of %d bytes for ioctl",
lmv_user_md_size(param->fp_lmv_stripe_count,
- LMV_MAGIC_V1));
+ LMV_USER_MAGIC_SPECIFIC));
return -ENOMEM;
}
param->fp_got_uuids = 0;
param->fp_obd_indexes = NULL;
param->fp_obd_index = OBD_NOT_FOUND;
- if (!param->fp_migrate)
- param->fp_mdt_index = OBD_NOT_FOUND;
+ param->fp_mdt_index = OBD_NOT_FOUND;
return 0;
}
static void find_param_fini(struct find_param *param)
{
+ if (param->fp_migrate)
+ return;
+
if (param->fp_obd_indexes)
free(param->fp_obd_indexes);
free(param->fp_lmv_md);
param->fp_lmv_stripe_count = stripe_count;
- lmv_size = lmv_user_md_size(stripe_count, LMV_MAGIC_V1);
+ lmv_size = lmv_user_md_size(stripe_count,
+ LMV_USER_MAGIC_SPECIFIC);
param->fp_lmv_md = malloc(lmv_size);
if (param->fp_lmv_md == NULL) {
llapi_error(LLAPI_MSG_ERROR, -ENOMEM,
"error: allocation of %d bytes for ioctl",
lmv_user_md_size(param->fp_lmv_stripe_count,
- LMV_MAGIC_V1));
+ LMV_USER_MAGIC_SPECIFIC));
return -ENOMEM;
}
goto again;
static int cb_migrate_mdt_init(char *path, DIR *parent, DIR **dirp,
void *param_data, struct dirent64 *de)
{
- struct find_param *param = (struct find_param *)param_data;
- DIR *tmp_parent = parent;
- char raw[MAX_IOC_BUFLEN] = {'\0'};
- char *rawbuf = raw;
- struct obd_ioctl_data data = { 0 };
- int fd;
- int ret;
- char *path_copy;
- char *filename;
- bool retry = false;
+ struct find_param *param = (struct find_param *)param_data;
+ struct lmv_user_md *lmu = param->fp_lmv_md;
+ DIR *tmp_parent = parent;
+ char raw[MAX_IOC_BUFLEN] = {'\0'};
+ char *rawbuf = raw;
+ struct obd_ioctl_data data = { 0 };
+ int fd;
+ int ret;
+ char *path_copy;
+ char *filename;
+ bool retry = false;
if (parent == NULL && dirp == NULL)
return -EINVAL;
+ if (!lmu)
+ return -EINVAL;
+
if (dirp != NULL)
closedir(*dirp);
path_copy = strdup(path);
filename = basename(path_copy);
+
data.ioc_inlbuf1 = (char *)filename;
data.ioc_inllen1 = strlen(filename) + 1;
- data.ioc_inlbuf2 = (char *)¶m->fp_mdt_index;
- data.ioc_inllen2 = sizeof(param->fp_mdt_index);
+ data.ioc_inlbuf2 = (char *)lmu;
+ data.ioc_inllen2 = lmv_user_md_size(lmu->lum_stripe_count,
+ lmu->lum_magic);
ret = llapi_ioctl_pack(&data, &rawbuf, sizeof(raw));
if (ret != 0) {
llapi_error(LLAPI_MSG_ERROR, ret,
path, strerror(-ret), ret);
goto out;
} else if (param->fp_verbose & VERBOSE_DETAIL) {
- fprintf(stdout, "migrate %s to MDT%d\n",
- path, param->fp_mdt_index);
+ fprintf(stdout, "migrate %s to MDT%d stripe count %d\n",
+ path, lmu->lum_stripe_offset, lmu->lum_stripe_count);
}
out: