aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/zfs/zfs_main.c28
-rw-r--r--config/user-commands.m41
-rw-r--r--include/libzfs.h1
-rw-r--r--lib/libshare/smb.c8
-rw-r--r--lib/libzfs/libzfs_mount.c14
-rw-r--r--man/man8/zfs.812
-rw-r--r--tests/runfiles/linux.run19
-rw-r--r--tests/zfs-tests/include/commands.cfg.in1
-rw-r--r--tests/zfs-tests/include/libtest.shlib142
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_005_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_007_neg.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_009_neg.ksh2
-rw-r--r--tests/zfs-tests/tests/functional/cli_root/zfs_unshare/Makefile.am3
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_001_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_002_pos.ksh6
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_003_pos.ksh2
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_006_pos.ksh88
17 files changed, 287 insertions, 46 deletions
diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c
index 8b6d9464c..5cfe588af 100644
--- a/cmd/zfs/zfs_main.c
+++ b/cmd/zfs/zfs_main.c
@@ -270,7 +270,7 @@ get_usage(zfs_help_t idx)
return (gettext("\tset <property=value> ... "
"<filesystem|volume|snapshot> ...\n"));
case HELP_SHARE:
- return (gettext("\tshare <-a | filesystem>\n"));
+ return (gettext("\tshare <-a [nfs|smb] | filesystem>\n"));
case HELP_SNAPSHOT:
return (gettext("\tsnapshot|snap [-r] [-o property=value] ... "
"<filesystem|volume>@<snap> ...\n"));
@@ -279,7 +279,7 @@ get_usage(zfs_help_t idx)
"<-a | filesystem|mountpoint>\n"));
case HELP_UNSHARE:
return (gettext("\tunshare "
- "<-a | filesystem|mountpoint>\n"));
+ "<-a [nfs|smb] | filesystem|mountpoint>\n"));
case HELP_ALLOW:
return (gettext("\tallow <filesystem|volume>\n"
"\tallow [-ldug] "
@@ -6436,7 +6436,7 @@ unshare_unmount(int op, int argc, char **argv)
char sharesmb[ZFS_MAXPROPLEN];
/* check options */
- while ((c = getopt(argc, argv, op == OP_SHARE ? "a" : "af")) != -1) {
+ while ((c = getopt(argc, argv, op == OP_SHARE ? ":a" : "af")) != -1) {
switch (c) {
case 'a':
do_all = 1;
@@ -6444,6 +6444,11 @@ unshare_unmount(int op, int argc, char **argv)
case 'f':
flags = MS_FORCE;
break;
+ case ':':
+ (void) fprintf(stderr, gettext("missing argument for "
+ "'%c' option\n"), optopt);
+ usage(B_FALSE);
+ break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
@@ -6475,6 +6480,19 @@ unshare_unmount(int op, int argc, char **argv)
unshare_unmount_node_t *node;
uu_avl_index_t idx;
uu_avl_walk_t *walk;
+ char *protocol = NULL;
+
+ if (op == OP_SHARE && argc > 0) {
+ if (strcmp(argv[0], "nfs") != 0 &&
+ strcmp(argv[0], "smb") != 0) {
+ (void) fprintf(stderr, gettext("share type "
+ "must be 'nfs' or 'smb'\n"));
+ usage(B_FALSE);
+ }
+ protocol = argv[0];
+ argc--;
+ argv++;
+ }
if (argc != 0) {
(void) fprintf(stderr, gettext("too many arguments\n"));
@@ -6567,8 +6585,8 @@ unshare_unmount(int op, int argc, char **argv)
switch (op) {
case OP_SHARE:
- if (zfs_unshareall_bypath(node->un_zhp,
- node->un_mountp) != 0)
+ if (zfs_unshareall_bytype(node->un_zhp,
+ node->un_mountp, protocol) != 0)
ret = 1;
break;
diff --git a/config/user-commands.m4 b/config/user-commands.m4
index b40606c3c..9f4a7ef22 100644
--- a/config/user-commands.m4
+++ b/config/user-commands.m4
@@ -116,6 +116,7 @@ AC_DEFUN([ZFS_AC_CONFIG_USER_COMMANDS_LINUX], [
AC_PATH_TOOL(READLINK, readlink, "")
AC_PATH_TOOL(SETFACL, setfacl, "")
AC_PATH_TOOL(SHARE, exportfs, "")
+ AC_PATH_TOOL(NET, net, "")
AC_PATH_TOOL(SWAP, swapon, "")
AC_PATH_TOOL(SWAPADD, swapon, "")
AC_PATH_TOOL(UDEVADM, udevadm, "")
diff --git a/include/libzfs.h b/include/libzfs.h
index 5744ce87a..67f4bf4b4 100644
--- a/include/libzfs.h
+++ b/include/libzfs.h
@@ -763,6 +763,7 @@ extern int zfs_unshare_smb(zfs_handle_t *, const char *);
extern int zfs_unshareall_nfs(zfs_handle_t *);
extern int zfs_unshareall_smb(zfs_handle_t *);
extern int zfs_unshareall_bypath(zfs_handle_t *, const char *);
+extern int zfs_unshareall_bytype(zfs_handle_t *, const char *, const char *);
extern int zfs_unshareall(zfs_handle_t *);
extern int zfs_deleg_share_nfs(libzfs_handle_t *, char *, char *, char *,
void *, void *, int, zfs_share_op_t);
diff --git a/lib/libshare/smb.c b/lib/libshare/smb.c
index f8b7118a3..343586508 100644
--- a/lib/libshare/smb.c
+++ b/lib/libshare/smb.c
@@ -354,17 +354,19 @@ smb_validate_shareopts(const char *shareopts)
static boolean_t
smb_is_share_active(sa_share_impl_t impl_share)
{
+ smb_share_t *iter = smb_shares;
+
if (!smb_available())
return (B_FALSE);
/* Retrieve the list of (possible) active shares */
smb_retrieve_shares();
- while (smb_shares != NULL) {
- if (strcmp(impl_share->sharepath, smb_shares->path) == 0)
+ while (iter != NULL) {
+ if (strcmp(impl_share->sharepath, iter->path) == 0)
return (B_TRUE);
- smb_shares = smb_shares->next;
+ iter = iter->next;
}
return (B_FALSE);
diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c
index 44781679d..ad8a3d20b 100644
--- a/lib/libzfs/libzfs_mount.c
+++ b/lib/libzfs/libzfs_mount.c
@@ -988,6 +988,20 @@ zfs_unshareall_bypath(zfs_handle_t *zhp, const char *mountpoint)
return (zfs_unshare_proto(zhp, mountpoint, share_all_proto));
}
+int
+zfs_unshareall_bytype(zfs_handle_t *zhp, const char *mountpoint,
+ const char *proto)
+{
+ if (proto == NULL)
+ return (zfs_unshare_proto(zhp, mountpoint, share_all_proto));
+ if (strcmp(proto, "nfs") == 0)
+ return (zfs_unshare_proto(zhp, mountpoint, nfs_only));
+ else if (strcmp(proto, "smb") == 0)
+ return (zfs_unshare_proto(zhp, mountpoint, smb_only));
+ else
+ return (1);
+}
+
/*
* Remove the mountpoint associated with the current dataset, if necessary.
* We only remove the underlying directory if:
diff --git a/man/man8/zfs.8 b/man/man8/zfs.8
index d8c150629..364daad52 100644
--- a/man/man8/zfs.8
+++ b/man/man8/zfs.8
@@ -160,12 +160,12 @@ zfs \- configures ZFS file systems
.LP
.nf
-\fBzfs\fR \fBshare\fR \fB-a\fR | \fIfilesystem\fR
+\fBzfs\fR \fBshare\fR [\fBnfs\fR|\fBsmb\fR] \fB-a\fR | \fIfilesystem\fR
.fi
.LP
.nf
-\fBzfs\fR \fBunshare\fR \fB-a\fR \fIfilesystem\fR|\fImountpoint\fR
+\fBzfs\fR \fBunshare\fR [\fBnfs\fR|\fBsmb\fR] \fB-a\fR | \fIfilesystem\fR|\fImountpoint\fR
.fi
.LP
@@ -2646,7 +2646,7 @@ Unmount the specified filesystem. The command can also be given a path to a \fBZ
.sp
.ne 2
.na
-\fB\fBzfs share\fR \fB-a\fR | \fIfilesystem\fR\fR
+\fB\fBzfs share\fR [\fBnfs\fR|\fBsmb\fR] \fB-a\fR | \fIfilesystem\fR\fR
.ad
.sp .6
.RS 4n
@@ -2658,7 +2658,7 @@ Shares available \fBZFS\fR file systems.
.ad
.sp .6
.RS 4n
-Share all available \fBZFS\fR file systems. Invoked automatically as part of the boot process.
+Share all available \fBZFS\fR file systems. Invoked automatically as part of the boot process. Additionally if one of \fBnfs\fR|\fBsmb\fR protocols is specified only share file systems whose \fBsharenfs\fR|\fBsharesmb\fR is set.
.RE
.sp
@@ -2676,11 +2676,11 @@ Share the specified filesystem according to the \fBsharenfs\fR and \fBsharesmb\f
.sp
.ne 2
.na
-\fB\fBzfs unshare\fR \fB-a\fR | \fIfilesystem\fR|\fImountpoint\fR\fR
+\fB\fBzfs unshare\fR [\fBnfs\fR|\fBsmb\fR] \fB-a\fR | \fIfilesystem\fR|\fImountpoint\fR\fR
.ad
.sp .6
.RS 4n
-Unshares currently shared \fBZFS\fR file systems. This is invoked automatically as part of the shutdown process.
+Unshares currently shared \fBZFS\fR file systems. This is invoked automatically as part of the shutdown process. Additionally if one of \fBnfs\fR|\fBsmb\fR is specified unshare only file systems currently shared by that protocol.
.sp
.ne 2
.na
diff --git a/tests/runfiles/linux.run b/tests/runfiles/linux.run
index 138221c50..d3c090b89 100644
--- a/tests/runfiles/linux.run
+++ b/tests/runfiles/linux.run
@@ -181,11 +181,12 @@ tests = ['cache_001_pos', 'cache_002_neg', 'canmount_001_pos',
'zfs_set_002_neg', 'zfs_set_003_neg', 'property_alias_001_pos']
# DISABLED: Tests need to be updated for Linux share behavior
-#[tests/functional/cli_root/zfs_share]
-#tests = ['zfs_share_001_pos', 'zfs_share_002_pos', 'zfs_share_003_pos',
-# 'zfs_share_004_pos', 'zfs_share_005_pos', 'zfs_share_006_pos',
-# 'zfs_share_007_neg', 'zfs_share_008_neg', 'zfs_share_009_neg',
-# 'zfs_share_010_neg', 'zfs_share_011_pos']
+# zfs_share_005_pos - needs investigation, probably unsupported NFS share format
+[tests/functional/cli_root/zfs_share]
+tests = ['zfs_share_001_pos', 'zfs_share_002_pos', 'zfs_share_003_pos',
+ 'zfs_share_004_pos', 'zfs_share_006_pos',
+ 'zfs_share_007_neg', 'zfs_share_008_neg', 'zfs_share_009_neg',
+ 'zfs_share_010_neg', 'zfs_share_011_pos']
[tests/functional/cli_root/zfs_snapshot]
tests = ['zfs_snapshot_001_neg', 'zfs_snapshot_002_neg',
@@ -203,9 +204,11 @@ tests = ['zfs_unmount_001_pos', 'zfs_unmount_002_pos', 'zfs_unmount_003_pos',
'zfs_unmount_007_neg', 'zfs_unmount_008_neg']
# DISABLED: Tests need to be updated for Linux unshare behavior
-#[tests/functional/cli_root/zfs_unshare]
-#tests = ['zfs_unshare_001_pos', 'zfs_unshare_002_pos', 'zfs_unshare_003_pos',
-# 'zfs_unshare_004_neg', 'zfs_unshare_005_neg']
+# zfs_unshare_002_pos - zfs set sharenfs=off won't unshare if it was already off
+# zfs_unshare_006_pos - some distros come with Samba "user shares" disabled
+[tests/functional/cli_root/zfs_unshare]
+tests = ['zfs_unshare_001_pos', 'zfs_unshare_003_pos',
+ 'zfs_unshare_004_neg', 'zfs_unshare_005_neg']
[tests/functional/cli_root/zfs_upgrade]
tests = ['zfs_upgrade_001_pos', 'zfs_upgrade_002_pos', 'zfs_upgrade_003_pos',
diff --git a/tests/zfs-tests/include/commands.cfg.in b/tests/zfs-tests/include/commands.cfg.in
index c8733e970..3bef9a5b7 100644
--- a/tests/zfs-tests/include/commands.cfg.in
+++ b/tests/zfs-tests/include/commands.cfg.in
@@ -67,6 +67,7 @@ export MOUNT="@MOUNT@"
export MPSTAT="@MPSTAT@"
export MV="@MV@"
export NAWK="@AWK@"
+export NET="@NET@"
export NEWFS="@NEWFS@"
export NPROC="@NPROC@"
export PAGESIZE="@PAGESIZE@"
diff --git a/tests/zfs-tests/include/libtest.shlib b/tests/zfs-tests/include/libtest.shlib
index 62f371c58..c5fd8b78a 100644
--- a/tests/zfs-tests/include/libtest.shlib
+++ b/tests/zfs-tests/include/libtest.shlib
@@ -1052,7 +1052,7 @@ function datasetnonexists
}
#
-# Given a mountpoint, or a dataset name, determine if it is shared.
+# Given a mountpoint, or a dataset name, determine if it is shared via NFS.
#
# Returns 0 if shared, 1 otherwise.
#
@@ -1061,11 +1061,6 @@ function is_shared
typeset fs=$1
typeset mtpt
- if is_linux; then
- log_unsupported "Currently unsupported by the test framework"
- return 1
- fi
-
if [[ $fs != "/"* ]] ; then
if datasetnonexists "$fs" ; then
return 1
@@ -1080,6 +1075,15 @@ function is_shared
fi
fi
+ if is_linux; then
+ for mtpt in `$SHARE | $AWK '{print $1}'` ; do
+ if [[ $mtpt == $fs ]] ; then
+ return 0
+ fi
+ done
+ return 1
+ fi
+
for mtpt in `$SHARE | $AWK '{print $2}'` ; do
if [[ $mtpt == $fs ]] ; then
return 0
@@ -1095,18 +1099,42 @@ function is_shared
}
#
-# Given a mountpoint, determine if it is not shared.
+# Given a dataset name determine if it is shared via SMB.
#
-# Returns 0 if not shared, 1 otherwise.
+# Returns 0 if shared, 1 otherwise.
#
-function not_shared
+function is_shared_smb
{
typeset fs=$1
+ typeset mtpt
+
+ if datasetnonexists "$fs" ; then
+ return 1
+ else
+ fs=$(echo $fs | sed 's@/@_@g')
+ fi
if is_linux; then
+ for mtpt in `$NET usershare list | $AWK '{print $1}'` ; do
+ if [[ $mtpt == $fs ]] ; then
+ return 0
+ fi
+ done
+ return 1
+ else
log_unsupported "Currently unsupported by the test framework"
return 1
fi
+}
+
+#
+# Given a mountpoint, determine if it is not shared via NFS.
+#
+# Returns 0 if not shared, 1 otherwise.
+#
+function not_shared
+{
+ typeset fs=$1
is_shared $fs
if (($? == 0)); then
@@ -1117,18 +1145,30 @@ function not_shared
}
#
-# Helper function to unshare a mountpoint.
+# Given a dataset determine if it is not shared via SMB.
#
-function unshare_fs #fs
+# Returns 0 if not shared, 1 otherwise.
+#
+function not_shared_smb
{
typeset fs=$1
- if is_linux; then
- log_unsupported "Currently unsupported by the test framework"
+ is_shared_smb $fs
+ if (($? == 0)); then
return 1
fi
- is_shared $fs
+ return 0
+}
+
+#
+# Helper function to unshare a mountpoint.
+#
+function unshare_fs #fs
+{
+ typeset fs=$1
+
+ is_shared $fs || is_shared_smb $fs
if (($? == 0)); then
log_must $ZFS unshare $fs
fi
@@ -1137,6 +1177,78 @@ function unshare_fs #fs
}
#
+# Helper function to share a NFS mountpoint.
+#
+function share_nfs #fs
+{
+ typeset fs=$1
+
+ if is_linux; then
+ is_shared $fs
+ if (($? != 0)); then
+ log_must $SHARE "*:$fs"
+ fi
+ else
+ is_shared $fs
+ if (($? != 0)); then
+ log_must $SHARE -F nfs $fs
+ fi
+ fi
+
+ return 0
+}
+
+#
+# Helper function to unshare a NFS mountpoint.
+#
+function unshare_nfs #fs
+{
+ typeset fs=$1
+
+ if is_linux; then
+ is_shared $fs
+ if (($? == 0)); then
+ log_must $UNSHARE -u "*:$fs"
+ fi
+ else
+ is_shared $fs
+ if (($? == 0)); then
+ log_must $UNSHARE -F nfs $fs
+ fi
+ fi
+
+ return 0
+}
+
+#
+# Helper function to show NFS shares.
+#
+function showshares_nfs
+{
+ if is_linux; then
+ $SHARE -v
+ else
+ $SHARE -F nfs
+ fi
+
+ return 0
+}
+
+#
+# Helper function to show SMB shares.
+#
+function showshares_smb
+{
+ if is_linux; then
+ $NET usershare list
+ else
+ $SHARE -F smb
+ fi
+
+ return 0
+}
+
+#
# Check NFS server status and trigger it online.
#
function setup_nfs_server
@@ -1149,7 +1261,7 @@ function setup_nfs_server
fi
if is_linux; then
- log_unsupported "Currently unsupported by the test framework"
+ log_note "NFS server must started prior to running test framework."
return
fi
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_005_pos.ksh
index eed0eaad4..9fec7e3ab 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_005_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_005_pos.ksh
@@ -68,7 +68,7 @@ do
log_fail "get sharenfs failed. ($option != ${shareopts[i]})"
fi
- $SHARE | $GREP $option > /dev/null 2>&1
+ showshares_nfs | $GREP $option > /dev/null 2>&1
if (( $? != 0 )); then
log_fail "The '$option' option was not found in share output."
fi
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_007_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_007_neg.ksh
index ace4e439b..de13bc559 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_007_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_007_neg.ksh
@@ -59,7 +59,7 @@ do
log_note "Setting sharenfs=${badopts[i]} $i "
log_mustnot $ZFS set sharenfs="${badopts[i]}" $TESTPOOL/$TESTFS
- $SHARE | $GREP $option > /dev/null 2>&1
+ showshares_nfs | $GREP $option > /dev/null 2>&1
if (( $? == 0 )); then
log_fail "An invalid setting '$option' was propagated."
fi
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_009_neg.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_009_neg.ksh
index 6b4f3037d..0eb862521 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_009_neg.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_share/zfs_share_009_neg.ksh
@@ -59,7 +59,7 @@ if [[ $sharenfs_val == off ]]; then
log_must $ZFS set sharenfs=on $fs
fi
-$SHARE | $GREP $mpt >/dev/null 2>&1
+showshares_nfs | $GREP $mpt >/dev/null 2>&1
if (( $? != 0 )); then
log_must $ZFS share $fs
fi
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/Makefile.am b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/Makefile.am
index c45469744..e1d2e6b8a 100644
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/Makefile.am
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/Makefile.am
@@ -6,4 +6,5 @@ dist_pkgdata_SCRIPTS = \
zfs_unshare_002_pos.ksh \
zfs_unshare_003_pos.ksh \
zfs_unshare_004_neg.ksh \
- zfs_unshare_005_neg.ksh
+ zfs_unshare_005_neg.ksh \
+ zfs_unshare_006_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_001_pos.ksh
index 033865b51..11044e5d3 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_001_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_001_pos.ksh
@@ -88,7 +88,7 @@ function test_unshare # <mntp> <filesystem>
if [[ $prop_value == "off" ]]; then
not_shared $mntp ||
- log_must $UNSHARE -F nfs $mntp
+ log_must eval "unshare_nfs $mntp"
log_must $ZFS set sharenfs=on $filesystem
is_shared $mntp || \
log_fail "'$ZFS set sharenfs=on' fails to make" \
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_002_pos.ksh
index ea1d079df..abe918434 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_002_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_002_pos.ksh
@@ -45,7 +45,7 @@ function cleanup
typeset -i i=0
while (( i < ${#mntp_fs[*]} )); do
is_shared ${mntp_fs[i]} && \
- log_must $UNSHARE -F nfs ${mntp_fs[i]}
+ log_must eval "unshare_nfs ${mntp_fs[i]}"
((i = i + 2))
done
@@ -86,7 +86,7 @@ function test_legacy_unshare # <mntp> <filesystem>
log_fail "'zfs set sharenfs=off' fails to make ZFS " \
"filesystem $filesystem unshared."
- log_must $SHARE -F nfs $mntp
+ log_must eval "share_nfs $mntp"
is_shared $mntp || \
log_fail "'share' command fails to share ZFS file system."
#
@@ -150,7 +150,7 @@ done
#
i=0
while (( i < ${#mntp_fs[*]} )); do
- $SHARE -F nfs ${mntp_fs[i]}
+ share_nfs ${mntp_fs[i]}
is_shared ${mntp_fs[i]} || \
log_fail "'$SHARE' shares ZFS filesystem failed."
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_003_pos.ksh
index 74cc41dbc..b5c8b040c 100755
--- a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_003_pos.ksh
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_003_pos.ksh
@@ -68,7 +68,7 @@ function test_snap_unshare # <mntp> <filesystem>
prop_value=$(get_prop "sharenfs" $filesystem)
if [[ $prop_value == "off" ]]; then
- is_shared $mntp || $UNSHARE -F nfs $mntp
+ is_shared $mntp || unshare_nfs $mntp
log_must $ZFS set sharenfs=on $filesystem
fi
diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_006_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_006_pos.ksh
new file mode 100755
index 000000000..7c3f6cd3a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_root/zfs_unshare/zfs_unshare_006_pos.ksh
@@ -0,0 +1,88 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2016, loli10K. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that 'zfs unshare [nfs|smb] -a' unshares only filesystems shared by the
+# specified protocol.
+#
+# STRATEGY:
+# 1. Share filesystems with different protocols.
+# 2. Invoke 'zfs unshare nfs -a' to unshare filesystems.
+# 3. Verify that only nfs filesystems are unshared.
+# 4. Share all filesystems again.
+# 5. Invoke 'zfs unshare smb -a' and verify only smb filesystems are unshared.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must $ZFS unshare -a
+ log_must $ZFS destroy -f $TESTPOOL/$TESTFS/shared1
+ log_must $ZFS destroy -f $TESTPOOL/$TESTFS/shared2
+ log_must $ZFS destroy -f $TESTPOOL/$TESTFS/shared3
+}
+
+log_assert "Verify '$ZFS unshare [nfs|smb] -a' only works on the specified "\
+ "protocol."
+log_onexit cleanup
+
+# 1. Share filesystems with different protocols.
+log_must $ZFS create $TESTPOOL/$TESTFS/shared1
+log_must $ZFS create $TESTPOOL/$TESTFS/shared2
+log_must $ZFS create $TESTPOOL/$TESTFS/shared3
+log_must $ZFS set mountpoint=$TESTDIR/1 $TESTPOOL/$TESTFS/shared1
+log_must $ZFS set mountpoint=$TESTDIR/2 $TESTPOOL/$TESTFS/shared2
+log_must $ZFS set mountpoint=$TESTDIR/3 $TESTPOOL/$TESTFS/shared3
+log_must $ZFS set sharenfs=on $TESTPOOL/$TESTFS/shared1
+log_must $ZFS set sharenfs=on $TESTPOOL/$TESTFS/shared2
+log_must $ZFS set sharesmb=on $TESTPOOL/$TESTFS/shared2
+log_must $ZFS set sharesmb=on $TESTPOOL/$TESTFS/shared3
+log_must $ZFS share -a
+
+# 2. Invoke 'zfs unshare nfs -a' to unshare filesystems.
+log_must $ZFS unshare nfs -a
+
+# 3. Verify that only nfs filesystems are unshared.
+log_must eval "not_shared $TESTPOOL/$TESTFS/shared1"
+log_must eval "not_shared $TESTPOOL/$TESTFS/shared2"
+log_must eval "is_shared_smb $TESTPOOL/$TESTFS/shared2"
+log_must eval "is_shared_smb $TESTPOOL/$TESTFS/shared3"
+
+# 4. Share all filesystems again.
+log_must $ZFS share -a
+
+# 5. Invoke 'zfs unshare smb -a' and verify only smb filesystems are unshared.
+log_must $ZFS unshare smb -a
+log_must eval "is_shared $TESTPOOL/$TESTFS/shared1"
+log_must eval "is_shared $TESTPOOL/$TESTFS/shared2"
+log_must eval "not_shared_smb $TESTPOOL/$TESTFS/shared2"
+log_must eval "not_shared_smb $TESTPOOL/$TESTFS/shared3"
+
+log_pass "'$ZFS unshare [nfs|smb] -a' only works on the specified protocol."