svn commit: r263410 - in stable: 8/cddl/contrib/opensolaris/cmd/zfs 8/cddl/contrib/opensolaris/cmd/zpool 8/cddl/contrib/opensolaris/lib/libzfs/common 8/cddl/contrib/opensolaris/lib/libzfs_core/comm...

Xin LI delphij at FreeBSD.org
Thu Mar 20 00:38:49 UTC 2014


Author: delphij
Date: Thu Mar 20 00:38:46 2014
New Revision: 263410
URL: http://svnweb.freebsd.org/changeset/base/263410

Log:
  MFC r260183:
  
  MFV r260154 + 260182:
  
  4369 implement zfs bookmarks
  4368 zfs send filesystems from readonly pools
  
  Illumos/illumos-gate at 78f171005391b928aaf1642b3206c534ed644332

Added:
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_bookmark.c
     - copied unchanged from r260183, head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_bookmark.c
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_bookmark.h
     - copied unchanged from r260183, head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_bookmark.h
Modified:
  stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs.8
  stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.c
  stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
  stable/8/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7
  stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
  stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
  stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
  stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c
  stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
  stable/8/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c
  stable/8/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h
  stable/8/cddl/contrib/opensolaris/lib/pyzfs/common/allow.py
  stable/8/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c
  stable/8/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h
  stable/8/sys/cddl/contrib/opensolaris/common/zfs/zfs_deleg.c
  stable/8/sys/cddl/contrib/opensolaris/common/zfs/zfs_deleg.h
  stable/8/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
  stable/8/sys/cddl/contrib/opensolaris/common/zfs/zfs_namecheck.c
  stable/8/sys/cddl/contrib/opensolaris/common/zfs/zfs_namecheck.h
  stable/8/sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c
  stable/8/sys/cddl/contrib/opensolaris/uts/common/Makefile.files
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_diff.c
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_deleg.h
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
  stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
  stable/8/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h
Directory Properties:
  stable/8/cddl/contrib/opensolaris/   (props changed)
  stable/8/cddl/contrib/opensolaris/cmd/zfs/   (props changed)
  stable/8/cddl/contrib/opensolaris/cmd/zpool/   (props changed)
  stable/8/cddl/contrib/opensolaris/lib/libzfs/   (props changed)
  stable/8/sys/   (props changed)
  stable/8/sys/cddl/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)

Changes in other areas also in this revision:
Added:
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_bookmark.c
     - copied unchanged from r260183, head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_bookmark.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_bookmark.h
     - copied unchanged from r260183, head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_bookmark.h
Modified:
  stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs.8
  stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.c
  stable/9/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
  stable/9/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7
  stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
  stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
  stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_impl.h
  stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_iter.c
  stable/9/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
  stable/9/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c
  stable/9/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h
  stable/9/cddl/contrib/opensolaris/lib/pyzfs/common/allow.py
  stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c
  stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h
  stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfs_deleg.c
  stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfs_deleg.h
  stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
  stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfs_namecheck.c
  stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfs_namecheck.h
  stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfs_prop.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/Makefile.files
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_diff.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_dataset.h
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dsl_deleg.h
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
  stable/9/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h
Directory Properties:
  stable/9/cddl/contrib/opensolaris/   (props changed)
  stable/9/cddl/contrib/opensolaris/cmd/zfs/   (props changed)
  stable/9/cddl/contrib/opensolaris/cmd/zpool/   (props changed)
  stable/9/cddl/contrib/opensolaris/lib/libzfs/   (props changed)
  stable/9/sys/   (props changed)
  stable/9/sys/cddl/contrib/opensolaris/   (props changed)

Modified: stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs.8
==============================================================================
--- stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs.8	Thu Mar 20 00:38:17 2014	(r263409)
+++ stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs.8	Thu Mar 20 00:38:46 2014	(r263410)
@@ -18,17 +18,18 @@
 .\" information: Portions Copyright [yyyy] [name of copyright owner]
 .\"
 .\" Copyright (c) 2010, Sun Microsystems, Inc. All Rights Reserved.
-.\" Copyright (c) 2012 by Delphix. All rights reserved.
+.\" Copyright (c) 2013 by Delphix. All rights reserved.
 .\" Copyright (c) 2011, Pawel Jakub Dawidek <pjd at FreeBSD.org>
 .\" Copyright (c) 2012, Glen Barber <gjb at FreeBSD.org>
 .\" Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
 .\" Copyright (c) 2013 Nexenta Systems, Inc. All Rights Reserved.
 .\" Copyright (c) 2013, Joyent, Inc. All rights reserved.
 .\" Copyright (c) 2013, Steven Hartland <smh at FreeBSD.org>
+.\" Copyright (c) 2014, Xin LI <delphij at FreeBSD.org>
 .\"
 .\" $FreeBSD$
 .\"
-.Dd December 24, 2013
+.Dd January 2, 2014
 .Dt ZFS 8
 .Os
 .Sh NAME
@@ -56,11 +57,16 @@
 .Cm destroy
 .Op Fl dnpRrv
 .Sm off
-.Ar snapshot
-.Op % Ns Ar snapname
+.Ar filesystem Ns | Ns volume
+.Ns @snap
+.Op % Ns Ar snap
+.Op , Ns Ar snap Op % Ns Ar snap
 .Op , Ns ...
 .Sm on
 .Nm
