Whamcloud - gitweb
LU-16622 utils: 'lfs find --ost' supports index range 02/55902/5
authorLei Feng <flei@whamcloud.com>
Tue, 30 Jul 2024 04:14:18 +0000 (12:14 +0800)
committerOleg Drokin <green@whamcloud.com>
Mon, 2 Dec 2024 05:47:01 +0000 (05:47 +0000)
'lfs find --ost' command can accept an index range. For example
    lfs find --ost 0,1-3
It equals to:
    lfs find --ost 0,1,2,3
'lfs find --mdt' can accept index range too.

Signed-off-by: Lei Feng <flei@whamcloud.com>
Test-Parameters: trivial
Change-Id: I094aa480c97440dad8ffaac8af902682b5916d6c
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55902
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Emoly Liu <emoly@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
lustre/doc/lfs-find.1
lustre/tests/sanity.sh
lustre/utils/lfs.c

index 7d1d6ee..352790f 100644 (file)
@@ -81,7 +81,7 @@ lfs-find \- Lustre client utility to list files with specific attributes
 .br
 .RB [[ ! ]
 .BR --mdt | --mdt-index | -m
-.IR UUID | INDEX ", ...]"
+.IR UUID | INDEX | INDEX_RANGE ", ...]"
 .br
 .RB [[ ! ]
 .BR --mdt-count | -T
@@ -113,7 +113,7 @@ lfs-find \- Lustre client utility to list files with specific attributes
 .IR REFERENCE ]
 .RB [[ ! ]
 .BR --ost | -O
-.IR INDEX ", ...]"
+.IR INDEX | INDEX_RANGE ", ...]"
 .br
 .RB [[ ! ]
 .B --perm
@@ -469,7 +469,7 @@ this test will fail for any files where the birth time is unknown.
 .BR -O ", " --ost
 File has an object on the specified OST(s).
 The OST names can be specified using the whole OST target name,
-or just the OST index number.
+or just the OST index number, or OST index range like 0-3.
 If multiple OSTs are given in a comma-separated list,
 the file may have an object on any of the given OSTs.
 Specifying multiple OSTs allows scanning the filesystem only once
index d3cda5d..945a0fb 100755 (executable)
@@ -7124,6 +7124,33 @@ test_56i() {
 }
 run_test 56i "check 'lfs find -ost UUID' skips directories"
 
+test_56ib() {
+       local dir=$DIR/$tdir
+       local file=$dir/$tfile
+       local idx=$((RANDOM % $OSTCOUNT))
+       local find_file
+       local cmd
+
+       test_mkdir $dir
+       echo "create file $file on OST $idx"
+       $LFS setstripe $file -o $idx||
+               error "failed to create test file $file"
+
+       cmd="$LFS find --ost 0,1-$idx,$idx $dir"
+       echo "Command: $cmd"
+       find_file=$($cmd)
+       echo "lfs find result: $find_file"
+       [[ "$find_file" == "$file" ]] ||
+               error "file $file is NOT found"
+
+       cmd="$LFS find ! --ost $idx-$((OSTCOUNT-1)),$idx $dir"
+       echo "Command: $cmd"
+       find_file=$($cmd)
+       [[ -z "$find_file" ]]  ||
+               error "should NOT find any file, but find $find_file"
+}
+run_test 56ib "check 'lfs find -ost INDEX_RANGE' command"
+
 test_56j() {
        local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE
 
index bbb4284..fb9b9c1 100755 (executable)
@@ -51,6 +51,7 @@
 #include <err.h>
 #include <pwd.h>
 #include <grp.h>
+#include <regex.h>
 #include <sys/ioctl.h>
 #include <sys/quota.h>
 #include <sys/time.h>
@@ -6160,79 +6161,96 @@ static int lfs_find(int argc, char **argv)
                case 'm':
                case 'i':
                case 'O': {
-                       char *buf, *token, *next, *p;
-                       int len = 1;
-                       void *tmp;
-
-                       buf = strdup(optarg);
-                       if (!buf) {
-                               ret = -ENOMEM;
-                               goto err;
-                       }
+                       int len, rc2;
+                       int *p_num, *p_alloc;
+                       struct obd_uuid **pp_uuid, *tmp;
+                       const char *p1 = optarg, *p2;
+                       char buf[UUID_MAX];
+                       const char *pattern = "^([0-9]+)-([0-9]+)$";
+                       regex_t reg;
+                       regmatch_t pmatch[3];
 
                        param.fp_exclude_obd = !!neg_opt;
-
-                       token = buf;
-                       while (token && *token) {
-                               token = strchr(token, ',');
-                               if (token) {
-                                       len++;
-                                       token++;
-                               }
-                       }
                        if (c == 'm') {
-                               param.fp_exclude_mdt = !!neg_opt;
-                               param.fp_num_alloc_mdts += len;
-                               tmp = realloc(param.fp_mdt_uuid,
-                                             param.fp_num_alloc_mdts *
-                                             sizeof(*param.fp_mdt_uuid));
-                               if (!tmp) {
-                                       ret = -ENOMEM;
-                                       goto err_free;
-                               }
-
-                               param.fp_mdt_uuid = tmp;
+                               p_num = &param.fp_num_mdts;
+                               p_alloc = &param.fp_num_alloc_mdts;
+                               pp_uuid = &param.fp_mdt_uuid;
                        } else {
-                               param.fp_exclude_obd = !!neg_opt;
-                               param.fp_num_alloc_obds += len;
-                               tmp = realloc(param.fp_obd_uuid,
-                                             param.fp_num_alloc_obds *
-                                             sizeof(*param.fp_obd_uuid));
-                               if (!tmp) {
-                                       ret = -ENOMEM;
-                                       goto err_free;
-                               }
-
-                               param.fp_obd_uuid = tmp;
+                               p_num = &param.fp_num_obds;
+                               p_alloc = &param.fp_num_alloc_obds;
+                               pp_uuid = &param.fp_obd_uuid;
                        }
-                       for (token = buf; token && *token; token = next) {
-                               struct obd_uuid *puuid;
+                       regcomp(&reg, pattern, REG_EXTENDED);
 
-                               if (c == 'm') {
-                                       puuid =
-                                       &param.fp_mdt_uuid[param.fp_num_mdts++];
-                               } else {
-                                       puuid =
-                                       &param.fp_obd_uuid[param.fp_num_obds++];
-                               }
-                               p = strchr(token, ',');
-                               next = 0;
-                               if (p) {
-                                       *p = 0;
-                                       next = p+1;
-                               }
+                       while (p1 && *p1 != '\0') {
+                               /* grab one uuid/idx/idx_range */
+                               p2 = strchr(p1, ',');
+                               if (p2 == NULL)
+                                       p2 = p1 + strlen(p1);
 
-                               if (strlen(token) > sizeof(puuid->uuid) - 1) {
+                               len = p2 - p1;
+                               if (len >= sizeof(buf)) {
+                                       regfree(&reg);
                                        ret = -E2BIG;
-                                       goto err_free;
+                                       goto err;
+                               }
+                               strncpy(buf, p1, len);
+                               buf[len] = '\0';
+
+                               if (*p2 == '\0')
+                                       p1 = p2;
+                               else
+                                       p1 = p2 + 1;
+
+                               /* extend array if necessary */
+                               if (*p_num >= *p_alloc) {
+                                       tmp = realloc(*pp_uuid,
+                                                     (*p_alloc + 16) *
+                                                     sizeof((*pp_uuid)[0]));
+                                       if (tmp == NULL) {
+                                               regfree(&reg);
+                                               ret = -ENOMEM;
+                                               goto err;
+                                       }
+                                       *pp_uuid = tmp;
+                                       *p_alloc += 16;
                                }
 
-                               strncpy(puuid->uuid, token,
-                                       sizeof(puuid->uuid));
+                               /* check pattern */
+                               rc2 = regexec(&reg, buf, 3, pmatch, 0);
+                               if (rc2 == 0) {
+                                       /* idx range such as 0-3 */
+                                       int start, end;
+
+                                       start = atoi(&buf[pmatch[1].rm_so]);
+                                       end = atoi(&buf[pmatch[2].rm_so]);
+                                       for ( ; start <= end; start++) {
+                                               if (*p_num >= *p_alloc) {
+                                                       tmp = realloc(*pp_uuid,
+                                                                     (*p_alloc + 16) *
+                                                                     sizeof((*pp_uuid)[0]));
+                                                       if (tmp == NULL) {
+                                                               regfree(&reg);
+                                                               ret = -ENOMEM;
+                                                               goto err;
+                                                       }
+                                                       *pp_uuid = tmp;
+                                                       *p_alloc += 16;
+                                               }
+                                               sprintf(buf, "%d", start);
+                                               strcpy((*pp_uuid)[(*p_num)++].uuid, buf);
+                                       }
+                               } else if (rc2 == REG_NOMATCH) {
+                                       /* single idx or uuid */
+                                       strcpy((*pp_uuid)[(*p_num)++].uuid, buf);
+                               } else {
+                                       regfree(&reg);
+                                       ret = -errno;
+                                       goto err;
+                               }
                        }
-err_free:
-                       if (buf)
-                               free(buf);
+
+                       regfree(&reg);
                        break;
                }
 #if LUSTRE_VERSION_CODE >= OBD_OCD_VERSION(2, 18, 53, 0)