mirror of
				https://git.proxmox.com/git/mirror_zfs.git
				synced 2025-10-26 18:05:04 +03:00 
			
		
		
		
	libshare: use AVL tree with static data, pass all data in arguments
This makes it so we don't leak a consistent 64 bytes anymore, makes the searches simpler and faster, removes /all allocations/ from the driver (quite trivially, since they were absolutely needless), and makes libshare thread-safe (except, maybe, linux/smb, but that only does pointer-width loads/stores so it's also mostly fine, except for leaking smb_shares) Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz> Closes #13165
This commit is contained in:
		
							parent
							
								
									4ccbb23971
								
							
						
					
					
						commit
						63ce6dd988
					
				| @ -27,6 +27,7 @@ | |||||||
| 
 | 
 | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
|  | #include <stddef.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <errno.h> | #include <errno.h> | ||||||
| #include <libintl.h> | #include <libintl.h> | ||||||
| @ -37,139 +38,84 @@ | |||||||
| #include <libzfs.h> | #include <libzfs.h> | ||||||
| #include <libshare.h> | #include <libshare.h> | ||||||
| #include "libshare_impl.h" | #include "libshare_impl.h" | ||||||
| #include "nfs.h" |  | ||||||
| #include "smb.h" |  | ||||||
| 
 | 
 | ||||||
| static sa_share_impl_t alloc_share(const char *zfsname, const char *path); | #define	init_share(zfsname, path, shareopts) \ | ||||||
| static void free_share(sa_share_impl_t share); | 	{ \ | ||||||
|  | 		.sa_zfsname = zfsname, \ | ||||||
|  | 		.sa_mountpoint = path, \ | ||||||
|  | 		.sa_shareopts = shareopts, \ | ||||||
|  | 	} | ||||||
|  | #define	find_proto(pcol) \ | ||||||
|  | 	/* CSTYLED */ \ | ||||||
|  | 	({ \ | ||||||
|  | 		sa_fstype_t prot = { \ | ||||||
|  | 			.protocol = pcol, \ | ||||||
|  | 		}; \ | ||||||
|  | 		avl_find(&fstypes, &prot, NULL); \ | ||||||
|  | 	}) | ||||||
| 
 | 
 | ||||||
| static int fstypes_count; | static avl_tree_t fstypes; | ||||||
| static sa_fstype_t *fstypes; |  | ||||||
| 
 | 
 | ||||||
