Whamcloud - gitweb
LU-16284 utils: lfs getstripe follows symlink 03/49003/6
authorLei Feng <flei@whamcloud.com>
Tue, 1 Nov 2022 02:57:39 +0000 (10:57 +0800)
committerOleg Drokin <green@whamcloud.com>
Fri, 13 Jan 2023 07:22:24 +0000 (07:22 +0000)
'lfs getstripe' prints the information of symlink target by default.
With '--no-follow' option it prints the information of symlink itself.

Signed-off-by: Lei Feng <flei@whamcloud.com>
Test-Parameters: trivial
Change-Id: I6cef01af5bb2235bdcbf0b5c99af4b9ed5869515
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/49003
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Jian Yu <yujian@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/doc/lfs-getstripe.1
lustre/include/lustre/lustreapi.h
lustre/tests/sanity.sh
lustre/utils/lfs.c
lustre/utils/liblustreapi.c

index 8d90c3e..768a277 100644 (file)
@@ -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<index>\fR | [\fB!\fR] \fB--mirror-id\fR=[\fB+-\fR]\fI<id>\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
index b5020d0..bec467a 100644 (file)
@@ -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 */
index 687d8fd..cb45e93 100755 (executable)
@@ -8411,6 +8411,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
index ed90a6f..4eb670b 100644 (file)
@@ -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"
         "                 <directory|filename> ..."},
        {"setdirstripe", lfs_setdirstripe, 0,
         "Create striped directory on specified MDT, same as mkdir.\n"
@@ -3354,6 +3355,7 @@ enum {
        LFS_INHERIT_RR_OPT,
        LFS_FIND_PERM,
        LFS_PRINTF_OPT,
+       LFS_NO_FOLLOW_OPT,
 };
 
 #ifndef LCME_USER_MIRROR_FLAGS
@@ -5769,6 +5771,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 }*/
@@ -5963,6 +5967,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;
index cfadd09..d1d0f54 100644 (file)
@@ -2043,6 +2043,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,
@@ -6085,7 +6086,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)
@@ -6098,10 +6099,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, &param->fp_lmd->lmd_lmm,
                                      param->fp_lum_size, GET_LMD_STRIPE);
        else if (d == -1 && (param->fp_get_lmv || param->fp_get_default_lmv)) {
@@ -6110,7 +6113,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;
@@ -6119,9 +6126,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, &param->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) {
                        /*