From 541c953bd3d20b8316240f3ff9315d4f3191214c Mon Sep 17 00:00:00 2001 From: wguanghao Date: Thu, 14 Dec 2023 16:13:05 +0800 Subject: [PATCH] backport bugfix patch from community (cherry picked from commit dd305ee53a4b5e6998ca72c37eb03d6d10b02741) --- ...ix-handling-of-error-from-match_fsid.patch | 40 ++++++ ...cache_open-before-workers-are-forked.patch | 76 ++++++++++++ ...gssd-fix-handling-DNS-lookup-failure.patch | 116 ++++++++++++++++++ nfs-utils.spec | 8 +- 4 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 0018-export-fix-handling-of-error-from-match_fsid.patch create mode 100644 0019-export-move-cache_open-before-workers-are-forked.patch create mode 100644 0020-gssd-fix-handling-DNS-lookup-failure.patch diff --git a/0018-export-fix-handling-of-error-from-match_fsid.patch b/0018-export-fix-handling-of-error-from-match_fsid.patch new file mode 100644 index 0000000..4ef1acc --- /dev/null +++ b/0018-export-fix-handling-of-error-from-match_fsid.patch @@ -0,0 +1,40 @@ +From 92a0f7d3cc7fc1206e0a763ab737f797b8946ca7 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Wed, 25 Oct 2023 12:34:45 -0400 +Subject: [PATCH] export: fix handling of error from match_fsid() + +If match_fsid() returns -1 we shouldn't assume that the path definitely +doesn't match the fsid, though it might not. +This is a similar situation to where an export is expected to be a mount +point, but is found not to be one. So it can be handled the same way, +by setting 'dev_missing'. +This will only have an effect if no other path matched the fsid, which +is what we want. + +The current code results in nothing being exported if any export point, +or any mount point beneath a crossmnt export point, fails a 'stat' +request, which is too harsh. + +Signed-off-by: NeilBrown +Signed-off-by: Steve Dickson +--- + support/export/cache.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/support/export/cache.c b/support/export/cache.c +index 19bbba5..e459502 100644 +--- a/support/export/cache.c ++++ b/support/export/cache.c +@@ -858,7 +858,8 @@ static void nfsd_fh(int f) + case 0: + continue; + case -1: +- goto out; ++ dev_missing ++; ++ continue; + } + if (is_ipaddr_client(dom) + && !ipaddr_client_matches(exp, ai)) +-- +1.8.3.1 + diff --git a/0019-export-move-cache_open-before-workers-are-forked.patch b/0019-export-move-cache_open-before-workers-are-forked.patch new file mode 100644 index 0000000..d03fdd8 --- /dev/null +++ b/0019-export-move-cache_open-before-workers-are-forked.patch @@ -0,0 +1,76 @@ +From e115a6edfaa07203c6d6d40eba9e4f097efe0cf2 Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Wed, 25 Oct 2023 12:40:24 -0400 +Subject: [PATCH] export: move cache_open() before workers are forked. + +If each worker has a separate open on a cache channel, then each worker +will potentially receive every upcall request resulting in duplicated +work. + +A worker will only not see a request that another worker sees if that +other worker answers the request before this worker gets a chance to +read it. + +To avoid duplicate effort between threads and so get maximum benefit +from multiple threads, open the cache channels before forking. + +Note that the kernel provides locking so that only one thread can be +reading to writing to any channel at any given moment. + +Fixes: 5fc3bac9e0c3 ("mountd: Ensure we don't share cache file descriptors among processes.") +Signed-off-by: NeilBrown +Signed-off-by: Steve Dickson +--- + utils/exportd/exportd.c | 8 ++++++-- + utils/mountd/mountd.c | 8 ++++++-- + 2 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/utils/exportd/exportd.c b/utils/exportd/exportd.c +index 2dd12cb..6f86644 100644 +--- a/utils/exportd/exportd.c ++++ b/utils/exportd/exportd.c +@@ -289,12 +289,16 @@ main(int argc, char **argv) + else if (num_threads > MAX_THREADS) + num_threads = MAX_THREADS; + ++ /* Open cache channel files BEFORE forking so each upcall is ++ * only handled by one thread. Kernel provides locking for both ++ * read and write. ++ */ ++ cache_open(); ++ + if (num_threads > 1) + fork_workers(); + + +- /* Open files now to avoid sharing descriptors among forked processes */ +- cache_open(); + v4clients_init(); + + /* Process incoming upcalls */ +diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c +index bcf749f..f9c62cd 100644 +--- a/utils/mountd/mountd.c ++++ b/utils/mountd/mountd.c +@@ -916,12 +916,16 @@ main(int argc, char **argv) + else if (num_threads > MAX_THREADS) + num_threads = MAX_THREADS; + ++ /* Open cache channel files BEFORE forking so each upcall is ++ * only handled by one thread. Kernel provides locking for both ++ * read and write. ++ */ ++ cache_open(); ++ + if (num_threads > 1) + fork_workers(); + + nfsd_path_init(); +- /* Open files now to avoid sharing descriptors among forked processes */ +- cache_open(); + v4clients_init(); + + xlog(L_NOTICE, "Version " VERSION " starting"); +-- +1.8.3.1 + diff --git a/0020-gssd-fix-handling-DNS-lookup-failure.patch b/0020-gssd-fix-handling-DNS-lookup-failure.patch new file mode 100644 index 0000000..55fafcd --- /dev/null +++ b/0020-gssd-fix-handling-DNS-lookup-failure.patch @@ -0,0 +1,116 @@ +From 75b04a9bff709a49f55326b439851822dd630be6 Mon Sep 17 00:00:00 2001 +From: Olga Kornievskaia +Date: Mon, 16 Oct 2023 11:45:54 -0400 +Subject: [PATCH] gssd: fix handling DNS lookup failure + +When the kernel does its first ever lookup for a given server ip it +sends down info for server, protocol, etc. On the gssd side as it +scans the pipefs structure and sees a new entry it reads that info +and creates a clp_info structure. At that time it also does +a DNS lookup of the provided ip to name using getnameinfo(), +this is saved in clp->servername for all other upcalls that is +down under that directory. + +If this 1st getnameinfo() results in a failed resolution for +whatever reason (a temporary DNS resolution problem), this cause +of all other future upcalls to fail. + +As a fix, this patch proposed to (1) save the server info that's +passed only in the initial pipefs new entry creation in the +clp_info structure, then (2) for the upcalls, if clp->servername +is NULL, then do the DNS lookup again and set all the needed +clp_info fields upon successful resolution. + +Signed-off-by: Olga Kornievskaia +Signed-off-by: Steve Dickson +--- + utils/gssd/gssd.c | 41 +++++++++++++++++++++++++++++++++++++++++ + utils/gssd/gssd.h | 6 ++++++ + 2 files changed, 47 insertions(+) + +diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c +index 833d8e0..ca9b326 100644 +--- a/utils/gssd/gssd.c ++++ b/utils/gssd/gssd.c +@@ -365,6 +365,12 @@ gssd_read_service_info(int dirfd, struct clnt_info *clp) + + fail: + printerr(0, "ERROR: failed to parse %s/info\n", clp->relpath); ++ clp->upcall_address = strdup(address); ++ clp->upcall_port = strdup(port); ++ clp->upcall_program = program; ++ clp->upcall_vers = version; ++ clp->upcall_protoname = strdup(protoname); ++ clp->upcall_service = strdup(service); + free(servername); + free(protoname); + clp->servicename = NULL; +@@ -408,6 +414,16 @@ gssd_free_client(struct clnt_info *clp) + free(clp->servicename); + free(clp->servername); + free(clp->protocol); ++ if (!clp->servername) { ++ if (clp->upcall_address) ++ free(clp->upcall_address); ++ if (clp->upcall_port) ++ free(clp->upcall_port); ++ if (clp->upcall_protoname) ++ free(clp->upcall_protoname); ++ if (clp->upcall_service) ++ free(clp->upcall_service); ++ } + free(clp); + } + +@@ -446,6 +462,31 @@ gssd_clnt_gssd_cb(int UNUSED(fd), short UNUSED(which), void *data) + { + struct clnt_info *clp = data; + ++ /* if there was a failure to translate IP to name for this server, ++ * try again ++ */ ++ if (!clp->servername) { ++ if (!gssd_addrstr_to_sockaddr((struct sockaddr *)&clp->addr, ++ clp->upcall_address, clp->upcall_port ? ++ clp->upcall_port : "")) { ++ goto do_upcall; ++ } ++ clp->servername = gssd_get_servername(clp->upcall_address, ++ (struct sockaddr *)&clp->addr, clp->upcall_address); ++ if (!clp->servername) ++ goto do_upcall; ++ ++ if (asprintf(&clp->servicename, "%s@%s", clp->upcall_service, ++ clp->servername) < 0) { ++ free(clp->servername); ++ clp->servername = NULL; ++ goto do_upcall; ++ } ++ clp->prog = clp->upcall_program; ++ clp->vers = clp->upcall_vers; ++ clp->protocol = strdup(clp->upcall_protoname); ++ } ++do_upcall: + handle_gssd_upcall(clp); + } + +diff --git a/utils/gssd/gssd.h b/utils/gssd/gssd.h +index 519dc43..4e070ed 100644 +--- a/utils/gssd/gssd.h ++++ b/utils/gssd/gssd.h +@@ -86,6 +86,12 @@ struct clnt_info { + int gssd_fd; + struct event *gssd_ev; + struct sockaddr_storage addr; ++ char *upcall_address; ++ char *upcall_port; ++ int upcall_program; ++ int upcall_vers; ++ char *upcall_protoname; ++ char *upcall_service; + }; + + struct clnt_upcall_info { +-- +1.8.3.1 + diff --git a/nfs-utils.spec b/nfs-utils.spec index 9bb40e3..9e46a10 100644 --- a/nfs-utils.spec +++ b/nfs-utils.spec @@ -4,7 +4,7 @@ Name: nfs-utils Version: 2.5.4 -Release: 14 +Release: 15 Epoch: 2 Summary: The Linux NFS userland utility package License: MIT and GPLv2 and GPLv2+ and BSD @@ -30,6 +30,9 @@ Patch14: 0014-Move-version.h-into-a-common-include-directory.patch Patch15: 0015-mountd-only-do-NFSv4-logging-on-supported-kernels.patch Patch16: 0016-libnfsidmap-try-to-get-the-domain-directly-from-host.patch Patch17: 0017-Fixed-a-regression-in-the-junction-code.patch +Patch18: 0018-export-fix-handling-of-error-from-match_fsid.patch +Patch19: 0019-export-move-cache_open-before-workers-are-forked.patch +Patch20: 0020-gssd-fix-handling-DNS-lookup-failure.patch BuildRequires: libevent-devel,libcap-devel, libtirpc-devel libblkid-devel BuildRequires: krb5-libs >= 1.4 autoconf >= 2.57 openldap-devel >= 2.2 @@ -298,6 +301,9 @@ fi %{_mandir}/*/* %changelog +* Thu Dec 14 2023 wuguanghao - 2:2.5.4-15 +- backport bugfix patches from community + * Tue Sep 12 2023 wuguanghao - 2:2.5.4-14 - backport bugfix patches from community -- Gitee