diff options
| author | marks <none@none> | 2007-06-26 07:44:24 -0700 |
|---|---|---|
| committer | marks <none@none> | 2007-06-26 07:44:24 -0700 |
| commit | ecd6cf800b63704be73fb264c3f5b6e0dafc068d (patch) | |
| tree | ec83d040bc56ee0a46e9533a645e832e58d8ba86 /usr/src/lib/libshare | |
| parent | 8ac1b93fdff76ea81638299d410b2d474240ee2b (diff) | |
| download | illumos-joyent-ecd6cf800b63704be73fb264c3f5b6e0dafc068d.tar.gz | |
PSARC/2006/465 ZFS Delegated Administration
PSARC/2006/577 zpool property to disable delegation
PSARC/2006/625 Enhancements to zpool history
PSARC/2007/228 ZFS delegation amendments
PSARC/2007/295 ZFS Delegated Administration Addendum
6280676 restore "owner" property
6349470 investigate non-root restore/backup
6572465 'zpool set bootfs=...' records history as 'zfs set bootfs=...'
Diffstat (limited to 'usr/src/lib/libshare')
| -rw-r--r-- | usr/src/lib/libshare/common/libshare.c | 4 | ||||
| -rw-r--r-- | usr/src/lib/libshare/common/libshare.h | 2 | ||||
| -rw-r--r-- | usr/src/lib/libshare/common/libshare_impl.h | 11 | ||||
| -rw-r--r-- | usr/src/lib/libshare/common/libshare_zfs.c | 75 | ||||
| -rw-r--r-- | usr/src/lib/libshare/common/libsharecore.c | 16 | ||||
| -rw-r--r-- | usr/src/lib/libshare/common/mapfile-vers | 4 | ||||
| -rw-r--r-- | usr/src/lib/libshare/common/plugin.c | 4 | ||||
| -rw-r--r-- | usr/src/lib/libshare/nfs/libshare_nfs.c | 105 |
8 files changed, 189 insertions, 32 deletions
diff --git a/usr/src/lib/libshare/common/libshare.c b/usr/src/lib/libshare/common/libshare.c index 6809ab92cf..25213e97a4 100644 --- a/usr/src/lib/libshare/common/libshare.c +++ b/usr/src/lib/libshare/common/libshare.c @@ -1367,10 +1367,10 @@ sa_disable_share(sa_share_t share, char *protocol) shared = sa_get_share_attr(share, "shared"); if (protocol != NULL) { - ret = sa_proto_unshare(protocol, path); + ret = sa_proto_unshare(share, protocol, path); } else { /* need to do all protocols */ - ret = sa_proto_unshare("nfs", path); + ret = sa_proto_unshare(share, "nfs", path); } if (ret == SA_OK) (void) sa_set_share_attr(share, "shared", NULL); diff --git a/usr/src/lib/libshare/common/libshare.h b/usr/src/lib/libshare/common/libshare.h index 754ef61c69..c78b0822c6 100644 --- a/usr/src/lib/libshare/common/libshare.h +++ b/usr/src/lib/libshare/common/libshare.h @@ -216,7 +216,7 @@ extern int sa_delete_sharetab(char *, char *); /* ZFS functions */ extern int sa_zfs_is_shared(sa_handle_t, char *); extern int sa_group_is_zfs(sa_group_t); - +extern int sa_path_is_zfs(char *); /* SA Handle specific functions */ extern sa_handle_t sa_find_group_handle(sa_group_t); diff --git a/usr/src/lib/libshare/common/libshare_impl.h b/usr/src/lib/libshare/common/libshare_impl.h index 2eef7559c9..a428110a81 100644 --- a/usr/src/lib/libshare/common/libshare_impl.h +++ b/usr/src/lib/libshare/common/libshare_impl.h @@ -38,6 +38,8 @@ #include <libscf.h> #include <scfutil.h> #include <libzfs.h> +#include <sharefs/share.h> +#include "sharetab.h" #ifdef __cplusplus extern "C" { @@ -58,7 +60,7 @@ struct sa_plugin_ops { int (*sa_init)(); void (*sa_fini)(); int (*sa_share)(sa_share_t); /* start sharing */ - int (*sa_unshare)(char *); /* stop sharing */ + int (*sa_unshare)(sa_share_t, char *); /* stop sharing */ int (*sa_valid_prop)(sa_property_t, sa_optionset_t); int (*sa_valid_space)(char *); /* is name valid optionspace? */ int (*sa_security_prop)(char *); /* property is security */ @@ -91,7 +93,7 @@ typedef struct propertylist { } property_list_t; extern int sa_proto_share(char *, sa_share_t); -extern int sa_proto_unshare(char *, char *); +extern int sa_proto_unshare(sa_share_t, char *, char *); extern int sa_proto_valid_prop(char *, sa_property_t, sa_optionset_t); extern int sa_proto_security_prop(char *, char *); extern int sa_proto_legacy_opts(char *, sa_group_t, char *); @@ -113,10 +115,15 @@ extern int sa_delete_share(scfutilhandle_t *, sa_group_t, sa_share_t); extern int sa_delete_instance(scfutilhandle_t *, char *); extern int sa_create_pgroup(scfutilhandle_t *, char *); extern int sa_delete_pgroup(scfutilhandle_t *, char *); +extern void sa_fillshare(sa_share_t share, char *proto, struct share *sh); +extern void sa_emptyshare(struct share *sh); /* ZFS functions */ extern int sa_get_zfs_shares(sa_handle_t, char *); extern int sa_zfs_update(sa_share_t); +extern int sa_share_zfs(sa_share_t, char *, share_t *, void *, boolean_t); +extern int sa_sharetab_fill_zfs(sa_share_t share, struct share *sh, + char *proto); /* plugin specific functions */ extern int proto_plugin_init(); diff --git a/usr/src/lib/libshare/common/libshare_zfs.c b/usr/src/lib/libshare/common/libshare_zfs.c index b7ac6c0d74..8beb621524 100644 --- a/usr/src/lib/libshare/common/libshare_zfs.c +++ b/usr/src/lib/libshare/common/libshare_zfs.c @@ -254,7 +254,7 @@ get_zfs_dataset(sa_handle_impl_t impl_handle, char *path) /* canmount must be set */ canmount[0] = '\0'; - if (!zfs_prop_get(zlist[i], ZFS_PROP_CANMOUNT, canmount, + if (zfs_prop_get(zlist[i], ZFS_PROP_CANMOUNT, canmount, sizeof (canmount), NULL, NULL, 0, B_FALSE) != 0 || strcmp(canmount, "off") == 0) continue; @@ -914,3 +914,76 @@ sa_path_is_zfs(char *path) sa_free_fstype(fstype); return (ret); } + +int +sa_sharetab_fill_zfs(sa_share_t share, share_t *sh, char *proto) +{ + char *path; + + path = sa_get_share_attr(share, "path"); + if (path != NULL) { + (void) memset(sh, 0, sizeof (sh)); + (void) sa_fillshare(share, proto, sh); + return (0); + } else + return (1); +} + +#define SMAX(i, j) \ + if ((j) > (i)) { \ + (i) = (j); \ + } + +int +sa_share_zfs(sa_share_t share, char *path, share_t *sh, + void *exportdata, boolean_t on) +{ + libzfs_handle_t *libhandle; + sa_group_t group; + sa_handle_t sahandle; + char *dataset; + int err = EINVAL; + int i, j; + + /* + * First find the dataset name + */ + if ((group = sa_get_parent_group(share)) == NULL) { + return (SA_SYSTEM_ERR); + } + if ((sahandle = sa_find_group_handle(group)) == NULL) { + return (SA_SYSTEM_ERR); + } + + if ((dataset = get_zfs_dataset(sahandle, path)) == NULL) { + return (SA_SYSTEM_ERR); + } + + libhandle = libzfs_init(); + if (libhandle != NULL) { + + i = (sh->sh_path ? strlen(sh->sh_path) : 0); + sh->sh_size = i; + + j = (sh->sh_res ? strlen(sh->sh_res) : 0); + sh->sh_size += j; + SMAX(i, j); + + j = (sh->sh_fstype ? strlen(sh->sh_fstype) : 0); + sh->sh_size += j; + SMAX(i, j); + + j = (sh->sh_opts ? strlen(sh->sh_opts) : 0); + sh->sh_size += j; + SMAX(i, j); + + j = (sh->sh_descr ? strlen(sh->sh_descr) : 0); + sh->sh_size += j; + SMAX(i, j); + err = zfs_deleg_share_nfs(libhandle, dataset, path, + exportdata, sh, i, on); + libzfs_fini(libhandle); + } + free(dataset); + return (err); +} diff --git a/usr/src/lib/libshare/common/libsharecore.c b/usr/src/lib/libshare/common/libsharecore.c index d3bf9f4f6d..cbef53feab 100644 --- a/usr/src/lib/libshare/common/libsharecore.c +++ b/usr/src/lib/libshare/common/libsharecore.c @@ -1832,12 +1832,12 @@ sa_free_derived_security(sa_security_t security) */ /* - * fillshare(share, proto, sh) + * sa_fillshare(share, proto, sh) * * Fill the struct share with values obtained from the share object. */ -static void -fillshare(sa_share_t share, char *proto, struct share *sh) +void +sa_fillshare(sa_share_t share, char *proto, struct share *sh) { char *groupname = NULL; char *value; @@ -1916,13 +1916,13 @@ fillshare(sa_share_t share, char *proto, struct share *sh) } /* - * emptyshare(sh) + * sa_emptyshare(sh) * * Free the strings in the non-NULL members of sh. */ -static void -emptyshare(struct share *sh) +void +sa_emptyshare(struct share *sh) { if (sh->sh_path != NULL) free(sh->sh_path); @@ -1962,9 +1962,9 @@ sa_update_sharetab(sa_share_t share, char *proto) /* * Fill in share structure and send it to the kernel. */ - (void) fillshare(share, proto, &sh); + (void) sa_fillshare(share, proto, &sh); (void) sharefs(SHAREFS_ADD, &sh); - emptyshare(&sh); + sa_emptyshare(&sh); sa_free_attr_string(path); } diff --git a/usr/src/lib/libshare/common/mapfile-vers b/usr/src/lib/libshare/common/mapfile-vers index eb71ae23fb..317623b3b4 100644 --- a/usr/src/lib/libshare/common/mapfile-vers +++ b/usr/src/lib/libshare/common/mapfile-vers @@ -62,10 +62,14 @@ SUNWprivate { sa_commit_properties; sa_parse_legacy_options; sa_zfs_is_shared; + sa_share_zfs; + sa_path_is_zfs; sa_get_derived_optionset; sa_move_share; sa_group_is_zfs; sa_update_config; + sa_sharetab_fill_zfs; + sa_emptyshare; sa_get_share_attr; sa_create_optionset; sa_valid_property; diff --git a/usr/src/lib/libshare/common/plugin.c b/usr/src/lib/libshare/common/plugin.c index ab682e6f10..83bc4d5d94 100644 --- a/usr/src/lib/libshare/common/plugin.c +++ b/usr/src/lib/libshare/common/plugin.c @@ -240,13 +240,13 @@ sa_proto_share(char *proto, sa_share_t share) */ int -sa_proto_unshare(char *proto, char *path) +sa_proto_unshare(sa_share_t share, char *proto, char *path) { struct sa_plugin_ops *ops = find_protocol(proto); int ret = SA_INVALID_PROTOCOL; if (ops != NULL && ops->sa_unshare != NULL) - ret = ops->sa_unshare(path); + ret = ops->sa_unshare(share, path); return (ret); } diff --git a/usr/src/lib/libshare/nfs/libshare_nfs.c b/usr/src/lib/libshare/nfs/libshare_nfs.c index f7b8e8ecba..ec25f19efe 100644 --- a/usr/src/lib/libshare/nfs/libshare_nfs.c +++ b/usr/src/lib/libshare/nfs/libshare_nfs.c @@ -49,6 +49,7 @@ #include "libshare_nfs.h" #include <rpcsvc/daemon_utils.h> #include <nfs/nfs.h> +#include <nfs/nfssys.h> /* should really be in some global place */ #define DEF_WIN 30000 @@ -56,12 +57,13 @@ int debug = 0; +#define NFS_SERVER_SVC "svc:/network/nfs/server:default" /* internal functions */ static int nfs_init(); static void nfs_fini(); static int nfs_enable_share(sa_share_t); -static int nfs_disable_share(char *); +static int nfs_disable_share(sa_share_t, char *); static int nfs_validate_property(sa_property_t, sa_optionset_t); static int nfs_validate_security_mode(char *); static int nfs_is_security_opt(char *); @@ -1616,6 +1618,7 @@ nfs_enable_share(sa_share_t share) char *path; int err = SA_OK; int i; + int iszfs; /* Don't drop core if the NFS module isn't loaded. */ (void) signal(SIGSYS, SIG_IGN); @@ -1625,6 +1628,7 @@ nfs_enable_share(sa_share_t share) if (path == NULL) return (SA_NO_SUCH_PATH); + iszfs = sa_path_is_zfs(path); /* * find the optionsets and security sets. There may not be * any or there could be one or two for each of optionset and @@ -1741,18 +1745,67 @@ nfs_enable_share(sa_share_t share) * call the exportfs system call which is implemented * via the nfssys() call as the EXPORTFS subfunction. */ - if ((err = exportfs(path, &export)) < 0) { + if (iszfs) { + struct exportfs_args ea; + share_t sh; + char *str; + priv_set_t *priv_effective; + int privileged; + + /* + * If we aren't a privileged user + * and NFS server service isn't running + * then print out an error message + * and return EPERM + */ + + priv_effective = priv_allocset(); + (void) getppriv(PRIV_EFFECTIVE, priv_effective); + + privileged = (priv_isfullset(priv_effective) == B_TRUE); + priv_freeset(priv_effective); + + if (!privileged && + (str = smf_get_state(NFS_SERVER_SVC)) != NULL) { + err = 0; + if (strcmp(str, SCF_STATE_STRING_ONLINE) != 0) { + (void) printf(dgettext(TEXT_DOMAIN, + "NFS: Cannot share remote " + "filesystem: %s\n"), path); + (void) printf(dgettext(TEXT_DOMAIN, + "NFS: Service needs to be enabled " + "by a privileged user\n")); + err = SA_SYSTEM_ERR; + errno = EPERM; + } + free(str); + } + + if (err == 0) { + ea.dname = path; + ea.uex = &export; + + sa_sharetab_fill_zfs(share, &sh, "nfs"); + err = sa_share_zfs(share, path, &sh, &ea, B_TRUE); + sa_emptyshare(&sh); + } + } else { + err = exportfs(path, &export); + } + + if (err < 0) { err = SA_SYSTEM_ERR; switch (errno) { case EREMOTE: (void) printf(dgettext(TEXT_DOMAIN, - "NFS: Cannot share remote " - "filesystem: %s\n"), path); + "NFS: Cannot share filesystems " + "in non-global zones: %s\n"), path); + err = SA_NOT_SUPPORTED; break; case EPERM: if (getzoneid() != GLOBAL_ZONEID) { (void) printf(dgettext(TEXT_DOMAIN, - "NFS: Cannot share filesystems " + "NFS: Cannot share file systems " "in non-global zones: %s\n"), path); err = SA_NOT_SUPPORTED; break; @@ -1764,7 +1817,9 @@ nfs_enable_share(sa_share_t share) } } else { /* update sharetab with an add/modify */ - (void) sa_update_sharetab(share, "nfs"); + if (!iszfs) { + (void) sa_update_sharetab(share, "nfs"); + } } if (err == SA_OK) { @@ -1817,38 +1872,56 @@ out: * done? We only do basic errors for now. */ static int -nfs_disable_share(char *share) +nfs_disable_share(sa_share_t share, char *path) { int err; int ret = SA_OK; + int iszfs; + + + if (path != NULL) { + iszfs = sa_path_is_zfs(path); + + if (iszfs) { + struct exportfs_args ea; + share_t sh = { 0 }; + + ea.dname = path; + ea.uex = NULL; + sh.sh_path = path; + sh.sh_fstype = "nfs"; - if (share != NULL) { - err = exportfs(share, NULL); + err = sa_share_zfs(share, path, &sh, &ea, B_FALSE); + } else + err = exportfs(path, NULL); if (err < 0) { /* - * TBD: only an error in some cases - need - * better analysis + * TBD: only an error in some + * cases - need better analysis */ + switch (errno) { case EPERM: case EACCES: ret = SA_NO_PERMISSION; - if (getzoneid() != GLOBAL_ZONEID) + if (getzoneid() != GLOBAL_ZONEID) { ret = SA_NOT_SUPPORTED; + } break; case EINVAL: case ENOENT: ret = SA_NO_SUCH_PATH; - break; + break; default: ret = SA_SYSTEM_ERR; - break; + break; } } if (ret == SA_OK || ret == SA_NO_SUCH_PATH) { - (void) sa_delete_sharetab(share, "nfs"); + if (!iszfs) + (void) sa_delete_sharetab(path, "nfs"); /* just in case it was logged */ - (void) nfslogtab_deactivate(share); + (void) nfslogtab_deactivate(path); } } return (ret); |