+.Cm destroy
+.Ar filesystem Ns | Ns Ar volume Ns # Ns Ar bookmark
+.Nm
 .Cm snapshot Ns | Ns Cm snap
 .Op Fl r
 .Oo Fl o Ar property Ns = Ns Ar value Oc Ns ...
@@ -167,11 +173,19 @@
 .Cm unshare
 .Fl a | Ar filesystem Ns | Ns Ar mountpoint
 .Nm
+.Cm bookmark
+.Ar snapshot
+.Ar bookmark
+.Nm
 .Cm send
 .Op Fl DnPpRv
 .Op Fl i Ar snapshot | Fl I Ar snapshot
 .Ar snapshot
 .Nm
+.Cm send
+.Op Fl i Ar snapshot Ns | Ns bookmark
+.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
+.Nm
 .Cm receive Ns | Ns Cm recv
 .Op Fl vnFu
 .Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
@@ -1645,6 +1659,13 @@ options, as they can destroy large porti
 behavior for mounted file systems in use.
 .It Xo
 .Nm
+.Cm destroy
+.Ar filesystem Ns | Ns Ar volume Ns # Ns Ar bookmark
+.Xc
+.Pp
+The given bookmark is destroyed.
+.It Xo
+.Nm
 .Cm snapshot Ns | Ns Cm snap
 .Op Fl r
 .Oo Fl o Ar property Ns = Ns Ar value Oc Ns ...
@@ -1677,14 +1698,24 @@ Roll back the given dataset to a previou
 back, all data that has changed since the snapshot is discarded, and the
 dataset reverts to the state at the time of the snapshot. By default, the
 command refuses to roll back to a snapshot other than the most recent one. In
-order to do so, all intermediate snapshots must be destroyed by specifying the
+order to do so, all intermediate snapshots and bookmarks must be destroyed
+by specifying the
 .Fl r
 option.
+.Pp
+The
+.Fl rR
+options do not recursively destroy the child snapshots of a
+recursive snapshot.
+Only direct snapshots of the specified filesystem
+are destroyed by either of these options.
+To completely roll back a
+recursive snapshot, you must rollback the individual child snapshots.
 .Bl -tag -width indent
 .It Fl r
-Recursively destroy any snapshots more recent than the one specified.
+Destroy any snapshots and bookmarks more recent than the one specified.
 .It Fl R
-Recursively destroy any more recent snapshots, as well as any clones of those
+Destroy any more recent snapshots and bookmarks, as well as any clones of those
 snapshots.
 .It Fl f
 Used with the
@@ -1859,7 +1890,7 @@ syntax.
 A comma-separated list of types to display, where
 .Ar type
 is one of
-.Sy filesystem , snapshot , snap,  volume , No or Sy all .
+.Sy filesystem , snapshot , snap , volume , bookmark , No or Sy all .
 For example, specifying
 .Fl t Cm snapshot
 displays only snapshots.
@@ -1956,7 +1987,7 @@ sections.
 The special value
 .Cm all
 can be used to display all properties that apply to the given dataset's type
-(filesystem, volume, or snapshot).
+(filesystem, volume, snapshot, or bookmark).
 .Bl -tag -width indent
 .It Fl r
 Recursively display properties for any children.
@@ -2274,6 +2305,26 @@ file system shared on the system.
 .El
 .It Xo
 .Nm
+.Cm bookmark
+.Ar snapshot
+.Ar bookmark
+.Xc
+.Pp
+Creates a bookmark of the given snapshot.
+Bookmarks mark the point in time
+when the snapshot was created, and can be used as the incremental source for
+a
+.Qq Nm Cm send
+command.
+.Pp
+This feature must be enabled to be used.
+See
+.Xr zpool-features 7
+for details on ZFS feature flags and the
+.Sy bookmark
+feature.
+.It Xo
+.Nm
 .Cm send
 .Op Fl DnPpRv
 .Op Fl i Ar snapshot | Fl I Ar snapshot
