X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=lib%2Flibzfs%2Flibzfs_mount.c;h=9a57ad98f050c13eaff6a5610436b398e70f5a1e;hb=389cf730cedd42dd1ef653e9358635c114e458d5;hp=42036a44b8bd30822b963794a2602b5a93653c84;hpb=c5d915f4237bbd1f5623b5044a1924a3cb91852b;p=zfs.git diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c index 42036a4..9a57ad9 100644 --- a/lib/libzfs/libzfs_mount.c +++ b/lib/libzfs/libzfs_mount.c @@ -72,9 +72,6 @@ #include #include #include -#ifdef HAVE_LIBSELINUX -#include -#endif /* HAVE_LIBSELINUX */ #include @@ -84,7 +81,6 @@ #include #define MAXISALEN 257 /* based on sysinfo(2) man page */ -#ifdef HAVE_ZPL 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); @@ -121,21 +117,20 @@ zfs_share_proto_t share_all_proto[] = { }; /* - * Search for NFS and SMB exports for the given mountpoint and protocol, returning + * 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); (void) fseek(hdl->libzfs_sharetab, 0, SEEK_SET); - /* Search /etc/exports for NFS exports */ - /* FIXME: Assumes the file is tab delimited. */ while (fgets(buf, sizeof (buf), hdl->libzfs_sharetab) != NULL) { /* the mountpoint is the first entry on each line */ @@ -144,15 +139,31 @@ is_shared(libzfs_handle_t *hdl, const char *mountpoint, zfs_share_proto_t proto) *tab = '\0'; if (strcmp(buf, mountpoint) == 0) { - if (proto == PROTO_NFS) - return (SHARED_NFS); - else - return (SHARED_NOT_SHARED); + /* + * 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); + } + } } } - /* XXX: Search /etc/samba/smb.conf for SMB exports, return SHARED_SMB */ - return (SHARED_NOT_SHARED); } @@ -273,7 +284,7 @@ do_mount(const char *src, const char *mntpt, char *opts) int rc; /* Return only the most critical mount error */ - rc = libzfs_run_process(argv[0], argv); + rc = libzfs_run_process(argv[0], argv, STDOUT_VERBOSE|STDERR_VERBOSE); if (rc) { if (rc & MOUNT_FILEIO) return EIO; @@ -314,11 +325,57 @@ do_unmount(const char *mntpt, int flags) } argv[count] = (char *)mntpt; - rc = libzfs_run_process(argv[0], argv); + 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) +{ + char *source; + uint64_t value; + + /* Skip adding duplicate default options */ + if ((strstr(options, on) != NULL) || (strstr(options, off) != NULL)) + return (0); + + /* + * zfs_prop_get_int() to not used to ensure our mount options + * are not influenced by the current /etc/mtab contents. + */ + value = getprop_uint64(zhp, prop, &source); + + (void) strlcat(options, ",", len); + (void) strlcat(options, value ? on : off, len); + + return (0); +} + +static int +zfs_add_options(zfs_handle_t *zhp, char *options, int len) +{ + int error = 0; + + error = zfs_add_option(zhp, options, len, + ZFS_PROP_ATIME, MNTOPT_ATIME, MNTOPT_NOATIME); + error = error ? error : zfs_add_option(zhp, options, len, + ZFS_PROP_DEVICES, MNTOPT_DEVICES, MNTOPT_NODEVICES); + error = error ? error : zfs_add_option(zhp, options, len, + ZFS_PROP_EXEC, MNTOPT_EXEC, MNTOPT_NOEXEC); + error = error ? error : zfs_add_option(zhp, options, len, + ZFS_PROP_READONLY, MNTOPT_RO, MNTOPT_RW); + error = error ? error : zfs_add_option(zhp, options, len, + ZFS_PROP_SETUID, MNTOPT_SETUID, MNTOPT_NOSETUID); + error = error ? error : zfs_add_option(zhp, options, len, + ZFS_PROP_XATTR, MNTOPT_XATTR, MNTOPT_NOXATTR); + error = error ? error : zfs_add_option(zhp, options, len, + ZFS_PROP_NBMAND, MNTOPT_NBMAND, MNTOPT_NONBMAND); + + return (error); +} + /* * Mount the given filesystem. */ @@ -329,12 +386,16 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags) char mountpoint[ZFS_MAXPROPLEN]; char mntopts[MNT_LINE_MAX]; libzfs_handle_t *hdl = zhp->zfs_hdl; - int rc; + int remount = 0, rc; - if (options == NULL) + if (options == NULL) { (void) strlcpy(mntopts, MNTOPT_DEFAULTS, sizeof (mntopts)); - else + } else { (void) strlcpy(mntopts, options, sizeof (mntopts)); + } + + if (strstr(mntopts, MNTOPT_REMOUNT) != NULL) + remount = 1; /* * If the pool is imported read-only then all mounts must be read-only @@ -343,16 +404,26 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags) (void) strlcat(mntopts, "," MNTOPT_RO, sizeof (mntopts)); /* + * Append default mount options which apply to the mount point. + * This is done because under Linux (unlike Solaris) multiple mount + * points may reference a single super block. This means that just + * given a super block there is no back reference to update the per + * mount point options. + */ + rc = zfs_add_options(zhp, mntopts, sizeof (mntopts)); + if (rc) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "default options unavailable")); + return (zfs_error_fmt(hdl, EZFS_MOUNTFAILED, + dgettext(TEXT_DOMAIN, "cannot mount '%s'"), + mountpoint)); + } + + /* * Append zfsutil option so the mount helper allow the mount */ strlcat(mntopts, "," MNTOPT_ZFSUTIL, sizeof (mntopts)); -#ifdef HAVE_LIBSELINUX - if (is_selinux_enabled()) - (void) strlcat(mntopts, ",context=\"system_u:" - "object_r:file_t:s0\"", sizeof (mntopts)); -#endif /* HAVE_LIBSELINUX */ - if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL)) return (0); @@ -369,9 +440,10 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags) /* * Determine if the mountpoint is empty. If so, refuse to perform the - * mount. We don't perform this check if 'remount' is specified. + * mount. We don't perform this check if 'remount' is + * specified or if overlay option(-O) is given */ - if (strstr(mntopts, MNTOPT_REMOUNT) == NULL && + if ((flags & MS_OVERLAY) == 0 && !remount && !dir_is_empty(mountpoint)) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "directory is not empty")); @@ -413,6 +485,10 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags) zhp->zfs_name)); } + /* remove the mounted entry before re-adding on remount */ + if (remount) + libzfs_mnttab_remove(hdl, zhp->zfs_name); + /* add the mounted entry into our cache */ libzfs_mnttab_add(hdl, zfs_get_name(zhp), mountpoint, mntopts); return (0); @@ -424,8 +500,10 @@ zfs_mount(zfs_handle_t *zhp, const char *options, int flags) static int unmount_one(libzfs_handle_t *hdl, const char *mountpoint, int flags) { - if (do_unmount(mountpoint, flags) != 0) { - zfs_error_aux(hdl, strerror(errno)); + int error; + + error = do_unmount(mountpoint, flags); + if (error != 0) { return (zfs_error_fmt(hdl, EZFS_UMOUNTFAILED, dgettext(TEXT_DOMAIN, "cannot unmount '%s'"), mountpoint)); @@ -566,97 +644,6 @@ zfs_is_shared_smb(zfs_handle_t *zhp, char **where) } /* - * Make sure things will work if libshare isn't installed by using - * wrapper functions that check to see that the pointers to functions - * initialized in _zfs_init_libshare() are actually present. - */ - -static sa_handle_t (*_sa_init)(int); -static void (*_sa_fini)(sa_handle_t); -static sa_share_t (*_sa_find_share)(sa_handle_t, char *); -static int (*_sa_enable_share)(sa_share_t, char *); -static int (*_sa_disable_share)(sa_share_t, char *); -static char *(*_sa_errorstr)(int); -static int (*_sa_parse_legacy_options)(sa_group_t, char *, char *); -static boolean_t (*_sa_needs_refresh)(sa_handle_t *); -static libzfs_handle_t *(*_sa_get_zfs_handle)(sa_handle_t); -static int (*_sa_zfs_process_share)(sa_handle_t, sa_group_t, sa_share_t, - char *, char *, zprop_source_t, char *, char *, char *); -static void (*_sa_update_sharetab_ts)(sa_handle_t); - -/* - * _zfs_init_libshare() - * - * Find the libshare.so.1 entry points that we use here and save the - * values to be used later. This is triggered by the runtime loader. - * Make sure the correct ISA version is loaded. - */ -#ifdef __GNUC__ -static void -_zfs_init_libshare(void) __attribute__((constructor)); -#else -#pragma init(_zfs_init_libshare) -#endif -static void -_zfs_init_libshare(void) -{ - void *libshare; - char path[MAXPATHLEN]; - char isa[MAXISALEN]; - -#if defined(_LP64) - if (sysinfo(SI_ARCHITECTURE_64, isa, MAXISALEN) == -1) - isa[0] = '\0'; -#else - isa[0] = '\0'; -#endif - (void) snprintf(path, MAXPATHLEN, - "/usr/lib/%s/libshare.so.1", isa); - - if ((libshare = dlopen(path, RTLD_LAZY | RTLD_GLOBAL)) != NULL) { - _sa_init = (sa_handle_t (*)(int))dlsym(libshare, "sa_init"); - _sa_fini = (void (*)(sa_handle_t))dlsym(libshare, "sa_fini"); - _sa_find_share = (sa_share_t (*)(sa_handle_t, char *)) - dlsym(libshare, "sa_find_share"); - _sa_enable_share = (int (*)(sa_share_t, char *))dlsym(libshare, - "sa_enable_share"); - _sa_disable_share = (int (*)(sa_share_t, char *))dlsym(libshare, - "sa_disable_share"); - _sa_errorstr = (char *(*)(int))dlsym(libshare, "sa_errorstr"); - _sa_parse_legacy_options = (int (*)(sa_group_t, char *, char *)) - dlsym(libshare, "sa_parse_legacy_options"); - _sa_needs_refresh = (boolean_t (*)(sa_handle_t *)) - dlsym(libshare, "sa_needs_refresh"); - _sa_get_zfs_handle = (libzfs_handle_t *(*)(sa_handle_t)) - dlsym(libshare, "sa_get_zfs_handle"); - _sa_zfs_process_share = (int (*)(sa_handle_t, sa_group_t, - sa_share_t, char *, char *, zprop_source_t, char *, - char *, char *))dlsym(libshare, "sa_zfs_process_share"); - _sa_update_sharetab_ts = (void (*)(sa_handle_t)) - dlsym(libshare, "sa_update_sharetab_ts"); - if (_sa_init == NULL || _sa_fini == NULL || - _sa_find_share == NULL || _sa_enable_share == NULL || - _sa_disable_share == NULL || _sa_errorstr == NULL || - _sa_parse_legacy_options == NULL || - _sa_needs_refresh == NULL || _sa_get_zfs_handle == NULL || - _sa_zfs_process_share == NULL || - _sa_update_sharetab_ts == NULL) { - _sa_init = NULL; - _sa_fini = NULL; - _sa_disable_share = NULL; - _sa_enable_share = NULL; - _sa_errorstr = NULL; - _sa_parse_legacy_options = NULL; - (void) dlclose(libshare); - _sa_needs_refresh = NULL; - _sa_get_zfs_handle = NULL; - _sa_zfs_process_share = NULL; - _sa_update_sharetab_ts = NULL; - } - } -} - -/* * zfs_init_libshare(zhandle, service) * * Initialize the libshare API if it hasn't already been initialized. @@ -669,9 +656,6 @@ zfs_init_libshare(libzfs_handle_t *zhandle, int service) { int ret = SA_OK; - if (_sa_init == NULL) - ret = SA_CONFIG_ERR; - if (ret == SA_OK && zhandle->libzfs_shareflags & ZFSSHARE_MISS) { /* * We had a cache miss. Most likely it is a new ZFS @@ -682,15 +666,14 @@ zfs_init_libshare(libzfs_handle_t *zhandle, int service) * internal cache. */ zhandle->libzfs_shareflags &= ~ZFSSHARE_MISS; - if (_sa_needs_refresh != NULL && - _sa_needs_refresh(zhandle->libzfs_sharehdl)) { + if (sa_needs_refresh(zhandle->libzfs_sharehdl)) { zfs_uninit_libshare(zhandle); - zhandle->libzfs_sharehdl = _sa_init(service); + zhandle->libzfs_sharehdl = sa_init(service); } } if (ret == SA_OK && zhandle && zhandle->libzfs_sharehdl == NULL) - zhandle->libzfs_sharehdl = _sa_init(service); + zhandle->libzfs_sharehdl = sa_init(service); if (ret == SA_OK && zhandle->libzfs_sharehdl == NULL) ret = SA_NO_MEMORY; @@ -708,8 +691,7 @@ void zfs_uninit_libshare(libzfs_handle_t *zhandle) { if (zhandle != NULL && zhandle->libzfs_sharehdl != NULL) { - if (_sa_fini != NULL) - _sa_fini(zhandle->libzfs_sharehdl); + sa_fini(zhandle->libzfs_sharehdl); zhandle->libzfs_sharehdl = NULL; } } @@ -723,59 +705,14 @@ zfs_uninit_libshare(libzfs_handle_t *zhandle) int zfs_parse_options(char *options, zfs_share_proto_t proto) { - if (_sa_parse_legacy_options != NULL) { - return (_sa_parse_legacy_options(NULL, options, - proto_table[proto].p_name)); - } - return (SA_CONFIG_ERR); -} - -/* - * zfs_sa_find_share(handle, path) - * - * wrapper around sa_find_share to find a share path in the - * configuration. - */ -static sa_share_t -zfs_sa_find_share(sa_handle_t handle, char *path) -{ - if (_sa_find_share != NULL) - return (_sa_find_share(handle, path)); - return (NULL); -} - -/* - * zfs_sa_enable_share(share, proto) - * - * Wrapper for sa_enable_share which enables a share for a specified - * protocol. - */ -static int -zfs_sa_enable_share(sa_share_t share, char *proto) -{ - if (_sa_enable_share != NULL) - return (_sa_enable_share(share, proto)); - return (SA_CONFIG_ERR); -} - -/* - * zfs_sa_disable_share(share, proto) - * - * Wrapper for sa_enable_share which disables a share for a specified - * protocol. - */ -static int -zfs_sa_disable_share(sa_share_t share, char *proto) -{ - if (_sa_disable_share != NULL) - return (_sa_disable_share(share, proto)); - return (SA_CONFIG_ERR); + return (sa_parse_legacy_options(NULL, options, + 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 the dirty work for us. + * on "libshare" to do the dirty work for us. */ static int zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto) @@ -793,12 +730,9 @@ zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto) return (0); if ((ret = zfs_init_libshare(hdl, SA_INIT_SHARE_API)) != SA_OK) { -#ifdef HAVE_SHARE (void) zfs_error_fmt(hdl, EZFS_SHARENFSFAILED, dgettext(TEXT_DOMAIN, "cannot share '%s': %s"), - zfs_get_name(zhp), _sa_errorstr != NULL ? - _sa_errorstr(ret) : ""); -#endif /* HAVE_SHARE */ + zfs_get_name(zhp), sa_errorstr(ret)); return (-1); } @@ -821,7 +755,7 @@ zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto) if (zfs_prop_get_int(zhp, ZFS_PROP_ZONED)) continue; - share = zfs_sa_find_share(hdl->libzfs_sharehdl, mountpoint); + share = sa_find_share(hdl->libzfs_sharehdl, mountpoint); if (share == NULL) { /* * This may be a new file system that was just @@ -832,7 +766,7 @@ zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto) * safe to add this to the internal * configuration. */ - if (_sa_zfs_process_share(hdl->libzfs_sharehdl, + 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) { @@ -843,12 +777,12 @@ zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto) return (-1); } hdl->libzfs_shareflags |= ZFSSHARE_MISS; - share = zfs_sa_find_share(hdl->libzfs_sharehdl, + share = sa_find_share(hdl->libzfs_sharehdl, mountpoint); } if (share != NULL) { int err; - err = zfs_sa_enable_share(share, + err = sa_enable_share(share, proto_table[*curr_proto].p_name); if (err != SA_OK) { (void) zfs_error_fmt(hdl, @@ -910,18 +844,18 @@ unshare_one(libzfs_handle_t *hdl, const char *name, const char *mountpoint, free(mntpt); /* don't need the copy anymore */ return (zfs_error_fmt(hdl, EZFS_SHARENFSFAILED, dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"), - name, _sa_errorstr(err))); + name, sa_errorstr(err))); } - share = zfs_sa_find_share(hdl->libzfs_sharehdl, mntpt); + share = sa_find_share(hdl->libzfs_sharehdl, mntpt); free(mntpt); /* don't need the copy anymore */ if (share != NULL) { - err = zfs_sa_disable_share(share, proto_table[proto].p_name); + err = sa_disable_share(share, proto_table[proto].p_name); if (err != SA_OK) { return (zfs_error_fmt(hdl, EZFS_UNSHARENFSFAILED, dgettext(TEXT_DOMAIN, "cannot unshare '%s': %s"), - name, _sa_errorstr(err))); + name, sa_errorstr(err))); } } else { return (zfs_error_fmt(hdl, EZFS_UNSHARENFSFAILED, @@ -955,11 +889,11 @@ zfs_unshare_proto(zfs_handle_t *zhp, const char *mountpoint, mntpt = zfs_strdup(zhp->zfs_hdl, entry.mnt_mountp); for (curr_proto = proto; *curr_proto != PROTO_END; - curr_proto++) { + curr_proto++) { if (is_shared(hdl, mntpt, *curr_proto) && unshare_one(hdl, zhp->zfs_name, - mntpt, *curr_proto) != 0) { + mntpt, *curr_proto) != 0) { if (mntpt != NULL) free(mntpt); return (-1); @@ -1212,7 +1146,7 @@ mountpoint_compare(const void *a, const void *b) * Unshare and unmount all datasets within the given pool. We don't want to * rely on traversing the DSL to discover the filesystems within the pool, * because this may be expensive (if not all of them are mounted), and can fail - * arbitrarily (on I/O error, for example). Instead, we walk /etc/mnttab and + * arbitrarily (on I/O error, for example). Instead, we walk /etc/mtab and * gather all the filesystems that are currently mounted. */ int @@ -1343,53 +1277,3 @@ out: return (ret); } - -#else /* HAVE_ZPL */ - -int -zfs_unshare_iscsi(zfs_handle_t *zhp) -{ - return 0; -} - -int -zfs_unmount(zfs_handle_t *zhp, const char *mountpoint, int flags) -{ - return 0; -} - -void -remove_mountpoint(zfs_handle_t *zhp) { - return; -} - -boolean_t -is_mounted(libzfs_handle_t *zfs_hdl, const char *special, char **where) -{ - return B_FALSE; -} - -boolean_t -zfs_is_mounted(zfs_handle_t *zhp, char **where) -{ - return is_mounted(zhp->zfs_hdl, zfs_get_name(zhp), where); -} - -boolean_t -zfs_is_shared(zfs_handle_t *zhp) -{ - return B_FALSE; -} - -int -zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags) -{ - return B_FALSE; -} - -int -zpool_disable_datasets(zpool_handle_t *zhp, boolean_t force) -{ - return B_FALSE; -} -#endif /* HAVE_ZPL */