Whamcloud - gitweb
EX-6856 utils: add -Z option for 'lfs getstripe/find'
authorBobi Jam <bobijam@whamcloud.com>
Wed, 28 Jun 2023 16:51:25 +0000 (00:51 +0800)
committerAndreas Dilger <adilger@whamcloud.com>
Thu, 6 Jul 2023 04:13:40 +0000 (04:13 +0000)
Add support for "lfs getstripe -Z" to get the last instantiated
component compression information.

Add support for "lfs find -Z <type>[:[+-]<level>]" to keep consistent
options with "lfs setstripe -Z".

Fixes: 093bd2f343 ("EX-6856 utils: add 'lfs find' support for compressed file")
Signed-off-by: Bobi Jam <bobijam@whamcloud.com>
Change-Id: Id3e788761656d05604bc9a72fb1e51c5f2a0ad3b
Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/51497
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
lustre/doc/lfs-find.1
lustre/doc/lfs-getstripe.1
lustre/doc/lfs-setstripe.1
lustre/include/lustre/lustreapi.h
lustre/include/uapi/linux/lustre/lustre_user.h
lustre/tests/sanity-pfl.sh
lustre/utils/lfs.c
lustre/utils/liblustreapi_layout.c

index fd1337e..4b60e8f 100644 (file)
@@ -39,9 +39,10 @@ mdt\fR,\fBraid0\fR,\fBcompress\fR,\fBreleased\fR]
       [[\fB!\fR] \fB--type\fR|\fB-t\fR {\fBbcdflps\fR}]
 [[\fB!\fR] \fB--uid\fR|\fB-u\fR|\fB--user\fR|\fB-U
 <\fIuname\fR>|<\fIuid>\fR]