| sa_fstype_t * | static int | ||||||
| register_fstype(const char *name, const sa_share_ops_t *ops) | fstypes_compar(const void *lhs, const void *rhs) | ||||||
| { | { | ||||||
| 	sa_fstype_t *fstype; | 	const sa_fstype_t *l = lhs, *r = rhs; | ||||||
| 
 | 	int cmp = strcmp(l->protocol, r->protocol); | ||||||
| 	fstype = calloc(1, sizeof (sa_fstype_t)); | 	return ((0 < cmp) - (cmp < 0)); | ||||||
| 
 |  | ||||||
| 	if (fstype == NULL) |  | ||||||
| 		return (NULL); |  | ||||||
| 
 |  | ||||||
| 	fstype->name = name; |  | ||||||
| 	fstype->ops = ops; |  | ||||||
| 	fstype->fsinfo_index = fstypes_count; |  | ||||||
| 
 |  | ||||||
| 	fstypes_count++; |  | ||||||
| 
 |  | ||||||
| 	fstype->next = fstypes; |  | ||||||
| 	fstypes = fstype; |  | ||||||
| 
 |  | ||||||
| 	return (fstype); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| __attribute__((constructor)) static void | __attribute__((constructor)) static void | ||||||
| libshare_init(void) | libshare_init(void) | ||||||
| { | { | ||||||
| 	libshare_nfs_init(); | 	avl_create(&fstypes, fstypes_compar, | ||||||
| 	libshare_smb_init(); | 	    sizeof (sa_fstype_t), offsetof(sa_fstype_t, node)); | ||||||
|  | 	avl_add(&fstypes, &libshare_nfs_type); | ||||||
|  | 	avl_add(&fstypes, &libshare_smb_type); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| sa_enable_share(const char *zfsname, const char *mountpoint, | sa_enable_share(const char *zfsname, const char *mountpoint, | ||||||
|     const char *shareopts, const char *protocol) |     const char *shareopts, const char *protocol) | ||||||
| { | { | ||||||
| 	int rc, ret = SA_OK; | 	sa_fstype_t *fstype = find_proto(protocol); | ||||||
| 	boolean_t found_protocol = B_FALSE; | 	if (!fstype) | ||||||
| 	sa_fstype_t *fstype; | 		return (SA_INVALID_PROTOCOL); | ||||||
| 
 | 
 | ||||||
| 	sa_share_impl_t impl_share = alloc_share(zfsname, mountpoint); | 	const struct sa_share_impl args = | ||||||
| 	if (impl_share == NULL) | 	    init_share(zfsname, mountpoint, shareopts); | ||||||
| 		return (SA_NO_MEMORY); | 	return (fstype->enable_share(&args)); | ||||||
| 
 |  | ||||||
| 	fstype = fstypes; |  | ||||||
| 	while (fstype != NULL) { |  | ||||||
| 		if (strcmp(fstype->name, protocol) == 0) { |  | ||||||
| 
 |  | ||||||
| 			rc = fstype->ops->update_shareopts(impl_share, |  | ||||||
| 			    shareopts); |  | ||||||
| 			if (rc != SA_OK) |  | ||||||
| 				break; |  | ||||||
| 
 |  | ||||||
| 			rc = fstype->ops->enable_share(impl_share); |  | ||||||
| 			if (rc != SA_OK) |  | ||||||
| 				ret = rc; |  | ||||||
| 
 |  | ||||||
| 			found_protocol = B_TRUE; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		fstype = fstype->next; |  | ||||||
| 	} |  | ||||||
| 	free_share(impl_share); |  | ||||||
| 
 |  | ||||||
| 	return (found_protocol ? ret : SA_INVALID_PROTOCOL); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| sa_disable_share(const char *mountpoint, const char *protocol) | sa_disable_share(const char *mountpoint, const char *protocol) | ||||||
| { | { | ||||||
| 	int rc, ret = SA_OK; | 	sa_fstype_t *fstype = find_proto(protocol); | ||||||
| 	boolean_t found_protocol = B_FALSE; | 	if (!fstype) | ||||||
| 	sa_fstype_t *fstype; | 		return (SA_INVALID_PROTOCOL); | ||||||
| 
 | 
 | ||||||
| 	sa_share_impl_t impl_share = alloc_share(NULL, mountpoint); | 	const struct sa_share_impl args = init_share(NULL, mountpoint, NULL); | ||||||
| 	if (impl_share == NULL) | 	return (fstype->disable_share(&args)); | ||||||
| 		return (SA_NO_MEMORY); |  | ||||||
| 
 |  | ||||||
| 	fstype = fstypes; |  | ||||||
| 	while (fstype != NULL) { |  | ||||||
| 		if (strcmp(fstype->name, protocol) == 0) { |  | ||||||
| 
 |  | ||||||
| 			rc = fstype->ops->disable_share(impl_share); |  | ||||||
| 			if (rc != SA_OK) |  | ||||||
| 				ret = rc; |  | ||||||
| 
 |  | ||||||
| 			found_protocol = B_TRUE; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		fstype = fstype->next; |  | ||||||
| 	} |  | ||||||
| 	free_share(impl_share); |  | ||||||
| 
 |  | ||||||
| 	return (found_protocol ? ret : SA_INVALID_PROTOCOL); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| boolean_t | boolean_t | ||||||
| sa_is_shared(const char *mountpoint, const char *protocol) | sa_is_shared(const char *mountpoint, const char *protocol) | ||||||
| { | { | ||||||
| 	sa_fstype_t *fstype; | 	sa_fstype_t *fstype = find_proto(protocol); | ||||||
| 	boolean_t ret = B_FALSE; | 	if (!fstype) | ||||||
| 
 |  | ||||||
| 	/* guid value is not used */ |  | ||||||
| 	sa_share_impl_t impl_share = alloc_share(NULL, mountpoint); |  | ||||||
| 	if (impl_share == NULL) |  | ||||||
| 		return (B_FALSE); | 		return (B_FALSE); | ||||||
| 
 | 
 | ||||||
| 	fstype = fstypes; | 	const struct sa_share_impl args = init_share(NULL, mountpoint, NULL); | ||||||
| 	while (fstype != NULL) { | 	return (fstype->is_shared(&args)); | ||||||
| 		if (strcmp(fstype->name, protocol) == 0) { |  | ||||||
| 			ret = fstype->ops->is_shared(impl_share); |  | ||||||
| 		} |  | ||||||
| 		fstype = fstype->next; |  | ||||||
| 	} |  | ||||||
| 	free_share(impl_share); |  | ||||||
| 	return (ret); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| sa_commit_shares(const char *protocol) | sa_commit_shares(const char *protocol) | ||||||
| { | { | ||||||
| 	sa_fstype_t *fstype = fstypes; | 	sa_fstype_t *fstype = find_proto(protocol); | ||||||
| 	while (fstype != NULL) { | 	if (!fstype) | ||||||
| 		if (strcmp(fstype->name, protocol) == 0) | 		return; | ||||||
| 			fstype->ops->commit_shares(); | 
 | ||||||
| 		fstype = fstype->next; | 	fstype->commit_shares(); | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
| @ -181,185 +127,91 @@ const char * | |||||||
| sa_errorstr(int err) | sa_errorstr(int err) | ||||||
| { | { | ||||||
| 	static char errstr[32]; | 	static char errstr[32]; | ||||||
| 	char *ret = NULL; |  | ||||||
| 
 | 
 | ||||||
| 	switch (err) { | 	switch (err) { | ||||||
| 	case SA_OK: | 	case SA_OK: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "ok"); | 		return (dgettext(TEXT_DOMAIN, "ok")); | ||||||
| 		break; |  | ||||||
| 	case SA_NO_SUCH_PATH: | 	case SA_NO_SUCH_PATH: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "path doesn't exist"); | 		return (dgettext(TEXT_DOMAIN, "path doesn't exist")); | ||||||
| 		break; |  | ||||||
| 	case SA_NO_MEMORY: | 	case SA_NO_MEMORY: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "no memory"); | 		return (dgettext(TEXT_DOMAIN, "no memory")); | ||||||
| 		break; |  | ||||||
| 	case SA_DUPLICATE_NAME: | 	case SA_DUPLICATE_NAME: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "name in use"); | 		return (dgettext(TEXT_DOMAIN, "name in use")); | ||||||
| 		break; |  | ||||||
| 	case SA_BAD_PATH: | 	case SA_BAD_PATH: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "bad path"); | 		return (dgettext(TEXT_DOMAIN, "bad path")); | ||||||
| 		break; |  | ||||||
| 	case SA_NO_SUCH_GROUP: | 	case SA_NO_SUCH_GROUP: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "no such group"); | 		return (dgettext(TEXT_DOMAIN, "no such group")); | ||||||
| 		break; |  | ||||||
| 	case SA_CONFIG_ERR: | 	case SA_CONFIG_ERR: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "configuration error"); | 		return (dgettext(TEXT_DOMAIN, "configuration error")); | ||||||
| 		break; |  | ||||||
| 	case SA_SYSTEM_ERR: | 	case SA_SYSTEM_ERR: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "system error"); | 		return (dgettext(TEXT_DOMAIN, "system error")); | ||||||
| 		break; |  | ||||||
| 	case SA_SYNTAX_ERR: | 	case SA_SYNTAX_ERR: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "syntax error"); | 		return (dgettext(TEXT_DOMAIN, "syntax error")); | ||||||
| 		break; |  | ||||||
| 	case SA_NO_PERMISSION: | 	case SA_NO_PERMISSION: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "no permission"); | 		return (dgettext(TEXT_DOMAIN, "no permission")); | ||||||
| 		break; |  | ||||||
| 	case SA_BUSY: | 	case SA_BUSY: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "busy"); | 		return (dgettext(TEXT_DOMAIN, "busy")); | ||||||
| 		break; |  | ||||||
| 	case SA_NO_SUCH_PROP: | 	case SA_NO_SUCH_PROP: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "no such property"); | 		return (dgettext(TEXT_DOMAIN, "no such property")); | ||||||
| 		break; |  | ||||||
| 	case SA_INVALID_NAME: | 	case SA_INVALID_NAME: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "invalid name"); | 		return (dgettext(TEXT_DOMAIN, "invalid name")); | ||||||
| 		break; |  | ||||||
| 	case SA_INVALID_PROTOCOL: | 	case SA_INVALID_PROTOCOL: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "invalid protocol"); | 		return (dgettext(TEXT_DOMAIN, "invalid protocol")); | ||||||
| 		break; |  | ||||||
| 	case SA_NOT_ALLOWED: | 	case SA_NOT_ALLOWED: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "operation not allowed"); | 		return (dgettext(TEXT_DOMAIN, "operation not allowed")); | ||||||
| 		break; |  | ||||||
| 	case SA_BAD_VALUE: | 	case SA_BAD_VALUE: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "bad property value"); | 		return (dgettext(TEXT_DOMAIN, "bad property value")); | ||||||
| 		break; |  | ||||||
| 	case SA_INVALID_SECURITY: | 	case SA_INVALID_SECURITY: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "invalid security type"); | 		return (dgettext(TEXT_DOMAIN, "invalid security type")); | ||||||
| 		break; |  | ||||||
| 	case SA_NO_SUCH_SECURITY: | 	case SA_NO_SUCH_SECURITY: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "security type not found"); | 		return (dgettext(TEXT_DOMAIN, "security type not found")); | ||||||
| 		break; |  | ||||||
| 	case SA_VALUE_CONFLICT: | 	case SA_VALUE_CONFLICT: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "property value conflict"); | 		return (dgettext(TEXT_DOMAIN, "property value conflict")); | ||||||
| 		break; |  | ||||||
| 	case SA_NOT_IMPLEMENTED: | 	case SA_NOT_IMPLEMENTED: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "not implemented"); | 		return (dgettext(TEXT_DOMAIN, "not implemented")); | ||||||
| 		break; |  | ||||||
| 	case SA_INVALID_PATH: | 	case SA_INVALID_PATH: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "invalid path"); | 		return (dgettext(TEXT_DOMAIN, "invalid path")); | ||||||
| 		break; |  | ||||||
| 	case SA_NOT_SUPPORTED: | 	case SA_NOT_SUPPORTED: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "operation not supported"); | 		return (dgettext(TEXT_DOMAIN, "operation not supported")); | ||||||
| 		break; |  | ||||||
| 	case SA_PROP_SHARE_ONLY: | 	case SA_PROP_SHARE_ONLY: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "property not valid for group"); | 		return (dgettext(TEXT_DOMAIN, "property not valid for group")); | ||||||
| 		break; |  | ||||||
| 	case SA_NOT_SHARED: | 	case SA_NOT_SHARED: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "not shared"); | 		return (dgettext(TEXT_DOMAIN, "not shared")); | ||||||
| 		break; |  | ||||||
| 	case SA_NO_SUCH_RESOURCE: | 	case SA_NO_SUCH_RESOURCE: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "no such resource"); | 		return (dgettext(TEXT_DOMAIN, "no such resource")); | ||||||
| 		break; |  | ||||||
| 	case SA_RESOURCE_REQUIRED: | 	case SA_RESOURCE_REQUIRED: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "resource name required"); | 		return (dgettext(TEXT_DOMAIN, "resource name required")); | ||||||
| 		break; |  | ||||||
| 	case SA_MULTIPLE_ERROR: | 	case SA_MULTIPLE_ERROR: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "errors from multiple protocols"); | 		return (dgettext(TEXT_DOMAIN, | ||||||
| 		break; | 		    "errors from multiple protocols")); | ||||||
| 	case SA_PATH_IS_SUBDIR: | 	case SA_PATH_IS_SUBDIR: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "path is a subpath of share"); | 		return (dgettext(TEXT_DOMAIN, "path is a subpath of share")); | ||||||
| 		break; |  | ||||||
| 	case SA_PATH_IS_PARENTDIR: | 	case SA_PATH_IS_PARENTDIR: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "path is parent of a share"); | 		return (dgettext(TEXT_DOMAIN, "path is parent of a share")); | ||||||
| 		break; |  | ||||||
| 	case SA_NO_SECTION: | 	case SA_NO_SECTION: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "protocol requires a section"); | 		return (dgettext(TEXT_DOMAIN, "protocol requires a section")); | ||||||
| 		break; |  | ||||||
| 	case SA_NO_PROPERTIES: | 	case SA_NO_PROPERTIES: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "properties not found"); | 		return (dgettext(TEXT_DOMAIN, "properties not found")); | ||||||
| 		break; |  | ||||||
| 	case SA_NO_SUCH_SECTION: | 	case SA_NO_SUCH_SECTION: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "section not found"); | 		return (dgettext(TEXT_DOMAIN, "section not found")); | ||||||
| 		break; |  | ||||||
| 	case SA_PASSWORD_ENC: | 	case SA_PASSWORD_ENC: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "passwords must be encrypted"); | 		return (dgettext(TEXT_DOMAIN, "passwords must be encrypted")); | ||||||
| 		break; |  | ||||||
| 	case SA_SHARE_EXISTS: | 	case SA_SHARE_EXISTS: | ||||||
| 		ret = dgettext(TEXT_DOMAIN, "path or file is already shared"); | 		return (dgettext(TEXT_DOMAIN, | ||||||
| 		break; | 		    "path or file is already shared")); | ||||||
| 	default: | 	default: | ||||||
| 		(void) snprintf(errstr, sizeof (errstr), | 		(void) snprintf(errstr, sizeof (errstr), | ||||||
| 		    dgettext(TEXT_DOMAIN, "unknown %d"), err); | 		    dgettext(TEXT_DOMAIN, "unknown %d"), err); | ||||||
| 		ret = errstr; | 		return (errstr); | ||||||
| 	} | 	} | ||||||
| 	return (ret); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| sa_validate_shareopts(const char *options, const char *proto) | sa_validate_shareopts(const char *options, const char *protocol) | ||||||
| { | { | ||||||
| 	sa_fstype_t *fstype; | 	sa_fstype_t *fstype = find_proto(protocol); | ||||||
| 
 | 	if (!fstype) | ||||||
| 	fstype = fstypes; |  | ||||||
| 	while (fstype != NULL) { |  | ||||||
| 		if (strcmp(fstype->name, proto) != 0) { |  | ||||||
| 			fstype = fstype->next; |  | ||||||
| 			continue; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		return (fstype->ops->validate_shareopts(options)); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 		return (SA_INVALID_PROTOCOL); | 		return (SA_INVALID_PROTOCOL); | ||||||
| } | 
 | ||||||
| 
 | 	return (fstype->validate_shareopts(options)); | ||||||
| static sa_share_impl_t |  | ||||||
| alloc_share(const char *zfsname, const char *mountpoint) |  | ||||||
| { |  | ||||||
| 	sa_share_impl_t impl_share; |  | ||||||
| 
 |  | ||||||
| 	impl_share = calloc(1, sizeof (struct sa_share_impl)); |  | ||||||
| 
 |  | ||||||
| 	if (impl_share == NULL) |  | ||||||
| 		return (NULL); |  | ||||||
| 
 |  | ||||||
| 	if (mountpoint != NULL && |  | ||||||
| 	    ((impl_share->sa_mountpoint = strdup(mountpoint)) == NULL)) { |  | ||||||
| 		free(impl_share); |  | ||||||
| 		return (NULL); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (zfsname != NULL && |  | ||||||
| 	    ((impl_share->sa_zfsname = strdup(zfsname)) == NULL)) { |  | ||||||
| 		free(impl_share->sa_mountpoint); |  | ||||||
| 		free(impl_share); |  | ||||||
| 		return (NULL); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	impl_share->sa_fsinfo = calloc(fstypes_count, |  | ||||||
| 	    sizeof (sa_share_fsinfo_t)); |  | ||||||
| 	if (impl_share->sa_fsinfo == NULL) { |  | ||||||
| 		free(impl_share->sa_mountpoint); |  | ||||||
| 		free(impl_share->sa_zfsname); |  | ||||||
| 		free(impl_share); |  | ||||||
| 		return (NULL); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return (impl_share); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| free_share(sa_share_impl_t impl_share) |  | ||||||
| { |  | ||||||
| 	sa_fstype_t *fstype; |  | ||||||
| 
 |  | ||||||
| 	fstype = fstypes; |  | ||||||
| 	while (fstype != NULL) { |  | ||||||
| 		fstype->ops->clear_shareopts(impl_share); |  | ||||||
| 		fstype = fstype->next; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	free(impl_share->sa_mountpoint); |  | ||||||
| 	free(impl_share->sa_zfsname); |  | ||||||
| 	free(impl_share->sa_fsinfo); |  | ||||||
| 	free(impl_share); |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -27,39 +27,26 @@ | |||||||
| #ifndef _LIBSPL_LIBSHARE_IMPL_H | #ifndef _LIBSPL_LIBSHARE_IMPL_H | ||||||
| #define	_LIBSPL_LIBSHARE_IMPL_H | #define	_LIBSPL_LIBSHARE_IMPL_H | ||||||
| 
 | 
 | ||||||
| typedef struct sa_share_fsinfo { | #include <sys/avl.h> | ||||||
| 	char *shareopts; |  | ||||||
| } sa_share_fsinfo_t; |  | ||||||
| 
 | 
 | ||||||
| typedef struct sa_share_impl { | typedef const struct sa_share_impl { | ||||||
| 	char *sa_mountpoint; | 	const char *sa_zfsname; | ||||||
| 	char *sa_zfsname; | 	const char *sa_mountpoint; | ||||||
| 
 | 	const char *sa_shareopts; | ||||||
| 	sa_share_fsinfo_t *sa_fsinfo; /* per-fstype information */ |  | ||||||
| } *sa_share_impl_t; | } *sa_share_impl_t; | ||||||
| 
 | 
 | ||||||
| #define	FSINFO(impl_share, fstype) \ | typedef struct { | ||||||
| 	(&(impl_share->sa_fsinfo[fstype->fsinfo_index])) | 	const char *protocol; | ||||||
| 
 | 
 | ||||||
| typedef struct sa_share_ops { | 	int (*const enable_share)(sa_share_impl_t share); | ||||||
| 	int (*enable_share)(sa_share_impl_t share); | 	int (*const disable_share)(sa_share_impl_t share); | ||||||
| 	int (*disable_share)(sa_share_impl_t share); | 	boolean_t (*const is_shared)(sa_share_impl_t share); | ||||||
| 	boolean_t (*is_shared)(sa_share_impl_t share); | 	int (*const validate_shareopts)(const char *shareopts); | ||||||
| 	int (*validate_shareopts)(const char *shareopts); | 	int (*const commit_shares)(void); | ||||||
| 	int (*update_shareopts)(sa_share_impl_t impl_share, |  | ||||||
| 	    const char *shareopts); |  | ||||||
| 	void (*clear_shareopts)(sa_share_impl_t impl_share); |  | ||||||
| 	int (*commit_shares)(void); |  | ||||||
| } sa_share_ops_t; |  | ||||||
| 
 | 
 | ||||||
| typedef struct sa_fstype { | 	avl_node_t node; | ||||||
| 	struct sa_fstype *next; |  | ||||||
| 
 |  | ||||||
| 	const char *name; |  | ||||||
| 	const sa_share_ops_t *ops; |  | ||||||
| 	int fsinfo_index; |  | ||||||
| } sa_fstype_t; | } sa_fstype_t; | ||||||
| 
 | 
 | ||||||
| sa_fstype_t *register_fstype(const char *name, const sa_share_ops_t *ops); | extern sa_fstype_t libshare_nfs_type, libshare_smb_type; | ||||||
| 
 | 
 | ||||||
| #endif /* _LIBSPL_LIBSHARE_IMPL_H */ | #endif /* _LIBSPL_LIBSHARE_IMPL_H */ | ||||||
|  | |||||||
| @ -28,8 +28,6 @@ | |||||||
| 
 | 
 | ||||||
| #define	FILE_HEADER		"# !!! DO NOT EDIT THIS FILE MANUALLY !!!\n\n" | #define	FILE_HEADER		"# !!! DO NOT EDIT THIS FILE MANUALLY !!!\n\n" | ||||||
| 
 | 
 | ||||||
| void libshare_nfs_init(void); |  | ||||||
| 
 |  | ||||||
| boolean_t nfs_is_shared_impl(const char *exports, sa_share_impl_t impl_share); | 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, | int nfs_toggle_share(const char *lockfile, const char *exports, | ||||||
|     const char *expdir, sa_share_impl_t impl_share, |     const char *expdir, sa_share_impl_t impl_share, | ||||||
|  | |||||||
| @ -52,8 +52,6 @@ __FBSDID("$FreeBSD$"); | |||||||
| #define	ZFS_EXPORTS_FILE	"/etc/zfs/exports" | #define	ZFS_EXPORTS_FILE	"/etc/zfs/exports" | ||||||
| #define	ZFS_EXPORTS_LOCK	ZFS_EXPORTS_FILE".lock" | #define	ZFS_EXPORTS_LOCK	ZFS_EXPORTS_FILE".lock" | ||||||
| 
 | 
 | ||||||
| static sa_fstype_t *nfs_fstype; |  | ||||||
| 
 |  | ||||||
| /*
 | /*
 | ||||||
|  * This function translates options to a format acceptable by exports(5), eg. |  * This function translates options to a format acceptable by exports(5), eg. | ||||||
|  * |  * | ||||||
| @ -107,7 +105,7 @@ translate_opts(const char *shareopts, FILE *out) | |||||||
| static int | static int | ||||||
| nfs_enable_share_impl(sa_share_impl_t impl_share, FILE *tmpfile) | nfs_enable_share_impl(sa_share_impl_t impl_share, FILE *tmpfile) | ||||||
| { | { | ||||||
| 	char *shareopts = FSINFO(impl_share, nfs_fstype)->shareopts; | 	const char *shareopts = impl_share->sa_shareopts; | ||||||
| 	if (strcmp(shareopts, "on") == 0) | 	if (strcmp(shareopts, "on") == 0) | ||||||
| 		shareopts = ""; | 		shareopts = ""; | ||||||
| 
 | 
 | ||||||
| @ -158,19 +156,6 @@ nfs_validate_shareopts(const char *shareopts) | |||||||
| 	return (SA_OK); | 	return (SA_OK); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int |  | ||||||
| nfs_update_shareopts(sa_share_impl_t impl_share, const char *shareopts) |  | ||||||
| { |  | ||||||
| 	FSINFO(impl_share, nfs_fstype)->shareopts = (char *)shareopts; |  | ||||||
| 	return (SA_OK); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void |  | ||||||
| nfs_clear_shareopts(sa_share_impl_t impl_share) |  | ||||||
| { |  | ||||||
| 	FSINFO(impl_share, nfs_fstype)->shareopts = NULL; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /*
 | /*
 | ||||||
|  * Commit the shares by restarting mountd. |  * Commit the shares by restarting mountd. | ||||||
|  */ |  */ | ||||||
| @ -201,22 +186,13 @@ start: | |||||||
| 	return (SA_OK); | 	return (SA_OK); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const sa_share_ops_t nfs_shareops = { | sa_fstype_t libshare_nfs_type = { | ||||||
|  | 	.protocol = "nfs", | ||||||
|  | 
 | ||||||
| 	.enable_share = nfs_enable_share, | 	.enable_share = nfs_enable_share, | ||||||
| 	.disable_share = nfs_disable_share, | 	.disable_share = nfs_disable_share, | ||||||
| 	.is_shared = nfs_is_shared, | 	.is_shared = nfs_is_shared, | ||||||
| 
 | 
 | ||||||
| 	.validate_shareopts = nfs_validate_shareopts, | 	.validate_shareopts = nfs_validate_shareopts, | ||||||
| 	.update_shareopts = nfs_update_shareopts, |  | ||||||
| 	.clear_shareopts = nfs_clear_shareopts, |  | ||||||
| 	.commit_shares = nfs_commit_shares, | 	.commit_shares = nfs_commit_shares, | ||||||
| }; | }; | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * Initializes the NFS functionality of libshare. |  | ||||||
|  */ |  | ||||||
| void |  | ||||||
| libshare_nfs_init(void) |  | ||||||
| { |  | ||||||
| 	nfs_fstype = register_fstype("nfs", &nfs_shareops); |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -27,8 +27,6 @@ | |||||||
| #include <libshare.h> | #include <libshare.h> | ||||||
| #include "libshare_impl.h" | #include "libshare_impl.h" | ||||||
| 
 | 
 | ||||||
| static sa_fstype_t *smb_fstype; |  | ||||||
| 
 |  | ||||||
| /*
 | /*
 | ||||||
|  * Enables SMB sharing for the specified share. |  * Enables SMB sharing for the specified share. | ||||||
|  */ |  */ | ||||||
| @ -71,51 +69,20 @@ smb_is_share_active(sa_share_impl_t impl_share) | |||||||
| 	return (B_FALSE); | 	return (B_FALSE); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 |  | ||||||
|  * Called to update a share's options. A share's options might be out of |  | ||||||
|  * date if the share was loaded from disk and the "sharesmb" dataset |  | ||||||
|  * property has changed in the meantime. This function also takes care |  | ||||||
|  * of re-enabling the share if necessary. |  | ||||||
|  */ |  | ||||||
| static int |  | ||||||
| smb_update_shareopts(sa_share_impl_t impl_share, const char *shareopts) |  | ||||||
| { |  | ||||||
| 	(void) impl_share, (void) shareopts; |  | ||||||
| 	return (SA_OK); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int | static int | ||||||
| smb_update_shares(void) | smb_update_shares(void) | ||||||
| { | { | ||||||
| 	/* Not implemented */ | 	/* Not implemented */ | ||||||
| 	return (0); | 	return (0); | ||||||
| } | } | ||||||
| /*
 |  | ||||||
|  * Clears a share's SMB options. Used by libshare to |  | ||||||
|  * clean up shares that are about to be free()'d. |  | ||||||
|  */ |  | ||||||
| static void |  | ||||||
| smb_clear_shareopts(sa_share_impl_t impl_share) |  | ||||||
| { |  | ||||||
| 	FSINFO(impl_share, smb_fstype)->shareopts = NULL; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| static const sa_share_ops_t smb_shareops = { | sa_fstype_t libshare_smb_type = { | ||||||
|  | 	.protocol = "smb", | ||||||
|  | 
 | ||||||
| 	.enable_share = smb_enable_share, | 	.enable_share = smb_enable_share, | ||||||
| 	.disable_share = smb_disable_share, | 	.disable_share = smb_disable_share, | ||||||
| 	.is_shared = smb_is_share_active, | 	.is_shared = smb_is_share_active, | ||||||
| 
 | 
 | ||||||
| 	.validate_shareopts = smb_validate_shareopts, | 	.validate_shareopts = smb_validate_shareopts, | ||||||
| 	.update_shareopts = smb_update_shareopts, |  | ||||||
| 	.clear_shareopts = smb_clear_shareopts, |  | ||||||
| 	.commit_shares = smb_update_shares, | 	.commit_shares = smb_update_shares, | ||||||
| }; | }; | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * Initializes the SMB functionality of libshare. |  | ||||||
|  */ |  | ||||||
| void |  | ||||||
| libshare_smb_init(void) |  | ||||||
| { |  | ||||||
| 	smb_fstype = register_fstype("smb", &smb_shareops); |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -45,8 +45,6 @@ | |||||||
| #define	ZFS_EXPORTS_FILE	ZFS_EXPORTS_DIR"/zfs.exports" | #define	ZFS_EXPORTS_FILE	ZFS_EXPORTS_DIR"/zfs.exports" | ||||||
| #define	ZFS_EXPORTS_LOCK	ZFS_EXPORTS_FILE".lock" | #define	ZFS_EXPORTS_LOCK	ZFS_EXPORTS_FILE".lock" | ||||||
| 
 | 
 | ||||||
| static sa_fstype_t *nfs_fstype; |  | ||||||
| 
 |  | ||||||
| typedef int (*nfs_shareopt_callback_t)(const char *opt, const char *value, | typedef int (*nfs_shareopt_callback_t)(const char *opt, const char *value, | ||||||
|     void *cookie); |     void *cookie); | ||||||
| 
 | 
 | ||||||
| @ -229,7 +227,6 @@ foreach_nfs_host(sa_share_impl_t impl_share, FILE *tmpfile, | |||||||
|     nfs_host_callback_t callback, void *cookie) |     nfs_host_callback_t callback, void *cookie) | ||||||
| { | { | ||||||
| 	nfs_host_cookie_t udata; | 	nfs_host_cookie_t udata; | ||||||
| 	char *shareopts; |  | ||||||
| 
 | 
 | ||||||
| 	udata.callback = callback; | 	udata.callback = callback; | ||||||
| 	udata.sharepath = impl_share->sa_mountpoint; | 	udata.sharepath = impl_share->sa_mountpoint; | ||||||
| @ -237,10 +234,8 @@ foreach_nfs_host(sa_share_impl_t impl_share, FILE *tmpfile, | |||||||
| 	udata.tmpfile = tmpfile; | 	udata.tmpfile = tmpfile; | ||||||
| 	udata.security = "sys"; | 	udata.security = "sys"; | ||||||
| 
 | 
 | ||||||
| 	shareopts = FSINFO(impl_share, nfs_fstype)->shareopts; | 	return (foreach_nfs_shareopt(impl_share->sa_shareopts, | ||||||
| 
 | 	    foreach_nfs_host_cb, &udata)); | ||||||
| 	return (foreach_nfs_shareopt(shareopts, foreach_nfs_host_cb, |  | ||||||
| 	    &udata)); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
| @ -411,11 +406,10 @@ nfs_add_entry(FILE *tmpfile, const char *sharepath, | |||||||
| static int | static int | ||||||
| nfs_enable_share_impl(sa_share_impl_t impl_share, FILE *tmpfile) | nfs_enable_share_impl(sa_share_impl_t impl_share, FILE *tmpfile) | ||||||
| { | { | ||||||
| 	char *shareopts, *linux_opts; | 	char *linux_opts; | ||||||
| 	int error; | 	int error; | ||||||
| 
 | 
 | ||||||
| 	shareopts = FSINFO(impl_share, nfs_fstype)->shareopts; | 	error = get_linux_shareopts(impl_share->sa_shareopts, &linux_opts); | ||||||
| 	error = get_linux_shareopts(shareopts, &linux_opts); |  | ||||||
| 	if (error != SA_OK) | 	if (error != SA_OK) | ||||||
| 		return (error); | 		return (error); | ||||||
| 
 | 
 | ||||||
| @ -475,23 +469,6 @@ nfs_validate_shareopts(const char *shareopts) | |||||||
| 	return (SA_OK); | 	return (SA_OK); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int |  | ||||||
| nfs_update_shareopts(sa_share_impl_t impl_share, const char *shareopts) |  | ||||||
| { |  | ||||||
| 	FSINFO(impl_share, nfs_fstype)->shareopts = (char *)shareopts; |  | ||||||
| 	return (SA_OK); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * Clears a share's NFS options. Used by libshare to |  | ||||||
|  * clean up shares that are about to be free()'d. |  | ||||||
|  */ |  | ||||||
| static void |  | ||||||
| nfs_clear_shareopts(sa_share_impl_t impl_share) |  | ||||||
| { |  | ||||||
| 	FSINFO(impl_share, nfs_fstype)->shareopts = NULL; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int | static int | ||||||
| nfs_commit_shares(void) | nfs_commit_shares(void) | ||||||
| { | { | ||||||
| @ -504,22 +481,13 @@ nfs_commit_shares(void) | |||||||
| 	return (libzfs_run_process(argv[0], argv, 0)); | 	return (libzfs_run_process(argv[0], argv, 0)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const sa_share_ops_t nfs_shareops = { | sa_fstype_t libshare_nfs_type = { | ||||||
|  | 	.protocol = "nfs", | ||||||
|  | 
 | ||||||
| 	.enable_share = nfs_enable_share, | 	.enable_share = nfs_enable_share, | ||||||
| 	.disable_share = nfs_disable_share, | 	.disable_share = nfs_disable_share, | ||||||
| 	.is_shared = nfs_is_shared, | 	.is_shared = nfs_is_shared, | ||||||
| 
 | 
 | ||||||
| 	.validate_shareopts = nfs_validate_shareopts, | 	.validate_shareopts = nfs_validate_shareopts, | ||||||
| 	.update_shareopts = nfs_update_shareopts, |  | ||||||
| 	.clear_shareopts = nfs_clear_shareopts, |  | ||||||
| 	.commit_shares = nfs_commit_shares, | 	.commit_shares = nfs_commit_shares, | ||||||
| }; | }; | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * Initializes the NFS functionality of libshare. |  | ||||||
|  */ |  | ||||||
| void |  | ||||||
| libshare_nfs_init(void) |  | ||||||
| { |  | ||||||
| 	nfs_fstype = register_fstype("nfs", &nfs_shareops); |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -63,8 +63,6 @@ | |||||||
| 
 | 
 | ||||||
| static boolean_t smb_available(void); | static boolean_t smb_available(void); | ||||||
| 
 | 
 | ||||||
| static sa_fstype_t *smb_fstype; |  | ||||||
| 
 |  | ||||||
| static smb_share_t *smb_shares; | static smb_share_t *smb_shares; | ||||||
| static int smb_disable_share(sa_share_impl_t impl_share); | static int smb_disable_share(sa_share_impl_t impl_share); | ||||||
| static boolean_t smb_is_share_active(sa_share_impl_t impl_share); | static boolean_t smb_is_share_active(sa_share_impl_t impl_share); | ||||||
| @ -265,19 +263,16 @@ smb_enable_share_one(const char *sharename, const char *sharepath) | |||||||
| static int | static int | ||||||
| smb_enable_share(sa_share_impl_t impl_share) | smb_enable_share(sa_share_impl_t impl_share) | ||||||
| { | { | ||||||
| 	char *shareopts; |  | ||||||
| 
 |  | ||||||
| 	if (!smb_available()) | 	if (!smb_available()) | ||||||
| 		return (SA_SYSTEM_ERR); | 		return (SA_SYSTEM_ERR); | ||||||
| 
 | 
 | ||||||
| 	if (smb_is_share_active(impl_share)) | 	if (smb_is_share_active(impl_share)) | ||||||
| 		smb_disable_share(impl_share); | 		smb_disable_share(impl_share); | ||||||
| 
 | 
 | ||||||
| 	shareopts = FSINFO(impl_share, smb_fstype)->shareopts; | 	if (impl_share->sa_shareopts == NULL) /* on/off */ | ||||||
| 	if (shareopts == NULL) /* on/off */ |  | ||||||
| 		return (SA_SYSTEM_ERR); | 		return (SA_SYSTEM_ERR); | ||||||
| 
 | 
 | ||||||
| 	if (strcmp(shareopts, "off") == 0) | 	if (strcmp(impl_share->sa_shareopts, "off") == 0) | ||||||
| 		return (SA_OK); | 		return (SA_OK); | ||||||
| 
 | 
 | ||||||
| 	/* Magic: Enable (i.e., 'create new') share */ | 	/* Magic: Enable (i.e., 'create new') share */ | ||||||
| @ -361,22 +356,6 @@ smb_is_share_active(sa_share_impl_t impl_share) | |||||||
| 	return (B_FALSE); | 	return (B_FALSE); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 |  | ||||||
|  * Called to update a share's options. A share's options might be out of |  | ||||||
|  * date if the share was loaded from disk and the "sharesmb" dataset |  | ||||||
|  * property has changed in the meantime. This function also takes care |  | ||||||
|  * of re-enabling the share if necessary. |  | ||||||
|  */ |  | ||||||
| static int |  | ||||||
| smb_update_shareopts(sa_share_impl_t impl_share, const char *shareopts) |  | ||||||
| { |  | ||||||
| 	if (!impl_share) |  | ||||||
| 		return (SA_SYSTEM_ERR); |  | ||||||
| 
 |  | ||||||
| 	FSINFO(impl_share, smb_fstype)->shareopts = (char *)shareopts; |  | ||||||
| 	return (SA_OK); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int | static int | ||||||
| smb_update_shares(void) | smb_update_shares(void) | ||||||
| { | { | ||||||
| @ -384,24 +363,14 @@ smb_update_shares(void) | |||||||
| 	return (0); | 	return (0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | sa_fstype_t libshare_smb_type = { | ||||||
|  * Clears a share's SMB options. Used by libshare to | 	.protocol = "smb", | ||||||
|  * clean up shares that are about to be free()'d. |  | ||||||
|  */ |  | ||||||
| static void |  | ||||||
| smb_clear_shareopts(sa_share_impl_t impl_share) |  | ||||||
| { |  | ||||||
| 	FSINFO(impl_share, smb_fstype)->shareopts = NULL; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| static const sa_share_ops_t smb_shareops = { |  | ||||||
| 	.enable_share = smb_enable_share, | 	.enable_share = smb_enable_share, | ||||||
| 	.disable_share = smb_disable_share, | 	.disable_share = smb_disable_share, | ||||||
| 	.is_shared = smb_is_share_active, | 	.is_shared = smb_is_share_active, | ||||||
| 
 | 
 | ||||||
| 	.validate_shareopts = smb_validate_shareopts, | 	.validate_shareopts = smb_validate_shareopts, | ||||||
| 	.update_shareopts = smb_update_shareopts, |  | ||||||
| 	.clear_shareopts = smb_clear_shareopts, |  | ||||||
| 	.commit_shares = smb_update_shares, | 	.commit_shares = smb_update_shares, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -422,12 +391,3 @@ smb_available(void) | |||||||
| 
 | 
 | ||||||
| 	return (B_TRUE); | 	return (B_TRUE); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * Initializes the SMB functionality of libshare. |  | ||||||
|  */ |  | ||||||
| void |  | ||||||
| libshare_smb_init(void) |  | ||||||
| { |  | ||||||
| 	smb_fstype = register_fstype("smb", &smb_shareops); |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -43,5 +43,3 @@ typedef struct smb_share_s { | |||||||
| 
 | 
 | ||||||
| 	struct smb_share_s *next; | 	struct smb_share_s *next; | ||||||
| } smb_share_t; | } smb_share_t; | ||||||
| 
 |  | ||||||
| void libshare_smb_init(void); |  | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 наб
						наб