Whamcloud - gitweb
LU-15536 utils: add lfs somsync utility
authorJian Yu <yujian@whamcloud.com>
Wed, 13 Apr 2022 18:35:30 +0000 (11:35 -0700)
committerAndreas Dilger <adilger@whamcloud.com>
Tue, 26 Apr 2022 00:12:41 +0000 (00:12 +0000)
This patch adds lfs somsync utility to synchronize
SOM xattr(s) for given FILE(s) or FID(s).

lfs somsync FILE ...
lfs somsync --by-fid MOUNT FID ...

Test-Parameters: trivial env=ONLY=807 testlist=sanity

Change-Id: Ie9ee39625d56ec026c89dcc0f27025904ca354e3
Signed-off-by: Jian Yu <yujian@whamcloud.com>
Reviewed-on: https://review.whamcloud.com/46942
Reviewed-by: John L. Hammond <jhammond@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Alex Zhuravlev <bzzz@whamcloud.com>
Reviewed-by: Yingjin Qian <qian@ddn.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
lustre/doc/lfs-somsync.1 [new file with mode: 0644]
lustre/tests/sanity.sh
lustre/utils/lfs.c

diff --git a/lustre/doc/lfs-somsync.1 b/lustre/doc/lfs-somsync.1
new file mode 100644 (file)
index 0000000..068baac
--- /dev/null
@@ -0,0 +1,26 @@
+.TH LFS-SOMSYNC 1 2022-03-28 "Lustre" "Lustre Utilities"
+.SH NAME
+lfs somsync \- synchronize SOM xattr for given file or FID
+.SH SYNOPSIS
+.B lfs somsync
+FILE ...
+.br
+.B lfs somsync
+--by-fid MOUNT FID ...
+.SH DESCRIPTION
+This command synchronizes SOM xattr(s) for given \fIFILE\fR(s) or \fIFID\fR(s).
+.br
+The \fIMOUNT\fR specifies a mountpoint of Lustre filesystem where given
+\fIFID\fR(s) are stored. \fIFID\fR(s) can be wrapped with square brackets.
+.SH EXAMPLES
+.TP
+.B lfs somsync /mnt/lustre/file
+Synchronize SOM xattr for file /mnt/lustre/file
+.TP
+.B lfs somsync --by-fid /mnt/lustre [0x200000400:0x1:0x0] [0x200000402:0x20:0x0]
+Synchronize SOM xattrs for FIDs [0x200000400:0x1:0x0] and [0x200000402:0x20:0x0]
+.SH AUTHOR
+The \fBlfs somsync\fR command is part of the Lustre filesystem.
+.SH SEE ALSO
+.BR lfs (1),
+.BR lfs-path2fid (1),
index ad95fef..7df2aea 100755 (executable)
@@ -26813,16 +26813,27 @@ test_806() {
 }
 run_test 806 "Verify Lazy Size on MDS"
 
-test_807() {
-       [ -n "$FILESET" ] && skip "Not functional for FILESET set"
-       [ $MDS1_VERSION -lt $(version_code 2.11.52) ] &&
+verify_som_sync_utility() {
+       local utility=$1
+       local use_llsom_sync=false
+
+       [[ -z "$FILESET" ]] || skip "Not functional for FILESET set"
+       [[ $MDS1_VERSION -ge $(version_code 2.11.52) ]] ||
                skip "Need MDS version at least 2.11.52"
 
-       # Registration step
-       changelog_register || error "changelog_register failed"
-       local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
-       changelog_users $SINGLEMDS | grep -q $cl_user ||
-               error "User $cl_user not found in changelog_users"
+       case $utility in
+               llsom_sync ) use_llsom_sync=true ;;
+               somsync ) use_llsom_sync=false ;;
+               *) error "invalid utility $utility" ;;
+       esac
+
+       if $use_llsom_sync; then
+               # Registration step
+               changelog_register || error "changelog_register failed"
+               local cl_user="${CL_USERS[$SINGLEMDS]%% *}"
+               changelog_users $SINGLEMDS | grep -q $cl_user ||
+                       error "User $cl_user not found in changelog_users"
+       fi
 
        local save="$TMP/$TESTSUITE-$TESTNAME.parameters"
        save_lustre_params client "llite.*.xattr_cache" > $save