-      [[\fB!\fR] \fB--compress-type\fR|\fB--compr-type\fR=<\fIcompress-type\fR>]
-      [[\fB!\fR] \fB--compress-level\fR|\fB--compr-level\fR=[\fB+-\fR]<\fIcompress-level\fR>]
-      [[\fB!\fR] \fB--compress-chunk\fR|\fB--compr-chunk\fR=[\fB+-\fR]<\fIcompress-chunk\fR>]
+      [[\fB!\fR] \fB-Z\fR|\fB--compress\fR|\fB--compr\fR=<\fIcompr_type\fR>[:[\fB+-\fR]<\fIcompr_level\fR>]]
+      [[\fB!\fR] \fB--compress-type\fR|\fB--compr-type\fR=<\fIcompress_type\fR>]
+      [[\fB!\fR] \fB--compress-level\fR|\fB--compr-level\fR=[\fB+-\fR]<\fIcompress_level\fR>]
+      [[\fB!\fR] \fB--compress-chunk\fR|\fB--compr-chunk\fR=[\fB+-\fR]<\fIcompress_chunk\fR[\fBKM\fR]>
 .SH DESCRIPTION
 .B lfs find
 is similar to the standard
@@ -426,31 +427,39 @@ Extension size is \fIn\fR bytes, or \fBK\fRibi-, \fBM\fRebi-,
 suffix is given.  For composite files, this matches the extension
 size of any extension component.
 .TP
-.BR --compress-type | --compr-type = \fIcompress-type
-Compress algorithm is \fIcompress-type\fR. The file must be a composite
+.BR -Z | --compress | --compr = \fIcompr_type\fR \fB[\fR:\fB[\fR +- \fB]\fR \fIcompr_level\fR\fB]\fR
+This matches any component which uses compress algorithm \fIcompr_type\fR and/or
+compress level \fIcompr_level\fR. If
+.BI + compr_level
+or
+.BI - compr_level
+is used, print components with respectively a larger or smaller \fIcompr_level\fR.
+.TP
+.BR --compress-type | --compr-type = \fIcompress_type
+Compress algorithm is \fIcompress_type\fR. The file must be a composite
 file containing compress component, this matches any component which uses
 the specified compress algorithm.
 .TP
-.BR --compress-level | --compr-level = [ +- ] \fIcompress-level
-The compress level which the compress algorithm uses is \fIcompress-level\fR.
+.BR --compress-level | --compr-level = [ +- ] \fIcompress_level
+The compress level which the compress algorithm uses is \fIcompress_level\fR.
 The file must be a composite file containing compress component, this matches
 any component which uses the specified compress level.  If
 .BI + compress-level
 or
 .BI - compress-level
 is used, print components with respectively a larger or smaller
-\fIcompress-level\fR.
+\fIcompress_level\fR.
 .TP
-.BR --compress-chunk | --compr-chunk = [ +- ] \fIcompress-chunk
+.BR --compress-chunk | --compr-chunk = [ +- ] \fIcompress_chunk\fR\fB[KM]\fR
 The compress chunk size (in KiB) which the compress algorithm uses is
-\fIcompress-chunk\fR.
+\fIcompress_chunk\fR.
 The file must be a composite file containing compress component, this matches
 any component which uses the specified compress chunk.  If
 .BI + compress-chunk
 or
 .BI - compress-chunk
 is used, print components with respectively a larger or smaller
-\fIcompress-chunk\fR.
+\fIcompress_chunk\fR.
 .TP
 .BR --type | -t
 File has type: \fBb\fRlock, \fBc\fRharacter, \fBd\fRirectory,
index 6367c65..7c514e9 100644 (file)
@@ -22,6 +22,7 @@ lfs getstripe \- Lustre client command to print layout parameters of a file
 [\fB--stripe-count\fR|\fB-c\fR]
 [\fB--stripe-index\fR|\fB-i\fR]
       [\fB--stripe-size\fR|\fB-S\fR] [\fB--mirror-count\fR|\fB-N\fR]
+      [\fB--compress\fR|\fB--compr\fR|\fB-Z\fR]
       [\fB--compress-type\fR|\fB--compr-type\fR]
 [\fB--compress-level\fR|\fB--compr-level\fR]
       [\fB--compress-chunk\fR|\fB--compr-chunk\fR]
@@ -48,6 +49,7 @@ specific layout information to be printed, then the
 .BR --component-start ,
 .BR --component-end ,
 .BR --pool,
+.BR --compress,
 .BR --compress-type,
 .BR --compress-level,
 .BR --compress-chunk,
@@ -249,14 +251,21 @@ size of the last initialized component.
 Print the extension size in bytes. For composite files this is the extension
 size of the first extension component.
 .TP
+.BR --compress | --compr | -Z
+Print the compression information of components in the file's layout if available.
+For composite files print the compression information of the last initialized component.
+.TP
 .BR --compress-type | --compr-type
 Print only the compress type of components in the file's layout if available.
+For composite files print the compression type of the last initialized component.
 .TP
 .BR --compress-level | --compr-level
 Print only the compress level of components in the file's layout if available.
+For composite files print the compression level of the last initialized component.
 .TP
 .BR --compress-chunk | --compr-chunk
 Print only the compress chunk size in KiB of components in the file's layout if available.
+For composite files print the compression chunk size of the last initialized component.
 .TP
 .BR --verbose | -v
 Also print the layout magic, FID sequence, FID object ID, and FID, in
index 0a698df..5b7ccd1 100644 (file)
@@ -225,7 +225,7 @@ faster the compression speed, at the cost of reduced compression ratio.
 - lzo. This one does not accept a compression level in its kernel
 implementation.
 .TP
-.B --compress-chunk\fR=<\fIsize\fR>
+.B --compress-chunk\fR=<\fIsize\fR[\fBKM\fR]>
 Used to specify the data chunk size in KiB used by compression algorithm,
 the value will be adjusted to power-of-two multiples of the base 64KiB.
 The
index 3a4cbb7..373899b 100644 (file)
@@ -474,7 +474,7 @@ int llapi_get_obd_count(char *mnt, int *count, int is_mdt);
 int llapi_parse_size(const char *optarg, unsigned long long *size,
                     unsigned long long *size_units, int bytes_spec);
 int llapi_parse_compress_type(const char *optarg, unsigned int *type,
-                             int *level);
+                             int *level, char *sign);
 int llapi_search_mounts(const char *pathname, int index, char *mntdir,
                        char *fsname);
 int llapi_search_fsname(const char *pathname, char *fsname);
index f966540..7e92a32 100644 (file)
@@ -2935,7 +2935,9 @@ enum ll_compr_type {
 };
 
 #define COMPR_CHUNK_MIN_BITS 16
-#define COMPR_MIN_PAGES (1 << (COMPR_CHUNK_MIN_BITS - PAGE_SHIFT))
+#define COMPR_CHUNK_MAX_BITS 31
+#define COMPR_LEVEL_MAX 31
+#define COMPR_MIN_PAGES (1UL << (COMPR_CHUNK_MIN_BITS - PAGE_SHIFT))
 #if defined(__cplusplus)
 }
 #endif
index 4b934cd..b1bfcf2 100644 (file)
@@ -2434,8 +2434,8 @@ run_test 25 "Verify old lov stripe API with PFL files"
 
 export LFS_SETSTRIPE_COMPR_OK="yes"
 test_100a() {
-       (( $MDS1_VERSION >= $(version_code 2.14.0.85) )) ||
-               skip "Need MDS >= 2.14.0.85 for compression support"
+       (( $MDS1_VERSION >= $(version_code 2.14.0.92) )) ||
+               skip "Need MDS >= 2.14.0.92 for compression support"
 
        local tf=$DIR/$tdir/$tfile
        local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
@@ -2462,8 +2462,8 @@ test_100a() {
 run_test 100a "set stripe component with nocompr"
 
 test_100b() {
-       (( $MDS1_VERSION >= $(version_code 2.14.0.88) )) ||
-               skip "Need MDS >= 2.14.0.88 for compression support"
+       (( $MDS1_VERSION >= $(version_code 2.14.0.92) )) ||
+               skip "Need MDS >= 2.14.0.92 for compression support"
 
        local tf=$DIR/$tdir/$tfile
        # putting lz4 twice:
@@ -2550,8 +2550,8 @@ test_100b() {
 run_test 100b "create with compress component"
 
 test_100c() {
-       (( $MDS1_VERSION >= $(version_code 2.14.0.88) )) ||
-               skip "Need MDS >= 2.14.0.88 for compression support"
+       (( $MDS1_VERSION >= $(version_code 2.14.0.92) )) ||
+               skip "Need MDS >= 2.14.0.92 for compression support"
 
        local tf=$DIR/$tdir/$tfile
        local d1=$DIR/$tdir/dir-1
@@ -2643,8 +2643,8 @@ test_100c() {
 run_test 100c "create compress file with improper compress arguments"
 
 test_100d() {
-       (( $MDS1_VERSION >= $(version_code 2.14.0.88) )) ||
-               skip "Need MDS >= 2.14.0.88 for compression support"
+       (( $MDS1_VERSION >= $(version_code 2.14.0.92) )) ||
+               skip "Need MDS >= 2.14.0.92 for compression support"
 
        local tf=$DIR/$tdir/$tfile
        # putting lz4 twice:
@@ -2748,6 +2748,18 @@ test_100d() {
        found=$($LFS find $flg_opts $DIR/$tdir | wc -l)
        (( $found == 1 )) ||
                error "found $found compress type gzip level 1 files != 1"
+       flg_opts="-Z gzip:2"
+       found=$($LFS find $flg_opts $DIR/$tdir | wc -l)
+       (( $found == 1 )) ||
+               error "found $found compress type gzip level 1 files != 1"
+       flg_opts="-Z gzip:+2"
+       found=$($LFS find $flg_opts $DIR/$tdir | wc -l)
+       (( $found == 0 )) ||
+               error "found $found compress type gzip level +1 files != 0"
+       flg_opts="-Z gzip:-3"
+       found=$($LFS find $flg_opts $DIR/$tdir | wc -l)
+       (( $found == 1 )) ||
+               error "found $found compress type gzip level -2 files != 1"
        flg_opts="--compr-type=gzip ! --compr-level=2"
        found=$($LFS find $flg_opts $DIR/$tdir | wc -l)
        (( $found == 0 )) ||
@@ -2763,7 +2775,7 @@ test_100d() {
                flg_opts="--compr-chunk=$chunk"
                found=$($LFS find $flg_opts $DIR/$tdir | wc -l)
                (( found == 1 )) ||
-                       error "found $found compress $chunk file != 1"
+                       error "found $found compress chunk $chunk file != 1"
 
                flg_opts="--compr-chunk=+$chunk"
                found=$($LFS find $flg_opts $DIR/$tdir | wc -l)
@@ -2783,8 +2795,8 @@ test_100d() {
 run_test 100d "lfs find compress component"
 
 test_100e() {
-       (( $MDS1_VERSION >= $(version_code 2.14.0.88) )) ||
-               skip "Need MDS >= 2.14.0.88 for compression support"
+       (( $MDS1_VERSION >= $(version_code 2.14.0.92) )) ||
+               skip "Need MDS >= 2.14.0.92 for compression support"
 
        local tf=$DIR/$tdir/$tfile
        local p="$TMP/$TESTSUITE-$TESTNAME.parameters"
index abae0c9..0af163e 100644 (file)
@@ -212,8 +212,10 @@ static inline int lfs_mirror_delete(int argc, char **argv)
        "                 [--overstripe-count|-C <stripe_count>]\n"     \
        "                 [--stripe-index|-i <start_ost_idx>]\n"        \
        "                 [--stripe-size|-S <stripe_size>]\n"           \
-       "                 [--compress|-Z <type>[:<level>]\n"            \
-       "                 [--compress-chunk=<size>]\n"                  \
+       "                 [--compress|-Z <compr_type>[:<compr_level>]\n"\
+       "                 [--compress-type=<compress_type>\n"           \
+       "                 [--compress-level=<compress_level>\n"         \
+       "                 [--compress-chunk=<chunk_size>]\n"            \
        "                 [--extension-size|--ext-size|-z]\n"           \
        "                 [--layout|-L <pattern>]\n"                    \
        "                 [--mirror-count|-N[mirror_count]]\n"          \
@@ -498,6 +500,7 @@ command_t cmdlist[] = {
         "                 [--extension-size|--ext-size|-z]\n"
         "                 [--component-start[=[+-]comp_start]]\n"
         "                 [--component-end[=[+-]comp_end]|-E[[+-]comp_end]]\n"
+        "                 [--compress|--compr|-Z]\n"
         "                 [--compress-type|--compr-type]\n"
         "                 [--compress-level|--compr-level]\n"
         "                 [--compress-chunk|--compr-chunk]\n"
@@ -540,8 +543,10 @@ command_t cmdlist[] = {
         "     [[!] --component-start [+-]N[kMGTPE]]\n"
         "     [[!] --component-end|-E [+-]N[kMGTPE]]\n"
         "     [[!] --component-flags {init,stale,prefer,offline,nosync,extension}]\n"
-        "     [[!] --compress-type=<compress-type>\n"
-        "     [[!] --compress-level=[+-]<compress-level>\n"
+        "     [[!] --compress|--compr|-Z <compr_type>[:[+-]<compr_level>]\n"
+        "     [[!] --compress-type=<compress_type>\n"
+        "     [[!] --compress-level=[+-]<compress_level>\n"
+        "     [[!] --compress-chunk=[+-]<chunk_size>[kM]\n"
         "     [[!] --extension-size|--ext-size|-z [+-]N[kMGT]]\n"
         "     [[!] --foreign[=<foreign_type>]]\n"
         "     [[!] --gid|-g|--group|-G <gid>|<gname>]\n"
@@ -3781,6 +3786,18 @@ static int lfs_setstripe_internal(int argc, char **argv,
                                                .has_arg = no_argument},
        { .val = LFS_COMP_NO_VERIFY_OPT,
                        .name = "no-verify",    .has_arg = no_argument},
+       { .val = LFS_COMPRESS_TYPE_OPT,
+                       .name = "compress-type",  .has_arg = required_argument},
+       { .val = LFS_COMPRESS_TYPE_OPT,
+                       .name = "compr-type",     .has_arg = required_argument},
+       { .val = LFS_COMPRESS_LEVEL_OPT,
+                       .name = "compress-level", .has_arg = required_argument},
+       { .val = LFS_COMPRESS_LEVEL_OPT,
+                       .name = "compr-level",    .has_arg = required_argument},
+       { .val = LFS_COMPRESS_CHUNK_OPT,
+                       .name = "compress-chunk", .has_arg = required_argument},
+       { .val = LFS_COMPRESS_CHUNK_OPT,
+                       .name = "compr-chunk",    .has_arg = required_argument},
        { .val = LFS_LAYOUT_FLAGS_OPT,
                        .name = "flags",        .has_arg = required_argument},
        { .val = LFS_LAYOUT_FOREIGN_OPT,
@@ -3796,8 +3813,6 @@ static int lfs_setstripe_internal(int argc, char **argv,
        { .val = LFS_STATS_INTERVAL_OPT,
                        .name = "stats-interval",
                                                .has_arg = required_argument},
-       { .val = LFS_COMPRESS_CHUNK_OPT,
-                       .name = "compress-chunk", .has_arg = required_argument},
        { .val = 'c',   .name = "stripe-count", .has_arg = required_argument},
        { .val = 'c',   .name = "stripe_count", .has_arg = required_argument},
        { .val = 'c',   .name = "mdt-count",    .has_arg = required_argument},
@@ -4372,6 +4387,7 @@ static int lfs_setstripe_internal(int argc, char **argv,
 
                        lsa.lsa_extension_comp = true;
                        break;
+               case LFS_COMPRESS_TYPE_OPT:
                case 'Z':
                        if (layout == NULL && mirror_list == NULL &&
                            lsa.lsa_comp_end == 0)
@@ -4380,7 +4396,8 @@ static int lfs_setstripe_internal(int argc, char **argv,
 
                        result = llapi_parse_compress_type(optarg,
                                                           &lsa.lsa_compr_type,
-                                                          &lsa.lsa_compr_lvl);
+                                                          &lsa.lsa_compr_lvl,
+                                                          NULL);
                        if (result) {
                                fprintf(stderr,
                                        "%s %s: invalid compression type/level '%s'\n",
@@ -4388,21 +4405,32 @@ static int lfs_setstripe_internal(int argc, char **argv,
                                goto usage_error;
                        }
                        break;
+               case LFS_COMPRESS_LEVEL_OPT:
+                       lsa.lsa_compr_lvl = strtoul(optarg, &end, 0);
+                       if (*end != '\0' ||
+                           lsa.lsa_compr_lvl > COMPR_LEVEL_MAX) {
+                               fprintf(stderr,
+                                       "%s %s: invalid compression level '%s'\n",
+                                       progname, argv[0], optarg);
+                               goto usage_error;
+                       }
+                       break;
                case LFS_COMPRESS_CHUNK_OPT: {
                        unsigned long long chunk_size;
 
                        size_units = 1024; /* default in KiB */
                        result = llapi_parse_size(optarg, &chunk_size,
                                                  &size_units, 1);
-                       if (result) {
+                       if (result ||
+                           chunk_size > 1ULL << COMPR_CHUNK_MAX_BITS) {
                                fprintf(stderr,
-                                       "%s %s: invalid compress chunk size '%s'\n",
+                                       "%s %s: invalid compression chunk size '%s'\n",
                                        progname, argv[0], optarg);
                                goto usage_error;
                        }
                        lsa.lsa_compr_chunk_size = chunk_size;
-               }
                        break;
+               }
                default:
                        fprintf(stderr, "%s %s: unrecognized option '%s'\n",
                                progname, argv[0], argv[optind - 1]);
@@ -5034,23 +5062,17 @@ static int lfs_find(int argc, char **argv)
                        .name = "component-start",
                                                .has_arg = required_argument },
        { .val = LFS_COMPRESS_TYPE_OPT,
-                       .name = "compr-type",
-                                               .has_arg = required_argument },
+                     .name = "compress-type",  .has_arg = required_argument },
        { .val = LFS_COMPRESS_TYPE_OPT,
-                       .name = "compress-type",
-                                               .has_arg = required_argument },
+                     .name = "compr-type",     .has_arg = required_argument },
        { .val = LFS_COMPRESS_LEVEL_OPT,
-                       .name = "compr-level",
-                                               .has_arg = required_argument },
+                     .name = "compress-level", .has_arg = required_argument },
        { .val = LFS_COMPRESS_LEVEL_OPT,
-                       .name = "compress-level",
-                                               .has_arg = required_argument },
+                     .name = "compr-level",    .has_arg = required_argument },
        { .val = LFS_COMPRESS_CHUNK_OPT,
-                       .name = "compr-chunk",
-                                               .has_arg = required_argument },
+                     .name = "compress-chunk", .has_arg = required_argument },
        { .val = LFS_COMPRESS_CHUNK_OPT,
-                       .name = "compress-chunk",
-                                               .has_arg = required_argument },
+                     .name = "compr-chunk",    .has_arg = required_argument },
        { .val = LFS_MIRROR_STATE_OPT,
                        .name = "mirror-state", .has_arg = required_argument },
        { .val = LFS_NEWERXY_OPT,
@@ -5159,6 +5181,8 @@ static int lfs_find(int argc, char **argv)
        { .val = 'z',   .name = "extension-size",
                                                .has_arg = required_argument },
        { .val = 'z',   .name = "ext-size",     .has_arg = required_argument },
+       { .val = 'Z',   .name = "compress",     .has_arg = required_argument },
+       { .val = 'Z',   .name = "compr",        .has_arg = required_argument },
        { .name = NULL } };
        int optidx = 0;
        int pathstart = -1;
@@ -5174,7 +5198,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:b:B:c:C:D:E:g:G:H:i:lL:m:M:n:N:O:Ppqrs:S:t:T:u:U:z:",
+               "-0A:b:B:c:C:D:E:g:G:H:i:lL:m:M:n:N:O:Ppqrs:S:t:T:u:U:z:Z:",
                long_opts, &optidx)) >= 0) {
                xtime = NULL;
                xsign = NULL;
@@ -5326,43 +5350,6 @@ static int lfs_find(int argc, char **argv)
                        param.fp_check_comp_start = 1;
                        param.fp_exclude_comp_start = !!neg_opt;
                        break;
-               case LFS_COMPRESS_TYPE_OPT:
-                       rc = llapi_parse_compress_type(optarg,
-                                                      &param.fp_compr_type,
-                                                      NULL);
-                       if (rc) {
-                               fprintf(stderr,
-                                       "error: unknown compress type '%s'\n",
-                                       optarg);
-                               goto err;
-                       }
-                       param.fp_check_compr_type = 1;
-                       param.fp_exclude_compr_type = !!neg_opt;
-                       break;
-               case LFS_COMPRESS_LEVEL_OPT:
-                       if (optarg[0] == '+') {
-                               param.fp_compr_lvl_sign = -1;
-                               optarg++;
-                       } else if (optarg[0] == '-') {
-                               param.fp_compr_lvl_sign = 1;
-                               optarg++;
-                       }
-                       param.fp_compr_lvl = atoi(optarg);
-                       param.fp_check_compr_lvl = 1;
-                       param.fp_exclude_compr_lvl = !!neg_opt;
-                       break;
-               case LFS_COMPRESS_CHUNK_OPT:
-                       if (optarg[0] == '+') {
-                               param.fp_compr_chunk_sign = -1;
-                               optarg++;
-                       } else if (optarg[0] == '-') {
-                               param.fp_compr_chunk_sign = 1;
-                               optarg++;
-                       }
-                       param.fp_compr_chunk = atoi(optarg);
-                       param.fp_check_compr_chunk = 1;
-                       param.fp_exclude_compr_chunk = !!neg_opt;
-                       break;
                case LFS_MIRROR_STATE_OPT:
                        rc = mirror_str2state(optarg, &param.fp_mirror_state,
                                              &param.fp_mirror_neg_state);
@@ -5953,6 +5940,82 @@ err_free:
                        param.fp_check_ext_size = 1;
                        param.fp_exclude_ext_size = !!neg_opt;
                        break;
+               case LFS_COMPRESS_TYPE_OPT:
+               case 'Z': {
+                       char sign = '\0';
+
+                       param.fp_compr_lvl = (unsigned int)-1;
+                       ret = llapi_parse_compress_type(optarg,
+                                               &param.fp_compr_type,
+                                               (int *)&param.fp_compr_lvl,
+                                               &sign);
+                       if (ret) {
+                               fprintf(stderr,
+                                       "error: unknown compress type '%s'\n",
+                                       optarg);
+                               goto err;
+                       }
+
+                       param.fp_check_compr_type = 1;
+                       param.fp_exclude_compr_type = !!neg_opt;
+
+                       if (param.fp_compr_lvl != (unsigned int)-1) {
+                               if (sign == '+') {
+                                       param.fp_compr_lvl_sign = -1;
+                               } else if (sign == '-') {
+                                       param.fp_compr_lvl *= -1;
+                                       param.fp_compr_lvl_sign = 1;
+                               }
+                               param.fp_check_compr_lvl = 1;
+                               param.fp_exclude_compr_lvl = !!neg_opt;
+                       }
+                       break;
+               }
+               case LFS_COMPRESS_LEVEL_OPT:
+                       if (optarg[0] == '+') {
+                               param.fp_compr_lvl_sign = -1;
+                               optarg++;
+                       } else if (optarg[0] == '-') {
+                               param.fp_compr_lvl_sign = 1;
+                               optarg++;
+                       }
+                       param.fp_compr_lvl = atoi(optarg);
+                       if (param.fp_compr_lvl > COMPR_LEVEL_MAX) {
+                               fprintf(stderr,
+                                       "error: bad compress level '%s'\n",
+                                       optarg);
+                               goto err;
+                       }
+                       param.fp_check_compr_lvl = 1;
+                       param.fp_exclude_compr_lvl = !!neg_opt;
+                       break;
+               case LFS_COMPRESS_CHUNK_OPT: {
+                       unsigned long long chunk_size;
+                       unsigned long long size_units;
+
+                       if (optarg[0] == '+') {
+                               param.fp_compr_chunk_sign = -1;
+                               optarg++;
+                       } else if (optarg[0] == '-') {
+                               param.fp_compr_chunk_sign = 1;
+                               optarg++;
+                       }
+
+                       size_units = 1024; /* default in KiB */
+                       ret = llapi_parse_size(optarg, &chunk_size,
+                                              &size_units, 1);
+                       if (ret || chunk_size > 1ULL << COMPR_CHUNK_MAX_BITS) {
+                               fprintf(stderr,
+                                       "error: bad compress chunk size '%s'\n",
+                                       optarg);
+                               goto err;
+                       }
+                       /* find in KiB */
+                       param.fp_compr_chunk = chunk_size >> 10;
+                       param.fp_check_compr_chunk = 1;
+                       param.fp_exclude_compr_chunk = !!neg_opt;
+                       break;
+               }
                default:
                        ret = CMD_HELP;
                        goto err;
@@ -6016,22 +6079,22 @@ static int lfs_getstripe_internal(int argc, char **argv,
                        .name = "comp-start",   .has_arg = optional_argument },
        { .val = LFS_COMP_START_OPT,
                .name = "component-start",      .has_arg = optional_argument },
-       { .val = LFS_MIRROR_INDEX_OPT,
-               .name = "mirror-index",         .has_arg = required_argument },
-       { .val = LFS_MIRROR_ID_OPT,
-               .name = "mirror-id",            .has_arg = required_argument },
        { .val = LFS_COMPRESS_TYPE_OPT,
-               .name ="compress-type",         .has_arg = no_argument },
+               .name = "compress-type",        .has_arg = no_argument },
        { .val = LFS_COMPRESS_TYPE_OPT,
-               .name ="compr-type",            .has_arg = no_argument },
+               .name = "compr-type",           .has_arg = no_argument },
        { .val = LFS_COMPRESS_LEVEL_OPT,
-               .name ="compress-level",        .has_arg = no_argument },
+               .name = "compress-level",       .has_arg = no_argument },
        { .val = LFS_COMPRESS_LEVEL_OPT,
-               .name ="compr-level",           .has_arg = no_argument },
+               .name = "compr-level",          .has_arg = no_argument },
        { .val = LFS_COMPRESS_CHUNK_OPT,
-               .name ="compress-chunk",        .has_arg = no_argument },
+               .name = "compress-chunk",       .has_arg = no_argument },
        { .val = LFS_COMPRESS_CHUNK_OPT,
-               .name ="compr-chunk",           .has_arg = no_argument },
+               .name = "compr-chunk",          .has_arg = no_argument },
+       { .val = LFS_MIRROR_INDEX_OPT,
+               .name = "mirror-index",         .has_arg = required_argument },
+       { .val = LFS_MIRROR_ID_OPT,
+               .name = "mirror-id",            .has_arg = required_argument },
        { .val = 'c',   .name = "stripe-count", .has_arg = no_argument },
        { .val = 'c',   .name = "stripe_count", .has_arg = no_argument },
 /* find        { .val = 'C',   .name = "ctime",        .has_arg = required_argument }*/
@@ -6074,6 +6137,8 @@ static int lfs_getstripe_internal(int argc, char **argv,
        { .val = 'y',   .name = "yaml",         .has_arg = no_argument },
        { .val = 'z',   .name = "extension-size", .has_arg = no_argument },
        { .val = 'z',   .name = "ext-size",     .has_arg = no_argument },
+       { .val = 'Z',   .name = "compress",     .has_arg = no_argument },
+       { .val = 'Z',   .name = "compr",        .has_arg = no_argument },
        { .name = NULL } };
        int c, rc;
        int neg_opt = 0;
@@ -6082,7 +6147,7 @@ static int lfs_getstripe_internal(int argc, char **argv,
        char *end, *tmp;
 
        while ((c = getopt_long(argc, argv,
-                       "-cdDE::FghiI::LmMNoO:pqrRsSvyz",
+                       "-cdDE::FghiI::LmMNoO:pqrRsSvyzZ",
                        long_opts, NULL)) != -1) {
                if (neg_opt)
                        --neg_opt;
@@ -6226,27 +6291,6 @@ static int lfs_getstripe_internal(int argc, char **argv,
                        param->fp_exclude_mirror_id = !!neg_opt;
                        break;
                }
-               case LFS_COMPRESS_TYPE_OPT: {
-                       if (!(param->fp_verbose & VERBOSE_DETAIL)) {
-                               param->fp_verbose |= VERBOSE_COMPRESS_TYPE;
-                               param->fp_max_depth = 0;
-                       }
-                       break;
-               }
-               case LFS_COMPRESS_LEVEL_OPT: {
-                       if (!(param->fp_verbose & VERBOSE_DETAIL)) {
-                               param->fp_verbose |= VERBOSE_COMPRESS_LEVEL;
-                               param->fp_max_depth = 0;
-                       }
-                       break;
-               }
-               case LFS_COMPRESS_CHUNK_OPT: {
-                       if (!(param->fp_verbose & VERBOSE_DETAIL)) {
-                               param->fp_verbose |= VERBOSE_COMPRESS_CHUNK;
-                               param->fp_max_depth = 0;
-                       }
-                       break;
-               }
                case 'd':
                        param->fp_max_depth = 0;
                        break;
@@ -6386,6 +6430,32 @@ static int lfs_getstripe_internal(int argc, char **argv,
                                param->fp_max_depth = 0;
                        }
                        break;
+               case 'Z':
+                       if (!(param->fp_verbose & VERBOSE_DETAIL)) {
+                               param->fp_verbose |= VERBOSE_COMPRESS_TYPE |
+                                                    VERBOSE_COMPRESS_LEVEL |
+                                                    VERBOSE_COMPRESS_CHUNK;
+                               param->fp_max_depth = 0;
+                       }
+                       break;
+               case LFS_COMPRESS_TYPE_OPT:
+                       if (!(param->fp_verbose & VERBOSE_DETAIL)) {
+                               param->fp_verbose |= VERBOSE_COMPRESS_TYPE;
+                               param->fp_max_depth = 0;
+                       }
+                       break;
+               case LFS_COMPRESS_LEVEL_OPT:
+                       if (!(param->fp_verbose & VERBOSE_DETAIL)) {
+                               param->fp_verbose |= VERBOSE_COMPRESS_LEVEL;
+                               param->fp_max_depth = 0;
+                       }
+                       break;
+               case LFS_COMPRESS_CHUNK_OPT:
+                       if (!(param->fp_verbose & VERBOSE_DETAIL)) {
+                               param->fp_verbose |= VERBOSE_COMPRESS_CHUNK;
+                               param->fp_max_depth = 0;
+                       }
+                       break;
                default:
                        return CMD_HELP;
                }
index 7cb5367..a9cf192 100644 (file)
@@ -1496,19 +1496,31 @@ static inline int msb_index(__u32 x)
  * -Z gzip:9
  * -Z fast
  * -Z best
+ *
+ * \param[in]  optarg  specified compression parameters
+ * \param[out] type    parsed compression type
+ * \param[out] level   parsed compression level
+ * \param[out] sign    parsed compression level sign
+ *
+ * \retval     0 on success
+ * \retval      -ve error number if arguments are invalid and sets errno
  */
 int llapi_parse_compress_type(const char *optarg, unsigned int *type,
-                             int *level)
+                             int *level, char *sign)
 {
-       char *ptr;
        char *argbuf = (char *)optarg;
-       int i;
+       char *ptr;
        bool found = false;
+       int i;
 
        ptr = strchr(argbuf, ':');
        if (ptr) {
                *ptr = '\0';
                ptr++;
+               if (sign)
+                       *sign = *ptr;
+       } else if (sign) {
+               *sign = '\0';
        }
 
        for (i = 0; i < ARRAY_SIZE(compr_type_table); i++) {
@@ -1520,19 +1532,24 @@ int llapi_parse_compress_type(const char *optarg, unsigned int *type,
        }
 
        if (!found)
-               return -1;
+               goto fail;
 
-       if (!level)
+       if (!level || !ptr)
                return 0;
 
-       if (ptr)
-               *level = strtoul(ptr, NULL, 0);
+       *level = strtoul(ptr, NULL, 0);
+       if (*level < -COMPR_LEVEL_MAX || *level > COMPR_LEVEL_MAX)
+               goto fail;
 
        if (*type == LL_COMPR_TYPE_LZ4HC && *level < LZ4HC_MIN_CLEVEL)
                /* if not an HC level, just use standard lz4 default */
                *level = LZ4_ACCELERATION_DEFAULT;
 
        return 0;
+
+fail:
+       errno = EINVAL;
+       return -errno;
 }
 
 /**
@@ -1542,20 +1559,20 @@ int llapi_parse_compress_type(const char *optarg, unsigned int *type,
  * \param[in] type     compress type
  * \param[in] level    compress level
  * \param[in] chunk_size       compress chunk size, the log bits is
- *                             (chunksize = 2^(chunk_log_bits + 16))
+ *                             (chunksize = 2^(chunk_log_bits + 16))
  * \param[in] stripe_size      stripe size, it must be a multiple of chunk size
  *
  * \retval     0 on success
- * \retval     -1 if arguments are invalid
+ * \retval     -ve error number if arguments are invalid and sets errno
  */
 int llapi_layout_compress_set(struct llapi_layout *layout,
                              enum ll_compr_type type, int level,
                              __u32 chunk_size, unsigned long long stripe_size)
 {
        struct llapi_layout_comp *comp;
-       int i;
        bool compr_level_set = false;
        int log_bits;
+       int i;
 
        comp = __llapi_layout_cur_comp(layout);
        if (comp == NULL)
@@ -1599,32 +1616,37 @@ int llapi_layout_compress_set(struct llapi_layout *layout,
         * adjust chunk_size to be power-of-two multiples of 64KiB,
         * llc_chunk_log_bits is limited to 4bits unsigned value.
         */
-       if (chunk_size <= (__u32)(1 << 16))
+       if (chunk_size <= (1U << COMPR_CHUNK_MIN_BITS))
                comp->llc_compr_chunk_log_bits = 0;
-       else if (chunk_size >= (__u32)(1 << 31))
-               comp->llc_compr_chunk_log_bits = 15;
+       else if (chunk_size >= (1U << COMPR_CHUNK_MAX_BITS))
+               comp->llc_compr_chunk_log_bits = COMPR_CHUNK_MAX_BITS -
+                                                COMPR_CHUNK_MIN_BITS;
        else
-               comp->llc_compr_chunk_log_bits = msb_index(chunk_size) - 16;
+               comp->llc_compr_chunk_log_bits = msb_index(chunk_size) -
+                                                COMPR_CHUNK_MIN_BITS;
 
        /* stripe size must be a multiple of chunk size */
        if (stripe_size != LLAPI_LAYOUT_DEFAULT) {
-               log_bits = comp->llc_compr_chunk_log_bits + 16;
+               log_bits = comp->llc_compr_chunk_log_bits +
+                          COMPR_CHUNK_MIN_BITS;
 
                while ((1 << log_bits) > stripe_size ||
                       stripe_size & ((1 << log_bits) - 1))
                        log_bits--;
 
-               if (log_bits < 16 || log_bits > 31)
+               if (log_bits < COMPR_CHUNK_MIN_BITS ||
+                   log_bits > COMPR_CHUNK_MAX_BITS)
                        goto fail;
-               else
-                       comp->llc_compr_chunk_log_bits = log_bits - 16;
+
+               comp->llc_compr_chunk_log_bits = log_bits -
+                                                COMPR_CHUNK_MIN_BITS;
        }
 
        return 0;
 
 fail:
        errno = EINVAL;
-       return -1;
+       return -errno;
 }
 
 int llapi_layout_compress_get(struct llapi_layout *layout,