Rename "lfs mirror dump" command to "lfs mirror read".
Add "lfs mirror write" command to write a mirror's content of a
mirrored file.
Usage:
lfs mirror write {--mirror-id|-N <mirror_id>}
[--inputfile|-i <input_file>] <mirrored_file>
Options:
--mirror-id|-N <mirror_id>
This option indicates the content of which mirror specified by
mirror_id needs to be written. The mirror_id is the numerical unique
identifier for a mirror.
--inputfile|-i <input_file>
The path name of the input file, if not specified, the standard
input stream will be used. The input stream or input_file cannot
be the same mirrored file as the mirrored_file.
This command will issue a RESYNC lease write lock to notify MDS to
prepare destination mirror for the write (instantiate components of
the mirror), then client copy data from a file or STDIN to the
specified mirror of the mirrored file. After the data copy, a
RESYNC_DONE lease unlock is issued to MDS to update the layout
of the mirrored file.
Signed-off-by: Bobi Jam <bobijam@whamcloud.com>
Change-Id: I02022349d4ce871319903a8714ffc4534186c0e4
Reviewed-on: https://review.whamcloud.com/33219
Tested-by: Jenkins
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Jian Yu <yujian@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
-.TH LFS-MIRROR-DUMP 1 2018-08-16 "Lustre" "Lustre Utilities"
+.TH LFS-MIRROR-READ 1 2018-08-16 "Lustre" "Lustre Utilities"
.SH NAME
-lfs mirror dump \- dump a mirror's content of a mirrored file
+lfs mirror read \- read a mirror's content of a mirrored file
.SH SYNOPSIS
-.B lfs mirror dump
-<\fB\-\-mirror-id|\-N\fR <\fImirror_id\fR>>
+.B lfs mirror read
+{\fB\-\-mirror-id|\-N\fR <\fImirror_id\fR>}
[\fB\-\-outfile|\-o\fR <\fIoutput_file\fR>]
<\fImirrored_file\fR>
.SH DESCRIPTION
-This command dumps the content of a file's mirror, the file is specified by the
+This command reads the content of a file's mirror, the file is specified by the
path name \fImirrored_file\fR, the mirror is specified by its mirror ID
\fImirror_id\fR.
.br
.TP
.BR \-\-mirror-id|\-N\fR\ <\fImirror_id\fR>
This option indicates the content of which mirror specified by \fImirror_id\fR
-needs to be dumped. The \fImirror_id\fR is the numerical unique identifier for
+needs to be read. The \fImirror_id\fR is the numerical unique identifier for
a mirror.
.TP
.BR \-\-outfile|\-o\fR\ <\fIoutput_file\fR>
will be used.
.SH EXAMPLES
.TP
-.B lfs mirror dump --mirror-id 3 /mnt/lustre/file1
+.B lfs mirror read --mirror-id 3 /mnt/lustre/file1
Dump the content of mirror with mirror ID 3 for /mnt/lustre/file1 to STDOUT.
.TP
-.B lfs mirror dump -N 2 -o /tmp/m2 /mnt/lustre/file1
+.B lfs mirror read -N 2 -o /tmp/m2 /mnt/lustre/file1
Dump the content of mirror with mirror ID 2 for /mnt/lustre/file1 to file
/tmp/m2.
.SH AUTHOR
-The \fBlfs mirror dump\fR command is part of the Lustre filesystem.
+The \fBlfs mirror read\fR command is part of the Lustre filesystem.
.SH SEE ALSO
.BR lfs (1),
.BR lfs-setstripe (1),
.BR lfs-mirror-extend (1),
.BR lfs-mirror-split (1),
.BR lfs-mirror-verify (1)
+.BR lfs-mirror-write (1)
--- /dev/null
+.TH LFS-MIRROR-WRITE 1 2018-09-23 "Lustre" "Lustre Utilities"
+.SH NAME
+lfs mirror write \- write a mirror's content of a mirrored file
+.SH SYNOPSIS
+.B lfs mirror write
+{\fB\-\-mirror-id|\-N\fR <\fImirror_id\fR>}
+[\fB\-\-inputfile|\-i\fR <\fIinput_file\fR>]
+<\fImirrored_file\fR>
+.SH DESCRIPTION
+This command writes the content of a file's mirror, the file is specified by the
+path name \fImirrored_file\fR, the mirror is specified by its mirror ID
+\fImirror_id\fR.
+.SH OPTIONS
+.TP
+.BR \-\-mirror-id|\-N\fR\ <\fImirror_id\fR>
+This option indicates the content of which mirror specified by \fImirror_id\fR
+needs to be written. The \fImirror_id\fR is the numerical unique identifier for
+a mirror.
+.TP
+.BR \-\-inputfile|\-i\fR\ <\fIinput_file\fR>
+The path name of the input file, if not specified, the standard input stream
+will be used. The input stream or input_file cannot be the same mirrored file
+as the \fImirrored_file\fR.
+.SH EXAMPLES
+.TP
+.B lfs mirror write --mirror-id 3 /mnt/lustre/file1 < /tmp/m2
+Write the content of /mnt/m2 to the mirror with miro ID 3 for
+/mnt/lustre/file1.
+.TP
+.B lfs mirror write -N2 -i /tmp/m2 /mnt/lustre/file1
+Write the content of /mnt/m2 to the mirror with mirror ID 2 for
+/mnt/lustre/file1.
+.SH AUTHOR
+The \fBlfs mirror write\fR command is part of the Lustre filesystem.
+.SH SEE ALSO
+.BR lfs (1),
+.BR lfs-setstripe (1),
+.BR lfs-getstripe (1),
+.BR lfs-mirror-create (1),
+.BR lfs-mirror-extend (1),
+.BR lfs-mirror-split (1),
+.BR lfs-mirror-verify (1),
+.BR lfs-mirror-read (1)
*/
struct md_layout_change {
enum md_layout_opc mlc_opc;
+ __u16 mlc_mirror_id;
struct layout_intent *mlc_intent;
struct lu_buf mlc_buf;
struct lustre_som_attrs mlc_som;
__u32 rs_padding6; /* rr_flags */
__u32 rs_padding7; /* rr_flags_h */
__u32 rs_padding8; /* rr_umask */
- __u32 rs_padding9; /* rr_padding_4 */
+ __u16 rs_mirror_id;
+ __u16 rs_padding9; /* rr_padding_4 */
};
/*
__u32 rr_flags;
__u32 rr_flags_h;
__u32 rr_umask;
- __u32 rr_padding_4; /* also fix lustre_swab_mdt_rec_reint */
+ __u16 rr_mirror_id;
+ __u16 rr_padding_4; /* also fix lustre_swab_mdt_rec_reint */
};
/* lmv structures */
__u32 lil_ids[0];
};
+struct ll_ioc_lease_id {
+ __u32 lil_mode;
+ __u32 lil_flags;
+ __u32 lil_count;
+ __u16 lil_mirror_id;
+ __u16 lil_padding1;
+ __u64 lil_padding2;
+ __u32 lil_ids[0];
+};
+
/*
* The ioctl naming rules:
* LL_* - works on the currently opened filehandle instead of parent dir
* After lease is taken, send the RPC MDS_REINT_RESYNC to the MDT
*/
static int ll_lease_file_resync(struct obd_client_handle *och,
- struct inode *inode)
+ struct inode *inode, unsigned long arg)
{
struct ll_sb_info *sbi = ll_i2sbi(inode);
struct md_op_data *op_data;
+ struct ll_ioc_lease_id ioc;
__u64 data_version_unused;
int rc;
ENTRY;
if (IS_ERR(op_data))
RETURN(PTR_ERR(op_data));
+ if (copy_from_user(&ioc, (struct ll_ioc_lease_id __user *)arg,
+ sizeof(ioc)))
+ RETURN(-EFAULT);
+
/* before starting file resync, it's necessary to clean up page cache
* in client memory, otherwise once the layout version is increased,
* writing back cached data will be denied the OSTs. */
GOTO(out, rc);
op_data->op_lease_handle = och->och_lease_handle;
+ op_data->op_mirror_id = ioc.lil_mirror_id;
rc = md_file_resync(sbi->ll_md_exp, op_data);
if (rc)
GOTO(out, rc);
RETURN(PTR_ERR(och));
if (ioc->lil_flags & LL_LEASE_RESYNC) {
- rc = ll_lease_file_resync(och, inode);
+ rc = ll_lease_file_resync(och, inode, arg);
if (rc) {
ll_lease_close(och, inode, NULL);
RETURN(rc);
RETURN(picked);
}
+static int lod_prepare_resync_mirror(const struct lu_env *env,
+ struct lod_object *lo,
+ __u16 mirror_id)
+{
+ struct lod_thread_info *info = lod_env_info(env);
+ struct lod_layout_component *lod_comp;
+ int i;
+
+ for (i = 0; i < lo->ldo_mirror_count; i++) {
+ if (lo->ldo_mirrors[i].lme_id != mirror_id)
+ continue;
+
+ lod_foreach_mirror_comp(lod_comp, lo, i) {
+ if (lod_comp_inited(lod_comp))
+ continue;
+
+ info->lti_comp_idx[info->lti_count++] =
+ lod_comp_index(lo, lod_comp);
+ }
+ }
+
+ return 0;
+}
+
/**
* figure out the components should be instantiated for resync.
*/
* prep uninited all components assuming any non-stale mirror
* could be picked as the primary mirror.
*/
- for (i = 0; i < lo->ldo_mirror_count; i++) {
- if (lo->ldo_mirrors[i].lme_stale)
- continue;
+ if (mlc->mlc_mirror_id == 0) {
+ /* normal resync */
+ for (i = 0; i < lo->ldo_mirror_count; i++) {
+ if (lo->ldo_mirrors[i].lme_stale)
+ continue;
- lod_foreach_mirror_comp(lod_comp, lo, i) {
- if (!lod_comp_inited(lod_comp))
- break;
+ lod_foreach_mirror_comp(lod_comp, lo, i) {
+ if (!lod_comp_inited(lod_comp))
+ break;
- if (extent.e_end < lod_comp->llc_extent.e_end)
- extent.e_end =
- lod_comp->llc_extent.e_end;
+ if (extent.e_end <
+ lod_comp->llc_extent.e_end)
+ extent.e_end =
+ lod_comp->llc_extent.e_end;
+ }
}
+ rc = lod_prepare_resync(env, lo, &extent);
+ if (rc)
+ GOTO(out, rc);
+ } else {
+ /* mirror write, try to init its all components */
+ rc = lod_prepare_resync_mirror(env, lo,
+ mlc->mlc_mirror_id);
+ if (rc)
+ GOTO(out, rc);
}
- rc = lod_prepare_resync(env, lo, &extent);
- if (rc)
- GOTO(out, rc);
/* change the file state to SYNC_PENDING */
lo->ldo_flr_state = LCM_FL_SYNC_PENDING;
}
lod_comp_index(lo, lod_comp);
}
} else { /* MD_LAYOUT_RESYNC */
- lod_foreach_mirror_comp(lod_comp, lo, primary) {
- if (!lod_comp_inited(lod_comp))
- break;
+ if (mlc->mlc_mirror_id == 0) {
+ /* normal resync */
+ lod_foreach_mirror_comp(lod_comp, lo, primary) {
+ if (!lod_comp_inited(lod_comp))
+ break;
- extent.e_end = lod_comp->llc_extent.e_end;
+ extent.e_end = lod_comp->llc_extent.e_end;
+ }
+
+ rc = lod_prepare_resync(env, lo, &extent);
+ if (rc)
+ GOTO(out, rc);
+ } else {
+ /* mirror write, try to init its all components */
+ rc = lod_prepare_resync_mirror(env, lo,
+ mlc->mlc_mirror_id);
+ if (rc)
+ GOTO(out, rc);
}
- rc = lod_prepare_resync(env, lo, &extent);
- if (rc)
- GOTO(out, rc);
/* change the file state to SYNC_PENDING */
lo->ldo_flr_state = LCM_FL_SYNC_PENDING;
}
rec->rs_cap = op_data->op_cap;
rec->rs_fid = op_data->op_fid1;
rec->rs_bias = op_data->op_bias;
+ rec->rs_mirror_id = op_data->op_mirror_id;
lock = ldlm_handle2lock(&op_data->op_lease_handle);
if (lock != NULL) {
void *rr_eadata;
int rr_eadatalen;
__u32 rr_flags;
+ __u16 rr_mirror_id;
};
enum mdt_reint_flag {
uc->uc_cap = rec->rs_cap;
rr->rr_fid1 = &rec->rs_fid;
+ rr->rr_mirror_id = rec->rs_mirror_id;
/* cookie doesn't need to be swapped but it has been swapped
* in lustre_swab_mdt_rec_reint() as rr_mtime, so here it needs
struct mdt_object *mo;
struct ldlm_lock *lease;
struct mdt_body *repbody;
- struct md_layout_change layout = { 0 };
+ struct md_layout_change layout = { .mlc_mirror_id = rr->rr_mirror_id };
bool lease_broken;
int rc, rc2;
ENTRY;
__swab32s(&rr->rr_flags);
__swab32s(&rr->rr_flags_h);
__swab32s(&rr->rr_umask);
+ __swab16s(&rr->rr_mirror_id);
CLASSERT(offsetof(typeof(*rr), rr_padding_4) != 0);
};
(long long)(int)offsetof(struct mdt_rec_resync, rs_padding8));
LASSERTF((int)sizeof(((struct mdt_rec_resync *)0)->rs_padding8) == 4, "found %lld\n",
(long long)(int)sizeof(((struct mdt_rec_resync *)0)->rs_padding8));
- LASSERTF((int)offsetof(struct mdt_rec_resync, rs_padding9) == 132, "found %lld\n",
+ LASSERTF((int)offsetof(struct mdt_rec_resync, rs_mirror_id) == 132, "found %lld\n",
+ (long long)(int)offsetof(struct mdt_rec_resync, rs_mirror_id));
+ LASSERTF((int)sizeof(((struct mdt_rec_resync *)0)->rs_mirror_id) == 2, "found %lld\n",
+ (long long)(int)sizeof(((struct mdt_rec_resync *)0)->rs_mirror_id));
+ LASSERTF((int)offsetof(struct mdt_rec_resync, rs_padding9) == 134, "found %lld\n",
(long long)(int)offsetof(struct mdt_rec_resync, rs_padding9));
- LASSERTF((int)sizeof(((struct mdt_rec_resync *)0)->rs_padding9) == 4, "found %lld\n",
+ LASSERTF((int)sizeof(((struct mdt_rec_resync *)0)->rs_padding9) == 2, "found %lld\n",
(long long)(int)sizeof(((struct mdt_rec_resync *)0)->rs_padding9));
/* Checks for struct mdt_rec_reint */
(long long)(int)offsetof(struct mdt_rec_reint, rr_umask));
LASSERTF((int)sizeof(((struct mdt_rec_reint *)0)->rr_umask) == 4, "found %lld\n",
(long long)(int)sizeof(((struct mdt_rec_reint *)0)->rr_umask));
- LASSERTF((int)offsetof(struct mdt_rec_reint, rr_padding_4) == 132, "found %lld\n",
+ LASSERTF((int)offsetof(struct mdt_rec_reint, rr_mirror_id) == 132, "found %lld\n",
+ (long long)(int)offsetof(struct mdt_rec_reint, rr_mirror_id));
+ LASSERTF((int)sizeof(((struct mdt_rec_reint *)0)->rr_mirror_id) == 2, "found %lld\n",
+ (long long)(int)sizeof(((struct mdt_rec_reint *)0)->rr_mirror_id));
+ LASSERTF((int)offsetof(struct mdt_rec_reint, rr_padding_4) == 134, "found %lld\n",
(long long)(int)offsetof(struct mdt_rec_reint, rr_padding_4));
- LASSERTF((int)sizeof(((struct mdt_rec_reint *)0)->rr_padding_4) == 4, "found %lld\n",
+ LASSERTF((int)sizeof(((struct mdt_rec_reint *)0)->rr_padding_4) == 2, "found %lld\n",
(long long)(int)sizeof(((struct mdt_rec_reint *)0)->rr_padding_4));
/* Checks for struct lmv_desc */
local tf=$DIR/$tfile
local tf2=$DIR/$tfile-2
local tf3=$DIR/$tfile-3
+ local tf4=$DIR/$tfile-4
create_files_37 $((RANDOM + 15 * 1048576)) $tf $tf2 $tf3
+ rm -f $tf4
+ cp $tf $tf4
# assume the mirror id will be 1, 2, and 3
declare -A checksums
local sum
for i in ${mirror_array[@]}; do
- sum=$($LFS mirror dump -N $i $tf | md5sum)
+ $LCTL set_param ldlm.namespaces.*.lru_size=clear > /dev/null
+ sum=$($LFS mirror read -N $i $tf | md5sum)
[ "$sum" = "${checksums[$i]}" ] ||
error "$i: mismatch: \'${checksums[$i]}\' vs. \'$sum\'"
done
+ # verify mirror write
+ echo "Verifying mirror write .."
+ $LFS mirror write -N2 $tf < $tf4
+
+ sum=$($LFS mirror read -N2 $tf | md5sum)
+ [[ "$sum" = "${checksums[1]}" ]] ||
+ error "2: mismatch \'${checksums[1]}\' vs. \'$sum\'"
+
# verify mirror copy, write to this mirrored file will invalidate
# the other two mirrors
echo "Verifying mirror copy .."
# verify copying is successful by checking checksums
remount_client $MOUNT
for i in ${mirror_array[@]}; do
- sum=$($LFS mirror dump -N $i $tf | md5sum)
+ sum=$($LFS mirror read -N $i $tf | md5sum)
[ "$sum" = "${checksums[1]}" ] ||
error "$i: mismatch checksum after copy"
done
local valid_mirror stale_mirror id mirror_cksum
for id in "${mirror_array[@]}"; do
- mirror_cksum=$($LFS mirror dump -N $id $tf | md5sum)
+ mirror_cksum=$($LFS mirror read -N $id $tf | md5sum)
[ "$ref_cksum" == "$mirror_cksum" ] &&
{ valid_mirror=$id; continue; }
mirror_io resync $tf || error "resync failed"
verify_flr_state $tf "ro"
- mirror_cksum=$($LFS mirror dump -N $stale_mirror $tf | md5sum)
+ mirror_cksum=$($LFS mirror read -N $stale_mirror $tf | md5sum)
[ "$file_cksum" = "$ref_cksum" ] || error "resync failed"
# case 2: inject an error to make mirror_io exit after changing
echo " **verify $tf-1 data consistency in all mirrors"
for i in 1 2 3; do
- local sum=$($LFS mirror dump -N$i $tf-1 | md5sum)
+ local sum=$($LFS mirror read -N$i $tf-1 | md5sum)
[[ "$sum" = "$sum0" ]] ||
error "$tf-1.$i: checksum mismatch: $sum != $sum0"
done
verify_flr_state $tf "wp"
verify_comp_attr lcme_flags $tf 0x20003 nosync,stale
- local sum1=$($LFS mirror dump -N1 $tf | md5sum)
- local sum2=$($LFS mirror dump -N2 $tf | md5sum)
+ local sum1=$($LFS mirror read -N1 $tf | md5sum)
+ local sum2=$($LFS mirror read -N2 $tf | md5sum)
echo " ** verify mirror 2 doesn't change"
echo "original checksum: $sum0"
verify_flr_state $tf "ro"
verify_comp_attr lcme_flags $tf 0x20003 nosync,^stale
- sum1=$($LFS mirror dump -N1 $tf | md5sum)
- sum2=$($LFS mirror dump -N2 $tf | md5sum)
+ sum1=$($LFS mirror read -N1 $tf | md5sum)
+ sum2=$($LFS mirror read -N2 $tf | md5sum)
echo " ** verify mirror 2 resync-ed"
echo "original checksum: $sum0"
mirror_io resync $tf
get_mirror_ids $tf
- local csum=$($LFS mirror dump -N ${mirror_array[0]} $tf | md5sum)
+ local csum=$($LFS mirror read -N ${mirror_array[0]} $tf | md5sum)
for id in ${mirror_array[@]:1}; do
- [ "$($LFS mirror dump -N $id $tf | md5sum)" = "$csum" ] ||
+ [ "$($LFS mirror read -N $id $tf | md5sum)" = "$csum" ] ||
error "checksum error for mirror $id"
done
static int lfs_list_commands(int argc, char **argv);
static inline int lfs_mirror_resync(int argc, char **argv);
static inline int lfs_mirror_verify(int argc, char **argv);
-static inline int lfs_mirror_dump(int argc, char **argv);
+static inline int lfs_mirror_read(int argc, char **argv);
+static inline int lfs_mirror_write(int argc, char **argv);
enum setstripe_origin {
SO_SETSTRIPE,
"\t mirror will be stored into. If not specified,\n"
"\t a new file named <mirrored_file>.mirror~<mirror_id>\n"
"\t will be used.\n" },
- { .pc_name = "dump", .pc_func = lfs_mirror_dump,
- .pc_help = "Dump the content of a specified mirror of a file.\n"
- "usage: lfs mirror dump <--mirror-id|-N <mirror_id> "
- "[--outfile|-o <output_file>] <mirrored_file>\n" },
+ { .pc_name = "read", .pc_func = lfs_mirror_read,
+ .pc_help = "Read the content of a specified mirror of a file.\n"
+ "usage: lfs mirror read <--mirror-id|-N <mirror_id> "
+ "[--outfile|-o <output_file>] <mirrored_file>\n" },
+ { .pc_name = "write", .pc_func = lfs_mirror_write,
+ .pc_help = "Write to a specified mirror of a file.\n"
+ "usage: lfs mirror write <--mirror-id|-N <mirror_id> "
+ "[--inputfile|-i <input_file>] <mirrored_file>\n" },
{ .pc_name = "resync", .pc_func = lfs_mirror_resync,
.pc_help = "Resynchronizes out-of-sync mirrored file(s).\n"
"usage: lfs mirror resync [--only <mirror_id[,...]>] "
"usage: lfs mirror verify "
"[--only <mirror_id,mirror_id2[,...]>] "
"[--verbose|-v] <mirrored_file> [<mirrored_file2> ...]\n"},
- { .pc_name = "--list-commands", .pc_func = lfs_mirror_list_commands,
+ { .pc_name = "list-commands", .pc_func = lfs_mirror_list_commands,
.pc_help = "list commands supported by lfs mirror"},
{ .pc_name = "help", .pc_func = Parser_help, .pc_help = "help" },
{ .pc_name = "exit", .pc_func = Parser_quit, .pc_help = "quit" },
"lfs mirror extend - add mirror(s) to an existing file\n"
"lfs mirror split - split a mirror from an existing mirrored file\n"
"lfs mirror resync - resynchronize out-of-sync mirrored file(s)\n"
- "lfs mirror dump - dump a mirror content of a mirrored file\n"
+ "lfs mirror read - read a mirror content of a mirrored file\n"
+ "lfs mirror write - write to a mirror of a mirrored file\n"
"lfs mirror verify - verify mirrored file(s)\n"},
{"getsom", lfs_getsom, 0, "To list the SOM info for a given file.\n"
"usage: getsom [-s] [-b] [-f] <path>\n"
/* ignore previous file's error, continue with next file */
/* reset ioc */
- memset(ioc, 0, sizeof(__u32) * 4096);
+ memset(ioc, 0, sizeof(*ioc) + sizeof(__u32) * 4096);
}
free(ioc);
return rc;
}
-static inline int lfs_mirror_dump(int argc, char **argv)
+static inline int verify_mirror_id_by_fd(int fd, __u16 mirror_id)
+{
+ struct llapi_layout *layout;
+ int rc;
+
+ layout = llapi_layout_get_by_fd(fd, 0);
+ if (layout == NULL) {
+ fprintf(stderr, "could not get layout.\n");
+ return -EINVAL;
+ }
+
+ rc = llapi_layout_comp_iterate(layout, find_mirror_id, &mirror_id);
+ if (rc < 0) {
+ fprintf(stderr, "failed to iterate layout\n");
+ llapi_layout_free(layout);
+
+ return rc;
+ } else if (rc == LLAPI_LAYOUT_ITER_CONT) {
+ fprintf(stderr, "does not find mirror with ID %u\n", mirror_id);
+ llapi_layout_free(layout);
+
+ return -EINVAL;
+ }
+ llapi_layout_free(layout);
+
+ return 0;
+}
+
+/**
+ * Check whether two files are the same file
+ * \retval 0 same file
+ * \retval 1 not the same file
+ * \retval <0 error code
+ */
+static inline int check_same_file(const char *f1, const char *f2)
+{
+ struct stat stbuf1;
+ struct stat stbuf2;
+
+ if (stat(f1, &stbuf1) < 0) {
+ fprintf(stderr, "%s: cannot stat file '%s': %s\n",
+ progname, f1, strerror(errno));
+ return -errno;
+ }
+
+ if (stat(f2, &stbuf2) < 0) {
+ fprintf(stderr, "%s: cannot stat file '%s': %s\n",
+ progname, f2, strerror(errno));
+ return -errno;
+ }
+
+ if (stbuf1.st_rdev == stbuf2.st_rdev &&
+ stbuf1.st_ino == stbuf2.st_ino)
+ return 0;
+
+ return 1;
+}
+
+static inline int lfs_mirror_read(int argc, char **argv)
{
int rc = CMD_HELP;
__u16 mirror_id = 0;
const char *outfile = NULL;
char *fname;
- struct stat stbuf;
int fd = 0;
- struct llapi_layout *layout;
int outfd;
int c;
- const size_t buflen = 4 << 20;
void *buf;
+ const size_t buflen = 4 << 20;
off_t pos;
-
struct option long_opts[] = {
{ .val = 'N', .name = "mirror-id", .has_arg = required_argument },
{ .val = 'o', .name = "outfile", .has_arg = required_argument },
case 'o':
outfile = optarg;
break;
+ default:
+ fprintf(stderr, "%s: option '%s' unrecognized.\n",
+ progname, argv[optind - 1]);
+ return -EINVAL;
}
}
/* open mirror file */
fname = argv[optind];
- if (stat(fname, &stbuf) < 0) {
- fprintf(stderr, "%s %s: cannot stat file '%s': %s.\n",
- progname, argv[0], fname, strerror(errno));
- return rc;
- }
-
- if (!S_ISREG(stbuf.st_mode)) {
- fprintf(stderr, "%s %s: '%s' is not a regular file.\n",
- progname, argv[0], fname);
- return rc;
+ if (outfile) {
+ rc = check_same_file(fname, outfile);
+ if (rc == 0) {
+ fprintf(stderr,
+ "%s %s: output file cannot be the mirrored file\n",
+ progname, argv[0]);
+ return -EINVAL;
+ }
+ if (rc < 0)
+ return rc;
}
fd = open(fname, O_DIRECT | O_RDONLY);
if (fd < 0) {
- fprintf(stderr, "%s %s: cannot open '%s': %s.\n",
+ fprintf(stderr, "%s %s: cannot open '%s': %s\n",
progname, argv[0], fname, strerror(errno));
return rc;
}
/* verify mirror id */
- layout = llapi_layout_get_by_fd(fd, 0);
- if (layout == NULL) {
- fprintf(stderr, "%s %s: could not get layout of file '%s'.\n",
- progname, argv[0], fname);
- rc = -EINVAL;
- goto close_fd;
- }
-
- rc = llapi_layout_comp_iterate(layout, find_mirror_id, &mirror_id);
- if (rc < 0) {
- fprintf(stderr, "%s %s: failed to iterate layout of '%s'.\n",
- progname, argv[0], fname);
- llapi_layout_free(layout);
- goto close_fd;
- } else if (rc == LLAPI_LAYOUT_ITER_CONT) {
+ rc = verify_mirror_id_by_fd(fd, mirror_id);
+ if (rc) {
fprintf(stderr,
- "%s %s: file '%s' does not contain mirror with ID %u\n",
- progname, argv[0], fname, mirror_id);
- llapi_layout_free(layout);
-
- rc = -EINVAL;
+ "%s %s: cannot find mirror with ID %u in '%s'\n",
+ progname, argv[0], mirror_id, fname);
goto close_fd;
}
- llapi_layout_free(layout);
/* open output file */
if (outfile) {
outfd = open(outfile, O_EXCL | O_WRONLY | O_CREAT, 0644);
if (outfd < 0) {
- fprintf(stderr, "%s %s: cannot create file '%s':%s.\n",
+ fprintf(stderr, "%s %s: cannot create file '%s': %s\n",
progname, argv[0], outfile, strerror(errno));
rc = -errno;
goto close_fd;
/* allocate buffer */
rc = posix_memalign(&buf, sysconf(_SC_PAGESIZE), buflen);
if (rc) {
- fprintf(stderr, "%s %s: posix_memalign returns %d.\n",
+ fprintf(stderr, "%s %s: posix_memalign returns %d\n",
progname, argv[0], rc);
goto close_outfd;
}
if (bytes_read < 0) {
rc = bytes_read;
fprintf(stderr,
- "%s %s: fail to read data from mirror %u:%s.\n",
+ "%s %s: fail to read data from mirror %u: %s\n",
progname, argv[0], mirror_id, strerror(-rc));
goto free_buf;
}
bytes_read - written);
if (written2 < 0) {
fprintf(stderr,
- "%s %s: fail to write %s:%s.\n",
+ "%s %s: fail to write %s: %s\n",
progname, argv[0], outfile ? : "STDOUT",
strerror(errno));
rc = -errno;
return rc;
}
+static inline int lfs_mirror_write(int argc, char **argv)
+{
+ int rc = CMD_HELP;
+ __u16 mirror_id = 0;
+ const char *inputfile = NULL;
+ char *fname;
+ int fd = 0;
+ int inputfd;
+ int c;
+ void *buf;
+ const size_t buflen = 4 << 20;
+ off_t pos;
+ size_t page_size = sysconf(_SC_PAGESIZE);
+ struct ll_ioc_lease_id ioc;
+
+ struct option long_opts[] = {
+ { .val = 'N', .name = "mirror-id", .has_arg = required_argument },
+ { .val = 'i', .name = "inputfile", .has_arg = required_argument },
+ { .name = NULL } };
+
+ while ((c = getopt_long(argc, argv, "N:i:", long_opts, NULL)) >= 0) {
+ char *end;
+
+ switch (c) {
+ case 'N':
+ mirror_id = strtoul(optarg, &end, 0);
+ if (*end != '\0' || mirror_id == 0) {
+ fprintf(stderr,
+ "%s %s: invalid mirror ID '%s'\n",
+ progname, argv[0], optarg);
+ return rc;
+ }
+ break;
+ case 'i':
+ inputfile = optarg;
+ break;
+ default:
+ fprintf(stderr, "%s: option '%s' unrecognized\n",
+ progname, argv[optind - 1]);
+ return -EINVAL;
+ }
+ }
+
+ if (argc == optind) {
+ fprintf(stderr, "%s %s: no mirrored file provided\n",
+ progname, argv[0]);
+ return rc;
+ } else if (argc > optind + 1) {
+ fprintf(stderr, "%s %s: too many files\n", progname, argv[0]);
+ return rc;
+ }
+
+ if (mirror_id == 0) {
+ fprintf(stderr, "%s %s: no valid mirror ID is provided\n",
+ progname, argv[0]);
+ return rc;
+ }
+
+ /* open mirror file */
+ fname = argv[optind];
+
+ if (inputfile) {
+ rc = check_same_file(fname, inputfile);
+ if (rc == 0) {
+ fprintf(stderr,
+ "%s %s: input file cannot be the mirrored file\n",
+ progname, argv[0]);
+ return -EINVAL;
+ }
+ if (rc < 0)
+ return rc;
+ }
+
+ fd = open(fname, O_DIRECT | O_WRONLY);
+ if (fd < 0) {
+ fprintf(stderr, "%s %s: cannot open '%s': %s\n",
+ progname, argv[0], fname, strerror(errno));
+ return rc;
+ }
+
+ /* verify mirror id */
+ rc = verify_mirror_id_by_fd(fd, mirror_id);
+ if (rc) {
+ fprintf(stderr,
+ "%s %s: cannot find mirror with ID %u in '%s'\n",
+ progname, argv[0], mirror_id, fname);
+ goto close_fd;
+ }
+
+ /* open input file */
+ if (inputfile) {
+ inputfd = open(inputfile, O_RDONLY, 0644);
+ if (inputfd < 0) {
+ fprintf(stderr, "%s %s: cannot open file '%s': %s\n",
+ progname, argv[0], inputfile, strerror(errno));
+ rc = -errno;
+ goto close_fd;
+ }
+ } else {
+ inputfd = STDIN_FILENO;
+ }
+
+ /* allocate buffer */
+ rc = posix_memalign(&buf, page_size, buflen);
+ if (rc) {
+ fprintf(stderr, "%s %s: posix_memalign returns %d\n",
+ progname, argv[0], rc);
+ goto close_inputfd;
+ }
+
+ /* prepare target mirror components instantiation */
+ ioc.lil_mode = LL_LEASE_WRLCK;
+ ioc.lil_flags = LL_LEASE_RESYNC;
+ ioc.lil_mirror_id = mirror_id;
+ rc = llapi_lease_set(fd, (struct ll_ioc_lease *)&ioc);
+ if (rc < 0) {
+ fprintf(stderr,
+ "%s %s: '%s' llapi_lease_get_ext failed: %s\n",
+ progname, argv[0], fname, strerror(errno));
+ goto free_buf;
+ }
+
+ pos = 0;
+ while (1) {
+ ssize_t bytes_read;
+ ssize_t written;
+ size_t to_write;
+
+ rc = llapi_lease_check(fd);
+ if (rc != LL_LEASE_WRLCK) {
+ fprintf(stderr, "%s %s: '%s' lost lease lock\n",
+ progname, argv[0], fname);
+ goto free_buf;
+ }
+
+ bytes_read = read(inputfd, buf, buflen);
+ if (bytes_read < 0) {
+ rc = bytes_read;
+ fprintf(stderr,
+ "%s %s: fail to read data from '%s': %s\n",
+ progname, argv[0], inputfile ? : "STDIN",
+ strerror(errno));
+ rc = -errno;
+ goto free_buf;
+ }
+
+ /* EOF reached */
+ if (bytes_read == 0)
+ break;
+
+ /* round up to page align to make direct IO happy. */
+ to_write = (bytes_read + page_size - 1) & ~(page_size - 1);
+
+ written = llapi_mirror_write(fd, mirror_id, buf, to_write,
+ pos);
+ if (written < 0) {
+ rc = written;
+ fprintf(stderr,
+ "%s %s: fail to write to mirror %u: %s\n",
+ progname, argv[0], mirror_id,
+ strerror(-rc));
+ goto free_buf;
+ }
+
+ pos += bytes_read;
+ }
+
+ if (pos & (page_size - 1)) {
+ rc = llapi_mirror_truncate(fd, mirror_id, pos);
+ if (rc < 0)
+ goto free_buf;
+ }
+
+ ioc.lil_mode = LL_LEASE_UNLCK;
+ ioc.lil_flags = LL_LEASE_RESYNC_DONE;
+ ioc.lil_count = 0;
+ rc = llapi_lease_set(fd, (struct ll_ioc_lease *)&ioc);
+ if (rc <= 0) {
+ if (rc == 0)
+ rc = -EBUSY;
+ fprintf(stderr,
+ "%s %s: release lease lock of '%s' failed: %s\n",
+ progname, argv[0], fname, strerror(errno));
+ goto free_buf;
+ }
+
+ rc = 0;
+
+free_buf:
+ free(buf);
+close_inputfd:
+ if (inputfile)
+ close(inputfd);
+close_fd:
+ close(fd);
+
+ return rc;
+}
+
/**
* struct verify_chunk - Mirror chunk to be verified.
* @chunk: [start, end) of the chunk.
verbose++;
break;
default:
- fprintf(stderr, "%s: options '%s' unrecognized.\n",
+ fprintf(stderr, "%s: option '%s' unrecognized.\n",
progname, argv[optind - 1]);
rc = -EINVAL;
goto error;
CHECK_MEMBER(mdt_rec_resync, rs_padding6);
CHECK_MEMBER(mdt_rec_resync, rs_padding7);
CHECK_MEMBER(mdt_rec_resync, rs_padding8);
+ CHECK_MEMBER(mdt_rec_resync, rs_mirror_id);
CHECK_MEMBER(mdt_rec_resync, rs_padding9);
}
CHECK_MEMBER(mdt_rec_reint, rr_flags);
CHECK_MEMBER(mdt_rec_reint, rr_flags_h);
CHECK_MEMBER(mdt_rec_reint, rr_umask);
+ CHECK_MEMBER(mdt_rec_reint, rr_mirror_id);
CHECK_MEMBER(mdt_rec_reint, rr_padding_4);
}
(long long)(int)offsetof(struct mdt_rec_resync, rs_padding8));
LASSERTF((int)sizeof(((struct mdt_rec_resync *)0)->rs_padding8) == 4, "found %lld\n",
(long long)(int)sizeof(((struct mdt_rec_resync *)0)->rs_padding8));
- LASSERTF((int)offsetof(struct mdt_rec_resync, rs_padding9) == 132, "found %lld\n",
+ LASSERTF((int)offsetof(struct mdt_rec_resync, rs_mirror_id) == 132, "found %lld\n",
+ (long long)(int)offsetof(struct mdt_rec_resync, rs_mirror_id));
+ LASSERTF((int)sizeof(((struct mdt_rec_resync *)0)->rs_mirror_id) == 2, "found %lld\n",
+ (long long)(int)sizeof(((struct mdt_rec_resync *)0)->rs_mirror_id));
+ LASSERTF((int)offsetof(struct mdt_rec_resync, rs_padding9) == 134, "found %lld\n",
(long long)(int)offsetof(struct mdt_rec_resync, rs_padding9));
- LASSERTF((int)sizeof(((struct mdt_rec_resync *)0)->rs_padding9) == 4, "found %lld\n",
+ LASSERTF((int)sizeof(((struct mdt_rec_resync *)0)->rs_padding9) == 2, "found %lld\n",
(long long)(int)sizeof(((struct mdt_rec_resync *)0)->rs_padding9));
/* Checks for struct mdt_rec_reint */
(long long)(int)offsetof(struct mdt_rec_reint, rr_umask));
LASSERTF((int)sizeof(((struct mdt_rec_reint *)0)->rr_umask) == 4, "found %lld\n",
(long long)(int)sizeof(((struct mdt_rec_reint *)0)->rr_umask));
- LASSERTF((int)offsetof(struct mdt_rec_reint, rr_padding_4) == 132, "found %lld\n",
+ LASSERTF((int)offsetof(struct mdt_rec_reint, rr_mirror_id) == 132, "found %lld\n",
+ (long long)(int)offsetof(struct mdt_rec_reint, rr_mirror_id));
+ LASSERTF((int)sizeof(((struct mdt_rec_reint *)0)->rr_mirror_id) == 2, "found %lld\n",
+ (long long)(int)sizeof(((struct mdt_rec_reint *)0)->rr_mirror_id));
+ LASSERTF((int)offsetof(struct mdt_rec_reint, rr_padding_4) == 134, "found %lld\n",
(long long)(int)offsetof(struct mdt_rec_reint, rr_padding_4));
- LASSERTF((int)sizeof(((struct mdt_rec_reint *)0)->rr_padding_4) == 4, "found %lld\n",
+ LASSERTF((int)sizeof(((struct mdt_rec_reint *)0)->rr_padding_4) == 2, "found %lld\n",
(long long)(int)sizeof(((struct mdt_rec_reint *)0)->rr_padding_4));
/* Checks for struct lmv_desc */