@@ -26843,33 +26854,51 @@ test_807() {
        # multi-client wirtes
        local num=$(get_node_count ${CLIENTS//,/ })
        local offset=0
-       local i=0
+       local -a pids
 
        echo "Test SOM for multi-client ($num) writes"
        touch $DIR/$tfile || error "touch $tfile failed"
        $TRUNCATE $DIR/$tfile 0
        for client in ${CLIENTS//,/ }; do
                do_node $client $MULTIOP $DIR/$tfile Oz${offset}w${bs}c &
-               local pids[$i]=$!
-               i=$((i + 1))
-               offset=$((offset + $bs))
-       done
-       for (( i=0; i < $num; i++ )); do
-               wait ${pids[$i]}
+               pids+=( $! )
+               offset=$((offset + bs))
        done
+       wait ${pids[@]}
 
        do_rpc_nodes "$CLIENTS" cancel_lru_locks osc
        do_nodes "$CLIENTS" "sync ; sleep 5 ; sync"
-       $LSOM_SYNC -u $cl_user -m $FSNAME-MDT0000 $MOUNT
+
+       if $use_llsom_sync; then
+               $LSOM_SYNC -u $cl_user -m $FSNAME-MDT0000 $MOUNT ||
+                       error "$LSOM_SYNC failed"
+       else
+               $LFS somsync $DIR/$tfile ||
+                       error "$LFS somsync $DIR/$tfile failed"
+               find $DIR/$tdir -type f | xargs $LFS path2fid |
+                       awk '{print $2}' | xargs $LFS somsync --by-fid $DIR ||
+                               error "$LFS somsync --by-fid $DIR failed"
+       fi
+
        check_lsom_data $DIR/$tdir/trunc
        check_lsom_data $DIR/$tdir/single_dd
        check_lsom_data $DIR/$tfile
 
        rm -rf $DIR/$tdir
        # Deregistration step
-       changelog_deregister || error "changelog_deregister failed"
+       ! $use_llsom_sync || changelog_deregister ||
+               error "changelog_deregister failed"
+}
+
+test_807a() {
+       verify_som_sync_utility llsom_sync
+}
+run_test 807a "verify LSOM syncing tool"
+
+test_807b() {
+       verify_som_sync_utility somsync
 }
-run_test 807 "verify LSOM syncing tool"
+run_test 807b "verify lfs somsync utility"
 
 check_som_nologged()
 {
index 1cf5a7d..992890f 100644 (file)
@@ -116,6 +116,7 @@ static int lfs_swap_layouts(int argc, char **argv);
 static int lfs_mv(int argc, char **argv);
 static int lfs_ladvise(int argc, char **argv);
 static int lfs_getsom(int argc, char **argv);
+static int lfs_somsync(int argc, char **argv);
 static int lfs_heat_get(int argc, char **argv);
 static int lfs_heat_set(int argc, char **argv);
 static int lfs_mirror(int argc, char **argv);
@@ -712,6 +713,10 @@ command_t cmdlist[] = {
         "\t-s: Only show the size value of the SOM data for a given file\n"
         "\t-b: Only show the blocks value of the SOM data for a given file\n"
         "\t-f: Only show the flags value of the SOM data for a given file\n"},
+       {"somsync", lfs_somsync, 0,
+        "Synchronize SOM xattr(s) for given file(s) or FID(s).\n"
+        "usage: somsync FILE ...\n"
+        "       somsync --by-fid MOUNT FID ...\n"},
        {"heat_get", lfs_heat_get, 0,
         "To get heat of files.\n"
         "usage: heat_get <file> ...\n"},
@@ -11897,6 +11902,182 @@ static int lfs_getsom(int argc, char **argv)
        return 0;
 }
 
+static inline int lfs_somsync_by_fd(int fd)
+{
+       __u64 dv;
+       struct stat st;
+       int rc = 0;
+
+       /* flush dirty pages from clients */
+       rc = llapi_get_data_version(fd, &dv, LL_DV_RD_FLUSH);
+       if (rc < 0)
+               goto out;
+
+       rc = fstat(fd, &st);
+       if (rc < 0)
+               rc = -errno;
+
+       /*
+        * After call fstat(), it already gets OST attrs to the client,
+        * when close the file, MDS will update the LSOM data itself
+        * according the size and blocks information from the client.
+        */
+out:
+       close(fd);
+       return rc;
+}
+
+static inline int lfs_somsync_by_path(const char *fname)
+{
+       int fd;
+       int rc = 0;
+
+       fd = open(fname, O_RDONLY | O_NOATIME);
+       if (fd < 0) {
+               rc = -errno;
+               fprintf(stderr,
+                       "%s somsync: cannot open '%s': %s\n",
+                       progname, fname, strerror(errno));
+               return rc;
+       }
+
+       rc = lfs_somsync_by_fd(fd);
+       if (rc < 0) {
+               fprintf(stderr,
+                       "%s somsync: cannot synchronize SOM data of '%s': %s\n",
+                       progname, fname, strerror(-rc));
+               return rc;
+       }
+
+       return 0;
+}
+
+static inline int lfs_somsync_by_fid(int dot_lustre_fid_fd, const struct lu_fid *fid)
+{
+       int fd = -1;
+       char fidstr[FID_LEN];
+       int rc = 0;
+
+       snprintf(fidstr, sizeof(fidstr), DFID, PFID(fid));
+       fd = openat(dot_lustre_fid_fd, fidstr, O_RDONLY | O_NOATIME);
+       if (fd < 0) {
+                rc = -errno;
+               fprintf(stderr,
+                       "%s somsync: cannot open '%s': %s\n",
+                       progname, fidstr, strerror(-rc));
+               return rc;
+       }
+
+       rc = lfs_somsync_by_fd(fd);
+       if (rc < 0) {
+               fprintf(stderr,
+                       "%s somsync: cannot synchronize SOM data of '%s': %s\n",
+                       progname, fidstr, strerror(-rc));
+               return rc;
+       }
+
+       return 0;
+}
+
+enum {
+       LFS_SOMSYNC_CLIENT_MOUNT = 1,
+};
+
+static int lfs_somsync(int argc, char **argv)
+{
+       struct option long_opts[] = {
+               { "by-fid", required_argument, NULL, LFS_SOMSYNC_CLIENT_MOUNT },
+               { NULL },
+       };
+       const char *client_mount = NULL;
+       int c;
+       int rc = 0, rc1;
+
+       while ((c = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
+               switch (c) {
+               case LFS_SOMSYNC_CLIENT_MOUNT:
+                       client_mount = optarg;
+                       break;
+               default:
+                       fprintf(stderr,
+                               "%s somsync: unrecognized option '%s'\n",
+                               progname, argv[optind - 1]);
+                       return CMD_HELP;
+               }
+       }
+
+       if (client_mount != NULL) {
+               /* lfs somsync --by-fid MOUNT FID ... */
+               char mntdir[PATH_MAX];
+               char path[PATH_MAX + 64];
+               int dot_lustre_fid_fd = -1;
+               struct lu_fid fid;
+               char *fidstr;
+               int found;
+
+               if (argc == optind) {
+                       fprintf(stderr, "%s somsync: missing FID\n", progname);
+                       return CMD_HELP;
+               }
+
+               rc = llapi_search_mounts(client_mount, 0, mntdir, NULL);
+               if (rc < 0) {
+                       fprintf(stderr,
+                               "%s somsync: invalid MOUNT '%s': %s\n",
+                               progname, client_mount, strerror(-rc));
+                       return rc;
+               }
+
+               snprintf(path, sizeof(path), "%s/.lustre/fid", mntdir);
+               dot_lustre_fid_fd = open(path, O_RDONLY | O_NOATIME);
+               if (dot_lustre_fid_fd < 0) {
+                       fprintf(stderr,
+                               "%s somsync: cannot open '%s': %s\n",
+                               progname, path, strerror(errno));
+                       return -errno;
+               }
+
+               rc = 0;
+               while (optind < argc) {
+                       found = 0;
+
+                       fidstr = argv[optind++];
+                       while (*fidstr == '[')
+                               fidstr++;
+                       found = sscanf(fidstr, SFID, RFID(&fid));
+                       if (found != 3) {
+                               fprintf(stderr,
+                                       "%s somsync: unrecognized FID: %s\n",
+                                       progname, argv[optind - 1]);
+                               close(dot_lustre_fid_fd);
+                               return -EINVAL;
+                       }
+
+                       rc1 = lfs_somsync_by_fid(dot_lustre_fid_fd, &fid);
+                       if (rc1 && !rc)
+                               rc = rc1;
+               }
+
+               close(dot_lustre_fid_fd);
+               return rc;
+       }
+
+       /* lfs somsync FILE ... */
+       if (argc == optind) {
+               fprintf(stderr, "%s somsync: missing FILE\n", progname);
+               return CMD_HELP;
+       }
+
+       rc = 0;
+       while (optind < argc) {
+               rc1 = lfs_somsync_by_path(argv[optind++]);
+               if (rc1 && !rc)
+                       rc = rc1;
+       }
+
+       return rc;
+}
+
 /**
  * lfs_mirror_list_commands() - List lfs mirror commands.
  * @argc: The count of command line arguments.