diff options
Diffstat (limited to 'lib/libzfs/libzfs_mount.c')
-rw-r--r-- | lib/libzfs/libzfs_mount.c | 321 |
1 files changed, 8 insertions, 313 deletions
diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c index 5bd3c67be..c2955ccfa 100644 --- a/lib/libzfs/libzfs_mount.c +++ b/lib/libzfs/libzfs_mount.c @@ -94,7 +94,6 @@ static int mount_tp_nthr = 512; /* tpool threads for multi-threaded mounting */ static void zfs_mount_task(void *); -static int zfs_share_proto(zfs_handle_t *, zfs_share_proto_t *); zfs_share_type_t zfs_is_shared_proto(zfs_handle_t *, char **, zfs_share_proto_t); @@ -102,13 +101,6 @@ zfs_share_type_t zfs_is_shared_proto(zfs_handle_t *, char **, * The share protocols table must be in the same order as the zfs_share_proto_t * enum in libzfs_impl.h */ -typedef struct { - zfs_prop_t p_prop; - char *p_name; - int p_share_err; - int p_unshare_err; -} proto_table_t; - proto_table_t proto_table[PROTO_END] = { {ZFS_PROP_SHARENFS, "nfs", EZFS_SHARENFSFAILED, EZFS_UNSHARENFSFAILED}, {ZFS_PROP_SHARESMB, "smb", EZFS_SHARESMBFAILED, EZFS_UNSHARESMBFAILED}, @@ -129,60 +121,7 @@ zfs_share_proto_t share_all_proto[] = { PROTO_END }; -/* - * Search the sharetab for the given mountpoint and protocol, returning - * a zfs_share_type_t value. - */ -static zfs_share_type_t -is_shared(libzfs_handle_t *hdl, const char *mountpoint, zfs_share_proto_t proto) -{ - char buf[MAXPATHLEN], *tab; - char *ptr; - - if (hdl->libzfs_sharetab == NULL) - return (SHARED_NOT_SHARED); - - /* Reopen ZFS_SHARETAB to prevent reading stale data from open file */ - if (freopen(ZFS_SHARETAB, "r", hdl->libzfs_sharetab) == NULL) - return (SHARED_NOT_SHARED); - - (void) fseek(hdl->libzfs_sharetab, 0, SEEK_SET); - - while (fgets(buf, sizeof (buf), hdl->libzfs_sharetab) != NULL) { - - /* the mountpoint is the first entry on each line */ - if ((tab = strchr(buf, '\t')) == NULL) - continue; - - *tab = '\0'; - if (strcmp(buf, mountpoint) == 0) { - /* - * the protocol field is the third field - * skip over second field - */ - ptr = ++tab; - if ((tab = strchr(ptr, '\t')) == NULL) - continue; - ptr = ++tab; - if ((tab = strchr(ptr, '\t')) == NULL) - continue; - *tab = '\0'; - if (strcmp(ptr, - proto_table[proto].p_name) == 0) { - switch (proto) { - case PROTO_NFS: - return (SHARED_NFS); - case PROTO_SMB: - return (SHARED_SMB); - default: - return (0); - } - } - } - } - return (SHARED_NOT_SHARED); -} static boolean_t dir_is_empty_stat(const char *dirname) @@ -304,7 +243,7 @@ zfs_is_mounted(zfs_handle_t *zhp, char **where) * Returns true if the given dataset is mountable, false otherwise. Returns the * mountpoint in 'buf'. */ -static boolean_t +boolean_t zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen, zprop_source_t *source, int flags) { @@ -329,10 +268,6 @@ zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen, getzoneid() == GLOBAL_ZONEID) return (B_FALSE); - if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED) && - getzoneid() == GLOBAL_ZONEID) - return (B_FALSE); - if (zfs_prop_get_int(zhp, ZFS_PROP_REDACTED) && !(flags & MS_FORCE)) return (B_FALSE); @@ -360,68 +295,6 @@ zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen, */ static int -do_mount(const char *src, const char *mntpt, char *opts) -{ - char *argv[9] = { - "/bin/mount", - "--no-canonicalize", - "-t", MNTTYPE_ZFS, - "-o", opts, - (char *)src, - (char *)mntpt, - (char *)NULL }; - int rc; - - /* Return only the most critical mount error */ - rc = libzfs_run_process(argv[0], argv, STDOUT_VERBOSE|STDERR_VERBOSE); - if (rc) { - if (rc & MOUNT_FILEIO) - return (EIO); - if (rc & MOUNT_USER) - return (EINTR); - if (rc & MOUNT_SOFTWARE) - return (EPIPE); - if (rc & MOUNT_BUSY) - return (EBUSY); - if (rc & MOUNT_SYSERR) - return (EAGAIN); - if (rc & MOUNT_USAGE) - return (EINVAL); - - return (ENXIO); /* Generic error */ - } - - return (0); -} - -static int -do_unmount(const char *mntpt, int flags) -{ - char force_opt[] = "-f"; - char lazy_opt[] = "-l"; - char *argv[7] = { - "/bin/umount", - "-t", MNTTYPE_ZFS, - NULL, NULL, NULL, NULL }; - int rc, count = 3; - - if (flags & MS_FORCE) { - argv[count] = force_opt; - count++; - } - - if (flags & MS_DETACH) { - argv[count] = lazy_opt; - count++; - } - - argv[count] = (char *)mntpt; - rc = libzfs_run_process(argv[0], argv, STDOUT_VERBOSE|STDERR_VERBOSE); - - return (rc ? EINVAL : 0); -} - -static int zfs_add_option(zfs_handle_t *zhp, char *options, int len, zfs_prop_t prop, char *on, char *off) { @@ -503,9 +376,8 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags) (void) strlcat(mntopts, "," MNTOPT_RO, sizeof (mntopts)); if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL, - flags)) { + flags)) return (0); - } /* * Append default mount options which apply to the mount point. @@ -599,7 +471,7 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags) } /* perform the mount */ - rc = do_mount(zfs_get_name(zhp), mountpoint, mntopts); + rc = do_mount(zfs_get_name(zhp), mountpoint, mntopts, flags); if (rc) { /* * Generic errors are nasty, but there are just way too many @@ -793,7 +665,7 @@ zfs_is_shared_proto(zfs_handle_t *zhp, char **where, zfs_share_proto_t proto) if (!zfs_is_mounted(zhp, &mountpoint)) return (SHARED_NOT_SHARED); - if ((rc = is_shared(zhp->zfs_hdl, mountpoint, proto)) + if ((rc = is_shared_impl(zhp->zfs_hdl, mountpoint, proto)) != SHARED_NOT_SHARED) { if (where != NULL) *where = mountpoint; @@ -821,44 +693,6 @@ zfs_is_shared_smb(zfs_handle_t *zhp, char **where) } /* - * zfs_init_libshare(zhandle, service) - * - * Initialize the libshare API if it hasn't already been initialized. - * In all cases it returns 0 if it succeeded and an error if not. The - * service value is which part(s) of the API to initialize and is a - * direct map to the libshare sa_init(service) interface. - */ -int -zfs_init_libshare(libzfs_handle_t *zhandle, int service) -{ - int ret = SA_OK; - - if (ret == SA_OK && zhandle->libzfs_shareflags & ZFSSHARE_MISS) { - /* - * We had a cache miss. Most likely it is a new ZFS - * dataset that was just created. We want to make sure - * so check timestamps to see if a different process - * has updated any of the configuration. If there was - * some non-ZFS change, we need to re-initialize the - * internal cache. - */ - zhandle->libzfs_shareflags &= ~ZFSSHARE_MISS; - if (sa_needs_refresh(zhandle->libzfs_sharehdl)) { - zfs_uninit_libshare(zhandle); - zhandle->libzfs_sharehdl = sa_init(service); - } - } - - if (ret == SA_OK && zhandle && zhandle->libzfs_sharehdl == NULL) - zhandle->libzfs_sharehdl = sa_init(service); - - if (ret == SA_OK && zhandle->libzfs_sharehdl == NULL) - ret = SA_NO_MEMORY; - - return (ret); -} - -/* * zfs_uninit_libshare(zhandle) * * Uninitialize the libshare API if it hasn't already been @@ -886,102 +720,6 @@ zfs_parse_options(char *options, zfs_share_proto_t proto) proto_table[proto].p_name)); } -/* - * Share the given filesystem according to the options in the specified - * protocol specific properties (sharenfs, sharesmb). We rely - * on "libshare" to do the dirty work for us. - */ -static int -zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto) -{ - char mountpoint[ZFS_MAXPROPLEN]; - char shareopts[ZFS_MAXPROPLEN]; - char sourcestr[ZFS_MAXPROPLEN]; - libzfs_handle_t *hdl = zhp->zfs_hdl; - sa_share_t share; - zfs_share_proto_t *curr_proto; - zprop_source_t sourcetype; - int ret; - - if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL, 0)) - return (0); - - for (curr_proto = proto; *curr_proto != PROTO_END; curr_proto++) { - /* - * Return success if there are no share options. - */ - if (zfs_prop_get(zhp, proto_table[*curr_proto].p_prop, - shareopts, sizeof (shareopts), &sourcetype, sourcestr, - ZFS_MAXPROPLEN, B_FALSE) != 0 || - strcmp(shareopts, "off") == 0) - continue; - - ret = zfs_init_libshare(hdl, SA_INIT_SHARE_API); - if (ret != SA_OK) { - (void) zfs_error_fmt(hdl, EZFS_SHARENFSFAILED, - dgettext(TEXT_DOMAIN, "cannot share '%s': %s"), - zfs_get_name(zhp), sa_errorstr(ret)); - return (-1); - } - - /* - * If the 'zoned' property is set, then zfs_is_mountable() - * will have already bailed out if we are in the global zone. - * But local zones cannot be NFS servers, so we ignore it for - * local zones as well. - */ - if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) - continue; - - share = sa_find_share(hdl->libzfs_sharehdl, mountpoint); - if (share == NULL) { - /* - * This may be a new file system that was just - * created so isn't in the internal cache - * (second time through). Rather than - * reloading the entire configuration, we can - * assume ZFS has done the checking and it is - * safe to add this to the internal - * configuration. - */ - if (sa_zfs_process_share(hdl->libzfs_sharehdl, - NULL, NULL, mountpoint, - proto_table[*curr_proto].p_name, sourcetype, - shareopts, sourcestr, zhp->zfs_name) != SA_OK) { - (void) zfs_error_fmt(hdl, - proto_table[*curr_proto].p_share_err, - dgettext(TEXT_DOMAIN, "cannot share '%s'"), - zfs_get_name(zhp)); - return (-1); - } - hdl->libzfs_shareflags |= ZFSSHARE_MISS; - share = sa_find_share(hdl->libzfs_sharehdl, - mountpoint); - } - if (share != NULL) { - int err; - err = sa_enable_share(share, - proto_table[*curr_proto].p_name); - if (err != SA_OK) { - (void) zfs_error_fmt(hdl, - proto_table[*curr_proto].p_share_err, - dgettext(TEXT_DOMAIN, "cannot share '%s'"), - zfs_get_name(zhp)); - return (-1); - } - } else { - (void) zfs_error_fmt(hdl, - proto_table[*curr_proto].p_share_err, - dgettext(TEXT_DOMAIN, "cannot share '%s'"), - zfs_get_name(zhp)); - return (-1); - } - - } - return (0); -} - - int zfs_share_nfs(zfs_handle_t *zhp) { @@ -1001,50 +739,6 @@ zfs_shareall(zfs_handle_t *zhp) } /* - * Unshare a filesystem by mountpoint. - */ -static int -unshare_one(libzfs_handle_t *hdl, const char *name, const char *mountpoint, - zfs_share_proto_t proto) -{ - sa_share_t share; - int err; - char *mntpt; - /* - * Mountpoint could get trashed if libshare calls getmntany - * which it does during API initialization, so strdup the - * value. - */ - mntpt = zfs_strdup(hdl, mountpoint); - - /* make sure libshare initialized */ - if ((err = zfs_init_libshare(hdl, SA_INIT_SHARE_API)) != SA_OK) { - free(mntpt); /* don't need the copy anymore */ - return (zfs_error_fmt(hdl, proto_table[proto].p_unshare_err, - dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"), - name, sa_errorstr(err))); - } - - share = sa_find_share(hdl->libzfs_sharehdl, mntpt); - free(mntpt); /* don't need the copy anymore */ - - if (share != NULL) { - err = sa_disable_share(share, proto_table[proto].p_name); - if (err != SA_OK) { - return (zfs_error_fmt(hdl, - proto_table[proto].p_unshare_err, - dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"), - name, sa_errorstr(err))); - } - } else { - return (zfs_error_fmt(hdl, proto_table[proto].p_unshare_err, - dgettext(TEXT_DOMAIN, "cannot unshare '%s': not found"), - name)); - } - return (0); -} - -/* * Unshare the given filesystem. */ int @@ -1069,7 +763,7 @@ zfs_unshare_proto(zfs_handle_t *zhp, const char *mountpoint, for (curr_proto = proto; *curr_proto != PROTO_END; curr_proto++) { - if (is_shared(hdl, mntpt, *curr_proto) && + if (is_shared_impl(hdl, mntpt, *curr_proto) && unshare_one(hdl, zhp->zfs_name, mntpt, *curr_proto) != 0) { if (mntpt != NULL) @@ -1170,7 +864,8 @@ remove_mountpoint(zfs_handle_t *zhp) char mountpoint[ZFS_MAXPROPLEN]; zprop_source_t source; - if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), &source, 0)) + if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), + &source, 0)) return; if (source == ZPROP_SRC_DEFAULT || @@ -1738,7 +1433,7 @@ zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force) zfs_share_proto_t *curr_proto; for (curr_proto = share_all_proto; *curr_proto != PROTO_END; curr_proto++) { - if (is_shared(hdl, mountpoints[i], *curr_proto) && + if (is_shared_impl(hdl, mountpoints[i], *curr_proto) && unshare_one(hdl, mountpoints[i], mountpoints[i], *curr_proto) != 0) goto out; |