From 3a1c8669452edfa03e3f4e1ca5e0625de70c093b Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Mon, 13 Nov 2023 11:02:24 +0100 Subject: [PATCH] LU-17173 utils: cleanup lfs flushctx When lfs flushctx is called without mount points, build the list of all mounts first, and then call the ioctl to flush associated contexts. Otherwise fetching the mount points unfortunately refreshes the contexts being flushed, because the mount points are being accessed. Lustre-change: https://review.whamcloud.com/52604 Lustre-commit: f0534544e3e3aef280ccc5f042e37d42d33b28d3 Test-Parameters: trivial Test-Parameters: kerberos=true testlist=sanity-krb5 Test-Parameters: testgroup=review-dne-selinux-ssk-part-2 Signed-off-by: Sebastien Buisson Change-Id: I75b9efe4c65ce66f5f692f9e49a28fde705d0140 Reviewed-by: Andreas Dilger Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/53909 Tested-by: jenkins Tested-by: Maloo --- lustre/utils/Makefile.am | 2 +- lustre/utils/lfs.c | 103 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 73 insertions(+), 32 deletions(-) diff --git a/lustre/utils/Makefile.am b/lustre/utils/Makefile.am index a9a930f..285009f 100644 --- a/lustre/utils/Makefile.am +++ b/lustre/utils/Makefile.am @@ -75,7 +75,7 @@ endif lctl_LDADD := $(LIBLUSTREAPI) $(PTHREAD_LIBS) $(LDLIBYAML) lctl_DEPENDENCIES := liblustreapi.la -lfs_SOURCES = lfs.c lfs_project.c lfs_project.h +lfs_SOURCES = lfs.c lfs_project.c lfs_project.h callvpe.c callvpe.h lfs_CFLAGS := -fPIC $(AM_CFLAGS) -I $(top_builddir)/lnet/utils lfs_LDADD := $(LIBLUSTREAPI) -lz lfs_LDADD += $(top_builddir)/lnet/utils/lnetconfig/liblnetconfig.la diff --git a/lustre/utils/lfs.c b/lustre/utils/lfs.c index 84d2baf..c103965 100644 --- a/lustre/utils/lfs.c +++ b/lustre/utils/lfs.c @@ -78,6 +78,7 @@ #include #include #include "lstddef.h" +#include "callvpe.h" #ifndef NSEC_PER_SEC # define NSEC_PER_SEC 1000000000UL @@ -9249,10 +9250,10 @@ static int flushctx_ioctl(char *mp) static int lfs_flushctx(int argc, char **argv) { - int kdestroy = 0, reap = 0, c; - char mntdir[PATH_MAX] = {'\0'}; - int index = 0; - int rc = 0; + int kdestroy = 0, reap = 0, c; + char **mnts = NULL, **mnt_ptr; + int mnt_num = 1, index = 0, rc = 0, rc2; + extern char **environ; while ((c = getopt(argc, argv, "kr")) != -1) { switch (c) { @@ -9270,44 +9271,84 @@ static int lfs_flushctx(int argc, char **argv) } } - if (kdestroy) { - rc = system("kdestroy > /dev/null"); - if (rc) { - rc = WEXITSTATUS(rc); - fprintf(stderr, - "error destroying tickets: %d, continuing\n", - rc); - } - } - if (optind >= argc) { - /* flush for all mounted lustre fs. */ - while (!llapi_search_mounts(NULL, index++, mntdir, NULL)) { - /* Check if we have a mount point */ - if (mntdir[0] == '\0') - continue; - - if (flushctx_ioctl(mntdir)) - rc = -1; + /* flush for all lustre mount points */ +again: + mnt_ptr = realloc(mnts, mnt_num * sizeof(char *)); + if (!mnt_ptr) { + mnt_num--; + rc = -ENOMEM; + goto reap; + } + mnts = mnt_ptr; + mnts[mnt_num - 1] = (char *)calloc(PATH_MAX + 1, sizeof(char)); + if (!mnts[mnt_num - 1]) { + rc = -ENOMEM; + goto reap; + } +next: + if (!llapi_search_mounts(NULL, index++, + mnts[mnt_num - 1], NULL)) { - mntdir[0] = '\0'; /* avoid matching in next loop */ + if (*mnts[mnt_num - 1] == '\0') + goto next; + mnt_num++; + goto again; + } else { + *mnts[mnt_num - 1] = '\0'; } + + mnt_ptr = mnts; + index = 0; } else { - /* flush fs as specified */ - while (optind < argc) { - if (flushctx_ioctl(argv[optind++])) - rc = -1; + /* flush for mounts as specified on command line */ + mnt_ptr = argv + optind; + mnt_num = argc - optind; + } + + for (index = 0; index < mnt_num; index++) { + /* Check if we have a mount point */ + if (*mnt_ptr[index] == '\0') + continue; + + rc2 = flushctx_ioctl(mnt_ptr[index]); + if (rc2) { + rc2 = -errno; + fprintf(stderr, + "error flushing contexts on mount point %s: %s\n", + mnt_ptr[index], strerror(errno)); + rc = rc ? rc : rc2; } } +reap: if (reap) { - rc = system("keyctl reap > /dev/null"); - if (rc != 0) { - rc = WEXITSTATUS(rc); - fprintf(stderr, "error reaping keyring: %d\n", rc); + static char *args[] = { "keyctl", "reap", NULL }; + + /* use callvpe to bypass the shell */ + rc2 = callvpe("keyctl", args, environ); + if (rc2) { + rc2 = WEXITSTATUS(rc2); + fprintf(stderr, "error reaping keyring: %d\n", rc2); } } + if (kdestroy) { + static char *args[] = { "kdestroy", NULL }; + + /* use callvpe to bypass the shell */ + rc2 = callvpe("kdestroy", args, environ); + if (rc2) { + rc2 = WEXITSTATUS(rc2); + fprintf(stderr, "error destroying tickets: %d\n", rc2); + } + } + + if (mnts) { + for (index = 0; index < mnt_num; index++) + free(mnts[index]); + free(mnts); + } return rc; } -- 1.8.3.1