From: Matt Ezell Date: Wed, 26 Mar 2014 15:00:16 +0000 (-0400) Subject: LU-4824 utils: lfs find should continue after errors X-Git-Tag: 2.6.0-RC1~108 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=785e7dc56613e79bdfd89fab762eeb82deb7564c LU-4824 utils: lfs find should continue after errors '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 Change-Id: I16ca35ec193e36134e7b93d91a20ff1d0778fe60 Reviewed-on: http://review.whamcloud.com/9794 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: James Nunez Reviewed-by: James Simmons Reviewed-by: Oleg Drokin --- diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 43888b0..6b308d0 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -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 diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 3c71801..daba1eb 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -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 = ¶m.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(¶m.fp_gid, optarg, GROUP); - if (ret) { + rc = name2id(¶m.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(¶m.fp_uid, optarg, USER); - if (ret) { + rc = name2id(¶m.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], ¶m); - } while (++pathstart < pathend && !ret); + do { + rc = llapi_find(argv[pathstart], ¶m); + if (rc != 0 && ret == 0) + ret = rc; + } while (++pathstart < pathend); if (ret) fprintf(stderr, "error: %s failed for %s.\n", diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index 56804b8..5247d58 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -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 = ¶m->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,