@@ -2292,17 +2343,15 @@ a file or to a different system (for exa
 By default, a full stream is generated.
 .Bl -tag -width indent
 .It Fl i Ar snapshot
-Generate an incremental stream from the
-.Fl i Ar snapshot
-to the last
-.Ar snapshot .
-The incremental source (the
-.Fl i Ar snapshot )
-can be specified as the last component of the snapshot name (for example, the
-part after the
-.Sy @ ) ,
-and it is assumed to be from the same file system as the last
-.Ar snapshot .
+Generate an incremental stream from the first
+.Ar snapshot Pq the incremental source
+to the second
+.Ar snapshot Pq the incremental target .
+The incremental source can be specified as the last component of the
+snapshot name
+.Pq the Em @ No character and following
+and
+it is assumed to be from the same file system as the incremental target.
 .Pp
 If the destination is a clone, the source may be the origin snapshot, which
 must be fully specified (for example,
@@ -2310,15 +2359,16 @@ must be fully specified (for example,
 not just
 .Cm @origin ) .
 .It Fl I Ar snapshot
-Generate a stream package that sends all intermediary snapshots from the
-.Fl I Ar snapshot
-to the last
+Generate a stream package that sends all intermediary snapshots from the first
+.Ar snapshot
+to the second
 .Ar snapshot .
 For example,
 .Ic -I @a fs at d
 is similar to
 .Ic -i @a fs at b; -i @b fs at c; -i @c fs at d .
-The incremental source snapshot may be specified as with the
+The incremental
+source may be specified as with the
 .Fl i
 option.
 .It Fl R
@@ -2371,6 +2421,35 @@ on future versions of
 .Tn ZFS .
 .It Xo
 .Nm
+.Cm send
+.Op Fl i Ar snapshot Ns | Ns Ar bookmark
+.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot
+.Xc
+.Pp
+Generate a send stream, which may be of a filesystem, and may be
+incremental from a bookmark.
+If the destination is a filesystem or volume,
+the pool must be read-only, or the filesystem must not be mounted.
+When the
+stream generated from a filesystem or volume is received, the default snapshot
+name will be
+.Pq --head-- .
+.Bl -tag -width indent
+.It Fl i Ar snapshot Ns | Ns bookmark
+Generate an incremental send stream.
+The incremental source must be an earlier
+snapshot in the destination's history.
+It will commonly be an earlier
+snapshot in the destination's filesystem, in which case it can be
+specified as the last component of the name
+.Pq the Em # No or Em @ No character and following .
+.Pp
+If the incremental target is a clone, the incremental source can
+be the origin snapshot, or an earlier snapshot in the origin's filesystem,
+or the origin's origin, etc.
+.El
+.It Xo
+.Nm
 .Cm receive Ns | Ns Cm recv
 .Op Fl vnFu
 .Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot

Modified: stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.c
==============================================================================
--- stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.c	Thu Mar 20 00:38:17 2014	(r263409)
+++ stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs_iter.c	Thu Mar 20 00:38:46 2014	(r263410)
@@ -24,6 +24,7 @@
  * Copyright (c) 2012 Pawel Jakub Dawidek <pawel at dawidek.net>.
  * All rights reserved.
  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
 #include <libintl.h>
@@ -72,7 +73,7 @@ uu_avl_pool_t *avl_pool;
  * Include snaps if they were requested or if this a zfs list where types
  * were not specified and the "listsnapshots" property is set on this pool.
  */
-static int
+static boolean_t
 zfs_include_snapshots(zfs_handle_t *zhp, callback_data_t *cb)
 {
 	zpool_handle_t *zph;
@@ -92,8 +93,9 @@ static int
 zfs_callback(zfs_handle_t *zhp, void *data)
 {
 	callback_data_t *cb = data;
-	int dontclose = 0;
-	int include_snaps = zfs_include_snapshots(zhp, cb);
+	boolean_t dontclose = B_FALSE;
+	boolean_t include_snaps = zfs_include_snapshots(zhp, cb);
+	boolean_t include_bmarks = (cb->cb_types & ZFS_TYPE_BOOKMARK);
 
 	if ((zfs_get_type(zhp) & cb->cb_types) ||
 	    ((zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) && include_snaps)) {
@@ -119,7 +121,7 @@ zfs_callback(zfs_handle_t *zhp, void *da
 				}
 			}
 			uu_avl_insert(cb->cb_avl, node, idx);
-			dontclose = 1;
+			dontclose = B_TRUE;
 		} else {
 			free(node);
 		}
@@ -134,11 +136,14 @@ zfs_callback(zfs_handle_t *zhp, void *da
 		cb->cb_depth++;
 		if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM)
 			(void) zfs_iter_filesystems(zhp, zfs_callback, data);
-		if ((zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) && include_snaps) {
+		if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
+		    ZFS_TYPE_BOOKMARK)) == 0) && include_snaps)
 			(void) zfs_iter_snapshots(zhp,
 			    (cb->cb_flags & ZFS_ITER_SIMPLE) != 0, zfs_callback,
 			    data);
-		}
+		if (((zfs_get_type(zhp) & (ZFS_TYPE_SNAPSHOT |
+		    ZFS_TYPE_BOOKMARK)) == 0) && include_bmarks)
+			(void) zfs_iter_bookmarks(zhp, zfs_callback, data);
 		cb->cb_depth--;
 	}
 

