From 501fa525603e4c94028e9cf92f8388e9862252fa 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. lustre-change: https://review.whamcloud.com/48155 lustre-commit: f5ca6853b8d8b918b0228af31fa8249be49d3000 Signed-off-by: Lei Feng Test-Parameters: trivial testlist=sanityn env=ONLY=113 Change-Id: I826a8e822af0a290f06ffaadadf1bb7f86899d99 Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/48935 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger --- lustre/doc/lfs.1 | 7 +++-- lustre/tests/sanityn.sh | 36 ++++++++++++++++++++++- lustre/utils/lfs.c | 19 +++++++++---- lustre/utils/liblustreapi.c | 60 +++++++++++++++++++++++++++++++++++---- lustre/utils/liblustreapi_fid.c | 4 +-- lustre/utils/liblustreapi_hsm.c | 2 +- lustre/utils/liblustreapi_pcc.c | 2 +- lustre/utils/lustreapi_internal.h | 5 +++- 8 files changed, 114 insertions(+), 21 deletions(-) diff --git a/lustre/doc/lfs.1 b/lustre/doc/lfs.1 index 2ca2c42..a864cfb 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 @@ -155,9 +155,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 76fe8f3..55a1d05 100755 --- a/lustre/tests/sanityn.sh +++ b/lustre/tests/sanityn.sh @@ -514,7 +514,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 @@ -5762,6 +5762,40 @@ test_109() { run_test 109 "Race with several mount instances on 1 node" +test_113 () { + (( MDS1_VERSION >= $(version_code 2.14.0) )) || + skip "Need server version at least 2.14.0" + + 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 f7ab8ae..47de646 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -533,8 +533,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 "}, + "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 " @@ -7111,7 +7111,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]; @@ -7119,7 +7119,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; @@ -7148,7 +7148,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", @@ -7156,7 +7163,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 9f7a695..c72b8b5 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; @@ -1300,7 +1302,8 @@ out: * Find the fsname, the full path, and/or an open fd. * Either the fsname or path must not be NULL */ -int get_root_path(int want, char *fsname, int *outfd, char *path, int index) +int get_root_path(int want, char *fsname, int *outfd, char *path, int index, + char *nid) { struct mntent mnt; char buf[PATH_MAX], mntdir[PATH_MAX]; @@ -1391,11 +1394,15 @@ int get_root_path(int want, char *fsname, int *outfd, char *path, int index) rc = -errno; llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'", mntdir); - } else { *outfd = fd; } } + 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'; + } } else if (want & WANT_ERROR) llapi_err_noerrno(LLAPI_MSG_ERROR, "'%s' not on a mounted Lustre filesystem", @@ -1429,7 +1436,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); + return get_root_path(want, fsname, NULL, mntdir, idx, NULL); } /* Given a path, find the corresponding Lustre fsname */ @@ -1500,7 +1507,8 @@ int llapi_search_fsname(const char *pathname, char *fsname) } } } - rc = get_root_path(WANT_FSNAME | WANT_ERROR, fsname, NULL, path, -1); + rc = get_root_path(WANT_FSNAME | WANT_ERROR, fsname, NULL, path, -1, + NULL); free(path); return rc; } @@ -1512,7 +1520,8 @@ int llapi_search_rootpath(char *pathname, const char *fsname) * clear it for safety */ pathname[0] = 0; - return get_root_path(WANT_PATH, (char *)fsname, NULL, pathname, -1); + return get_root_path(WANT_PATH, (char *)fsname, NULL, pathname, -1, + NULL); } /** @@ -6541,10 +6550,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) @@ -6557,7 +6583,29 @@ 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, 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 578c6e6..be439bf 100644 --- a/lustre/utils/liblustreapi_fid.c +++ b/lustre/utils/liblustreapi_fid.c @@ -215,10 +215,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); + (char *)path_or_device, -1, NULL); else rc = get_root_path(WANT_FD, (char *)path_or_device, - &mnt_fd, NULL, -1); + &mnt_fd, NULL, -1, NULL); if (rc < 0) goto out; diff --git a/lustre/utils/liblustreapi_hsm.c b/lustre/utils/liblustreapi_hsm.c index ba99cd3..9f99ecf 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); + rc = get_root_path(WANT_FD, NULL, &fd, (char *)path, -1, NULL); if (rc) return rc; diff --git a/lustre/utils/liblustreapi_pcc.c b/lustre/utils/liblustreapi_pcc.c index 8ea726e..d5a26ac 100644 --- a/lustre/utils/liblustreapi_pcc.c +++ b/lustre/utils/liblustreapi_pcc.c @@ -304,7 +304,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); + rc = get_root_path(WANT_FD, NULL, &fd, (char *)mntpath, -1, 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 aea7c2f..fcd08ae 100644 --- a/lustre/utils/lustreapi_internal.h +++ b/lustre/utils/lustreapi_internal.h @@ -51,6 +51,8 @@ #define WANT_FD 0x4 #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 @@ -62,7 +64,8 @@ #define PROC_MOUNTS "/proc/mounts" #endif -int get_root_path(int want, char *fsname, int *outfd, char *path, int index); +int get_root_path(int want, char *fsname, int *outfd, char *path, int index, + 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