From patchwork Thu Oct 19 10:34:41 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolay Borisov X-Patchwork-Id: 10016395 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5E67A60215 for ; Thu, 19 Oct 2017 10:34:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 61AA9287B3 for ; Thu, 19 Oct 2017 10:34:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5630D28CD1; Thu, 19 Oct 2017 10:34:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9088D287B3 for ; Thu, 19 Oct 2017 10:34:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751890AbdJSKer (ORCPT ); Thu, 19 Oct 2017 06:34:47 -0400 Received: from mx2.suse.de ([195.135.220.15]:42291 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751437AbdJSKeq (ORCPT ); Thu, 19 Oct 2017 06:34:46 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 7CFCCAC73; Thu, 19 Oct 2017 10:34:45 +0000 (UTC) From: Nikolay Borisov To: linux-xfs@vger.kernel.org Cc: sandeen@sandeen.net, Nikolay Borisov Subject: [PATCH] fiemap: Implement ranged query Date: Thu, 19 Oct 2017 13:34:41 +0300 Message-Id: <1508409281-7183-1-git-send-email-nborisov@suse.com> X-Mailer: git-send-email 2.7.4 Sender: linux-xfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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