Whamcloud - gitweb
LU-10705 utils: add "lfs find --blocks" 93/31393/4
authorAndreas Dilger <andreas.dilger@intel.com>
Fri, 23 Feb 2018 07:34:22 +0000 (00:34 -0700)
committerOleg Drokin <oleg.drokin@intel.com>
Thu, 8 Mar 2018 17:37:01 +0000 (17:37 +0000)
Add support for "lfs find --blocks|-b <block>" to be able to find
files with the specified number of allocated blocks (in kilobytes or
other specified units). This is distinct from "--size <size>" since
that doesn't properly check the space used for sparse files.

Signed-off-by: Andreas Dilger <andreas.dilger@intel.com>
Change-Id: I7d48f919d95242c11ef7d3075ecc3f7e963ebbe5
Reviewed-on: https://review.whamcloud.com/31393
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Jian Yu <jian.yu@intel.com>
Reviewed-by: Ben Evans <bevans@cray.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/doc/lfs-find.1
lustre/include/lustre/lustreapi.h
lustre/tests/sanity.sh
lustre/utils/lfs.c
lustre/utils/liblustreapi.c

index 8ba1963..e842178 100644 (file)
@@ -4,7 +4,8 @@ lfs-find \- Lustre client utility to list files with specific attributes
 .SH SYNOPSIS
 .B lfs find \fR<\fIdirectory\fR|\fIfilename \fR...>
       [[\fB!\fR] \fB--atime\fR|\fB-A\fR [\fB-+\fR]\fIn\fR]
-[[\fB!\fR] \fB--ctime\fR|\fB-C\fR [\fB+-\fR]\fIn\fR]
+[[\fB!\fR] \fB--blocks\fR|\fB-b\fR [\fB+-\fR]\fIn\fR]
+      [[\fB!\fR] \fB--ctime\fR|\fB-C\fR [\fB+-\fR]\fIn\fR]
       [[\fB!\fR] \fB--component-count|\fB--comp-count\fR [\fB+-\fR]\fIn\fR]
       [[\fB!\fR] \fB--component-end|\fB--comp-end\fR|\fB-E\fR [\fB+-\fR]\fIn\fR[\fBKMGTPE\fR]]
       [[\fB!\fR] \fB--component-flags|\fB--comp-flags\fR <[^]\fIflag\fB,\fR...>]
@@ -46,6 +47,11 @@ OST and MDT location, and composite layout attributes.
 .BR --atime | -A
 File was last accessed \fIn\fR*24 hours ago.
 .TP
+.BR --blocks | -b
+Blocks allocated by the file is \fIn\fR kibibytes (if no units are given),
+\fIn\fR 512-byte \fBb\fRlocks, or \fBK\fRibi-, \fBM\fRebi-, \fBG\fRibi-,
+\fBT\fRebi-, \fBP\fRebi-, or \fBE\fRbi-bytes if that suffix is given.
+.TP
 .BR --ctime | -C
 File's status was last changed \fIn\fR*24 hours ago.
 .TP
