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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.