Modified: stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c
==============================================================================
--- stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c	Thu Mar 20 00:38:17 2014	(r263409)
+++ stable/8/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c	Thu Mar 20 00:38:46 2014	(r263410)
@@ -105,6 +105,7 @@ static int zfs_do_release(int argc, char
 static int zfs_do_diff(int argc, char **argv);
 static int zfs_do_jail(int argc, char **argv);
 static int zfs_do_unjail(int argc, char **argv);
+static int zfs_do_bookmark(int argc, char **argv);
 
 /*
  * Enable a reasonable set of defaults for libumem debugging on DEBUG builds.
@@ -153,6 +154,7 @@ typedef enum {
 	HELP_HOLDS,
 	HELP_RELEASE,
 	HELP_DIFF,
+	HELP_BOOKMARK,
 } zfs_help_t;
 
 typedef struct zfs_command {
@@ -179,6 +181,7 @@ static zfs_command_t command_table[] = {
 	{ "clone",	zfs_do_clone,		HELP_CLONE		},
 	{ "promote",	zfs_do_promote,		HELP_PROMOTE		},
 	{ "rename",	zfs_do_rename,		HELP_RENAME		},
+	{ "bookmark",	zfs_do_bookmark,	HELP_BOOKMARK		},
 	{ NULL },
 	{ "list",	zfs_do_list,		HELP_LIST		},
 	{ NULL },
@@ -229,11 +232,12 @@ get_usage(zfs_help_t idx)
 	case HELP_DESTROY:
 		return (gettext("\tdestroy [-fnpRrv] <filesystem|volume>\n"
 		    "\tdestroy [-dnpRrv] "
-		    "<snapshot>[%<snapname>][,...]\n"));
+		    "<filesystem|volume>@<snap>[%<snap>][,...]\n"
+		    "\tdestroy <filesystem|volume>#<bookmark>\n"));
 	case HELP_GET:
 		return (gettext("\tget [-rHp] [-d max] "
-		    "[-o \"all\" | field[,...]] [-t type[,...]] "
-		    "[-s source[,...]]\n"
+		    "[-o \"all\" | field[,...]]\n"
+		    "\t    [-t type[,...]] [-s source[,...]]\n"
 		    "\t    <\"all\" | property[,...]> "
 		    "[filesystem|volume|snapshot] ...\n"));
 	case HELP_INHERIT:
@@ -262,15 +266,16 @@ get_usage(zfs_help_t idx)
 	case HELP_RENAME:
 		return (gettext("\trename [-f] <filesystem|volume|snapshot> "
 		    "<filesystem|volume|snapshot>\n"
-		    "\trename [-f] -p <filesystem|volume> "
-		    "<filesystem|volume>\n"
+		    "\trename [-f] -p <filesystem|volume> <filesystem|volume>\n"
 		    "\trename -r <snapshot> <snapshot>\n"
 		    "\trename -u [-p] <filesystem> <filesystem>"));
 	case HELP_ROLLBACK:
 		return (gettext("\trollback [-rRf] <snapshot>\n"));
 	case HELP_SEND:
-		return (gettext("\tsend [-DnPpRv] "
-		    "[-i snapshot | -I snapshot] <snapshot>\n"));
+		return (gettext("\tsend [-DnPpRv] [-[iI] snapshot] "
+		    "<snapshot>\n"
+		    "\tsend [-i snapshot|bookmark] "
+		    "<filesystem|volume|snapshot>\n"));
 	case HELP_SET:
 		return (gettext("\tset <property=value> "
 		    "<filesystem|volume|snapshot> ...\n"));
@@ -278,7 +283,7 @@ get_usage(zfs_help_t idx)
 		return (gettext("\tshare <-a | filesystem>\n"));
 	case HELP_SNAPSHOT:
 		return (gettext("\tsnapshot|snap [-r] [-o property=value] ... "
-		    "<filesystem at snapname|volume at snapname> ...\n"));
+		    "<filesystem|volume>@<snap> ...\n"));
 	case HELP_UNMOUNT:
 		return (gettext("\tunmount|umount [-f] "
 		    "<-a | filesystem|mountpoint>\n"));
@@ -307,11 +312,13 @@ get_usage(zfs_help_t idx)
 		    "<filesystem|volume>\n"));
 	case HELP_USERSPACE:
 		return (gettext("\tuserspace [-Hinp] [-o field[,...]] "
-		    "[-s field]...\n\t    [-S field]... [-t type[,...]] "
+		    "[-s field] ...\n"
+		    "\t    [-S field] ... [-t type[,...]] "
 		    "<filesystem|snapshot>\n"));
 	case HELP_GROUPSPACE:
 		return (gettext("\tgroupspace [-Hinp] [-o field[,...]] "
-		    "[-s field]...\n\t    [-S field]... [-t type[,...]] "
+		    "[-s field] ...\n"
+		    "\t    [-S field] ... [-t type[,...]] "
 		    "<filesystem|snapshot>\n"));
 	case HELP_HOLD:
 		return (gettext("\thold [-r] <tag> <snapshot> ...\n"));
@@ -322,6 +329,8 @@ get_usage(zfs_help_t idx)
 	case HELP_DIFF:
 		return (gettext("\tdiff [-FHt] <snapshot> "
 		    "[snapshot|filesystem]\n"));
+	case HELP_BOOKMARK:
+		return (gettext("\tbookmark <snapshot> <bookmark>\n"));
 	}
 
 	abort();
@@ -913,6 +922,7 @@ typedef struct destroy_cbdata {
 	char		*cb_prevsnap;
 	int64_t		cb_snapused;
 	char		*cb_snapspec;
+	char		*cb_bookmark;
 } destroy_cbdata_t;
 
 /*
@@ -1182,7 +1192,7 @@ zfs_do_destroy(int argc, char **argv)
 	int err = 0;
 	int c;
 	zfs_handle_t *zhp = NULL;
-	char *at;
+	char *at, *pound;
 	zfs_type_t type = ZFS_TYPE_DATASET;
 
 	/* check options */
@@ -1234,6 +1244,7 @@ zfs_do_destroy(int argc, char **argv)
 	}
 
 	at = strchr(argv[0], '@');