index c6a15f3..5df3050 100644 (file)
@@ -198,7 +198,8 @@ struct find_param {
                                 fp_comp_end_sign:2,
                                 fp_comp_count_sign:2,
                                 fp_mirror_count_sign:2,
-                                fp_mdt_count_sign:2;
+                                fp_mdt_count_sign:2,
+                                fp_blocks_sign:2;
        unsigned long long       fp_size;
        unsigned long long       fp_size_units;
 
@@ -247,7 +248,9 @@ struct find_param {
                                 fp_exclude_mdt_count:1,
                                 fp_check_hash_type:1,
                                 fp_exclude_hash_type:1,
-                                fp_yaml:1;     /* output layout in YAML */
+                                fp_yaml:1,     /* output layout in YAML */
+                                fp_check_blocks:1,
+                                fp_exclude_blocks:1;
 
        int                      fp_verbose;
        int                      fp_quiet;
@@ -294,6 +297,8 @@ struct find_param {
        unsigned long long       fp_comp_end_units;
        unsigned long long       fp_mdt_count;
        unsigned                 fp_projid;
+       unsigned long long       fp_blocks;
+       unsigned long long       fp_blocks_units;
 
        /* In-process parameters. */
        unsigned long            fp_got_uuids:1,
index 61e6b0d..93f71ef 100755 (executable)
@@ -5732,12 +5732,35 @@ test_56aa() { # LU-5937
        $LFS setdirstripe -c$MDSCOUNT $dir/striped_dir
 
        createmany -o $dir/striped_dir/${tfile}- 1024
-       local dirs=$(lfs find --size +8k $dir/)
+       local dirs=$($LFS find --size +8k $dir/)
 
        [ -n "$dirs" ] || error "lfs find --size wrong under striped dir"
 }
 run_test 56aa "lfs find --size under striped dir"
 
+test_56ab() { # LU-10705
+       test_mkdir $DIR/$tdir
+       dd if=/dev/zero of=$DIR/$tdir/$tfile.1 bs=8k count=1 seek=2k
+       dd if=/dev/zero of=$DIR/$tdir/$tfile.2 bs=4k count=1 seek=4k
+       dd if=/dev/zero of=$DIR/$tdir/$tfile.3 bs=1M count=2 seek=16
+       # Flush writes to ensure valid blocks.  Need to be more thorough for
+       # ZFS, since blocks are not allocated/returned to client immediately.
+       sync_all_data
+       wait_zfs_commit ost1 2
+       cancel_lru_locks osc
+       ls -ls $DIR/$tdir
+
+       local files=$($LFS find --size +16M $DIR/$tdir | wc -l)
+
+       [[ $files == 3 ]] || error ">16M size files $files isn't 3 as expected"
+
+       files=$($LFS find --blocks +1M $DIR/$tdir | wc -l)
+       [[ $files == 1 ]] || error ">1M blocks files $files isn't 1 as expected"
+
+       rm -f $DIR/$tdir/$tfile.[123]
+}
+run_test 56ab "lfs find --blocks"
+
 test_56ba() {
        # Create composite files with one component
        local dir=$DIR/$tdir
index 80ae711..1219665 100644 (file)
@@ -361,7 +361,7 @@ command_t cmdlist[] = {
         "find files matching given attributes recursively in directory tree.\n"
         "usage: find <directory|filename> ...\n"
         "     [[!] --atime|-A [+-]N] [[!] --ctime|-C [+-]N]\n"
-        "     [[!] --mtime|-M [+-]N] [--maxdepth|-D N]\n"
+        "     [[!] --mtime|-M [+-]N] [--maxdepth|-D N] [[!] --blocks|-b N]\n"
         "     [[!] --mdt-index|--mdt|-m <uuid|index,...>]\n"
         "     [[!] --name|-n <pattern>] [[!] --ost|-O <uuid|index,...>]\n"
         "     [--print|-P] [--print0|-0] [[!] --size|-s [+-]N[bkMGTPE]]\n"
@@ -3340,6 +3340,7 @@ static int lfs_find(int argc, char **argv)
        };
         struct option long_opts[] = {
        { .val = 'A',   .name = "atime",        .has_arg = required_argument },
+       { .val = 'b',   .name = "blocks",       .has_arg = required_argument },
        { .val = LFS_COMP_COUNT_OPT,
                        .name = "comp-count",   .has_arg = required_argument },
        { .val = LFS_COMP_COUNT_OPT,
@@ -3414,7 +3415,7 @@ static int lfs_find(int argc, char **argv)
 
        /* when getopt_long_only() hits '!' it returns 1, puts "!" in optarg */
        while ((c = getopt_long_only(argc, argv,
-                       "-0A:c:C:D:E:g:G:H:i:L:m:M:n:N:O:Ppqrs:S:t:T:u:U:v",
+                       "-0A:b:c:C:D:E:g:G:H:i:L:m:M:n:N:O:Ppqrs:S:t:T:u:U:v",
                        long_opts, NULL)) >= 0) {
                 xtime = NULL;
                 xsign = NULL;
@@ -3476,6 +3477,26 @@ static int lfs_find(int argc, char **argv)
                        if (rc)
                                *xsign = rc;
                        break;
+               case 'b':
+                       if (optarg[0] == '+') {
+                               param.fp_blocks_sign = -1;
+                               optarg++;
+                       } else if (optarg[0] == '-') {
+                               param.fp_blocks_sign =  1;
+                               optarg++;
+                       }
+
+                       param.fp_blocks_units = 1024;
+                       ret = llapi_parse_size(optarg, &param.fp_blocks,
+                                              &param.fp_blocks_units, 0);
+                       if (ret) {
+                               fprintf(stderr, "error: bad blocks '%s'\n",
+                                       optarg);
+                               goto err;
+                       }
+                       param.fp_check_blocks = 1;
+                       param.fp_exclude_blocks = !!neg_opt;
+                       break;
                case LFS_COMP_COUNT_OPT:
                        if (optarg[0] == '+') {
                                param.fp_comp_count_sign = -1;
@@ -3914,6 +3935,7 @@ static int lfs_getstripe_internal(int argc, char **argv,
 {
        struct option long_opts[] = {
 /* find        { .val = 'A',   .name = "atime",        .has_arg = required_argument }*/
+/* find        { .val = 'b',   .name = "blocks",       .has_arg = required_argument }*/
        { .val = LFS_COMP_COUNT_OPT,
                        .name = "comp-count",   .has_arg = no_argument },
        { .val = LFS_COMP_COUNT_OPT,
index 1e678b6..4b00539 100644 (file)
@@ -3963,7 +3963,8 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp,
        if (param->fp_obd_uuid || param->fp_mdt_uuid ||
            param->fp_check_uid || param->fp_check_gid ||
            param->fp_atime || param->fp_mtime || param->fp_ctime ||
-           param->fp_check_size || find_check_lmm_info(param) ||
+           param->fp_check_size || param->fp_check_blocks ||
+           find_check_lmm_info(param) ||
            param->fp_check_mdt_count || param->fp_check_hash_type)
                decision = 0;
 
@@ -4215,10 +4216,8 @@ obd_matches:
            The regular stat is almost of the same speed as some new
            'glimpse-size-ioctl'. */
 
-       if (param->fp_check_size && S_ISREG(st->st_mode) && stripe_count)
-               decision = 0;
-
-       if (param->fp_check_size && S_ISDIR(st->st_mode))
+       if ((param->fp_check_size || param->fp_check_blocks) &&
+           ((S_ISREG(st->st_mode) && stripe_count) || S_ISDIR(st->st_mode)))
                decision = 0;
 
        if (!decision) {
@@ -4259,20 +4258,30 @@ obd_matches:
                        goto decided;
        }
 
-       if (param->fp_check_size)
+       if (param->fp_check_size) {
                decision = find_value_cmp(st->st_size, param->fp_size,
                                          param->fp_size_sign,
                                          param->fp_exclude_size,
                                          param->fp_size_units, 0);
+               if (decision == -1)
+                       goto decided;
+       }
 
-       if (decision != -1) {
-               llapi_printf(LLAPI_MSG_NORMAL, "%s", path);
-               if (param->fp_zero_end)
-                       llapi_printf(LLAPI_MSG_NORMAL, "%c", '\0');
-               else
-                       llapi_printf(LLAPI_MSG_NORMAL, "\n");
+       if (param->fp_check_blocks) { /* convert st_blocks to bytes */
+               decision = find_value_cmp(st->st_blocks * 512, param->fp_blocks,
+                                         param->fp_blocks_sign,
+                                         param->fp_exclude_blocks,
+                                         param->fp_blocks_units, 0);
+               if (decision == -1)
+                       goto decided;
        }
 
+       llapi_printf(LLAPI_MSG_NORMAL, "%s", path);
+       if (param->fp_zero_end)
+               llapi_printf(LLAPI_MSG_NORMAL, "%c", '\0');
+       else
+               llapi_printf(LLAPI_MSG_NORMAL, "\n");
+
 decided:
        ret = 0;
        /* Do not get down anymore? */