From ede037cda73675f42b1452187e8dd3438fafc220 Mon Sep 17 00:00:00 2001 From: Don Brady Date: Fri, 9 Sep 2022 11:54:16 -0600 Subject: [PATCH] Make zfs-share service resilient to stale exports The are a few cases where stale entries in /etc/exports.d/zfs.exports will cause the nfs-server service to fail when starting up. Since the nfs-server startup consumes /etc/exports.d/zfs.exports, the zfs-share service (which rebuilds the list of zfs exports) should run before the nfs-server service. To make the zfs-share service resilient to stale exports, this change truncates the zfs config file as part of the zfs share -a operation. Reviewed-by: Allan Jude Reviewed-by: Brian Behlendorf Signed-off-by: Don Brady Closes #13775 --- cmd/zfs/zfs_main.c | 3 ++ etc/systemd/system/zfs-share.service.in | 2 +- include/libzfs.h | 3 +- lib/libshare/libshare.c | 12 +++++- lib/libshare/libshare_impl.h | 3 +- lib/libshare/nfs.c | 12 ++++++ lib/libshare/nfs.h | 2 + lib/libshare/os/freebsd/nfs.c | 9 +++- lib/libshare/os/linux/nfs.c | 9 +++- lib/libspl/include/libshare.h | 3 +- lib/libzfs/libzfs.abi | 55 ++++++++++++++++++------- lib/libzfs/libzfs_mount.c | 12 +++++- 12 files changed, 101 insertions(+), 24 deletions(-) diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index f1d686753c..008f1bea0e 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -7093,6 +7093,9 @@ share_mount(int op, int argc, char **argv) share_mount_state.sm_total = cb.cb_used; pthread_mutex_init(&share_mount_state.sm_lock, NULL); + /* For a 'zfs share -a' operation start with a clean slate. */ + zfs_truncate_shares(NULL); + /* * libshare isn't mt-safe, so only do the operation in parallel * if we're mounting. Additionally, the key-loading option must diff --git a/etc/systemd/system/zfs-share.service.in b/etc/systemd/system/zfs-share.service.in index 263055e528..1a6342a06f 100644 --- a/etc/systemd/system/zfs-share.service.in +++ b/etc/systemd/system/zfs-share.service.in @@ -1,7 +1,7 @@ [Unit] Description=ZFS file system shares Documentation=man:zfs(8) -After=nfs-server.service nfs-kernel-server.service +Before=nfs-server.service nfs-kernel-server.service After=smb.service Before=rpc-statd-notify.service Wants=zfs-mount.service diff --git a/include/libzfs.h b/include/libzfs.h index 96cf1e1865..92c7bf6d1c 100644 --- a/include/libzfs.h +++ b/include/libzfs.h @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011, 2020 by Delphix. All rights reserved. + * Copyright (c) 2011, 2022 by Delphix. All rights reserved. * Copyright Joyent, Inc. * Copyright (c) 2013 Steven Hartland. All rights reserved. * Copyright (c) 2016, Intel Corporation. @@ -895,6 +895,7 @@ _LIBZFS_H int zfs_unshare(zfs_handle_t *zhp, const char *mountpoint, _LIBZFS_H int zfs_unshareall(zfs_handle_t *zhp, const enum sa_protocol *proto); _LIBZFS_H void zfs_commit_shares(const enum sa_protocol *proto); +_LIBZFS_H void zfs_truncate_shares(const enum sa_protocol *proto); _LIBZFS_H int zfs_nicestrtonum(libzfs_handle_t *, const char *, uint64_t *); diff --git a/lib/libshare/libshare.c b/lib/libshare/libshare.c index d6257aa1ef..d50b4550d6 100644 --- a/lib/libshare/libshare.c +++ b/lib/libshare/libshare.c @@ -22,7 +22,7 @@ /* * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011 Gunnar Beutner - * Copyright (c) 2018, 2020 by Delphix. All rights reserved. + * Copyright (c) 2018, 2022 by Delphix. All rights reserved. */ #include @@ -96,6 +96,16 @@ sa_commit_shares(enum sa_protocol protocol) fstypes[protocol]->commit_shares(); } +void +sa_truncate_shares(enum sa_protocol protocol) +{ + /* CSTYLED */ + VALIDATE_PROTOCOL(protocol, ); + + if (fstypes[protocol]->truncate_shares != NULL) + fstypes[protocol]->truncate_shares(); +} + int sa_validate_shareopts(const char *options, enum sa_protocol protocol) { diff --git a/lib/libshare/libshare_impl.h b/lib/libshare/libshare_impl.h index b845eb2d8a..d8c924757f 100644 --- a/lib/libshare/libshare_impl.h +++ b/lib/libshare/libshare_impl.h @@ -22,7 +22,7 @@ /* * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011 Gunnar Beutner - * Copyright (c) 2019, 2020 by Delphix. All rights reserved. + * Copyright (c) 2019, 2022 by Delphix. All rights reserved. */ #ifndef _LIBSPL_LIBSHARE_IMPL_H #define _LIBSPL_LIBSHARE_IMPL_H @@ -39,6 +39,7 @@ typedef struct { boolean_t (*const is_shared)(sa_share_impl_t share); int (*const validate_shareopts)(const char *shareopts); int (*const commit_shares)(void); + void (*const truncate_shares)(void); } sa_fstype_t; extern const sa_fstype_t libshare_nfs_type, libshare_smb_type; diff --git a/lib/libshare/nfs.c b/lib/libshare/nfs.c index 161bbfb0ce..bbaea93fca 100644 --- a/lib/libshare/nfs.c +++ b/lib/libshare/nfs.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "nfs.h" @@ -281,6 +282,17 @@ fullerr: return (error); } +void +nfs_reset_shares(const char *lockfile, const char *exports) +{ + int nfs_lock_fd = -1; + + if (nfs_exports_lock(lockfile, &nfs_lock_fd) == 0) { + (void) ! truncate(exports, 0); + nfs_exports_unlock(lockfile, &nfs_lock_fd); + } +} + static boolean_t nfs_is_shared_cb(void *userdata, char *line, boolean_t found_mountpoint) { diff --git a/lib/libshare/nfs.h b/lib/libshare/nfs.h index 58523c8f02..f4340b18f8 100644 --- a/lib/libshare/nfs.h +++ b/lib/libshare/nfs.h @@ -22,6 +22,7 @@ /* * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011 Gunnar Beutner + * Copyright (c) 2022 by Delphix. All rights reserved. */ #include "libshare_impl.h" @@ -33,3 +34,4 @@ boolean_t nfs_is_shared_impl(const char *exports, sa_share_impl_t impl_share); int nfs_toggle_share(const char *lockfile, const char *exports, const char *expdir, sa_share_impl_t impl_share, int(*cbk)(sa_share_impl_t impl_share, FILE *tmpfile)); +void nfs_reset_shares(const char *lockfile, const char *exports); diff --git a/lib/libshare/os/freebsd/nfs.c b/lib/libshare/os/freebsd/nfs.c index 78977a25f4..521631c51f 100644 --- a/lib/libshare/os/freebsd/nfs.c +++ b/lib/libshare/os/freebsd/nfs.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Copyright (c) 2020 by Delphix. All rights reserved. + * Copyright (c) 2020, 2022 by Delphix. All rights reserved. */ #include @@ -195,6 +195,12 @@ start: return (SA_OK); } +static void +nfs_truncate_shares(void) +{ + nfs_reset_shares(ZFS_EXPORTS_LOCK, ZFS_EXPORTS_FILE); +} + const sa_fstype_t libshare_nfs_type = { .enable_share = nfs_enable_share, .disable_share = nfs_disable_share, @@ -202,4 +208,5 @@ const sa_fstype_t libshare_nfs_type = { .validate_shareopts = nfs_validate_shareopts, .commit_shares = nfs_commit_shares, + .truncate_shares = nfs_truncate_shares, }; diff --git a/lib/libshare/os/linux/nfs.c b/lib/libshare/os/linux/nfs.c index 0870f37e58..0d63c989d3 100644 --- a/lib/libshare/os/linux/nfs.c +++ b/lib/libshare/os/linux/nfs.c @@ -23,7 +23,7 @@ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011 Gunnar Beutner * Copyright (c) 2012 Cyril Plisko. All rights reserved. - * Copyright (c) 2019, 2020 by Delphix. All rights reserved. + * Copyright (c) 2019, 2022 by Delphix. All rights reserved. */ #include @@ -495,6 +495,12 @@ nfs_commit_shares(void) return (libzfs_run_process(argv[0], argv, 0)); } +static void +nfs_truncate_shares(void) +{ + nfs_reset_shares(ZFS_EXPORTS_LOCK, ZFS_EXPORTS_FILE); +} + const sa_fstype_t libshare_nfs_type = { .enable_share = nfs_enable_share, .disable_share = nfs_disable_share, @@ -502,6 +508,7 @@ const sa_fstype_t libshare_nfs_type = { .validate_shareopts = nfs_validate_shareopts, .commit_shares = nfs_commit_shares, + .truncate_shares = nfs_truncate_shares, }; static boolean_t diff --git a/lib/libspl/include/libshare.h b/lib/libspl/include/libshare.h index d976f096ac..deeb15c977 100644 --- a/lib/libspl/include/libshare.h +++ b/lib/libspl/include/libshare.h @@ -22,7 +22,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * Copyright (c) 2019, 2020 by Delphix. All rights reserved. + * Copyright (c) 2019, 2022 by Delphix. All rights reserved. */ #ifndef _LIBSPL_LIBSHARE_H #define _LIBSPL_LIBSHARE_H extern __attribute__((visibility("default"))) @@ -88,6 +88,7 @@ _LIBSPL_LIBSHARE_H int sa_enable_share(const char *, const char *, const char *, _LIBSPL_LIBSHARE_H int sa_disable_share(const char *, enum sa_protocol); _LIBSPL_LIBSHARE_H boolean_t sa_is_shared(const char *, enum sa_protocol); _LIBSPL_LIBSHARE_H void sa_commit_shares(enum sa_protocol); +_LIBSPL_LIBSHARE_H void sa_truncate_shares(enum sa_protocol); /* protocol specific interfaces */ _LIBSPL_LIBSHARE_H int sa_validate_shareopts(const char *, enum sa_protocol); diff --git a/lib/libzfs/libzfs.abi b/lib/libzfs/libzfs.abi index 0494aec208..7dd12df817 100644 --- a/lib/libzfs/libzfs.abi +++ b/lib/libzfs/libzfs.abi @@ -245,6 +245,7 @@ + @@ -428,6 +429,7 @@ + @@ -758,6 +760,10 @@ + + + + @@ -787,7 +793,7 @@ - + @@ -803,6 +809,9 @@ + + + @@ -816,6 +825,8 @@ + + @@ -832,6 +843,9 @@ + + + @@ -2302,6 +2316,7 @@ + @@ -3034,6 +3049,10 @@ + + + + @@ -3150,6 +3169,7 @@ + @@ -3750,7 +3770,7 @@ - + @@ -3790,6 +3810,9 @@ + + + @@ -3903,16 +3926,17 @@ + - + - + @@ -4032,8 +4056,8 @@ - - + + @@ -4102,15 +4126,15 @@ - + - - + + @@ -4123,7 +4147,7 @@ - + @@ -4771,8 +4795,8 @@ - - + + @@ -4872,7 +4896,7 @@ - + @@ -4935,7 +4959,7 @@ - + @@ -5013,7 +5037,7 @@ - + @@ -5455,7 +5479,6 @@ - diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c index fdfdd8d280..44f7d698c8 100644 --- a/lib/libzfs/libzfs_mount.c +++ b/lib/libzfs/libzfs_mount.c @@ -22,7 +22,7 @@ /* * Copyright 2015 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, 2021 by Delphix. All rights reserved. + * Copyright (c) 2014, 2022 by Delphix. All rights reserved. * Copyright 2016 Igor Kozhukhov * Copyright 2017 RackTop Systems. * Copyright (c) 2018 Datto Inc. @@ -788,6 +788,16 @@ zfs_commit_shares(const enum sa_protocol *proto) sa_commit_shares(*p); } +void +zfs_truncate_shares(const enum sa_protocol *proto) +{ + if (proto == NULL) + proto = share_all_proto; + + for (const enum sa_protocol *p = proto; *p != SA_NO_PROTOCOL; ++p) + sa_truncate_shares(*p); +} + /* * Unshare the given filesystem. */