From 919f2c921866b8ab1f9cad3fe8d86eee7924e85d Mon Sep 17 00:00:00 2001 From: Maximilian Dilger Date: Tue, 28 May 2024 13:55:27 -0400 Subject: [PATCH] LU-10522 utils: new --mindepth for lfs find Added [--mindepth | -d] option for 'lfs find' to print only the results found after N levels. Similar usage to existing mindepth found in find. Signed-off-by: Maximilian Dilger Change-Id: I7816e27355f6796edc8437f700342da1b7e564d0 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55226 Reviewed-by: Andreas Dilger Reviewed-by: Jian Yu Reviewed-by: Oleg Drokin Tested-by: jenkins Tested-by: Maloo --- lustre/doc/lfs-find.1 | 5 ++++- lustre/doc/lfs.1 | 2 +- lustre/include/lustre/lustreapi.h | 1 + lustre/tests/sanity.sh | 20 ++++++++++++++++++++ lustre/utils/lfs.c | 25 +++++++++++++++++++++++-- lustre/utils/liblustreapi.c | 5 +++++ 6 files changed, 54 insertions(+), 4 deletions(-) diff --git a/lustre/doc/lfs-find.1 b/lustre/doc/lfs-find.1 index 9a9a6ba..09a1bbc 100644 --- a/lustre/doc/lfs-find.1 +++ b/lustre/doc/lfs-find.1 @@ -18,7 +18,7 @@ lfs-find \- Lustre client utility to list files with specific attributes [\fB--help\fR|\fB-h\fR] [[\fB!\fR] \fB--layout\fR|\fB-L mdt\fR,\fBraid0\fR,\fBreleased\fR] [\fB--lazy|-l\fR] - [[\fB!\fR] \fB--links\fR [\fB+-\fR]\fIn\fR] [\fB--maxdepth\fR|\fB-D\fI n\fR] + [[\fB!\fR] \fB--links\fR [\fB+-\fR]\fIn\fR] [\fB--maxdepth\fR|\fB-D\fI n\fR] [\fB--mindepth\fR|\fB-d\fI n\fR] [[\fB!\fR] \fB--mdt\fR|\fB--mdt-index\fR|\fB-m\fR \fIUUID\fR|\fIINDEX\fR,...] [[\fB!\fR] \fB--mdt-count\fR|\fB-T\fR [\fB+-\fR]\fIn\fR] [[\fB!\fR] \fB--mdt-hash\fR|\fB-H \fR<[^]\fIHASHFLAG\fR,[^]\fIHASHTYPE\fR,...>] @@ -174,6 +174,9 @@ File has \fIn\fR links. .BR --maxdepth Limits find to decend at most \fIn\fR levels of directory tree. .TP +.BR --mindepth +Starts find at \fIn\fR levels of directory tree. +.TP .BR --mdt | --mdt-index | -m File or directory inode is located on the specified MDT(s). .TP diff --git a/lustre/doc/lfs.1 b/lustre/doc/lfs.1 index 7746b82..de7ab1d 100644 --- a/lustre/doc/lfs.1 +++ b/lustre/doc/lfs.1 @@ -27,7 +27,7 @@ lfs \- client utility for Lustre-specific file layout and other attributes [[\fB!\fR] \fB--mirror-state\fR <[^]\fIstate\fR>] [[\fB!\fR] \fB--gid\fR|\fB-g\fR|\fB--group\fR|\fB-G\fR <\fIgname\fR>|<\fIgid\fR>] [[\fB!\fR] \fB--layout\fR|\fB-L mdt\fR,\fBraid0\fR,\fBreleased\fR] -[\fB--maxdepth\fR|\fB-D\fI n\fR] +[\fB--maxdepth\fR|\fB-D\fI n\fR] [\fB--mindepth\fR|\fB-d\fI n\fR] [[\fB!\fR] \fB--mdt\fR|\fB--mdt-index\fR|\fB-m\fR <\fIuuid\fR|\fIindex\fR,...>] [[\fB!\fR] \fB--mdt-count\fR|\fB-T\fR [\fB+-\fR]\fIn\fR] [[\fB!\fR] \fB--mdt-hash\fR|\fB-H \fI\fR] diff --git a/lustre/include/lustre/lustreapi.h b/lustre/include/lustre/lustreapi.h index 5be8c33..5b7bb4a 100644 --- a/lustre/include/lustre/lustreapi.h +++ b/lustre/include/lustre/lustreapi.h @@ -268,6 +268,7 @@ struct xattr_match_info { */ struct find_param { unsigned int fp_max_depth; + unsigned int fp_min_depth; dev_t fp_dev; mode_t fp_type; /* S_IFIFO,... */ uid_t fp_uid; diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 83bb14a..1a08b90 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -9040,6 +9040,26 @@ test_56dc() { } run_test 56dc "test 'lfs df -o' only shows OST devices" +test_56dd() { + local dir=$DIR/d$(basetest $testnum)g.$TESTSUITE + + setup_56 $dir $NUMFILES $NUMDIRS + + local lfscount=($($LFS find $dir -mindepth 1 -maxdepth 2 | sort)) + local findcount=($(find $dir -mindepth 1 -maxdepth 2 | sort)) + + if [[ ${#lfscount[@]} != ${#findcount[@]} ]]; then + error "lfs find returned ${#lfscount[@]} files, find returned ${#findcount[@]} files" + fi + + for ((i = 0; i < ${#lfscount[@]}; i++)); do + [[ "${lfscount[$i]}" == "${findcount[$i]}" ]] && + echo "${lfscount[$i]}" || + error "${#lfscount[@]} != ${#findcount[@]}" + done +} +run_test 56dd "test lfs find with mindepth argument" + test_56ea() { #LU-10378 local path=$DIR/$tdir local pool=$TESTNAME diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 24a50ec..f779290 100755 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -391,7 +391,8 @@ command_t cmdlist[] = { " [[!] --foreign[=]]\n" " [[!] --gid|-g|--group|-G |] [--help|-h]\n" " [[!] --layout|-L released,raid0,mdt] [--lazy|-l] [[!] --links [+-]n]\n" - " [--maxdepth|-D N] [[!] --mdt-count|-T [+-]]\n" + " [--maxdepth|-D N] [--mindepth|-d N]\n" + " [[!] --mdt-count|-T [+-]]\n" " [[!] --mdt-hash|-H <[^][blm],[^]fnv_1a_64,all_char,crush,...>\n" " [[!] --mdt-index|--mdt|-m ]\n" " [[!] --mirror-count|-N [+-]]\n" @@ -5321,6 +5322,7 @@ static int lfs_find(int argc, char **argv) time_t t; struct find_param param = { .fp_max_depth = -1, + .fp_min_depth = 0, .fp_quiet = 1, .fp_time_margin = FP_DEFAULT_TIME_MARGIN, }; @@ -5404,6 +5406,7 @@ static int lfs_find(int argc, char **argv) { .val = 'c', .name = "stripe_count", .has_arg = required_argument }, { .val = 'C', .name = "ctime", .has_arg = required_argument }, /* getstripe { .val = 'd', .name = "directory", .has_arg = no_argument }, */ + { .val = 'd', .name = "mindepth", .has_arg = required_argument }, { .val = 'D', .name = "maxdepth", .has_arg = required_argument }, { .val = 'E', .name = "comp-end", .has_arg = required_argument }, { .val = 'E', .name = "component-end", @@ -5475,7 +5478,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:hH:i:k:lL:m:M:n:N:O:Ppqrs:S:t:T:u:U:z:", + "-0A:b:B:c:C:d:D:E:g:G:hH:i:k:lL:m:M:n:N:O:Ppqrs:S:t:T:u:U:z:", long_opts, &optidx)) >= 0) { xtime = NULL; xsign = NULL; @@ -5676,6 +5679,17 @@ static int lfs_find(int argc, char **argv) param.fp_check_stripe_count = 1; param.fp_exclude_stripe_count = !!neg_opt; break; + case 'd': + errno = 0; + param.fp_min_depth = strtoul(optarg, 0, 0); + if (errno != 0 || param.fp_min_depth > PATH_MAX / 2) { + fprintf(stderr, + "error: bad mindepth '%s'\n", + optarg); + ret = -1; + goto err; + } + break; case 'D': errno = 0; param.fp_max_depth = strtol(optarg, 0, 0); @@ -6281,6 +6295,13 @@ err_free: pathend = argc; } + if (param.fp_min_depth > param.fp_max_depth) { + fprintf(stderr, "error: %s: mindepth %u > maxdepth %u\n", + argv[0], param.fp_min_depth, param.fp_max_depth); + ret = CMD_HELP; + goto err; + } + do { rc = llapi_find(argv[pathstart], ¶m); if (rc) { diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index 2693b3e..d46da02 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -2022,6 +2022,7 @@ static int llapi_semantic_traverse(char *path, int size, int parent, __func__, dent->d_name, dent->d_type); break; case DT_DIR: + /* recursion down into a new subdirectory here */ rc = llapi_semantic_traverse(path, size, d, sem_init, sem_fini, data, dent); if (rc != 0 && ret == 0) @@ -5575,6 +5576,9 @@ static int cb_find_init(char *path, int p, int *dp, if (p == -1 && d == -1) return -EINVAL; + /* if below minimum depth do not process further */ + if (param->fp_depth < param->fp_min_depth) + goto decided; /* Reset this value between invocations */ param->fp_get_lmv = 0; @@ -6121,6 +6125,7 @@ print: llapi_printf(LLAPI_MSG_NORMAL, "%s%c", path, param->fp_zero_end ? '\0' : '\n'); + decided: ret = 0; /* Do not get down anymore? */ -- 1.8.3.1