From 6f2b56e0fd8e60137b8fcacd82ce1bea4c07f9a6 Mon Sep 17 00:00:00 2001 From: Lei Feng Date: Tue, 1 Nov 2022 10:57:39 +0800 Subject: [PATCH] LU-16284 utils: lfs getstripe follows symlink 'lfs getstripe' prints the information of symlink target by default. With '--no-follow' option it prints the information of symlink itself. Lustre-change: https://review.whamcloud.com/49003 Lustre-commit: af32b516593dbf2a8e7a85d885c33fd017926ada Signed-off-by: Lei Feng Test-Parameters: trivial Change-Id: I6cef01af5bb2235bdcbf0b5c99af4b9ed5869515 Reviewed-by: Andreas Dilger Reviewed-by: Jian Yu Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/53162 Reviewed-by: Oleg Drokin Tested-by: jenkins Tested-by: Maloo --- lustre/doc/lfs-getstripe.1 | 6 +++++- lustre/include/lustre/lustreapi.h | 3 ++- lustre/tests/sanity.sh | 26 ++++++++++++++++++++++++++ lustre/utils/lfs.c | 7 +++++++ lustre/utils/liblustreapi.c | 27 +++++++++++++++++++++++---- 5 files changed, 63 insertions(+), 6 deletions(-) diff --git a/lustre/doc/lfs-getstripe.1 b/lustre/doc/lfs-getstripe.1 index aa3a8df..5854bbc 100644 --- a/lustre/doc/lfs-getstripe.1 +++ b/lustre/doc/lfs-getstripe.1 @@ -25,8 +25,9 @@ lfs getstripe \- Lustre client command to print layout parameters of a file [\fB--stripe-size\fR|\fB-S\fR] [\fB--mirror-count\fR|\fB-N\fR] [[\fB!\fR] \fB--mirror-index\fR=[\fB+-\fR]\fI\fR | [\fB!\fR] \fB--mirror-id\fR=[\fB+-\fR]\fI\fR] [\fB--verbose\fR|\fB-v\fR] -[\fB--yaml\fR|\fB-y\fR] +[\fB--yaml\fR|\fB-y\fR][\fB--no-follow\fR] <\fIdirname\fR|\fIfilename\fR> ... + .SH DESCRIPTION .B lfs getstripe is used to list the layout/striping information for a given filename or @@ -255,6 +256,9 @@ addition to the normally-printed attributes. .BR --yaml | -y Always print the layout in YAML format, rather than only using this format for composite files. +.TP +.BR --no-follow +Print the stripe information of symbolic link itself. .br .SH EXAMPLES .TP diff --git a/lustre/include/lustre/lustreapi.h b/lustre/include/lustre/lustreapi.h index 4acfbf7..8d921b0 100644 --- a/lustre/include/lustre/lustreapi.h +++ b/lustre/include/lustre/lustreapi.h @@ -397,7 +397,8 @@ struct find_param { unsigned long long fp_blocks_units; unsigned long fp_got_uuids:1, - fp_obds_printed:1; + fp_obds_printed:1, + fp_no_follow:1; unsigned int fp_depth; unsigned int fp_hash_type; unsigned int fp_time_margin; /* time margin in seconds */ diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index 55a31ee..35ceaa5 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -8266,6 +8266,32 @@ test_56ea() { #LU-10378 } run_test 56ea "test lfs find -printf option" +test_56eb() { + local dir=$DIR/$tdir + local subdir_1=$dir/subdir_1 + + test_mkdir -p $subdir_1 + ln -s subdir_1 $dir/link_1 + + $LFS getstripe $dir | grep "^$dir/link_1$" -A1 || + error "symlink is not followed" + + $LFS getstripe --no-follow $dir | + grep "^$dir/link_1 has no stripe info$" || + error "symlink should not have stripe info" + + touch $dir/testfile + ln -s testfile $dir/file_link_2 + + $LFS getstripe $dir | grep "^$dir/file_link_2$" -A1 || + error "symlink is not followed" + + $LFS getstripe --no-follow $dir | + grep "^$dir/file_link_2 has no stripe info$" || + error "symlink should not have stripe info" +} +run_test 56eb "check lfs getstripe on symlink" + test_57a() { [ $PARALLEL == "yes" ] && skip "skip parallel run" # note test will not do anything if MDS is not local diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 425df77..95780b9 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -363,6 +363,7 @@ command_t cmdlist[] = { " [--component-end[=[+-]COMP_END]|-E[[+-]comp_end]]\n" " [[!] --mirror-index=[+-]INDEX |\n" " [!] --mirror-id=[+-]MIRROR_ID] [--mirror-count|-N]\n" + " [--no-follow]\n" " ..."}, {"setdirstripe", lfs_setdirstripe, 0, "Create striped directory on specified MDT, same as mkdir.\n" @@ -3352,6 +3353,7 @@ enum { LFS_INHERIT_RR_OPT, LFS_FIND_PERM, LFS_PRINTF_OPT, + LFS_NO_FOLLOW_OPT, }; #ifndef LCME_USER_MIRROR_FLAGS @@ -5765,6 +5767,8 @@ static int lfs_getstripe_internal(int argc, char **argv, .name = "mirror-index", .has_arg = required_argument }, { .val = LFS_MIRROR_ID_OPT, .name = "mirror-id", .has_arg = required_argument }, + { .val = LFS_NO_FOLLOW_OPT, + .name = "no-follow", .has_arg = no_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 }*/ @@ -5959,6 +5963,9 @@ static int lfs_getstripe_internal(int argc, char **argv, param->fp_exclude_mirror_id = !!neg_opt; break; } + case LFS_NO_FOLLOW_OPT: + param->fp_no_follow = true; + break; case 'd': param->fp_max_depth = 0; break; diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index f897ab61..29b1e4e 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -2366,6 +2366,7 @@ static int llapi_semantic_traverse(char *path, int size, int parent, if (rc == -ENOENT) continue; } + switch (dent->d_type) { case DT_UNKNOWN: llapi_err_noerrno(LLAPI_MSG_ERROR, @@ -6400,7 +6401,7 @@ static int cb_getstripe(char *path, int p, int *dp, void *data, struct dirent64 *de) { struct find_param *param = (struct find_param *)data; - int d = dp == NULL ? -1 : *dp; + int d = dp == NULL ? -1 : *dp, fd = -1; int ret = 0; if (p == -1 && d == -1) @@ -6413,10 +6414,12 @@ static int cb_getstripe(char *path, int p, int *dp, void *data, return ret; } + if (!param->fp_no_follow && de && de->d_type == DT_LNK && d == -1) + d = fd = open(path, O_RDONLY | O_DIRECTORY); + if (d != -1 && (param->fp_get_lmv || param->fp_get_default_lmv)) ret = cb_get_dirstripe(path, &d, param); - else if (d != -1 || - (p != -1 && !param->fp_get_lmv && !param->fp_get_default_lmv)) + else if (d != -1) ret = get_lmd_info_fd(path, p, d, ¶m->fp_lmd->lmd_lmm, param->fp_lum_size, GET_LMD_STRIPE); else if (d == -1 && (param->fp_get_lmv || param->fp_get_default_lmv)) { @@ -6425,7 +6428,11 @@ static int cb_getstripe(char *path, int p, int *dp, void *data, * to get LMV just in case, and by opening it as a file but * with O_NOFOLLOW ... */ - int fd = open(path, O_RDONLY | O_NOFOLLOW); + int flag = O_RDONLY; + + if (param->fp_no_follow) + flag = O_RDONLY | O_NOFOLLOW; + fd = open(path, flag); if (fd == -1) return 0; @@ -6434,9 +6441,21 @@ static int cb_getstripe(char *path, int p, int *dp, void *data, llapi_lov_dump_user_lmm(param, path, LDF_IS_DIR); close(fd); return 0; + } else if (d == -1) { + if (!param->fp_no_follow && de && de->d_type == DT_LNK) { + /* open the target of symlink as a file */ + fd = open(path, O_RDONLY); + if (fd == -1) + return 0; + } + ret = get_lmd_info_fd(path, p, fd, ¶m->fp_lmd->lmd_lmm, + param->fp_lum_size, GET_LMD_STRIPE); } else return 0; + if (fd >= 0) + close(fd); + if (ret) { if (errno == ENODATA && d != -1) { /* -- 1.8.3.1