From: Dave Chinner <david@fromorbit.com>
To: "Darrick J. Wong" <darrick.wong@oracle.com>
Cc: xfs@oss.sgi.com
Subject: Re: [PATCH 08/11] xfs_io: support reflinking and deduping file ranges
Date: Tue, 22 Sep 2015 12:17:55 +1000 [thread overview]
Message-ID: <20150922021755.GF19114@dastard> (raw)
In-Reply-To: <20150826003311.23973.64761.stgit@birch.djwong.org>
On Tue, Aug 25, 2015 at 05:33:11PM -0700, Darrick J. Wong wrote:
> +static int
> +dedupe_f(
> + int argc,
> + char **argv)
> +{
> + off64_t soffset, doffset;
> + long long count, total;
> + char s1[64], s2[64], ts[64];
Magic!
> + char *infile;
> + int Cflag, qflag, wflag, Wflag;
Urk. Variables that differ only by case!
> + struct xfs_ioctl_file_extent_same_args *args = NULL;
> + struct xfs_ioctl_file_extent_same_info *info;
verbosity--;
> + size_t fsblocksize, fssectsize;
> + struct timeval t1, t2;
> + int c, fd = -1;
> +
> + Cflag = qflag = wflag = Wflag = 0;
> + init_cvtnum(&fsblocksize, &fssectsize);
> +
> + while ((c = getopt(argc, argv, "CqwW")) != EOF) {
> + switch (c) {
> + case 'C':
> + Cflag = 1;
> + break;
> + case 'q':
> + qflag = 1;
> + break;
> + case 'w':
> + wflag = 1;
> + break;
> + case 'W':
> + Wflag = 1;
> + break;
> + default:
> + return command_usage(&dedupe_cmd);
> + }
> + }
> + if (optind != argc - 4)
> + return command_usage(&dedupe_cmd);
> + infile = argv[optind];
> + optind++;
> + soffset = cvtnum(fsblocksize, fssectsize, argv[optind]);
> + if (soffset < 0) {
> + printf(_("non-numeric src offset argument -- %s\n"), argv[optind]);
> + return 0;
> + }
> + optind++;
> + doffset = cvtnum(fsblocksize, fssectsize, argv[optind]);
> + if (doffset < 0) {
> + printf(_("non-numeric dest offset argument -- %s\n"), argv[optind]);
> + return 0;
> + }
> + optind++;
> + count = cvtnum(fsblocksize, fssectsize, argv[optind]);
> + if (count < 1) {
> + printf(_("non-positive length argument -- %s\n"), argv[optind]);
> + return 0;
> + }
> +
> + c = IO_READONLY;
> + fd = openfile(infile, NULL, c, 0);
> + if (fd < 0)
> + return 0;
> +
> + gettimeofday(&t1, NULL);
> + args = calloc(1, sizeof(struct xfs_ioctl_file_extent_same_args) +
> + sizeof(struct xfs_ioctl_file_extent_same_info));
> + if (!args)
> + goto done;
> + info = (struct xfs_ioctl_file_extent_same_info *)(args + 1);
> + args->logical_offset = soffset;
> + args->length = count;
> + args->dest_count = 1;
> + info->fd = file->fd;
> + info->logical_offset = doffset;
> + do {
> + c = ioctl(fd, XFS_IOC_FILE_EXTENT_SAME, args);
> + if (c)
> + break;
> + args->logical_offset += info->bytes_deduped;
> + info->logical_offset += info->bytes_deduped;
> + args->length -= info->bytes_deduped;
> + } while (c == 0 && info->status == 0 && info->bytes_deduped > 0);
What's "c"? it's actually a return value, and it's already been
handled if it's non zero. and there's nothing preventing
args->length from going negative.
> + if (c)
> + perror(_("dedupe ioctl"));
> + if (info->status < 0)
> + printf("dedupe: %s\n", _(strerror(-info->status)));
> + if (info->status == XFS_SAME_DATA_DIFFERS)
"same data differs"? Really? :P
> + printf(_("Extents did not match.\n"));
And putting hte error messages outside the loop is going to be hard
to maintain. I'd much prefer to see this written as:
while (args->length > 0) {
result = ioctl(fd, XFS_IOC_FILE_EXTENT_SAME, args);
if (result) {
perror("XFS_IOC_FILE_EXTENT_SAME");
goto done;
}
if (info->status != 0) {
printf("dedupe: %s\n", _(strerror(-info->status)));
if (info->status == XFS_SAME_DATA_DIFFERS)
printf(_("Extents did not match.\n"));
goto done;
}
if (info->bytes_deduped == 0)
break;
args->logical_offset += info->bytes_deduped;
info->logical_offset += info->bytes_deduped;
args->length -= info->bytes_deduped;
}
Actually, I'd really lik eto see this bit factored out into a
separate function, so there's clear separation between arg parsing,
the operation and post-op cleanup.
> + total = info->bytes_deduped;
> + c = 1;
> + if (Wflag)
> + fsync(file->fd);
> + if (wflag)
> + fdatasync(file->fd);
So these flags are just for syncing. This does not need to be a part
of this function, because the user can simply do:
xfs_io -c "dedupe ...." -c "fsync" ...
if an fsync or fdatasync is required after dedupe. So kill those
options.
> + if (qflag)
> + goto done;
Urk.
> + gettimeofday(&t2, NULL);
> + t2 = tsub(t2, t1);
> +
> + /* Finally, report back -- -C gives a parsable format */
> + timestr(&t2, ts, sizeof(ts), Cflag ? VERBOSE_FIXED_TIME : 0);
> + if (!Cflag) {
> + cvtstr((double)total, s1, sizeof(s1));
> + cvtstr(tdiv((double)total, t2), s2, sizeof(s2));
> + printf(_("linked %lld/%lld bytes at offset %lld\n"),
> + total, count, (long long)doffset);
> + printf(_("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n"),
> + s1, c, ts, s2, tdiv((double)c, t2));
> + } else {/* bytes,ops,time,bytes/sec,ops/sec */
> + printf("%lld,%d,%s,%.3f,%.3f\n",
> + total, c, ts,
> + tdiv((double)total, t2), tdiv((double)c, t2));
> + }
This must be common with other timing code. Factor it out?
> +static void
> +reflink_help(void)
> +{
> + printf(_(
> +"\n"
> +" Links a range of bytes (in block size increments) from a file into a range \n"
> +" of bytes in the open file. The two extent ranges need not contain identical\n"
> +" data. \n"
> +"\n"
> +" Example:\n"
> +" 'reflink some_file 0 4096 32768' - links 32768 bytes from some_file at \n"
> +" offset 0 to into the open file at \n"
> +" position 4096\n"
> +" 'reflink some_file' - links all bytes from some_file into the open file\n"
> +" at position 0\n"
> +"\n"
> +" Reflink a range of blocks from a given input file to the open file. Both\n"
> +" files share the same range of physical disk blocks; a write to the shared\n"
> +" range of either file should result in the write landing in a new block and\n"
> +" that range of the file being remapped (i.e. copy-on-write). Both files\n"
> +" must reside on the same filesystem.\n"
> +" -w -- call fdatasync(2) at the end (included in timing results)\n"
> +" -W -- call fsync(2) at the end (included in timing results)\n"
> +"\n"));
> +}
FWIW, could these just be a single string like:
"
Links a range of bytes (in block size increments) from a file into a range
of bytes in the open file. The two extent ranges need not contain identical
....
\n"));
So we don't have to mangle the entire layout if we modify the help
tet in future?
> +static int
> +reflink_f(
> + int argc,
> + char **argv)
> +{
Same comments as the dedupe_f() function about factoring and
variable names and reusing "c" for a bunch of unrelated values.
indeed, most of this is common with the dedupe_f function, so
perhaps it might be worth putting them in the same file and
factoring them appropriately to shared common elements?
> diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h
> index 89689c6..0c922ad 100644
> --- a/libxfs/xfs_fs.h
> +++ b/libxfs/xfs_fs.h
> @@ -559,6 +559,42 @@ typedef struct xfs_swapext
> #define XFS_IOC_GOINGDOWN _IOR ('X', 125, __uint32_t)
> /* XFS_IOC_GETFSUUID ---------- deprecated 140 */
>
> +/* reflink ioctls; these MUST match the btrfs ioctl definitions */
> +struct xfs_ioctl_clone_range_args {
> + __s64 src_fd;
> + __u64 src_offset;
> + __u64 src_length;
> + __u64 dest_offset;
> +};
struct xfs_clone_args
> +
> +#define XFS_SAME_DATA_DIFFERS 1
#define XFS_EXTENT_DATA_SAME 0
#define XFS_EXTENT_DATA_DIFFERS 1
> +/* For extent-same ioctl */
> +struct xfs_ioctl_file_extent_same_info {
> + __s64 fd; /* in - destination file */
> + __u64 logical_offset; /* in - start of extent in destination */
> + __u64 bytes_deduped; /* out - total # of bytes we were able
> + * to dedupe from this file */
> + /* status of this dedupe operation:
> + * 0 if dedup succeeds
> + * < 0 for error
> + * == XFS_SAME_DATA_DIFFERS if data differs
> + */
> + __s32 status; /* out - see above description */
> + __u32 reserved;
> +};
struct xfs_extent_data_info
> +
> +struct xfs_ioctl_file_extent_same_args {
> + __u64 logical_offset; /* in - start of extent in source */
> + __u64 length; /* in - length of extent */
> + __u16 dest_count; /* in - total elements in info array */
> + __u16 reserved1;
> + __u32 reserved2;
> + struct xfs_ioctl_file_extent_same_info info[0];
> +};
struct xfs_extent_data
> +
> +#define XFS_IOC_CLONE _IOW (0x94, 9, int)
> +#define XFS_IOC_CLONE_RANGE _IOW (0x94, 13, struct xfs_ioctl_clone_range_args)
> +#define XFS_IOC_FILE_EXTENT_SAME _IOWR(0x94, 54, struct xfs_ioctl_file_extent_same_args)
FWIW, these structure and ioctl definitions really need to be in a
separate patch as they need to be shared with the kernel code.
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next prev parent reply other threads:[~2015-09-22 2:21 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-26 0:32 [PATCH v3 00/11] xfsprogs fuzzing fixes Darrick J. Wong
2015-08-26 0:32 ` [PATCH 01/11] xfs_repair: set args.geo in dir2_kill_block Darrick J. Wong
2015-08-26 0:32 ` [PATCH 02/11] libxfs: verifier should set buffer error when da block has a bad magic number Darrick J. Wong
2015-08-26 0:32 ` [PATCH 03/11] libxfs: fix XFS_WANT_CORRUPTED_* macros to return negative error codes Darrick J. Wong
2015-08-26 0:32 ` [PATCH 04/11] libxfs: clear buffer state flags in libxfs_getbuf and variants Darrick J. Wong
2015-08-26 1:02 ` Dave Chinner
2015-08-26 4:05 ` Darrick J. Wong
2015-08-26 5:23 ` [PATCH v2 " Darrick J. Wong
2015-08-26 0:32 ` [PATCH 05/11] xfs_repair: ignore "repaired" flag after we decide to clear xattr block Darrick J. Wong
2015-08-26 0:32 ` [PATCH 06/11] xfs_repair: check v5 filesystem attr block header sanity Darrick J. Wong
2015-08-26 0:45 ` Dave Chinner
2015-08-26 0:59 ` Darrick J. Wong
2015-08-26 1:15 ` Dave Chinner
2015-08-26 4:50 ` Darrick J. Wong
2015-08-26 6:20 ` Dave Chinner
2015-08-26 0:33 ` [PATCH 07/11] xfs_repair: force not-so-bad bmbt blocks back through the verifier Darrick J. Wong
2015-08-26 0:54 ` Dave Chinner
2015-08-26 3:59 ` Darrick J. Wong
2015-08-26 5:24 ` [PATCH v2 " Darrick J. Wong
2015-08-26 0:33 ` [PATCH 08/11] xfs_io: support reflinking and deduping file ranges Darrick J. Wong
2015-09-22 2:17 ` Dave Chinner [this message]
2015-09-28 17:03 ` Darrick J. Wong
2015-08-26 0:33 ` [PATCH 09/11] xfs_db: enable blocktrash for checksummed filesystems Darrick J. Wong
2015-08-26 0:33 ` [PATCH 10/11] xfs_db: trash the block at the top of the cursor stack Darrick J. Wong
2015-08-26 0:33 ` [PATCH 11/11] xfs_db: enable blockget for v5 filesystems Darrick J. Wong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150922021755.GF19114@dastard \
--to=david@fromorbit.com \
--cc=darrick.wong@oracle.com \
--cc=xfs@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox