From patchwork Mon Jan 29 23:29:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 10191089 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 D78C460375 for ; Mon, 29 Jan 2018 23:29:24 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CEEA52015F for ; Mon, 29 Jan 2018 23:29:24 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C37DE20700; Mon, 29 Jan 2018 23:29:24 +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 CC32F2015F for ; Mon, 29 Jan 2018 23:29:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751786AbeA2X3X (ORCPT ); Mon, 29 Jan 2018 18:29:23 -0500 Received: from mail-it0-f42.google.com ([209.85.214.42]:39993 "EHLO mail-it0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751542AbeA2X3W (ORCPT ); Mon, 29 Jan 2018 18:29:22 -0500 Received: by mail-it0-f42.google.com with SMTP id 196so11294353iti.5 for ; Mon, 29 Jan 2018 15:29:21 -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=VWdzsIVlTQclpb9na3F3zQFyf+uNtQ9YEBUNKtYHsXFeiWPqNsXNKX/ccr9P93Qxi7 mgKSp2v2qpamTl76+XSN5R3Bx3YThsLke5OkXo+Xvok5ierDE1wW7S5uaPojWK7WOaCN +4rwdXLye9Zx00gqheNDqmFHy+ZOaG9mRysAqYydmLjTTeuaqKJePEAi54LRRJKqPYjf HdztyfjBsvgJs9w64JWEz0QVKzC5Xx7iWpFoJNG7/CDvnhc2+idywvFPkwY1cfsAv4MD 6jno/Axp39WTZKD4PYrCWkrRVKkQQCmQQRKNim51baVmCZYUSNbU44VrM8EbuXVNoQyg QhOQ== 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=IxCV0yl9/47+oLhSwYFnDHdehFlPqf8cLsNlcwVFXRJxUsgxqAAgB6/yI7mO8yuBO7 /Dwg7g6zN1AknMbVjk2UvC2t3HWcO5RdOtKFfD971hKtSYvt+jF02DV5C4iW9+wH8XJP /1kcQzHlPQltqgkN8Q7PfcloIK81uHCGfEF7OzHfPCofxRamYHaR1HpHY1Vj3tmC6MmO K0qKuMi9QmL2C4/IKSj5wNt1QnMGEWxATohOEbHyK9U5fVbZoy4FDyOKe+CBk8MMYpFi df74ToT5j4jwAK9HEzqkZ+95GHjOHz4S9i9Av8P6YpTV2cxaJlQA4LMWSfyzUO8d5LWZ ePeg== X-Gm-Message-State: AKwxytfyR9oAtrbLiVvE4GrooHKjBXCfsD1hhXkQG0MnTBGssZrbtAjq uvPVjHH6X2AqyykOOUULhGkwjw== X-Google-Smtp-Source: AH8x226NpCxRbL6ZXIUS7TF52pC/Vd6XLT9EpOLVei7bi5XOaNCnXJ/UWJ2eXFtRp2z+p798Ngwhtg== X-Received: by 10.36.23.78 with SMTP id 75mr27979113ith.24.1517268561235; Mon, 29 Jan 2018 15:29:21 -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 r186sm6595583itb.13.2018.01.29.15.29.20 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 29 Jan 2018 15:29:20 -0800 (PST) Subject: [PATCH v4 4/5] mountd: Solder in support for NFS basic junctions From: Chuck Lever To: linux-nfs@vger.kernel.org Date: Mon, 29 Jan 2018 18:29:20 -0500 Message-ID: <20180129232920.10141.5558.stgit@manet.1015granger.net> In-Reply-To: <20180129232527.10141.69789.stgit@manet.1015granger.net> References: <20180129232527.10141.69789.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) {