From f5ca6853b8d8b918b0228af31fa8249be49d3000 Mon Sep 17 00:00:00 2001 From: Lei Feng Date: Mon, 8 Aug 2022 10:59:25 +0800 Subject: [PATCH] LU-16076 utils: enhance 'lfs check' command Add optional argument to 'lfs check' command so that only the servers related to the specified lustre file system is checked. Signed-off-by: Lei Feng Test-Parameters: trivial testlist=sanityn env=ONLY=113 Change-Id: I826a8e822af0a290f06ffaadadf1bb7f86899d99 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/48155 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Emoly Liu Reviewed-by: Jian Yu Reviewed-by: Oleg Drokin --- lustre/doc/lfs.1 | 7 ++-- lustre/tests/sanityn.sh | 36 ++++++++++++++++++- lustre/utils/lfs.c | 19 ++++++---- lustre/utils/liblustreapi.c | 76 +++++++++++++++++++++++++++++++++------ lustre/utils/liblustreapi_fid.c | 4 +-- lustre/utils/liblustreapi_hsm.c | 2 +- lustre/utils/liblustreapi_pcc.c | 2 +- lustre/utils/lustreapi_internal.h | 3 +- 8 files changed, 123 insertions(+), 26 deletions(-) diff --git a/lustre/doc/lfs.1 b/lustre/doc/lfs.1 index 1e3b9c1..d550166 100644 --- a/lustre/doc/lfs.1 +++ b/lustre/doc/lfs.1 @@ -7,7 +7,7 @@ lfs \- client utility for Lustre-specific file layout and other attributes .br .B lfs changelog_clear <\fImdtname\fR> <\fIid\fR> <\fIendrec\fR> .br -.B lfs check \fR<\fBmgts\fR|\fBmdts\fR|\fBosts\fR|\fBall\fR> +.B lfs check \fR<\fBmgts\fR|\fBmdts\fR|\fBosts\fR|\fBall\fR> [\fIpath\fR] .br .B lfs data_version \fR[\fB-nrw\fR] \fB<\fIfilename\fR> .br @@ -158,9 +158,10 @@ interest to a particular consumer , potentially allowing the MDT to free up disk space. An of 0 indicates the current last record. Changelog consumers must be registered on the MDT node using \fBlctl\fR. .TP -.B check +.B check [path] Display the status of the MGTs, MDTs or OSTs (as specified in the command) or -all the servers (MGTs, MDTs and OSTs). +all the servers (MGTs, MDTs and OSTs). If \fBpath\fR is provided, display +the status of the lustre file system mounted at specified \fBpath\fR only. .TP .B data_version [-nrw] Display the current version of file data. If -n is specified, the data version diff --git a/lustre/tests/sanityn.sh b/lustre/tests/sanityn.sh index 4a9771d..ed2cc2a 100755 --- a/lustre/tests/sanityn.sh +++ b/lustre/tests/sanityn.sh @@ -510,7 +510,7 @@ test_16d() { $LFS setstripe -c -1 $file1 # b=10919 $LCTL set_param ldlm.namespaces.*.lru_size=clear - + # direct write on one client and direct read from another dd if=/dev/urandom of=$file1 bs=1M count=100 oflag=direct dd if=$file2 of=$tmpfile iflag=direct bs=1M @@ -5885,6 +5885,40 @@ test_112() { } run_test 112 "update max-inherit in default LMV" +test_113 () { + (( MDS1_VERSION >= $(version_code 2.15.50) )) || + skip "Need server version at least 2.15.50" + + local instance + local nid + + instance=$($LFS getname -i $DIR1) || + error "cannot get instance of $DIR1" + + $LFS check osts $DIR1 | grep $instance || + error "cannot find OSTs of instance $instance" + + $LFS check osts $DIR1 | grep -v $instance + if (( $? == 0 )); then + error "find OSTs other than instance $instance" + fi + + $LFS check osts | grep $instance || + error "cannot find other OSTs" + + nid=$(df $DIR2 | tail -1 | sed 's%:/.*%%') || + error "cannot parse nid for $DIR2" + + $LFS check mgts $DIR2 | grep MGC$nid || + error "cannot find mgc of $nid" + + $LFS check mgts $DIR2 | grep -v MGC$nid + if (( $? == 0 )); then + error "find MGTs other than nid $nid" + fi +} +run_test 113 "check servers of specified fs" + log "cleanup: ======================================================" # kill and wait in each test only guarentee script finish, but command in script diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index e80814d..3b1d6ea 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -428,8 +428,8 @@ command_t cmdlist[] = { "\t ^: used before a flag indicates to exclude it\n"}, {"check", lfs_check, 0, "Display the status of MGTs, MDTs or OSTs (as specified in the command)\n" - "or all the servers (MGTs, MDTs and OSTs).\n" - "usage: check {mgts|osts|mdts|all}"}, + "or all the servers (MGTs, MDTs and OSTs) [for specified path only].\n" + "usage: check {mgts|osts|mdts|all} [path]"}, {"osts", lfs_osts, 0, "list OSTs connected to client " "[for specified path only]\n" "usage: osts [path]"}, {"mdts", lfs_mdts, 0, "list MDTs connected to client " @@ -7380,7 +7380,7 @@ static int lfs_getname(int argc, char **argv) static int lfs_check(int argc, char **argv) { - char mntdir[PATH_MAX] = {'\0'}; + char mntdir[PATH_MAX] = {'\0'}, path[PATH_MAX] = {'\0'}; int num_types = 1; char *obd_types[3]; char obd_type1[4]; @@ -7388,7 +7388,7 @@ static int lfs_check(int argc, char **argv) char obd_type3[4]; int rc; - if (argc != 2) { + if (argc < 2 || argc > 3) { fprintf(stderr, "%s check: server type must be specified\n", progname); return CMD_HELP; @@ -7417,7 +7417,14 @@ static int lfs_check(int argc, char **argv) return CMD_HELP; } - rc = llapi_search_mounts(NULL, 0, mntdir, NULL); + if (argc >= 3 && !realpath(argv[2], path)) { + rc = -errno; + fprintf(stderr, "error: invalid path '%s': %s\n", + argv[2], strerror(-rc)); + return rc; + } + + rc = llapi_search_mounts(path, 0, mntdir, NULL); if (rc < 0 || mntdir[0] == '\0') { fprintf(stderr, "%s check: cannot find mounted Lustre filesystem: %s\n", @@ -7425,7 +7432,7 @@ static int lfs_check(int argc, char **argv) return rc; } - rc = llapi_target_check(num_types, obd_types, mntdir); + rc = llapi_target_check(num_types, obd_types, path); if (rc) fprintf(stderr, "%s check: cannot check target '%s': %s\n", progname, argv[1], strerror(-rc)); diff --git a/lustre/utils/liblustreapi.c b/lustre/utils/liblustreapi.c index c4dc701..5614fbb 100644 --- a/lustre/utils/liblustreapi.c +++ b/lustre/utils/liblustreapi.c @@ -84,6 +84,8 @@ #include "lstddef.h" #define FORMATTED_BUF_LEN 1024 +#define MAX_LINE_LEN 256 +#define MAX_INSTANCE_LEN 32 static int llapi_msg_level = LLAPI_MSG_MAX; const char *liblustreapi_cmd; @@ -1254,12 +1256,13 @@ static struct { dev_t dev; char fsname[PATH_MAX]; char mnt_dir[PATH_MAX]; + char nid[MAX_LINE_LEN]; } root_cached = { 0 }; static pthread_rwlock_t root_cached_lock = PTHREAD_RWLOCK_INITIALIZER; static int get_root_path_fast(int want, char *fsname, int *outfd, char *path, - dev_t *dev) + dev_t *dev, char *nid) { int rc = -ENODEV; int fsnamelen; @@ -1298,14 +1301,15 @@ static int get_root_path_fast(int want, char *fsname, int *outfd, char *path, *dev = root_cached.dev; if ((want & WANT_FD) && outfd) rc = get_root_fd(root_cached.mnt_dir, outfd); - + if ((want & WANT_NID) && nid) + strcpy(nid, root_cached.nid); out_unlock: pthread_rwlock_unlock(&root_cached_lock); return rc; } static int get_root_path_slow(int want, char *fsname, int *outfd, char *path, - int index, dev_t *dev) + int index, dev_t *dev, char *nid) { struct mntent mnt; char buf[PATH_MAX]; @@ -1392,6 +1396,10 @@ static int get_root_path_slow(int want, char *fsname, int *outfd, char *path, strncpy(root_cached.mnt_dir, mnt.mnt_dir, mntlen); root_cached.mnt_dir[mntlen] = '\0'; root_cached.dev = devmnt; + ptr_end = strchr(mnt.mnt_fsname, ':'); + strncpy(root_cached.nid, mnt.mnt_fsname, + ptr_end - mnt.mnt_fsname); + root_cached.nid[ptr_end - mnt.mnt_fsname] = '\0'; pthread_rwlock_unlock(&root_cached_lock); } @@ -1408,6 +1416,11 @@ static int get_root_path_slow(int want, char *fsname, int *outfd, char *path, *dev = devmnt; if ((want & WANT_FD) && outfd) rc = get_root_fd(mnt.mnt_dir, outfd); + if ((want & WANT_NID) && nid) { + ptr_end = strchr(mnt.mnt_fsname, ':'); + strncpy(nid, mnt.mnt_fsname, ptr_end - mnt.mnt_fsname); + nid[ptr_end - mnt.mnt_fsname] = '\0'; + } out: endmntent(fp); @@ -1419,14 +1432,15 @@ out: * Either the fsname or path must not be NULL */ int get_root_path(int want, char *fsname, int *outfd, char *path, int index, - dev_t *dev) + dev_t *dev, char *nid) { int rc = -ENODEV; if (!(want & WANT_INDEX)) - rc = get_root_path_fast(want, fsname, outfd, path, dev); + rc = get_root_path_fast(want, fsname, outfd, path, dev, nid); if (rc) - rc = get_root_path_slow(want, fsname, outfd, path, index, dev); + rc = get_root_path_slow(want, fsname, outfd, path, index, dev, + nid); if (!rc || !(want & WANT_ERROR)) return rc; @@ -1468,7 +1482,7 @@ int llapi_search_mounts(const char *pathname, int index, char *mntdir, if (fsname) want |= WANT_FSNAME; - return get_root_path(want, fsname, NULL, mntdir, idx, NULL); + return get_root_path(want, fsname, NULL, mntdir, idx, NULL, NULL); } /* Given a path, find the corresponding Lustre fsname */ @@ -1501,7 +1515,7 @@ int llapi_search_fsname(const char *pathname, char *fsname) } rc = get_root_path(WANT_FSNAME | WANT_ERROR, fsname, NULL, NULL, -1, - &dev); + &dev, NULL); return rc; } @@ -1517,7 +1531,7 @@ int llapi_search_rootpath(char *pathname, const char *fsname) */ pathname[0] = 0; return get_root_path(WANT_PATH, (char *)fsname, NULL, pathname, -1, - NULL); + NULL, NULL); } int llapi_search_rootpath_by_dev(char *pathname, dev_t dev) @@ -1530,7 +1544,7 @@ int llapi_search_rootpath_by_dev(char *pathname, dev_t dev) * clear it for safety */ pathname[0] = 0; - return get_root_path(WANT_PATH, NULL, NULL, pathname, -1, &dev); + return get_root_path(WANT_PATH, NULL, NULL, pathname, -1, &dev, NULL); } /** @@ -6694,10 +6708,27 @@ free_path: return rc; } +struct check_target_filter { + char *nid; + char *instance; +}; + static void do_target_check(char *obd_type_name, char *obd_name, char *obd_uuid, void *args) { int rc; + struct check_target_filter *filter = args; + + if (filter != NULL) { + /* check nid if obd type is mgc */ + if (strcmp(obd_type_name, "mgc") == 0) { + if (strcmp(obd_name + 3, filter->nid) != 0) + return; + } + /* check instance for other types of device (osc/mdc) */ + else if (strstr(obd_name, filter->instance) == NULL) + return; + } rc = llapi_ping(obd_type_name, obd_name); if (rc == ENOTCONN) @@ -6710,7 +6741,30 @@ static void do_target_check(char *obd_type_name, char *obd_name, int llapi_target_check(int type_num, char **obd_type, char *dir) { - return llapi_target_iterate(type_num, obd_type, NULL, do_target_check); + char nid[MAX_LINE_LEN], instance[MAX_INSTANCE_LEN]; + struct check_target_filter filter = {NULL, NULL}; + int rc; + + if (dir == NULL || dir[0] == '\0') + return llapi_target_iterate(type_num, obd_type, NULL, + do_target_check); + + rc = get_root_path(WANT_NID | WANT_ERROR, NULL, NULL, dir, -1, NULL, + nid); + if (rc) { + llapi_error(LLAPI_MSG_ERROR, rc, + "cannot get nid of path '%s'", dir); + return rc; + } + filter.nid = nid; + + rc = llapi_get_instance(dir, instance, ARRAY_SIZE(instance)); + if (rc) + return rc; + filter.instance = instance; + + return llapi_target_iterate(type_num, obd_type, &filter, + do_target_check); } #undef MAX_STRING_SIZE diff --git a/lustre/utils/liblustreapi_fid.c b/lustre/utils/liblustreapi_fid.c index 8d3f268..cc76ae6 100644 --- a/lustre/utils/liblustreapi_fid.c +++ b/lustre/utils/liblustreapi_fid.c @@ -224,10 +224,10 @@ int llapi_fid2path(const char *path_or_device, const char *fidstr, char *path, if (*path_or_device == '/') rc = get_root_path(WANT_FD, NULL, &mnt_fd, - (char *)path_or_device, -1, NULL); + (char *)path_or_device, -1, NULL, NULL); else rc = get_root_path(WANT_FD, (char *)path_or_device, - &mnt_fd, NULL, -1, NULL); + &mnt_fd, NULL, -1, NULL, NULL); if (rc < 0) goto out; diff --git a/lustre/utils/liblustreapi_hsm.c b/lustre/utils/liblustreapi_hsm.c index 052e6cd..e634293 100644 --- a/lustre/utils/liblustreapi_hsm.c +++ b/lustre/utils/liblustreapi_hsm.c @@ -1592,7 +1592,7 @@ int llapi_hsm_request(const char *path, const struct hsm_user_request *request) int rc; int fd; - rc = get_root_path(WANT_FD, NULL, &fd, (char *)path, -1, NULL); + rc = get_root_path(WANT_FD, NULL, &fd, (char *)path, -1, NULL, NULL); if (rc) return rc; diff --git a/lustre/utils/liblustreapi_pcc.c b/lustre/utils/liblustreapi_pcc.c index b1652c2..a2ed766 100644 --- a/lustre/utils/liblustreapi_pcc.c +++ b/lustre/utils/liblustreapi_pcc.c @@ -212,7 +212,7 @@ int llapi_pcc_detach_fid(const char *mntpath, const struct lu_fid *fid, int fd; struct lu_pcc_detach_fid detach; - rc = get_root_path(WANT_FD, NULL, &fd, (char *)mntpath, -1, NULL); + rc = get_root_path(WANT_FD, NULL, &fd, (char *)mntpath, -1, NULL, NULL); if (rc) { llapi_error(LLAPI_MSG_ERROR, rc, "cannot get root path: %s", mntpath); diff --git a/lustre/utils/lustreapi_internal.h b/lustre/utils/lustreapi_internal.h index 41b7087..502fb8b 100644 --- a/lustre/utils/lustreapi_internal.h +++ b/lustre/utils/lustreapi_internal.h @@ -51,6 +51,7 @@ #define WANT_INDEX 0x8 #define WANT_ERROR 0x10 #define WANT_DEV 0x20 +#define WANT_NID 0x40 /* Define a fixed 4096-byte encryption unit size */ #define LUSTRE_ENCRYPTION_BLOCKBITS 12 @@ -63,7 +64,7 @@ #endif int get_root_path(int want, char *fsname, int *outfd, char *path, int index, - dev_t *dev); + dev_t *dev, char *nid); int llapi_ioctl_pack(struct obd_ioctl_data *data, char **pbuf, int max_len); int llapi_ioctl_unpack(struct obd_ioctl_data *data, char *pbuf, int max_len); int sattr_cache_get_defaults(const char *const fsname, -- 1.8.3.1