Whamcloud - gitweb
LU-4824 utils: lfs find should continue after errors 94/9794/11
authorMatt Ezell <ezellma@ornl.gov>
Wed, 26 Mar 2014 15:00:16 +0000 (11:00 -0400)
committerOleg Drokin <oleg.drokin@intel.com>
Mon, 16 Jun 2014 02:01:28 +0000 (02:01 +0000)
'lfs find' stops as soon as it encounters an error, such as EACCES.
Change the behavior to match the regular find command: just note the
failure but continue on, returning a non-zero exit code at the end.

Signed-off-by: Matt Ezell <ezellma@ornl.gov>
Change-Id: I16ca35ec193e36134e7b93d91a20ff1d0778fe60
Reviewed-on: http://review.whamcloud.com/9794
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: James Nunez <james.a.nunez@intel.com>
Reviewed-by: James Simmons <uja.ornl@gmail.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/tests/sanity.sh
lustre/utils/lfs.c
lustre/utils/liblustreapi.c

index 43888b0..6b308d0 100644 (file)
@@ -4910,6 +4910,30 @@ test_56y() {
 }
 run_test 56y "lfs find -L raid0|released"
 
+test_56z() { # LU-4824
+       # This checks to make sure 'lfs find' continues after errors
+       # There are two classes of errors that should be caught:
+       # - If multiple paths are provided, all should be searched even if one
+       #   errors out
+       # - If errors are encountered during the search, it should not terminate
+       #   early
+       local i
+       test_mkdir $DIR/$tdir
+       for i in d{0..9}; do
+               test_mkdir $DIR/$tdir/$i
+       done
+       touch $DIR/$tdir/d{0..9}/$tfile
+       $LFS find $DIR/non_existent_dir $DIR/$tdir &&
+               error "$LFS find did not return an error"
+       # Make a directory unsearchable. This should NOT be the last entry in
+       # directory order.  Arbitrarily pick the 6th entry
+       chmod 700 $(lfs find $DIR/$tdir -type d | sed '6!d')
+       local count=$($RUNAS $LFS find $DIR/non_existent $DIR/$tdir | wc -l)
+       # The user should be able to see 10 directories and 9 files
+       [ $count == 19 ] || error "$LFS find did not continue after error"
+}
+run_test 56z "lfs find should continue after an error"
+
 test_57a() {
        [ $PARALLEL == "yes" ] && skip "skip parallel run" && return
        # note test will not do anything if MDS is not local
index 3c71801..daba1eb 100644 (file)
@@ -882,7 +882,8 @@ static int name2layout(__u32 *layout, char *name)
 #define FIND_POOL_OPT 3
 static int lfs_find(int argc, char **argv)
 {
-        int c, ret;
+       int c, rc;
+       int ret = 0;
         time_t t;
        struct find_param param = {
                .fp_max_depth = -1,
@@ -984,14 +985,14 @@ static int lfs_find(int argc, char **argv)
                                xsign = &param.fp_msign;
                                param.fp_exclude_mtime = !!neg_opt;
                        }
-                        ret = set_time(&t, xtime, optarg);
-                        if (ret == INT_MAX) {
-                                ret = -1;
-                                goto err;
-                        }
-                        if (ret)
-                                *xsign = ret;
-                        break;
+                       rc = set_time(&t, xtime, optarg);
+                       if (rc == INT_MAX) {
+                               ret = -1;
+                               goto err;
+                       }
+                       if (rc)
+                               *xsign = rc;
+                       break;
                 case 'c':
                         if (optarg[0] == '+') {
                                 param.stripecount_sign = -1;
@@ -1016,8 +1017,8 @@ static int lfs_find(int argc, char **argv)
                        break;
                case 'g':
                case 'G':
-                       ret = name2id(&param.fp_gid, optarg, GROUP);
-                       if (ret) {
+                       rc = name2id(&param.fp_gid, optarg, GROUP);
+                       if (rc) {
                                param.fp_gid = strtoul(optarg, &endptr, 10);
                                 if (*endptr != '\0') {
                                         fprintf(stderr, "Group/GID: %s cannot "
@@ -1038,8 +1039,8 @@ static int lfs_find(int argc, char **argv)
                        break;
                 case 'u':
                 case 'U':
-                       ret = name2id(&param.fp_uid, optarg, USER);
-                       if (ret) {
+                       rc = name2id(&param.fp_uid, optarg, USER);
+                       if (rc) {
                                param.fp_uid = strtoul(optarg, &endptr, 10);
                                 if (*endptr != '\0') {
                                         fprintf(stderr, "User/UID: %s cannot "
@@ -1228,9 +1229,11 @@ err_free:
                 pathend = argc;
         }
 
-        do {
-                ret = llapi_find(argv[pathstart], &param);
-        } while (++pathstart < pathend && !ret);
+       do {
+               rc = llapi_find(argv[pathstart], &param);
+               if (rc != 0 && ret == 0)
+                       ret = rc;
+       } while (++pathstart < pathend);
 
         if (ret)
                 fprintf(stderr, "error: %s failed for %s.\n",
index 56804b8..5247d58 100644 (file)
@@ -1559,8 +1559,8 @@ static int llapi_semantic_traverse(char *path, int size, DIR *parent,
        int len, ret;
        DIR *d, *p = NULL;
 
-        ret = 0;
-        len = strlen(path);
+       ret = 0;
+       len = strlen(path);
 
         d = opendir(path);
         if (!d && errno != ENOTDIR) {
@@ -1580,12 +1580,12 @@ static int llapi_semantic_traverse(char *path, int size, DIR *parent,
        if (sem_init && (ret = sem_init(path, parent ?: p, &d, data, de)))
                goto err;
 
-       if (!d || (param->get_lmv && !param->recursive)) {
-               ret = 0;
+       if (!d || (param->get_lmv && !param->recursive))
                goto out;
-       }
 
        while ((dent = readdir64(d)) != NULL) {
+               int rc;
+
                param->have_fileinfo = 0;
 
                 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
@@ -1608,13 +1608,15 @@ static int llapi_semantic_traverse(char *path, int size, DIR *parent,
                 if (dent->d_type == DT_UNKNOWN) {
                        lstat_t *st = &param->lmd->lmd_st;
 
-                       ret = get_lmd_info(path, d, NULL, param->lmd,
+                       rc = get_lmd_info(path, d, NULL, param->lmd,
                                           param->lumlen);
-                       if (ret == 0)
+                       if (rc == 0)
                                dent->d_type = IFTODT(st->st_mode);
+                       else if (ret == 0)
+                               ret = rc;
 
-                        if (ret == -ENOENT)
-                                continue;
+                       if (rc == -ENOENT)
+                               continue;
                }
                 switch (dent->d_type) {
                 case DT_UNKNOWN:
@@ -1622,21 +1624,21 @@ static int llapi_semantic_traverse(char *path, int size, DIR *parent,
                                           "error: %s: '%s' is UNKNOWN type %d",
                                           __func__, dent->d_name, dent->d_type);
                         break;
-                case DT_DIR:
-                        ret = llapi_semantic_traverse(path, size, d, sem_init,
-                                                      sem_fini, data, dent);
-                        if (ret < 0)
-                                goto out;
-                        break;
-                default:
-                        ret = 0;
-                        if (sem_init) {
-                                ret = sem_init(path, d, NULL, data, dent);
-                                if (ret < 0)
-                                        goto out;
-                        }
-                        if (sem_fini && ret == 0)
-                                sem_fini(path, d, NULL, data, dent);
+               case DT_DIR:
+                       rc = llapi_semantic_traverse(path, size, d, sem_init,
+                                                     sem_fini, data, dent);
+                       if (rc != 0 && ret == 0)
+                               ret = rc;
+                       break;
+               default:
+                       rc = 0;
+                       if (sem_init) {
+                               rc = sem_init(path, d, NULL, data, dent);
+                               if (rc < 0 && ret == 0)
+                                       ret = rc;
+                       }
+                       if (sem_fini && rc == 0)
+                               sem_fini(path, d, NULL, data, dent);
                 }
         }
 
@@ -1650,7 +1652,7 @@ err:
                 closedir(d);
         if (p)
                 closedir(p);
-        return ret;
+       return ret;
 }
 
 static int param_callback(char *path, semantic_func_t sem_init,