From patchwork Sun Jan 28 18:35:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 10187919 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3B24F60384 for ; Sun, 28 Jan 2018 18:35:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 28E52285D2 for ; Sun, 28 Jan 2018 18:35:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1D80328707; Sun, 28 Jan 2018 18:35:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A389F285D2 for ; Sun, 28 Jan 2018 18:35:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752200AbeA1SfN (ORCPT ); Sun, 28 Jan 2018 13:35:13 -0500 Received: from mail-it0-f68.google.com ([209.85.214.68]:36334 "EHLO mail-it0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752065AbeA1SfM (ORCPT ); Sun, 28 Jan 2018 13:35:12 -0500 Received: by mail-it0-f68.google.com with SMTP id n206so4425469itg.1 for ; Sun, 28 Jan 2018 10:35:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:subject:from:to:date:message-id:in-reply-to:references :user-agent:mime-version:content-transfer-encoding; bh=klOiYNNyFAnWwE3blvVPXiuyOrQGyGMbumDOpZOBA14=; b=P2gwGJxrWGZqsiuT/ov7gUv30FobwW1/Pbc49Zw98XeoALXuwbBH6nw18osladedD6 DweucnWfVDTwKfaG/wLBIhddZt/uNfnqsMZodiG6r5c8LKli90See/+EKEWSPeoKsHrm /CsWudOX5IJvpkQBjsyhy5ASJmPCfGWbO/rGiBNWOxi472E4RYb9sySu4AMbYKPPJoqL n8bU0xPziHduEfpweKkCHM0LMkeQsJR2RvhBRFguxRIlW1/iU/AJqpjluXenCAfnrQp2 6yuPOYA0C8ji7AwNcnzoqPsvSSoOdfRhDBd6dqZM8r/aA3sLt8/PCvEMOp8av+wmyYh8 lMLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:subject:from:to:date:message-id :in-reply-to:references:user-agent:mime-version :content-transfer-encoding; bh=klOiYNNyFAnWwE3blvVPXiuyOrQGyGMbumDOpZOBA14=; b=DlZtJQRrerisE0YBsrkhDAFSxMUNGI67rIoZJoBePPayHnS+KrDeGy6W5vz3kJX0AF FUeLZmjVYk0mImaKNlNEUtVRcaVdzgXDwwFmC9asauPIk7JBxylx1gVjuFOg7MTQPBGn VZtFt+9nL/ECsamvO5IALR4DFSXqm6MzLBLk3KBTVxTUJpolzraEQ3UkXzT1eTe0LWE+ 2n32JELFau7lHPvc6CQNOnSJnkJAI+gGJMnqOpR7lYKKWBefhdgpIujpGckC/PM+/WXx PWpaj3SFSpAh5Ec+cJTyl3At1/L+UzO2QWyNqjdrCNpFyhqgPEp4yOHeXNseHjpetTgo CKxw== X-Gm-Message-State: AKwxytdEUhAQCHDb33JUWEQXRHAP7WmpVh8TnRqCdgdF5ZEfIkQ+5x2o 2geScu32lxmmrEHYRYzyAlPqXA== X-Google-Smtp-Source: AH8x2256XRf2dQLB4ne2Biy/teSxKap2DOu+VESaTXZ8UHQFyNU2EyEWw2EDKnVf9f84sZiuuK594g== X-Received: by 10.36.112.206 with SMTP id f197mr22218700itc.133.1517164511149; Sun, 28 Jan 2018 10:35:11 -0800 (PST) Received: from manet.1015granger.net (c-68-61-232-219.hsd1.mi.comcast.net. [68.61.232.219]) by smtp.gmail.com with ESMTPSA id j204sm3123012itj.37.2018.01.28.10.35.10 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 28 Jan 2018 10:35:10 -0800 (PST) Subject: [PATCH v3 2/3] mountd: Solder in support for NFS basic junctions From: Chuck Lever To: linux-nfs@vger.kernel.org Date: Sun, 28 Jan 2018 13:35:10 -0500 Message-ID: <20180128183510.3092.98784.stgit@manet.1015granger.net> In-Reply-To: <20180128183357.3092.38903.stgit@manet.1015granger.net> References: <20180128183357.3092.38903.stgit@manet.1015granger.net> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch does two things: 1. Reverts ab74900ff59e ("mountd: Support junction management plug-ins") 2. Re-implements support for NFS basic junctions directly in mountd So no more support for FedFS junctions, and no more need to have a dynamically load component installed from another package. The downside is that mountd has to be linked with libxml2 to get this support. Thus to make the use of libxml2 optional, built-in support for junctions is enabled only when --enable-junction is specified on the command line. Signed-off-by: Chuck Lever --- configure.ac | 5 - utils/mountd/Makefile.am | 8 ++ utils/mountd/cache.c | 189 ++++++++++++++++++++++------------------------ 3 files changed, 98 insertions(+), 104 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/configure.ac b/configure.ac index 8e7f036..d2e48a5 100644 --- a/configure.ac +++ b/configure.ac @@ -308,8 +308,6 @@ AC_CHECK_FUNC([getservbyname], , AC_CHECK_LIB([crypt], [crypt], [LIBCRYPT="-lcrypt"]) -AC_CHECK_LIB([dl], [dlclose], [LIBDL="-ldl"]) - if test "$enable_nfsv4" = yes; then dnl check for libevent libraries and headers AC_LIBEVENT @@ -372,7 +370,6 @@ AC_SUBST(LIBSOCKET) AC_SUBST(LIBCRYPT) AC_SUBST(LIBBSD) AC_SUBST(LIBBLKID) -AC_SUBST(LIBDL) if test "$enable_libmount" = yes; then AC_CHECK_LIB(mount, mnt_context_do_mount, [LIBMOUNT="-lmount"], AC_MSG_ERROR([libmount needed])) @@ -466,7 +463,7 @@ AC_CHECK_HEADERS([arpa/inet.h fcntl.h libintl.h limits.h \ stdlib.h string.h sys/file.h sys/ioctl.h sys/mount.h \ sys/param.h sys/socket.h sys/time.h sys/vfs.h \ syslog.h unistd.h com_err.h et/com_err.h \ - ifaddrs.h nfs-plugin.h libio.h]) + ifaddrs.h libio.h]) dnl ************************************************************* dnl Checks for typedefs, structures, and compiler characteristics diff --git a/utils/mountd/Makefile.am b/utils/mountd/Makefile.am index 153a90a..73eeb3f 100644 --- a/utils/mountd/Makefile.am +++ b/utils/mountd/Makefile.am @@ -1,5 +1,10 @@ ## Process this file with automake to produce Makefile.in +OPTLIBS = +if CONFIG_JUNCTION +OPTLIBS += ../../support/junction/libjunction.la $(LIBXML2) +endif + man8_MANS = mountd.man EXTRA_DIST = $(man8_MANS) @@ -13,7 +18,8 @@ mountd_SOURCES = mountd.c mount_dispatch.c auth.c rmtab.c cache.c \ mountd_LDADD = ../../support/export/libexport.a \ ../../support/nfs/libnfs.la \ ../../support/misc/libmisc.a \ - $(LIBBSD) $(LIBWRAP) $(LIBNSL) $(LIBBLKID) $(LIBDL) $(LIBTIRPC) + $(OPTLIBS) \ + $(LIBBSD) $(LIBWRAP) $(LIBNSL) $(LIBBLKID) $(LIBTIRPC) mountd_CPPFLAGS = $(AM_CPPFLAGS) $(CPPFLAGS) \ -I$(top_builddir)/support/include \ -I$(top_srcdir)/support/export diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c index e49300d..6f42512 100644 --- a/utils/mountd/cache.c +++ b/utils/mountd/cache.c @@ -976,10 +976,15 @@ lookup_export(char *dom, char *path, struct addrinfo *ai) return found; } -#ifdef HAVE_NFS_PLUGIN_H -#include -#include -#include +#ifdef CONFIG_JUNCTION + +#include "junction.h" + +struct nfs_fsloc_set { + int ns_ttl; + struct nfs_fsloc *ns_current; + struct nfs_fsloc *ns_list; +}; /* * Find the export entry for the parent of "pathname". @@ -1035,13 +1040,39 @@ out_default: return mkexportent("*", "/", "insecure"); } +static int get_next_location(struct nfs_fsloc_set *locset, + char **hostname, char **export_path, int *ttl) +{ + char *hostname_tmp, *export_path_tmp; + struct nfs_fsloc *fsloc; + + if (locset->ns_current == NULL) + return ENOENT; + fsloc = locset->ns_current; + + hostname_tmp = strdup(fsloc->nfl_hostname); + if (hostname_tmp == NULL) + return ENOMEM; + + if (nsdb_path_array_to_posix(fsloc->nfl_rootpath, + &export_path_tmp)) { + free(hostname_tmp); + return EINVAL; + } + + *hostname = hostname_tmp; + *export_path = export_path_tmp; + *ttl = locset->ns_ttl; + locset->ns_current = locset->ns_current->nfl_next; + return 0; +} + /* * Walk through a set of FS locations and build an e_fslocdata string. * Returns true if all went to plan; otherwise, false. */ -static bool locations_to_fslocdata(struct jp_ops *ops, - nfs_fsloc_set_t locations, char *fslocdata, - size_t remaining, int *ttl) +static bool locations_to_fslocdata(struct nfs_fsloc_set *locations, + char *fslocdata, size_t remaining, int *ttl) { char *server, *last_path, *rootpath, *ptr; _Bool seen = false; @@ -1056,13 +1087,13 @@ static bool locations_to_fslocdata(struct jp_ops *ops, enum jp_status status; int len; - status = ops->jp_get_next_location(locations, &server, + status = get_next_location(locations, &server, &rootpath, ttl); - if (status == JP_EMPTY) + if (status == ENOENT) break; - if (status != JP_OK) { + if (status) { xlog(D_GENERAL, "%s: failed to parse location: %s", - __func__, ops->jp_error(status)); + __func__, strerror(status)); goto out_false; } xlog(D_GENERAL, "%s: Location: %s:%s", @@ -1159,116 +1190,73 @@ out_nomem: * Walk through the set of FS locations and build an exportent. * Returns pointer to an exportent if "junction" refers to a junction. */ -static struct exportent *locations_to_export(struct jp_ops *ops, - nfs_fsloc_set_t locations, const char *junction, - struct exportent *parent) +static struct exportent *locations_to_export(struct nfs_fsloc_set *locations, + const char *junction, struct exportent *parent) { static char fslocdata[BUFSIZ]; int ttl; fslocdata[0] = '\0'; - if (!locations_to_fslocdata(ops, locations, - fslocdata, sizeof(fslocdata), &ttl)) + if (!locations_to_fslocdata(locations, fslocdata, sizeof(fslocdata), &ttl)) return NULL; return create_junction_exportent(parent, junction, fslocdata, ttl); } -/* - * Retrieve locations information in "junction" and dump it to the - * kernel. Returns pointer to an exportent if "junction" refers - * to a junction. - */ -static struct exportent *invoke_junction_ops(void *handle, char *dom, - const char *junction, struct addrinfo *ai) +static int +nfs_get_basic_junction(const char *junct_path, struct nfs_fsloc_set **locset) { - struct exportent *parent, *exp = NULL; - nfs_fsloc_set_t locations; - enum jp_status status; - struct jp_ops *ops; - char *error; - - ops = (struct jp_ops *)dlsym(handle, "nfs_junction_ops"); - error = dlerror(); - if (error != NULL) { - xlog(D_GENERAL, "%s: dlsym(jp_junction_ops): %s", - __func__, error); - return NULL; - } -#ifdef JP_API_VERSION - if (ops->jp_api_version != JP_API_VERSION) { - xlog(D_GENERAL, "%s: unrecognized junction API version: %u", - __func__, ops->jp_api_version); - return NULL; - } -#endif - status = ops->jp_init(false); - if (status != JP_OK) { - xlog(D_GENERAL, "%s: failed to resolve %s: %s", - __func__, junction, ops->jp_error(status)); - return NULL; + struct nfs_fsloc_set *new; + FedFsStatus retval; + + new = calloc(1, sizeof(struct nfs_fsloc_set)); + if (new == NULL) + return ENOMEM; + + retval = nfs_get_locations(junct_path, &new->ns_list); + if (retval) { + nfs_free_locations(new->ns_list); + free(new); + return EINVAL; } - status = ops->jp_get_locations(junction, &locations); - switch (status) { - case JP_OK: - break; - case JP_NOTJUNCTION: + locset->ns_current = locset->ns_list; + new->ns_ttl = 300; + *locset = new; + return 0; +} + +static struct exportent *lookup_junction(char *dom, const char *pathname, + struct addrinfo *ai) +{ + struct exportent *parent, *exp = NULL; + struct nfs_fsloc_set *locations; + int status; + + xmlInitParser(); + + if (nfs_is_junction(pathname)) { xlog(D_GENERAL, "%s: %s is not a junction", - __func__, junction); + __func__, pathname); goto out; - default: + } + status = nfs_get_basic_junction(pathname, &locations); + switch (status) { xlog(L_WARNING, "Dangling junction %s: %s", - junction, ops->jp_error(status)); + pathname, strerro(status)); goto out; } - parent = lookup_parent_export(dom, junction, ai); + parent = lookup_parent_export(dom, pathname, ai); if (parent == NULL) goto out; - exp = locations_to_export(ops, locations, junction, parent); + exp = locations_to_export(locations, pathname, parent); - ops->jp_put_locations(locations); + nfs_free_locations(locset->ns_list); + free(locset); out: - ops->jp_done(); - return exp; -} - -/* - * Load the junction plug-in, then try to resolve "pathname". - * Returns pointer to an initialized exportent if "junction" - * refers to a junction, or NULL if not. - */ -static struct exportent *lookup_junction(char *dom, const char *pathname, - struct addrinfo *ai) -{ - struct exportent *exp; - struct link_map *map; - void *handle; - -#ifdef JP_NFSPLUGIN_SONAME - handle = dlopen(JP_NFSPLUGIN_SONAME, RTLD_NOW); -#else - handle = dlopen("libnfsjunct.so.0", RTLD_NOW); -#endif - if (handle == NULL) { - xlog(D_GENERAL, "%s: dlopen: %s", __func__, dlerror()); - return NULL; - } - - if (dlinfo(handle, RTLD_DI_LINKMAP, &map) == 0) - xlog(D_GENERAL, "%s: loaded plug-in %s", - __func__, map->l_name); - - (void)dlerror(); /* Clear any error */ - - exp = invoke_junction_ops(handle, dom, pathname, ai); - - /* We could leave it loaded to make junction resolution - * faster next time. However, if we want to replace the - * library, that would require restarting mountd. */ - (void)dlclose(handle); + xmlCleanupParser(); return exp; } @@ -1284,13 +1272,16 @@ static void lookup_nonexport(int f, char *buf, int buflen, char *dom, char *path exportent_release(eep); free(eep); } -#else /* !HAVE_NFS_PLUGIN_H */ + +#else /* !CONFIG_JUNCTION */ + static void lookup_nonexport(int f, char *buf, int buflen, char *dom, char *path, struct addrinfo *UNUSED(ai)) { dump_to_cache(f, buf, buflen, dom, path, NULL, 0); } -#endif /* !HAVE_NFS_PLUGIN_H */ + +#endif /* !CONFIG_JUNCTION */ static void nfsd_export(int f) {