+	pound = strchr(argv[0], '#');
 	if (at != NULL) {
 
 		/* Build the list of snaps to destroy in cb_nvl. */
@@ -1295,6 +1306,46 @@ zfs_do_destroy(int argc, char **argv)
 
 		if (err != 0)
 			rv = 1;
+	} else if (pound != NULL) {
+		int err;
+		nvlist_t *nvl;
+
+		if (cb.cb_dryrun) {
+			(void) fprintf(stderr,
+			    "dryrun is not supported with bookmark\n");
+			return (-1);
+		}
+
+		if (cb.cb_defer_destroy) {
+			(void) fprintf(stderr,
+			    "defer destroy is not supported with bookmark\n");
+			return (-1);
+		}
+
+		if (cb.cb_recurse) {
+			(void) fprintf(stderr,
+			    "recursive is not supported with bookmark\n");
+			return (-1);
+		}
+
+		if (!zfs_bookmark_exists(argv[0])) {
+			(void) fprintf(stderr, gettext("bookmark '%s' "
+			    "does not exist.\n"), argv[0]);
+			return (1);
+		}
+
+		nvl = fnvlist_alloc();
+		fnvlist_add_boolean(nvl, argv[0]);
+
+		err = lzc_destroy_bookmarks(nvl, NULL);
+		if (err != 0) {
+			(void) zfs_standard_error(g_zfs, err,
+			    "cannot destroy bookmark");
+		}
+
+		nvlist_free(cb.cb_nvl);
+
+		return (err);
 	} else {
 		/* Open the given dataset */
 		if ((zhp = zfs_open(g_zfs, argv[0], type)) == NULL)
@@ -1657,7 +1708,8 @@ zfs_do_get(int argc, char **argv)
 			flags &= ~ZFS_ITER_PROP_LISTSNAPS;
 			while (*optarg != '\0') {
 				static char *type_subopts[] = { "filesystem",
-				    "volume", "snapshot", "all", NULL };
+				    "volume", "snapshot", "bookmark",
+				    "all", NULL };
 
 				switch (getsubopt(&optarg, type_subopts,
 				    &value)) {
@@ -1671,7 +1723,11 @@ zfs_do_get(int argc, char **argv)
 					types |= ZFS_TYPE_SNAPSHOT;
 					break;
 				case 3:
-					types = ZFS_TYPE_DATASET;
+					types |= ZFS_TYPE_BOOKMARK;
+					break;
+				case 4:
+					types = ZFS_TYPE_DATASET |
+					    ZFS_TYPE_BOOKMARK;
 					break;
 
 				default:
@@ -3016,7 +3072,8 @@ zfs_do_list(int argc, char **argv)
 			flags &= ~ZFS_ITER_PROP_LISTSNAPS;
 			while (*optarg != '\0') {
 				static char *type_subopts[] = { "filesystem",
-				    "volume", "snapshot", "snap", "all", NULL };
+				    "volume", "snapshot", "snap", "bookmark",
+				    "all", NULL };
 
 				switch (getsubopt(&optarg, type_subopts,
 				    &value)) {
@@ -3031,9 +3088,12 @@ zfs_do_list(int argc, char **argv)
 					types |= ZFS_TYPE_SNAPSHOT;
 					break;
 				case 4:
-					types = ZFS_TYPE_DATASET;
+					types |= ZFS_TYPE_BOOKMARK;
+					break;
+				case 5:
+					types = ZFS_TYPE_DATASET |
+					    ZFS_TYPE_BOOKMARK;
 					break;
-
 				default:
 					(void) fprintf(stderr,
 					    gettext("invalid type '%s'\n"),
@@ -3273,9 +3333,29 @@ typedef struct rollback_cbdata {
 	char		*cb_target;
 	int		cb_error;
 	boolean_t	cb_recurse;
-	boolean_t	cb_dependent;
 } rollback_cbdata_t;
 
+static int
+rollback_check_dependent(zfs_handle_t *zhp, void *data)
+{
+	rollback_cbdata_t *cbp = data;
+
+	if (cbp->cb_first && cbp->cb_recurse) {
+		(void) fprintf(stderr, gettext("cannot rollback to "
+		    "'%s': clones of previous snapshots exist\n"),
+		    cbp->cb_target);
+		(void) fprintf(stderr, gettext("use '-R' to "
+		    "force deletion of the following clones and "
+		    "dependents:\n"));
+		cbp->cb_first = 0;
+		cbp->cb_error = 1;
+	}
+
+	(void) fprintf(stderr, "%s\n", zfs_get_name(zhp));
+
+	zfs_close(zhp);
+	return (0);
+}
 /*
  * Report any snapshots more recent than the one specified.  Used when '-r' is
  * not specified.  We reuse this same callback for the snapshot dependents - if
@@ -3292,52 +3372,30 @@ rollback_check(zfs_handle_t *zhp, void *
 		return (0);
 	}
 
-	if (!cbp->cb_dependent) {
-		if (strcmp(zfs_get_name(zhp), cbp->cb_target) != 0 &&
-		    zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT &&
-		    zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) >
-		    cbp->cb_create) {
-
-			if (cbp->cb_first && !cbp->cb_recurse) {
-				(void) fprintf(stderr, gettext("cannot "
-				    "rollback to '%s': more recent snapshots "
-				    "exist\n"),
-				    cbp->cb_target);
-				(void) fprintf(stderr, gettext("use '-r' to "
-				    "force deletion of the following "
-				    "snapshots:\n"));
-				cbp->cb_first = 0;
-				cbp->cb_error = 1;
-			}
-
-			if (cbp->cb_recurse) {
-				cbp->cb_dependent = B_TRUE;
-				if (zfs_iter_dependents(zhp, B_TRUE,
-				    rollback_check, cbp) != 0) {
-					zfs_close(zhp);
-					return (-1);
-				}
-				cbp->cb_dependent = B_FALSE;
-			} else {
-				(void) fprintf(stderr, "%s\n",
-				    zfs_get_name(zhp));
-			}
-		}
-	} else {
-		if (cbp->cb_first && cbp->cb_recurse) {
-			(void) fprintf(stderr, gettext("cannot rollback to "
-			    "'%s': clones of previous snapshots exist\n"),
+	if (zfs_prop_get_int(zhp, ZFS_PROP_CREATETXG) > cbp->cb_create) {
+		if (cbp->cb_first && !cbp->cb_recurse) {
+			(void) fprintf(stderr, gettext("cannot "
+			    "rollback to '%s': more recent snapshots "
+			    "or bookmarks exist\n"),
 			    cbp->cb_target);
-			(void) fprintf(stderr, gettext("use '-R' to "
-			    "force deletion of the following clones and "
-			    "dependents:\n"));
+			(void) fprintf(stderr, gettext("use '-r' to "
+			    "force deletion of the following "
+			    "snapshots and bookmarks:\n"));
 			cbp->cb_first = 0;
 			cbp->cb_error = 1;
 		}
 
-		(void) fprintf(stderr, "%s\n", zfs_get_name(zhp));
+		if (cbp->cb_recurse) {
+			if (zfs_iter_dependents(zhp, B_TRUE,
+			    rollback_check_dependent, cbp) != 0) {
+				zfs_close(zhp);
+				return (-1);
+			}
+		} else {
+			(void) fprintf(stderr, "%s\n",
+			    zfs_get_name(zhp));
+		}
 	}
-
 	zfs_close(zhp);
 	return (0);
 }
@@ -3407,7 +3465,9 @@ zfs_do_rollback(int argc, char **argv)
 	cb.cb_create = zfs_prop_get_int(snap, ZFS_PROP_CREATETXG);
 	cb.cb_first = B_TRUE;
 	cb.cb_error = 0;
-	if ((ret = zfs_iter_children(zhp, rollback_check, &cb)) != 0)
+	if ((ret = zfs_iter_snapshots(zhp, B_FALSE, rollback_check, &cb)) != 0)
+		goto out;
+	if ((ret = zfs_iter_bookmarks(zhp, rollback_check, &cb)) != 0)
 		goto out;
 
 	if ((ret = cb.cb_error) != 0)
@@ -3702,12 +3762,45 @@ zfs_do_send(int argc, char **argv)
 		return (1);
 	}
 
-	cp = strchr(argv[0], '@');
-	if (cp == NULL) {
-		(void) fprintf(stderr,
-		    gettext("argument must be a snapshot\n"));
-		usage(B_FALSE);
+	/*
+	 * Special case sending a filesystem, or from a bookmark.
+	 */
+	if (strchr(argv[0], '@') == NULL ||
+	    (fromname && strchr(fromname, '#') != NULL)) {
+		char frombuf[ZFS_MAXNAMELEN];
+
+		if (flags.replicate || flags.doall || flags.props ||
+		    flags.dedup || flags.dryrun || flags.verbose ||
+		    flags.progress) {
+			(void) fprintf(stderr,
+			    gettext("Error: "
+			    "Unsupported flag with filesystem or bookmark.\n"));
+			return (1);
+		}
+
+		zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET);
+		if (zhp == NULL)
+			return (1);
+
+		if (fromname != NULL &&
+		    (fromname[0] == '#' || fromname[0] == '@')) {
+			/*
+			 * Incremental source name begins with # or @.
+			 * Default to same fs as target.
+			 */
+			(void) strncpy(frombuf, argv[0], sizeof (frombuf));
+			cp = strchr(frombuf, '@');
+			if (cp != NULL)
+				*cp = '\0';
+			(void) strlcat(frombuf, fromname, sizeof (frombuf));
+			fromname = frombuf;
+		}
+		err = zfs_send_one(zhp, fromname, STDOUT_FILENO);
+		zfs_close(zhp);
+		return (err != 0);
 	}
+
+	cp = strchr(argv[0], '@');
 	*cp = '\0';
 	toname = cp + 1;
 	zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME);
@@ -3863,6 +3956,7 @@ zfs_do_receive(int argc, char **argv)
 #define	ZFS_DELEG_PERM_HOLD		"hold"
 #define	ZFS_DELEG_PERM_RELEASE		"release"
 #define	ZFS_DELEG_PERM_DIFF		"diff"
+#define	ZFS_DELEG_PERM_BOOKMARK		"bookmark"
 
 #define	ZFS_NUM_DELEG_NOTES ZFS_DELEG_NOTE_NONE
 
@@ -3882,6 +3976,7 @@ static zfs_deleg_perm_tab_t zfs_deleg_pe
 	{ ZFS_DELEG_PERM_SEND, ZFS_DELEG_NOTE_SEND },
 	{ ZFS_DELEG_PERM_SHARE, ZFS_DELEG_NOTE_SHARE },
 	{ ZFS_DELEG_PERM_SNAPSHOT, ZFS_DELEG_NOTE_SNAPSHOT },
+	{ ZFS_DELEG_PERM_BOOKMARK, ZFS_DELEG_NOTE_BOOKMARK },
 
 	{ ZFS_DELEG_PERM_GROUPQUOTA, ZFS_DELEG_NOTE_GROUPQUOTA },
 	{ ZFS_DELEG_PERM_GROUPUSED, ZFS_DELEG_NOTE_GROUPUSED },
@@ -6653,6 +6748,108 @@ zfs_do_diff(int argc, char **argv)
 	return (err != 0);
 }
 
+/*
+ * zfs bookmark <fs at snap> <fs#bmark>
+ *
+ * Creates a bookmark with the given name from the given snapshot.
+ */
+static int
+zfs_do_bookmark(int argc, char **argv)
+{
+	char snapname[ZFS_MAXNAMELEN];
+	zfs_handle_t *zhp;
+	nvlist_t *nvl;
+	int ret = 0;
+	int c;
+
+	/* check options */
+	while ((c = getopt(argc, argv, "")) != -1) {
+		switch (c) {
+		case '?':
+			(void) fprintf(stderr,
+			    gettext("invalid option '%c'\n"), optopt);
+			goto usage;
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	/* check number of arguments */
+	if (argc < 1) {
+		(void) fprintf(stderr, gettext("missing snapshot argument\n"));
+		goto usage;
+	}
+	if (argc < 2) {
+		(void) fprintf(stderr, gettext("missing bookmark argument\n"));
+		goto usage;
+	}
+
+	if (strchr(argv[1], '#') == NULL) {
+		(void) fprintf(stderr,
+		    gettext("invalid bookmark name '%s' -- "
+		    "must contain a '#'\n"), argv[1]);
+		goto usage;
+	}
+
+	if (argv[0][0] == '@') {
+		/*
+		 * Snapshot name begins with @.
+		 * Default to same fs as bookmark.
+		 */
+		(void) strncpy(snapname, argv[1], sizeof (snapname));
+		*strchr(snapname, '#') = '\0';
+		(void) strlcat(snapname, argv[0], sizeof (snapname));
+	} else {
+		(void) strncpy(snapname, argv[0], sizeof (snapname));
+	}
+	zhp = zfs_open(g_zfs, snapname, ZFS_TYPE_SNAPSHOT);
+	if (zhp == NULL)
+		goto usage;
+	zfs_close(zhp);
+
+
+	nvl = fnvlist_alloc();
+	fnvlist_add_string(nvl, argv[1], snapname);
+	ret = lzc_bookmark(nvl, NULL);
+	fnvlist_free(nvl);
+
+	if (ret != 0) {
+		const char *err_msg;
+		char errbuf[1024];
+
+		(void) snprintf(errbuf, sizeof (errbuf),
+		    dgettext(TEXT_DOMAIN,
+		    "cannot create bookmark '%s'"), argv[1]);
+
+		switch (ret) {
+		case EXDEV:
+			err_msg = "bookmark is in a different pool";
+			break;
+		case EEXIST:
+			err_msg = "bookmark exists";
+			break;
+		case EINVAL:
+			err_msg = "invalid argument";
+			break;
+		case ENOTSUP:
+			err_msg = "bookmark feature not enabled";
+			break;
+		default:
+			err_msg = "unknown error";
+			break;
+		}
+		(void) fprintf(stderr, "%s: %s\n", errbuf,
+		    dgettext(TEXT_DOMAIN, err_msg));
+	}
+
+	return (ret);
+
+usage:
+	usage(B_FALSE);
+	return (-1);
+}
+
 int
 main(int argc, char **argv)
 {

Modified: stable/8/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7
==============================================================================
--- stable/8/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7	Thu Mar 20 00:38:17 2014	(r263409)
+++ stable/8/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7	Thu Mar 20 00:38:46 2014	(r263410)
@@ -23,7 +23,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd December 31, 2013
+.Dd January 2, 2014
 .Dt ZPOOL-FEATURES 7
 .Os
 .Sh NAME
@@ -222,12 +222,16 @@ command. Please note that doing so will
 immediately activate the
 .Sy lz4_compress
 feature on the underlying
-pool (even before any data is written). Since this feature is not
-read-only compatible, this operation will render the pool unimportable
-on systems without support for the
+pool
+.Pq even before any data is written ,
+and the feature will not be
+deactivated.
+Since this feature is not read-only compatible, this
+operation will render the pool unimportable on systems without support
+for the
 .Sy lz4_compress
-feature. At the
-moment, this operation cannot be reversed. Booting off of
+feature.
+Booting off of
 .Sy lz4
 -compressed root pools is supported.
 .It Sy multi_vdev_crash_dump
@@ -286,6 +290,25 @@ and will be returned to the
 .Sy enabled
 state when all datasets that use
 this feature are destroyed.
+.It Sy bookmarks
+.Bl -column "READ\-ONLY COMPATIBLE" "com.delphix:bookmarks"
+.It GUID Ta com.delphix:bookmarks
+.It READ\-ONLY COMPATIBLE Ta yes
+.It DEPENDENCIES Ta extensible_dataset
+.El
+.Pp
+This feature enables use of the
+.Nm zfs
+.Cm bookmark
+subcommand.
+.Pp
+This feature is
+.Sy active
+while any bookmarks exist in the pool.
+All bookmarks in the pool can be listed by running
+.Nm zfs
+.Cm list
+.Fl t No bookmark Fl r Ar poolname .
 .It Sy enabled_txg
 .Bl -column "READ\-ONLY COMPATIBLE" "com.delphix:enabled_txg"
 .It GUID Ta com.delphix:enabled_txg

Modified: stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
==============================================================================
--- stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h	Thu Mar 20 00:38:17 2014	(r263409)
+++ stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h	Thu Mar 20 00:38:46 2014	(r263410)
@@ -23,7 +23,7 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011 Pawel Jakub Dawidek <pawel at dawidek.net>.
  * All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  * Copyright (c) 2012 Martin Matuska <mm at FreeBSD.org>. All rights reserved.
  * Copyright (c) 2013 Steven Hartland. All rights reserved.
@@ -193,6 +193,7 @@ extern int zpool_log_history(libzfs_hand
 extern int libzfs_errno(libzfs_handle_t *);
 extern const char *libzfs_error_action(libzfs_handle_t *);
 extern const char *libzfs_error_description(libzfs_handle_t *);
+extern int zfs_standard_error(libzfs_handle_t *, int, const char *);
 extern void libzfs_mnttab_init(libzfs_handle_t *);
 extern void libzfs_mnttab_fini(libzfs_handle_t *);
 extern void libzfs_mnttab_cache(libzfs_handle_t *, boolean_t);
@@ -537,6 +538,7 @@ extern int zfs_iter_filesystems(zfs_hand
 extern int zfs_iter_snapshots(zfs_handle_t *, boolean_t, zfs_iter_f, void *);
 extern int zfs_iter_snapshots_sorted(zfs_handle_t *, zfs_iter_f, void *);
 extern int zfs_iter_snapspec(zfs_handle_t *, const char *, zfs_iter_f, void *);
+extern int zfs_iter_bookmarks(zfs_handle_t *, zfs_iter_f, void *);
 
 typedef struct get_all_cb {
 	zfs_handle_t	**cb_handles;
@@ -611,6 +613,7 @@ typedef boolean_t (snapfilter_cb_t)(zfs_
 
 extern int zfs_send(zfs_handle_t *, const char *, const char *,
     sendflags_t *, int, snapfilter_cb_t, void *, nvlist_t **);
+extern int zfs_send_one(zfs_handle_t *, const char *, int);
 
 extern int zfs_promote(zfs_handle_t *);
 extern int zfs_hold(zfs_handle_t *, const char *, const char *,
@@ -680,6 +683,7 @@ extern zfs_handle_t *zfs_path_to_zhandle
 extern boolean_t zfs_dataset_exists(libzfs_handle_t *, const char *,
     zfs_type_t);
 extern int zfs_spa_version(zfs_handle_t *, int *);
+extern boolean_t zfs_bookmark_exists(const char *path);
 
 /*
  * Mount support functions.

Modified: stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
==============================================================================
--- stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c	Thu Mar 20 00:38:17 2014	(r263409)
+++ stable/8/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c	Thu Mar 20 00:38:46 2014	(r263410)
@@ -295,7 +295,7 @@ zpool_handle(zfs_handle_t *zhp)
 	int len;
 	zpool_handle_t *zph;
 
-	len = strcspn(zhp->zfs_name, "/@") + 1;
+	len = strcspn(zhp->zfs_name, "/@#") + 1;
 	pool_name = zfs_alloc(zhp->zfs_hdl, len);
 	(void) strlcpy(pool_name, zhp->zfs_name, len);
 
@@ -579,6 +579,70 @@ zfs_handle_dup(zfs_handle_t *zhp_orig)
 	return (zhp);
 }
 
+boolean_t
+zfs_bookmark_exists(const char *path)
+{
+	nvlist_t *bmarks;
+	nvlist_t *props;
+	char fsname[ZFS_MAXNAMELEN];
+	char *bmark_name;
+	char *pound;
+	int err;
+	boolean_t rv;
+
+
+	(void) strlcpy(fsname, path, sizeof (fsname));
+	pound = strchr(fsname, '#');
+	if (pound == NULL)
+		return (B_FALSE);
+
+	*pound = '\0';
+	bmark_name = pound + 1;
+	props = fnvlist_alloc();
+	err = lzc_get_bookmarks(fsname, props, &bmarks);
+	nvlist_free(props);
+	if (err != 0) {
+		nvlist_free(bmarks);
+		return (B_FALSE);
+	}
+
+	rv = nvlist_exists(bmarks, bmark_name);
+	nvlist_free(bmarks);
+	return (rv);
+}
+
+zfs_handle_t *
+make_bookmark_handle(zfs_handle_t *parent, const char *path,
+    nvlist_t *bmark_props)
+{
+	zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
+
+	if (zhp == NULL)
+		return (NULL);
+
+	/* Fill in the name. */
+	zhp->zfs_hdl = parent->zfs_hdl;
+	(void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
+
+	/* Set the property lists. */
+	if (nvlist_dup(bmark_props, &zhp->zfs_props, 0) != 0) {
+		free(zhp);
+		return (NULL);
+	}
+
+	/* Set the types. */
+	zhp->zfs_head_type = parent->zfs_head_type;
+	zhp->zfs_type = ZFS_TYPE_BOOKMARK;
+
+	if ((zhp->zpool_hdl = zpool_handle(zhp)) == NULL) {
+		nvlist_free(zhp->zfs_props);
+		free(zhp);
+		return (NULL);
+	}
+
+	return (zhp);
+}
+
 /*
  * Opens the given snapshot, filesystem, or volume.   The 'types'
  * argument is a mask of acceptable types.  The function will print an
@@ -2271,6 +2335,9 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop
 		case ZFS_TYPE_SNAPSHOT:
 			str = "snapshot";
 			break;
+		case ZFS_TYPE_BOOKMARK:
+			str = "bookmark";
+			break;
 		default:
 			abort();
 		}
@@ -3133,6 +3200,19 @@ zfs_destroy(zfs_handle_t *zhp, boolean_t
 {
 	zfs_cmd_t zc = { 0 };
 
+	if (zhp->zfs_type == ZFS_TYPE_BOOKMARK) {
+		nvlist_t *nv = fnvlist_alloc();
+		fnvlist_add_boolean(nv, zhp->zfs_name);
+		int error = lzc_destroy_bookmarks(nv, NULL);
+		fnvlist_free(nv);
+		if (error != 0) {

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-stable-8 mailing list