From 88be221925efbeba8d43d068dbe6de8140af1e0d Mon Sep 17 00:00:00 2001 From: Jian Yu Date: Wed, 13 Apr 2022 11:35:30 -0700 Subject: [PATCH] LU-15536 utils: add lfs somsync utility 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 Reviewed-on: https://review.whamcloud.com/46942 Reviewed-by: John L. Hammond Tested-by: jenkins Tested-by: Maloo Reviewed-by: Alex Zhuravlev Reviewed-by: Yingjin Qian Reviewed-by: Andreas Dilger --- lustre/doc/lfs-somsync.1 | 26 +++++++ lustre/tests/sanity.sh | 65 ++++++++++++----- lustre/utils/lfs.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 254 insertions(+), 18 deletions(-) create mode 100644 lustre/doc/lfs-somsync.1 diff --git a/lustre/doc/lfs-somsync.1 b/lustre/doc/lfs-somsync.1 new file mode 100644 index 0000000..068baac --- /dev/null +++ b/lustre/doc/lfs-somsync.1 @@ -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), diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index ad95fef..7df2aea 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -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() { diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 1cf5a7d..992890f 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -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 ...\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. -- 1.8.3.1