* [PATCH] fiemap: Implement ranged query
@ 2017-10-19 10:34 Nikolay Borisov
2017-10-25 7:00 ` Darrick J. Wong
0 siblings, 1 reply; 2+ messages in thread
From: Nikolay Borisov @ 2017-10-19 10:34 UTC (permalink / raw)
To: linux-xfs; +Cc: sandeen, Nikolay Borisov
Currently the fiemap implementation of xfs_io doesn't support making ranged
queries. This patch implements two optional arguments which take the starting
offset and the length of the region to be queried. The impelmentation also
calculates printed holes as an extent for the purpose of terminating the query.
I.e. if we create a file with the following layout :
xfs_io -f -c "falloc 0 32k" -c "fpunch 0 4k" -c "fpunch 8k 4k" \
-c "fpunch 28k 4k" -c "fiemap" fragmented-file
H D H D H
|--------|--------|---------|--------------|-----------------|
0 4k 8k 12k 28k 32k
Then the output is :
xfs_io -c "fiemap 0 10k" fragmented-file
fragmented-file:
0: [0..7]: hole
1: [8..15]: 897844104..897844111
2: [16..23]: hole
xfs_io -c "fiemap 0" fragmented-file
fragmented-file:
0: [0..7]: hole
1: [8..15]: 897844104..897844111
2: [16..23]: hole
3: [24..55]: 897844120..897844151
4: [56..63]: hole
xfs_io -c "fiemap 10k 5k" fragmented-file
fragmented-file:
0: [20..23]: hole
1: [24..55]: 897844120..897844151
xfs_io -c "fiemap 10k 18k" fragmented-file
fragmented-file:
0: [20..23]: hole
1: [24..55]: 897844120..897844151
2: [56..63]: hole
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
---
io/fiemap.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++---------
man/man8/xfs_io.8 | 5 +++--
2 files changed, 54 insertions(+), 12 deletions(-)
diff --git a/io/fiemap.c b/io/fiemap.c
index e6fd66da753d..844741cb07d3 100644
--- a/io/fiemap.c
+++ b/io/fiemap.c
@@ -27,6 +27,8 @@
static cmdinfo_t fiemap_cmd;
static int max_extents = -1;
+static __u64 covered_length = 0;
+static bool range_limit = false;
static void
fiemap_help(void)
@@ -79,7 +81,7 @@ print_hole(
boff_w, _("hole"), tot_w, lstart - llast);
}
-
+ covered_length += BBTOB(lstart - llast);
}
static int
@@ -90,7 +92,8 @@ print_verbose(
int tot_w,
int flg_w,
int cur_extent,
- __u64 last_logical)
+ __u64 last_logical,
+ __u64 limit)
{
__u64 lstart;
__u64 llast;
@@ -122,7 +125,7 @@ print_verbose(
cur_extent++;
}
- if (cur_extent == max_extents)
+ if (cur_extent == max_extents || (range_limit && covered_length >= limit))
return 1;
snprintf(lbuf, sizeof(lbuf), "[%llu..%llu]:", lstart,
@@ -140,7 +143,8 @@ print_plain(
struct fiemap_extent *extent,
int lflag,
int cur_extent,
- __u64 last_logical)
+ __u64 last_logical,
+ __u64 limit)
{
__u64 lstart;
__u64 llast;
@@ -157,7 +161,7 @@ print_plain(
cur_extent++;
}
- if (cur_extent == max_extents)
+ if (cur_extent == max_extents || (range_limit && covered_length >= limit))
return 1;
printf("\t%d: [%llu..%llu]: %llu..%llu", cur_extent,
@@ -211,6 +215,7 @@ calc_print_format(
}
}
+
int
fiemap_f(
int argc,
@@ -231,8 +236,14 @@ fiemap_f(
int tot_w = 5; /* 5 since its just one number */
int flg_w = 5;
__u64 last_logical = 0;
+ __u64 len = -1LL;
+ __u64 stop_offset = -1LL;
+ off64_t start_offset = 0;
+ size_t fsblocksize, fssectsize;
struct stat st;
+ init_cvtnum(&fsblocksize, &fssectsize);
+
while ((c = getopt(argc, argv, "aln:v")) != EOF) {
switch (c) {
case 'a':
@@ -252,6 +263,27 @@ fiemap_f(
}
}
+ if (optind < argc) {
+ start_offset = cvtnum(fsblocksize, fssectsize, argv[optind]);
+ if (start_offset < 0) {
+ printf("non-numeric offset argument -- %s\n", argv[optind]);
+ return 0;
+ }
+ last_logical = start_offset;
+ optind++;
+ }
+
+ if (optind < argc) {
+ off64_t length = cvtnum(fsblocksize, fssectsize, argv[optind]);
+ if (length < 0) {
+ printf("non-numeric len argument -- %s\n", argv[optind]);
+ return 0;
+ }
+ len = length;
+ stop_offset = start_offset + len;
+ range_limit = true;
+ }
+
map_size = sizeof(struct fiemap) +
(EXTENT_BATCH * sizeof(struct fiemap_extent));
fiemap = malloc(map_size);
@@ -269,7 +301,7 @@ fiemap_f(
memset(fiemap, 0, map_size);
fiemap->fm_flags = fiemap_flags;
fiemap->fm_start = last_logical;
- fiemap->fm_length = -1LL;
+ fiemap->fm_length = len;
fiemap->fm_extent_count = EXTENT_BATCH;
ret = ioctl(file->fd, FS_IOC_FIEMAP, (unsigned long)fiemap);
@@ -300,14 +332,18 @@ fiemap_f(
num_printed = print_verbose(extent, foff_w,
boff_w, tot_w,
flg_w, cur_extent,
- last_logical);
+ last_logical,
+ stop_offset);
} else
num_printed = print_plain(extent, lflag,
cur_extent,
- last_logical);
+ last_logical,
+ stop_offset);
cur_extent += num_printed;
last_logical = extent->fe_logical + extent->fe_length;
+ if (num_printed == 2)
+ covered_length += extent->fe_length;
if (extent->fe_flags & FIEMAP_EXTENT_LAST) {
last = 1;
@@ -316,6 +352,9 @@ fiemap_f(
if (cur_extent == max_extents)
break;
+
+ if (range_limit && covered_length >= start_offset + len)
+ goto out;
}
}
@@ -331,9 +370,11 @@ fiemap_f(
return 0;
}
- if (cur_extent && last_logical < st.st_size)
+ if (cur_extent && last_logical < st.st_size &&
+ (!range_limit || covered_length < start_offset + len)) {
print_hole(foff_w, boff_w, tot_w, cur_extent, lflag, !vflag,
BTOBBT(last_logical), BTOBBT(st.st_size));
+ }
out:
free(fiemap);
@@ -348,7 +389,7 @@ fiemap_init(void)
fiemap_cmd.argmin = 0;
fiemap_cmd.argmax = -1;
fiemap_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
- fiemap_cmd.args = _("[-alv] [-n nx]");
+ fiemap_cmd.args = _("[-alv] [-n nx] [start offset [len]]");
fiemap_cmd.oneline = _("print block mapping for a file");
fiemap_cmd.help = fiemap_help;
diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8
index 0fd9b951199c..27f1ae163913 100644
--- a/man/man8/xfs_io.8
+++ b/man/man8/xfs_io.8
@@ -295,11 +295,12 @@ Prints the block mapping for the current open file. Refer to the
.BR xfs_bmap (8)
manual page for complete documentation.
.TP
-.BI "fiemap [ \-alv ] [ \-n " nx " ]"
+.BI "fiemap [ \-alv ] [ \-n " nx " ] [ " offset " [ " len " ]]"
Prints the block mapping for the current open file using the fiemap
ioctl. Options behave as described in the
.BR xfs_bmap (8)
-manual page.
+manual page. Optionally, this command also supports passing the start offset
+from where to begin the fiemap and the length of that region.
.TP
.BI "fsmap [ \-d | \-l | \-r ] [ \-m | \-v ] [ \-n " nx " ] [ " start " ] [ " end " ]
Prints the mapping of disk blocks used by the filesystem hosting the current
--
2.7.4
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH] fiemap: Implement ranged query
2017-10-19 10:34 [PATCH] fiemap: Implement ranged query Nikolay Borisov
@ 2017-10-25 7:00 ` Darrick J. Wong
0 siblings, 0 replies; 2+ messages in thread
From: Darrick J. Wong @ 2017-10-25 7:00 UTC (permalink / raw)
To: Nikolay Borisov; +Cc: linux-xfs, sandeen
On Thu, Oct 19, 2017 at 01:34:41PM +0300, Nikolay Borisov wrote:
> Currently the fiemap implementation of xfs_io doesn't support making ranged
> queries. This patch implements two optional arguments which take the starting
> offset and the length of the region to be queried. The impelmentation also
> calculates printed holes as an extent for the purpose of terminating the query.
>
> I.e. if we create a file with the following layout :
>
> xfs_io -f -c "falloc 0 32k" -c "fpunch 0 4k" -c "fpunch 8k 4k" \
> -c "fpunch 28k 4k" -c "fiemap" fragmented-file
>
> H D H D H
> |--------|--------|---------|--------------|-----------------|
> 0 4k 8k 12k 28k 32k
>
> Then the output is :
>
> xfs_io -c "fiemap 0 10k" fragmented-file
> fragmented-file:
> 0: [0..7]: hole
> 1: [8..15]: 897844104..897844111
> 2: [16..23]: hole
>
> xfs_io -c "fiemap 0" fragmented-file
> fragmented-file:
> 0: [0..7]: hole
> 1: [8..15]: 897844104..897844111
> 2: [16..23]: hole
> 3: [24..55]: 897844120..897844151
> 4: [56..63]: hole
>
> xfs_io -c "fiemap 10k 5k" fragmented-file
> fragmented-file:
> 0: [20..23]: hole
> 1: [24..55]: 897844120..897844151
>
> xfs_io -c "fiemap 10k 18k" fragmented-file
> fragmented-file:
> 0: [20..23]: hole
> 1: [24..55]: 897844120..897844151
> 2: [56..63]: hole
>
> Signed-off-by: Nikolay Borisov <nborisov@suse.com>
> ---
> io/fiemap.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++---------
> man/man8/xfs_io.8 | 5 +++--
> 2 files changed, 54 insertions(+), 12 deletions(-)
>
> diff --git a/io/fiemap.c b/io/fiemap.c
> index e6fd66da753d..844741cb07d3 100644
> --- a/io/fiemap.c
> +++ b/io/fiemap.c
> @@ -27,6 +27,8 @@
>
> static cmdinfo_t fiemap_cmd;
> static int max_extents = -1;
> +static __u64 covered_length = 0;
> +static bool range_limit = false;
>
> static void
> fiemap_help(void)
> @@ -79,7 +81,7 @@ print_hole(
> boff_w, _("hole"), tot_w, lstart - llast);
> }
>
> -
> + covered_length += BBTOB(lstart - llast);
> }
>
> static int
> @@ -90,7 +92,8 @@ print_verbose(
> int tot_w,
> int flg_w,
> int cur_extent,
> - __u64 last_logical)
> + __u64 last_logical,
> + __u64 limit)
> {
> __u64 lstart;
> __u64 llast;
> @@ -122,7 +125,7 @@ print_verbose(
> cur_extent++;
> }
>
> - if (cur_extent == max_extents)
> + if (cur_extent == max_extents || (range_limit && covered_length >= limit))
> return 1;
>
> snprintf(lbuf, sizeof(lbuf), "[%llu..%llu]:", lstart,
> @@ -140,7 +143,8 @@ print_plain(
> struct fiemap_extent *extent,
> int lflag,
> int cur_extent,
> - __u64 last_logical)
> + __u64 last_logical,
> + __u64 limit)
> {
> __u64 lstart;
> __u64 llast;
> @@ -157,7 +161,7 @@ print_plain(
> cur_extent++;
> }
>
> - if (cur_extent == max_extents)
> + if (cur_extent == max_extents || (range_limit && covered_length >= limit))
As mentioned on IRC, I don't think it's correct to compare
covered_length against limit here. If we want to fiemap blocks 200-300
we'd issue the command "fiemap 200k 100k", after which start_offset =
200, len = 100, and stop_offset = 300. We start the loop and
covered_length = 0, and at this point we end up comparing
(range_limit && covered_length >= limit) => (true && 0 >= 300)....
> return 1;
>
> printf("\t%d: [%llu..%llu]: %llu..%llu", cur_extent,
> @@ -211,6 +215,7 @@ calc_print_format(
> }
> }
>
> +
> int
> fiemap_f(
> int argc,
> @@ -231,8 +236,14 @@ fiemap_f(
> int tot_w = 5; /* 5 since its just one number */
> int flg_w = 5;
> __u64 last_logical = 0;
> + __u64 len = -1LL;
> + __u64 stop_offset = -1LL;
> + off64_t start_offset = 0;
> + size_t fsblocksize, fssectsize;
> struct stat st;
>
> + init_cvtnum(&fsblocksize, &fssectsize);
> +
> while ((c = getopt(argc, argv, "aln:v")) != EOF) {
> switch (c) {
> case 'a':
> @@ -252,6 +263,27 @@ fiemap_f(
> }
> }
>
> + if (optind < argc) {
> + start_offset = cvtnum(fsblocksize, fssectsize, argv[optind]);
> + if (start_offset < 0) {
> + printf("non-numeric offset argument -- %s\n", argv[optind]);
> + return 0;
> + }
> + last_logical = start_offset;
> + optind++;
> + }
> +
> + if (optind < argc) {
> + off64_t length = cvtnum(fsblocksize, fssectsize, argv[optind]);
> + if (length < 0) {
> + printf("non-numeric len argument -- %s\n", argv[optind]);
> + return 0;
> + }
> + len = length;
> + stop_offset = start_offset + len;
> + range_limit = true;
> + }
> +
> map_size = sizeof(struct fiemap) +
> (EXTENT_BATCH * sizeof(struct fiemap_extent));
> fiemap = malloc(map_size);
> @@ -269,7 +301,7 @@ fiemap_f(
> memset(fiemap, 0, map_size);
> fiemap->fm_flags = fiemap_flags;
> fiemap->fm_start = last_logical;
> - fiemap->fm_length = -1LL;
> + fiemap->fm_length = len;
Need to shorten len as we go around the loop.
> fiemap->fm_extent_count = EXTENT_BATCH;
>
> ret = ioctl(file->fd, FS_IOC_FIEMAP, (unsigned long)fiemap);
> @@ -300,14 +332,18 @@ fiemap_f(
> num_printed = print_verbose(extent, foff_w,
> boff_w, tot_w,
> flg_w, cur_extent,
> - last_logical);
> + last_logical,
> + stop_offset);
> } else
> num_printed = print_plain(extent, lflag,
> cur_extent,
> - last_logical);
> + last_logical,
> + stop_offset);
>
> cur_extent += num_printed;
> last_logical = extent->fe_logical + extent->fe_length;
> + if (num_printed == 2)
> + covered_length += extent->fe_length;
>
> if (extent->fe_flags & FIEMAP_EXTENT_LAST) {
> last = 1;
> @@ -316,6 +352,9 @@ fiemap_f(
>
> if (cur_extent == max_extents)
> break;
> +
> + if (range_limit && covered_length >= start_offset + len)
> + goto out;
> }
> }
>
> @@ -331,9 +370,11 @@ fiemap_f(
> return 0;
> }
>
> - if (cur_extent && last_logical < st.st_size)
> + if (cur_extent && last_logical < st.st_size &&
> + (!range_limit || covered_length < start_offset + len)) {
covered_length < stop_offset?
> print_hole(foff_w, boff_w, tot_w, cur_extent, lflag, !vflag,
> BTOBBT(last_logical), BTOBBT(st.st_size));
> + }
>
> out:
> free(fiemap);
> @@ -348,7 +389,7 @@ fiemap_init(void)
> fiemap_cmd.argmin = 0;
> fiemap_cmd.argmax = -1;
> fiemap_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK;
> - fiemap_cmd.args = _("[-alv] [-n nx]");
> + fiemap_cmd.args = _("[-alv] [-n nx] [start offset [len]]");
[offset [len]]
Otherwise it sounds like fiemap takes three parameters.
> fiemap_cmd.oneline = _("print block mapping for a file");
> fiemap_cmd.help = fiemap_help;
>
> diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8
> index 0fd9b951199c..27f1ae163913 100644
> --- a/man/man8/xfs_io.8
> +++ b/man/man8/xfs_io.8
> @@ -295,11 +295,12 @@ Prints the block mapping for the current open file. Refer to the
> .BR xfs_bmap (8)
> manual page for complete documentation.
> .TP
> -.BI "fiemap [ \-alv ] [ \-n " nx " ]"
> +.BI "fiemap [ \-alv ] [ \-n " nx " ] [ " offset " [ " len " ]]"
> Prints the block mapping for the current open file using the fiemap
> ioctl. Options behave as described in the
> .BR xfs_bmap (8)
> -manual page.
> +manual page. Optionally, this command also supports passing the start offset
> +from where to begin the fiemap and the length of that region.
New sentences should start on their own line, per linux-manpages custom.
(Or maybe not; we violate that plenty in xfsprogs land...)
Also, fstests testcases needed.
--D
> .TP
> .BI "fsmap [ \-d | \-l | \-r ] [ \-m | \-v ] [ \-n " nx " ] [ " start " ] [ " end " ]
> Prints the mapping of disk blocks used by the filesystem hosting the current
> --
> 2.7.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2017-10-25 7:01 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-10-19 10:34 [PATCH] fiemap: Implement ranged query Nikolay Borisov
2017-10-25 7:00 ` Darrick J. Wong
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox