Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 18 Jul 2012 10:51:11 +0000 (UTC)
From:      Martin Matuska <mm@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org
Subject:   svn commit: r238590 - in vendor-sys/illumos/dist: common/zfs uts/common/fs/zfs uts/common/fs/zfs/sys uts/common/sys uts/common/sys/fs
Message-ID:  <201207181051.q6IApBGk062334@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mm
Date: Wed Jul 18 10:51:11 2012
New Revision: 238590
URL: http://svn.freebsd.org/changeset/base/238590

Log:
  Update vendor-sys/illumos/dist to illumos-gate 13752:9f5f6c52ba19
  
  Obtained from:	ssh://anonhg@hg.illumos.org/illumos-gate

Modified:
  vendor-sys/illumos/dist/common/zfs/zfs_comutil.c
  vendor-sys/illumos/dist/common/zfs/zfs_comutil.h
  vendor-sys/illumos/dist/common/zfs/zprop_common.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_objset.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_send.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_tx.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_dataset.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_deleg.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_dir.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_prop.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_scan.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_synctask.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/rrwlock.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/spa.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/spa_history.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dmu.h
  vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dmu_objset.h
  vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dsl_dataset.h
  vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dsl_deleg.h
  vendor-sys/illumos/dist/uts/common/fs/zfs/sys/dsl_prop.h
  vendor-sys/illumos/dist/uts/common/fs/zfs/sys/rrwlock.h
  vendor-sys/illumos/dist/uts/common/fs/zfs/sys/spa.h
  vendor-sys/illumos/dist/uts/common/fs/zfs/sys/zfs_ioctl.h
  vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_ctldir.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_ioctl.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/zfs_vfsops.c
  vendor-sys/illumos/dist/uts/common/fs/zfs/zvol.c
  vendor-sys/illumos/dist/uts/common/sys/feature_tests.h
  vendor-sys/illumos/dist/uts/common/sys/fs/zfs.h

Modified: vendor-sys/illumos/dist/common/zfs/zfs_comutil.c
==============================================================================
--- vendor-sys/illumos/dist/common/zfs/zfs_comutil.c	Wed Jul 18 10:46:31 2012	(r238589)
+++ vendor-sys/illumos/dist/common/zfs/zfs_comutil.c	Wed Jul 18 10:51:11 2012	(r238590)
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 /*
@@ -157,7 +158,11 @@ zfs_spa_version_map(int zpl_version)
 	return (version);
 }
 
-const char *zfs_history_event_names[LOG_END] = {
+/*
+ * This is the table of legacy internal event names; it should not be modified.
+ * The internal events are now stored in the history log as strings.
+ */
+const char *zfs_history_event_names[ZFS_NUM_LEGACY_HISTORY_EVENTS] = {
 	"invalid event",
 	"pool create",
 	"vdev add",

Modified: vendor-sys/illumos/dist/common/zfs/zfs_comutil.h
==============================================================================
--- vendor-sys/illumos/dist/common/zfs/zfs_comutil.h	Wed Jul 18 10:46:31 2012	(r238589)
+++ vendor-sys/illumos/dist/common/zfs/zfs_comutil.h	Wed Jul 18 10:51:11 2012	(r238590)
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #ifndef	_ZFS_COMUTIL_H
@@ -37,7 +38,8 @@ extern void zpool_get_rewind_policy(nvli
 
 extern int zfs_zpl_version_map(int spa_version);
 extern int zfs_spa_version_map(int zpl_version);
-extern const char *zfs_history_event_names[LOG_END];
+#define	ZFS_NUM_LEGACY_HISTORY_EVENTS 41
+extern const char *zfs_history_event_names[ZFS_NUM_LEGACY_HISTORY_EVENTS];
 
 #ifdef	__cplusplus
 }

Modified: vendor-sys/illumos/dist/common/zfs/zprop_common.c
==============================================================================
--- vendor-sys/illumos/dist/common/zfs/zprop_common.c	Wed Jul 18 10:46:31 2012	(r238589)
+++ vendor-sys/illumos/dist/common/zfs/zprop_common.c	Wed Jul 18 10:51:11 2012	(r238590)
@@ -22,6 +22,9 @@
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
 
 /*
  * Common routines used by zfs and zpool property management.
@@ -129,7 +132,8 @@ zprop_register_hidden(int prop, const ch
     zprop_attr_t attr, int objset_types, const char *colname)
 {
 	zprop_register_impl(prop, name, type, 0, NULL, attr,
-	    objset_types, NULL, colname, B_FALSE, B_FALSE, NULL);
+	    objset_types, NULL, colname,
+	    type == PROP_TYPE_NUMBER, B_FALSE, NULL);
 }
 
 

Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_objset.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_objset.c	Wed Jul 18 10:46:31 2012	(r238589)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_objset.c	Wed Jul 18 10:51:11 2012	(r238590)
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 /* Portions Copyright 2010 Robert Milkowski */
@@ -699,30 +700,33 @@ dmu_objset_create_sync(void *arg1, void 
 	spa_t *spa = dd->dd_pool->dp_spa;
 	struct oscarg *oa = arg2;
 	uint64_t obj;
+	dsl_dataset_t *ds;
+	blkptr_t *bp;
 
 	ASSERT(dmu_tx_is_syncing(tx));
 
 	obj = dsl_dataset_create_sync(dd, oa->lastname,
 	    oa->clone_origin, oa->flags, oa->cr, tx);
 
-	if (oa->clone_origin == NULL) {
-		dsl_pool_t *dp = dd->dd_pool;
-		dsl_dataset_t *ds;
-		blkptr_t *bp;
-		objset_t *os;
-
-		VERIFY3U(0, ==, dsl_dataset_hold_obj(dp, obj, FTAG, &ds));
-		bp = dsl_dataset_get_blkptr(ds);
-		ASSERT(BP_IS_HOLE(bp));
-
-		os = dmu_objset_create_impl(spa, ds, bp, oa->type, tx);
+	VERIFY3U(0, ==, dsl_dataset_hold_obj(dd->dd_pool, obj, FTAG, &ds));
+	bp = dsl_dataset_get_blkptr(ds);
+	if (BP_IS_HOLE(bp)) {
+		objset_t *os =
+		    dmu_objset_create_impl(spa, ds, bp, oa->type, tx);
 
 		if (oa->userfunc)
 			oa->userfunc(os, oa->userarg, oa->cr, tx);
-		dsl_dataset_rele(ds, FTAG);
 	}
 
-	spa_history_log_internal(LOG_DS_CREATE, spa, tx, "dataset = %llu", obj);
+	if (oa->clone_origin == NULL) {
+		spa_history_log_internal_ds(ds, "create", tx, "");
+	} else {
+		char namebuf[MAXNAMELEN];
+		dsl_dataset_name(oa->clone_origin, namebuf);
+		spa_history_log_internal_ds(ds, "clone", tx,
+		    "origin=%s (%llu)", namebuf, oa->clone_origin->ds_object);
+	}
+	dsl_dataset_rele(ds, FTAG);
 }
 
 int
@@ -799,34 +803,40 @@ dmu_objset_destroy(const char *name, boo
 	return (error);
 }
 
-struct snaparg {
-	dsl_sync_task_group_t *dstg;
-	char *snapname;
-	char *htag;
-	char failed[MAXPATHLEN];
-	boolean_t recursive;
-	boolean_t needsuspend;
-	boolean_t temporary;
-	nvlist_t *props;
-	struct dsl_ds_holdarg *ha;	/* only needed in the temporary case */
-	dsl_dataset_t *newds;
-};
+typedef struct snapallarg {
+	dsl_sync_task_group_t *saa_dstg;
+	boolean_t saa_needsuspend;
+	nvlist_t *saa_props;
+
+	/* the following are used only if 'temporary' is set: */
+	boolean_t saa_temporary;
+	const char *saa_htag;
+	struct dsl_ds_holdarg *saa_ha;
+	dsl_dataset_t *saa_newds;
+} snapallarg_t;
+
+typedef struct snaponearg {
+	const char *soa_longname; /* long snap name */
+	const char *soa_snapname; /* short snap name */
+	snapallarg_t *soa_saa;
+} snaponearg_t;
 
 static int
 snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
 {
 	objset_t *os = arg1;
-	struct snaparg *sn = arg2;
+	snaponearg_t *soa = arg2;
+	snapallarg_t *saa = soa->soa_saa;
 	int error;
 
 	/* The props have already been checked by zfs_check_userprops(). */
 
 	error = dsl_dataset_snapshot_check(os->os_dsl_dataset,
-	    sn->snapname, tx);
+	    soa->soa_snapname, tx);
 	if (error)
 		return (error);
 
-	if (sn->temporary) {
+	if (saa->saa_temporary) {
 		/*
 		 * Ideally we would just call
 		 * dsl_dataset_user_hold_check() and
@@ -844,12 +854,13 @@ snapshot_check(void *arg1, void *arg2, d
 		 * Not checking number of tags because the tag will be
 		 * unique, as it will be the only tag.
 		 */
-		if (strlen(sn->htag) + MAX_TAG_PREFIX_LEN >= MAXNAMELEN)
+		if (strlen(saa->saa_htag) + MAX_TAG_PREFIX_LEN >= MAXNAMELEN)
 			return (E2BIG);
 
-		sn->ha = kmem_alloc(sizeof (struct dsl_ds_holdarg), KM_SLEEP);
-		sn->ha->temphold = B_TRUE;
-		sn->ha->htag = sn->htag;
+		saa->saa_ha = kmem_alloc(sizeof (struct dsl_ds_holdarg),
+		    KM_SLEEP);
+		saa->saa_ha->temphold = B_TRUE;
+		saa->saa_ha->htag = saa->saa_htag;
 	}
 	return (error);
 }
@@ -859,24 +870,25 @@ snapshot_sync(void *arg1, void *arg2, dm
 {
 	objset_t *os = arg1;
 	dsl_dataset_t *ds = os->os_dsl_dataset;
-	struct snaparg *sn = arg2;
+	snaponearg_t *soa = arg2;
+	snapallarg_t *saa = soa->soa_saa;
 
-	dsl_dataset_snapshot_sync(ds, sn->snapname, tx);
+	dsl_dataset_snapshot_sync(ds, soa->soa_snapname, tx);
 
-	if (sn->props) {
+	if (saa->saa_props != NULL) {
 		dsl_props_arg_t pa;
-		pa.pa_props = sn->props;
+		pa.pa_props = saa->saa_props;
 		pa.pa_source = ZPROP_SRC_LOCAL;
 		dsl_props_set_sync(ds->ds_prev, &pa, tx);
 	}
 
-	if (sn->temporary) {
+	if (saa->saa_temporary) {
 		struct dsl_ds_destroyarg da;
 
-		dsl_dataset_user_hold_sync(ds->ds_prev, sn->ha, tx);
-		kmem_free(sn->ha, sizeof (struct dsl_ds_holdarg));
-		sn->ha = NULL;
-		sn->newds = ds->ds_prev;
+		dsl_dataset_user_hold_sync(ds->ds_prev, saa->saa_ha, tx);
+		kmem_free(saa->saa_ha, sizeof (struct dsl_ds_holdarg));
+		saa->saa_ha = NULL;
+		saa->saa_newds = ds->ds_prev;
 
 		da.ds = ds->ds_prev;
 		da.defer = B_TRUE;
@@ -885,131 +897,180 @@ snapshot_sync(void *arg1, void *arg2, dm
 }
 
 static int
-dmu_objset_snapshot_one(const char *name, void *arg)
+snapshot_one_impl(const char *snapname, void *arg)
 {
-	struct snaparg *sn = arg;
+	char fsname[MAXPATHLEN];
+	snapallarg_t *saa = arg;
+	snaponearg_t *soa;
 	objset_t *os;
 	int err;
-	char *cp;
 
-	/*
-	 * If the objset starts with a '%', then ignore it unless it was
-	 * explicitly named (ie, not recursive).  These hidden datasets
-	 * are always inconsistent, and by not opening them here, we can
-	 * avoid a race with dsl_dir_destroy_check().
-	 */
-	cp = strrchr(name, '/');
-	if (cp && cp[1] == '%' && sn->recursive)
-		return (0);
-
-	(void) strcpy(sn->failed, name);
-
-	/*
-	 * Check permissions if we are doing a recursive snapshot.  The
-	 * permission checks for the starting dataset have already been
-	 * performed in zfs_secpolicy_snapshot()
-	 */
-	if (sn->recursive && (err = zfs_secpolicy_snapshot_perms(name, CRED())))
-		return (err);
+	(void) strlcpy(fsname, snapname, sizeof (fsname));
+	strchr(fsname, '@')[0] = '\0';
 
-	err = dmu_objset_hold(name, sn, &os);
+	err = dmu_objset_hold(fsname, saa, &os);
 	if (err != 0)
 		return (err);
 
 	/*
 	 * If the objset is in an inconsistent state (eg, in the process
-	 * of being destroyed), don't snapshot it.  As with %hidden
-	 * datasets, we return EBUSY if this name was explicitly
-	 * requested (ie, not recursive), and otherwise ignore it.
+	 * of being destroyed), don't snapshot it.
 	 */
 	if (os->os_dsl_dataset->ds_phys->ds_flags & DS_FLAG_INCONSISTENT) {
-		dmu_objset_rele(os, sn);
-		return (sn->recursive ? 0 : EBUSY);
+		dmu_objset_rele(os, saa);
+		return (EBUSY);
 	}
 
-	if (sn->needsuspend) {
+	if (saa->saa_needsuspend) {
 		err = zil_suspend(dmu_objset_zil(os));
 		if (err) {
-			dmu_objset_rele(os, sn);
+			dmu_objset_rele(os, saa);
 			return (err);
 		}
 	}
-	dsl_sync_task_create(sn->dstg, snapshot_check, snapshot_sync,
-	    os, sn, 3);
+
+	soa = kmem_zalloc(sizeof (*soa), KM_SLEEP);
+	soa->soa_saa = saa;
+	soa->soa_longname = snapname;
+	soa->soa_snapname = strchr(snapname, '@') + 1;
+
+	dsl_sync_task_create(saa->saa_dstg, snapshot_check, snapshot_sync,
+	    os, soa, 3);
 
 	return (0);
 }
 
+/*
+ * The snapshots must all be in the same pool.
+ */
 int
-dmu_objset_snapshot(char *fsname, char *snapname, char *tag,
-    nvlist_t *props, boolean_t recursive, boolean_t temporary, int cleanup_fd)
+dmu_objset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors)
 {
 	dsl_sync_task_t *dst;
-	struct snaparg sn;
+	snapallarg_t saa = { 0 };
 	spa_t *spa;
-	minor_t minor;
+	int rv = 0;
 	int err;
+	nvpair_t *pair;
 
-	(void) strcpy(sn.failed, fsname);
+	pair = nvlist_next_nvpair(snaps, NULL);
+	if (pair == NULL)
+		return (0);
 
-	err = spa_open(fsname, &spa, FTAG);
+	err = spa_open(nvpair_name(pair), &spa, FTAG);
 	if (err)
 		return (err);
-
-	if (temporary) {
-		if (cleanup_fd < 0) {
-			spa_close(spa, FTAG);
-			return (EINVAL);
+	saa.saa_dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
+	saa.saa_props = props;
+	saa.saa_needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
+
+	for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
+	    pair = nvlist_next_nvpair(snaps, pair)) {
+		err = snapshot_one_impl(nvpair_name(pair), &saa);
+		if (err != 0) {
+			if (errors != NULL) {
+				fnvlist_add_int32(errors,
+				    nvpair_name(pair), err);
+			}
+			rv = err;
 		}
-		if ((err = zfs_onexit_fd_hold(cleanup_fd, &minor)) != 0) {
-			spa_close(spa, FTAG);
-			return (err);
+	}
+
+	/*
+	 * If any call to snapshot_one_impl() failed, don't execute the
+	 * sync task.  The error handling code below will clean up the
+	 * snaponearg_t from any successful calls to
+	 * snapshot_one_impl().
+	 */
+	if (rv == 0)
+		err = dsl_sync_task_group_wait(saa.saa_dstg);
+	if (err != 0)
+		rv = err;
+
+	for (dst = list_head(&saa.saa_dstg->dstg_tasks); dst;
+	    dst = list_next(&saa.saa_dstg->dstg_tasks, dst)) {
+		objset_t *os = dst->dst_arg1;
+		snaponearg_t *soa = dst->dst_arg2;
+		if (dst->dst_err != 0) {
+			if (errors != NULL) {
+				fnvlist_add_int32(errors,
+				    soa->soa_longname, dst->dst_err);
+			}
+			rv = dst->dst_err;
 		}
+
+		if (saa.saa_needsuspend)
+			zil_resume(dmu_objset_zil(os));
+		dmu_objset_rele(os, &saa);
+		kmem_free(soa, sizeof (*soa));
 	}
 
-	sn.dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
-	sn.snapname = snapname;
-	sn.htag = tag;
-	sn.props = props;
-	sn.recursive = recursive;
-	sn.needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
-	sn.temporary = temporary;
-	sn.ha = NULL;
-	sn.newds = NULL;
-
-	if (recursive) {
-		err = dmu_objset_find(fsname,
-		    dmu_objset_snapshot_one, &sn, DS_FIND_CHILDREN);
-	} else {
-		err = dmu_objset_snapshot_one(fsname, &sn);
+	dsl_sync_task_group_destroy(saa.saa_dstg);
+	spa_close(spa, FTAG);
+	return (rv);
+}
+
+int
+dmu_objset_snapshot_one(const char *fsname, const char *snapname)
+{
+	int err;
+	char *longsnap = kmem_asprintf("%s@%s", fsname, snapname);
+	nvlist_t *snaps = fnvlist_alloc();
+
+	fnvlist_add_boolean(snaps, longsnap);
+	err = dmu_objset_snapshot(snaps, NULL, NULL);
+	fnvlist_free(snaps);
+	strfree(longsnap);
+	return (err);
+}
+
+int
+dmu_objset_snapshot_tmp(const char *snapname, const char *tag, int cleanup_fd)
+{
+	dsl_sync_task_t *dst;
+	snapallarg_t saa = { 0 };
+	spa_t *spa;
+	minor_t minor;
+	int err;
+
+	err = spa_open(snapname, &spa, FTAG);
+	if (err)
+		return (err);
+	saa.saa_dstg = dsl_sync_task_group_create(spa_get_dsl(spa));
+	saa.saa_htag = tag;
+	saa.saa_needsuspend = (spa_version(spa) < SPA_VERSION_FAST_SNAP);
+	saa.saa_temporary = B_TRUE;
+
+	if (cleanup_fd < 0) {
+		spa_close(spa, FTAG);
+		return (EINVAL);
+	}
+	if ((err = zfs_onexit_fd_hold(cleanup_fd, &minor)) != 0) {
+		spa_close(spa, FTAG);
+		return (err);
 	}
 
+	err = snapshot_one_impl(snapname, &saa);
+
 	if (err == 0)
-		err = dsl_sync_task_group_wait(sn.dstg);
+		err = dsl_sync_task_group_wait(saa.saa_dstg);
 
-	for (dst = list_head(&sn.dstg->dstg_tasks); dst;
-	    dst = list_next(&sn.dstg->dstg_tasks, dst)) {
+	for (dst = list_head(&saa.saa_dstg->dstg_tasks); dst;
+	    dst = list_next(&saa.saa_dstg->dstg_tasks, dst)) {
 		objset_t *os = dst->dst_arg1;
-		dsl_dataset_t *ds = os->os_dsl_dataset;
-		if (dst->dst_err) {
-			dsl_dataset_name(ds, sn.failed);
-		} else if (temporary) {
-			dsl_register_onexit_hold_cleanup(sn.newds, tag, minor);
-		}
-		if (sn.needsuspend)
+		dsl_register_onexit_hold_cleanup(saa.saa_newds, tag, minor);
+		if (saa.saa_needsuspend)
 			zil_resume(dmu_objset_zil(os));
-		dmu_objset_rele(os, &sn);
+		dmu_objset_rele(os, &saa);
 	}
 
-	if (err)
-		(void) strcpy(fsname, sn.failed);
-	if (temporary)
-		zfs_onexit_fd_rele(cleanup_fd);
-	dsl_sync_task_group_destroy(sn.dstg);
+	zfs_onexit_fd_rele(cleanup_fd);
+	dsl_sync_task_group_destroy(saa.saa_dstg);
 	spa_close(spa, FTAG);
 	return (err);
 }
 
+
 static void
 dmu_objset_sync_dnodes(list_t *list, list_t *newlist, dmu_tx_t *tx)
 {

Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_send.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_send.c	Wed Jul 18 10:46:31 2012	(r238589)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_send.c	Wed Jul 18 10:51:11 2012	(r238590)
@@ -387,9 +387,48 @@ backup_cb(spa_t *spa, zilog_t *zilog, co
 	return (err);
 }
 
+/*
+ * Return TRUE if 'earlier' is an earlier snapshot in 'later's timeline.
+ * For example, they could both be snapshots of the same filesystem, and
+ * 'earlier' is before 'later'.  Or 'earlier' could be the origin of
+ * 'later's filesystem.  Or 'earlier' could be an older snapshot in the origin's
+ * filesystem.  Or 'earlier' could be the origin's origin.
+ */
+static boolean_t
+is_before(dsl_dataset_t *later, dsl_dataset_t *earlier)
+{
+	dsl_pool_t *dp = later->ds_dir->dd_pool;
+	int error;
+	boolean_t ret;
+	dsl_dataset_t *origin;
+
+	if (earlier->ds_phys->ds_creation_txg >=
+	    later->ds_phys->ds_creation_txg)
+		return (B_FALSE);
+
+	if (later->ds_dir == earlier->ds_dir)
+		return (B_TRUE);
+	if (!dsl_dir_is_clone(later->ds_dir))
+		return (B_FALSE);
+
+	rw_enter(&dp->dp_config_rwlock, RW_READER);
+	if (later->ds_dir->dd_phys->dd_origin_obj == earlier->ds_object) {
+		rw_exit(&dp->dp_config_rwlock);
+		return (B_TRUE);
+	}
+	error = dsl_dataset_hold_obj(dp,
+	    later->ds_dir->dd_phys->dd_origin_obj, FTAG, &origin);
+	rw_exit(&dp->dp_config_rwlock);
+	if (error != 0)
+		return (B_FALSE);
+	ret = is_before(origin, earlier);
+	dsl_dataset_rele(origin, FTAG);
+	return (ret);
+}
+
 int
-dmu_send(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
-    int outfd, vnode_t *vp, offset_t *off)
+dmu_send(objset_t *tosnap, objset_t *fromsnap, int outfd, vnode_t *vp,
+    offset_t *off)
 {
 	dsl_dataset_t *ds = tosnap->os_dsl_dataset;
 	dsl_dataset_t *fromds = fromsnap ? fromsnap->os_dsl_dataset : NULL;
@@ -402,30 +441,13 @@ dmu_send(objset_t *tosnap, objset_t *fro
 	if (ds->ds_phys->ds_next_snap_obj == 0)
 		return (EINVAL);
 
-	/* fromsnap must be an earlier snapshot from the same fs as tosnap */
-	if (fromds && (ds->ds_dir != fromds->ds_dir ||
-	    fromds->ds_phys->ds_creation_txg >= ds->ds_phys->ds_creation_txg))
+	/*
+	 * fromsnap must be an earlier snapshot from the same fs as tosnap,
+	 * or the origin's fs.
+	 */
+	if (fromds != NULL && !is_before(ds, fromds))
 		return (EXDEV);
 
-	if (fromorigin) {
-		dsl_pool_t *dp = ds->ds_dir->dd_pool;
-
-		if (fromsnap)
-			return (EINVAL);
-
-		if (dsl_dir_is_clone(ds->ds_dir)) {
-			rw_enter(&dp->dp_config_rwlock, RW_READER);
-			err = dsl_dataset_hold_obj(dp,
-			    ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &fromds);
-			rw_exit(&dp->dp_config_rwlock);
-			if (err)
-				return (err);
-		} else {
-			fromorigin = B_FALSE;
-		}
-	}
-
-
 	drr = kmem_zalloc(sizeof (dmu_replay_record_t), KM_SLEEP);
 	drr->drr_type = DRR_BEGIN;
 	drr->drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC;
@@ -450,7 +472,7 @@ dmu_send(objset_t *tosnap, objset_t *fro
 	drr->drr_u.drr_begin.drr_creation_time =
 	    ds->ds_phys->ds_creation_time;
 	drr->drr_u.drr_begin.drr_type = tosnap->os_phys->os_type;
-	if (fromorigin)
+	if (fromds != NULL && ds->ds_dir != fromds->ds_dir)
 		drr->drr_u.drr_begin.drr_flags |= DRR_FLAG_CLONE;
 	drr->drr_u.drr_begin.drr_toguid = ds->ds_phys->ds_guid;
 	if (ds->ds_phys->ds_flags & DS_FLAG_CI_DATASET)
@@ -462,8 +484,6 @@ dmu_send(objset_t *tosnap, objset_t *fro
 
 	if (fromds)
 		fromtxg = fromds->ds_phys->ds_creation_txg;
-	if (fromorigin)
-		dsl_dataset_rele(fromds, FTAG);
 
 	dsp = kmem_zalloc(sizeof (dmu_sendarg_t), KM_SLEEP);
 
@@ -521,8 +541,7 @@ out:
 }
 
 int
-dmu_send_estimate(objset_t *tosnap, objset_t *fromsnap, boolean_t fromorigin,
-    uint64_t *sizep)
+dmu_send_estimate(objset_t *tosnap, objset_t *fromsnap, uint64_t *sizep)
 {
 	dsl_dataset_t *ds = tosnap->os_dsl_dataset;
 	dsl_dataset_t *fromds = fromsnap ? fromsnap->os_dsl_dataset : NULL;
@@ -534,27 +553,13 @@ dmu_send_estimate(objset_t *tosnap, objs
 	if (ds->ds_phys->ds_next_snap_obj == 0)
 		return (EINVAL);
 
-	/* fromsnap must be an earlier snapshot from the same fs as tosnap */
-	if (fromds && (ds->ds_dir != fromds->ds_dir ||
-	    fromds->ds_phys->ds_creation_txg >= ds->ds_phys->ds_creation_txg))
+	/*
+	 * fromsnap must be an earlier snapshot from the same fs as tosnap,
+	 * or the origin's fs.
+	 */
+	if (fromds != NULL && !is_before(ds, fromds))
 		return (EXDEV);
 
-	if (fromorigin) {
-		if (fromsnap)
-			return (EINVAL);
-
-		if (dsl_dir_is_clone(ds->ds_dir)) {
-			rw_enter(&dp->dp_config_rwlock, RW_READER);
-			err = dsl_dataset_hold_obj(dp,
-			    ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &fromds);
-			rw_exit(&dp->dp_config_rwlock);
-			if (err)
-				return (err);
-		} else {
-			fromorigin = B_FALSE;
-		}
-	}
-
 	/* Get uncompressed size estimate of changed data. */
 	if (fromds == NULL) {
 		size = ds->ds_phys->ds_uncompressed_bytes;
@@ -562,8 +567,6 @@ dmu_send_estimate(objset_t *tosnap, objs
 		uint64_t used, comp;
 		err = dsl_dataset_space_written(fromds, ds,
 		    &used, &comp, &size);
-		if (fromorigin)
-			dsl_dataset_rele(fromds, FTAG);
 		if (err)
 			return (err);
 	}
@@ -662,8 +665,7 @@ recv_new_sync(void *arg1, void *arg2, dm
 		    rbsa->ds, &rbsa->ds->ds_phys->ds_bp, rbsa->type, tx);
 	}
 
-	spa_history_log_internal(LOG_DS_REPLAY_FULL_SYNC,
-	    dd->dd_pool->dp_spa, tx, "dataset = %lld", dsobj);
+	spa_history_log_internal_ds(rbsa->ds, "receive new", tx, "");
 }
 
 /* ARGSUSED */
@@ -764,8 +766,7 @@ recv_existing_sync(void *arg1, void *arg
 
 	rbsa->ds = cds;
 
-	spa_history_log_internal(LOG_DS_REPLAY_INC_SYNC,
-	    dp->dp_spa, tx, "dataset = %lld", dsobj);
+	spa_history_log_internal_ds(cds, "receive over existing", tx, "");
 }
 
 static boolean_t
@@ -1573,6 +1574,7 @@ recv_end_sync(void *arg1, void *arg2, dm
 
 	dmu_buf_will_dirty(ds->ds_dbuf, tx);
 	ds->ds_phys->ds_flags &= ~DS_FLAG_INCONSISTENT;
+	spa_history_log_internal_ds(ds, "finished receiving", tx, "");
 }
 
 static int

Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_tx.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_tx.c	Wed Jul 18 10:46:31 2012	(r238589)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/dmu_tx.c	Wed Jul 18 10:51:11 2012	(r238590)
@@ -48,7 +48,7 @@ dmu_tx_create_dd(dsl_dir_t *dd)
 {
 	dmu_tx_t *tx = kmem_zalloc(sizeof (dmu_tx_t), KM_SLEEP);
 	tx->tx_dir = dd;
-	if (dd)
+	if (dd != NULL)
 		tx->tx_pool = dd->dd_pool;
 	list_create(&tx->tx_holds, sizeof (dmu_tx_hold_t),
 	    offsetof(dmu_tx_hold_t, txh_node));

Modified: vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_dataset.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_dataset.c	Wed Jul 18 10:46:31 2012	(r238589)
+++ vendor-sys/illumos/dist/uts/common/fs/zfs/dsl_dataset.c	Wed Jul 18 10:51:11 2012	(r238590)
@@ -914,7 +914,8 @@ dsl_dataset_create_sync(dsl_dir_t *pdd, 
  * The snapshots must all be in the same pool.
  */
 int
-dmu_snapshots_destroy_nvl(nvlist_t *snaps, boolean_t defer, char *failed)
+dmu_snapshots_destroy_nvl(nvlist_t *snaps, boolean_t defer,
+    nvlist_t *errlist)
 {
 	int err;
 	dsl_sync_task_t *dst;
@@ -949,7 +950,7 @@ dmu_snapshots_destroy_nvl(nvlist_t *snap
 		} else if (err == ENOENT) {
 			err = 0;
 		} else {
-			(void) strcpy(failed, nvpair_name(pair));
+			fnvlist_add_int32(errlist, nvpair_name(pair), err);
 			break;
 		}
 	}
@@ -963,10 +964,12 @@ dmu_snapshots_destroy_nvl(nvlist_t *snap
 		dsl_dataset_t *ds = dsda->ds;
 
 		/*
-		 * Return the file system name that triggered the error
+		 * Return the snapshots that triggered the error.
 		 */
-		if (dst->dst_err) {
-			dsl_dataset_name(ds, failed);
+		if (dst->dst_err != 0) {
+			char name[ZFS_MAXNAMELEN];
+			dsl_dataset_name(ds, name);
+			fnvlist_add_int32(errlist, name, dst->dst_err);
 		}
 		ASSERT3P(dsda->rm_origin, ==, NULL);
 		dsl_dataset_disown(ds, dstg);
@@ -1045,7 +1048,6 @@ dsl_dataset_destroy(dsl_dataset_t *ds, v
 	dsl_dir_t *dd;
 	uint64_t obj;
 	struct dsl_ds_destroyarg dsda = { 0 };
-	dsl_dataset_t dummy_ds = { 0 };
 
 	dsda.ds = ds;
 
@@ -1065,8 +1067,6 @@ dsl_dataset_destroy(dsl_dataset_t *ds, v
 	}
 
 	dd = ds->ds_dir;
-	dummy_ds.ds_dir = dd;
-	dummy_ds.ds_object = ds->ds_object;
 
 	/*
 	 * Check for errors and mark this ds as inconsistent, in
@@ -1153,7 +1153,7 @@ dsl_dataset_destroy(dsl_dataset_t *ds, v
 		dsl_sync_task_create(dstg, dsl_dataset_destroy_check,
 		    dsl_dataset_destroy_sync, &dsda, tag, 0);
 		dsl_sync_task_create(dstg, dsl_dir_destroy_check,
-		    dsl_dir_destroy_sync, &dummy_ds, FTAG, 0);
+		    dsl_dir_destroy_sync, dd, FTAG, 0);
 		err = dsl_sync_task_group_wait(dstg);
 		dsl_sync_task_group_destroy(dstg);
 
@@ -1328,14 +1328,12 @@ static void
 dsl_dataset_destroy_begin_sync(void *arg1, void *arg2, dmu_tx_t *tx)
 {
 	dsl_dataset_t *ds = arg1;
-	dsl_pool_t *dp = ds->ds_dir->dd_pool;
 
 	/* Mark it as inconsistent on-disk, in case we crash */
 	dmu_buf_will_dirty(ds->ds_dbuf, tx);
 	ds->ds_phys->ds_flags |= DS_FLAG_INCONSISTENT;
 
-	spa_history_log_internal(LOG_DS_DESTROY_BEGIN, dp->dp_spa, tx,
-	    "dataset = %llu", ds->ds_object);
+	spa_history_log_internal_ds(ds, "destroy begin", tx, "");
 }
 
 static int
@@ -1660,9 +1658,13 @@ dsl_dataset_destroy_sync(void *arg1, voi
 		ASSERT(spa_version(dp->dp_spa) >= SPA_VERSION_USERREFS);
 		dmu_buf_will_dirty(ds->ds_dbuf, tx);
 		ds->ds_phys->ds_flags |= DS_FLAG_DEFER_DESTROY;
+		spa_history_log_internal_ds(ds, "defer_destroy", tx, "");
 		return;
 	}
 
+	/* We need to log before removing it from the namespace. */
+	spa_history_log_internal_ds(ds, "destroy", tx, "");
+
 	/* signal any waiters that this dataset is going away */
 	mutex_enter(&ds->ds_lock);
 	ds->ds_owner = dsl_reaper;
@@ -1957,8 +1959,6 @@ dsl_dataset_destroy_sync(void *arg1, voi
 		dsl_dataset_rele(ds_prev, FTAG);
 
 	spa_prop_clear_bootfs(dp->dp_spa, ds->ds_object, tx);
-	spa_history_log_internal(LOG_DS_DESTROY, dp->dp_spa, tx,
-	    "dataset = %llu", ds->ds_object);
 
 	if (ds->ds_phys->ds_next_clones_obj != 0) {
 		uint64_t count;
@@ -2006,7 +2006,7 @@ dsl_dataset_snapshot_reserve_space(dsl_d
 		return (ENOSPC);
 
 	/*
-	 * Propogate any reserved space for this snapshot to other
+	 * Propagate any reserved space for this snapshot to other
 	 * snapshot checks in this sync group.
 	 */
 	if (asize > 0)
@@ -2016,10 +2016,9 @@ dsl_dataset_snapshot_reserve_space(dsl_d
 }
 
 int
-dsl_dataset_snapshot_check(void *arg1, void *arg2, dmu_tx_t *tx)
+dsl_dataset_snapshot_check(dsl_dataset_t *ds, const char *snapname,
+    dmu_tx_t *tx)
 {
-	dsl_dataset_t *ds = arg1;
-	const char *snapname = arg2;
 	int err;
 	uint64_t value;
 
@@ -2031,7 +2030,7 @@ dsl_dataset_snapshot_check(void *arg1, v
 		return (EAGAIN);
 
 	/*
-	 * Check for conflicting name snapshot name.
+	 * Check for conflicting snapshot name.
 	 */
 	err = dsl_dataset_snap_lookup(ds, snapname, &value);
 	if (err == 0)
@@ -2055,10 +2054,9 @@ dsl_dataset_snapshot_check(void *arg1, v
 }
 
 void
-dsl_dataset_snapshot_sync(void *arg1, void *arg2, dmu_tx_t *tx)
+dsl_dataset_snapshot_sync(dsl_dataset_t *ds, const char *snapname,
+    dmu_tx_t *tx)
 {
-	dsl_dataset_t *ds = arg1;
-	const char *snapname = arg2;
 	dsl_pool_t *dp = ds->ds_dir->dd_pool;
 	dmu_buf_t *dbuf;
 	dsl_dataset_phys_t *dsphys;
@@ -2164,8 +2162,7 @@ dsl_dataset_snapshot_sync(void *arg1, vo
 
 	dsl_dir_snap_cmtime_update(ds->ds_dir);
 
-	spa_history_log_internal(LOG_DS_SNAPSHOT, dp->dp_spa, tx,
-	    "dataset = %llu", dsobj);
+	spa_history_log_internal_ds(ds->ds_prev, "snapshot", tx, "");
 }
 
 void
@@ -2252,7 +2249,20 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvl
 {
 	uint64_t refd, avail, uobjs, aobjs, ratio;
 
-	dsl_dir_stats(ds->ds_dir, nv);
+	ratio = ds->ds_phys->ds_compressed_bytes == 0 ? 100 :
+	    (ds->ds_phys->ds_uncompressed_bytes * 100 /
+	    ds->ds_phys->ds_compressed_bytes);
+
+	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRATIO, ratio);
+
+	if (dsl_dataset_is_snapshot(ds)) {
+		dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_COMPRESSRATIO, ratio);
+		dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USED,
+		    ds->ds_phys->ds_unique_bytes);
+		get_clones_stat(ds, nv);
+	} else {
+		dsl_dir_stats(ds->ds_dir, nv);
+	}
 
 	dsl_dataset_space(ds, &refd, &avail, &uobjs, &aobjs);
 	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_AVAILABLE, avail);
@@ -2297,22 +2307,6 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvl
 		}
 	}
 
-	ratio = ds->ds_phys->ds_compressed_bytes == 0 ? 100 :
-	    (ds->ds_phys->ds_uncompressed_bytes * 100 /
-	    ds->ds_phys->ds_compressed_bytes);
-	dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REFRATIO, ratio);
-
-	if (ds->ds_phys->ds_next_snap_obj) {
-		/*
-		 * This is a snapshot; override the dd's space used with
-		 * our unique space and compression ratio.
-		 */
-		dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_USED,
-		    ds->ds_phys->ds_unique_bytes);
-		dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_COMPRESSRATIO, ratio);
-
-		get_clones_stat(ds, nv);
-	}
 }
 
 void
@@ -2321,27 +2315,25 @@ dsl_dataset_fast_stat(dsl_dataset_t *ds,
 	stat->dds_creation_txg = ds->ds_phys->ds_creation_txg;
 	stat->dds_inconsistent = ds->ds_phys->ds_flags & DS_FLAG_INCONSISTENT;
 	stat->dds_guid = ds->ds_phys->ds_guid;
-	if (ds->ds_phys->ds_next_snap_obj) {
+	stat->dds_origin[0] = '\0';
+	if (dsl_dataset_is_snapshot(ds)) {
 		stat->dds_is_snapshot = B_TRUE;
 		stat->dds_num_clones = ds->ds_phys->ds_num_children - 1;
 	} else {
 		stat->dds_is_snapshot = B_FALSE;
 		stat->dds_num_clones = 0;
-	}
-
-	/* clone origin is really a dsl_dir thing... */
-	rw_enter(&ds->ds_dir->dd_pool->dp_config_rwlock, RW_READER);
-	if (dsl_dir_is_clone(ds->ds_dir)) {
-		dsl_dataset_t *ods;
 
-		VERIFY(0 == dsl_dataset_get_ref(ds->ds_dir->dd_pool,
-		    ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &ods));
-		dsl_dataset_name(ods, stat->dds_origin);
-		dsl_dataset_drop_ref(ods, FTAG);
-	} else {
-		stat->dds_origin[0] = '\0';
+		rw_enter(&ds->ds_dir->dd_pool->dp_config_rwlock, RW_READER);
+		if (dsl_dir_is_clone(ds->ds_dir)) {
+			dsl_dataset_t *ods;
+
+			VERIFY(0 == dsl_dataset_get_ref(ds->ds_dir->dd_pool,
+			    ds->ds_dir->dd_phys->dd_origin_obj, FTAG, &ods));
+			dsl_dataset_name(ods, stat->dds_origin);
+			dsl_dataset_drop_ref(ods, FTAG);
+		}
+		rw_exit(&ds->ds_dir->dd_pool->dp_config_rwlock);
 	}
-	rw_exit(&ds->ds_dir->dd_pool->dp_config_rwlock);
 }
 
 uint64_t
@@ -2458,8 +2450,8 @@ dsl_dataset_snapshot_rename_sync(void *a
 	    ds->ds_snapname, 8, 1, &ds->ds_object, tx);
 	ASSERT3U(err, ==, 0);
 
-	spa_history_log_internal(LOG_DS_RENAME, dd->dd_pool->dp_spa, tx,
-	    "dataset = %llu", ds->ds_object);
+	spa_history_log_internal_ds(ds, "rename", tx,
+	    "-> @%s", newsnapname);
 	dsl_dataset_rele(hds, FTAG);
 }
 
@@ -2939,8 +2931,7 @@ dsl_dataset_promote_sync(void *arg1, voi
 	origin_ds->ds_phys->ds_unique_bytes = pa->unique;
 
 	/* log history record */
-	spa_history_log_internal(LOG_DS_PROMOTE, dd->dd_pool->dp_spa, tx,
-	    "dataset = %llu", hds->ds_object);
+	spa_history_log_internal_ds(hds, "promote", tx, "");
 
 	dsl_dir_close(odd, FTAG);
 }
@@ -3298,6 +3289,9 @@ dsl_dataset_clone_swap_sync(void *arg1, 
 	    csa->ohds->ds_phys->ds_deadlist_obj);
 
 	dsl_scan_ds_clone_swapped(csa->ohds, csa->cds, tx);
+
+	spa_history_log_internal_ds(csa->cds, "clone swap", tx,
+	    "parent=%s", csa->ohds->ds_dir->dd_myname);
 }
 
 /*
@@ -3454,9 +3448,8 @@ dsl_dataset_set_quota_sync(void *arg1, v
 		dmu_buf_will_dirty(ds->ds_dbuf, tx);
 		ds->ds_quota = effective_value;
 
-		spa_history_log_internal(LOG_DS_REFQUOTA,
-		    ds->ds_dir->dd_pool->dp_spa, tx, "%lld dataset = %llu ",
-		    (longlong_t)ds->ds_quota, ds->ds_object);
+		spa_history_log_internal_ds(ds, "set refquota", tx,
+		    "refquota=%lld", (longlong_t)ds->ds_quota);
 	}
 }
 
@@ -3561,9 +3554,8 @@ dsl_dataset_set_reservation_sync(void *a
 	dsl_dir_diduse_space(ds->ds_dir, DD_USED_REFRSRV, delta, 0, 0, tx);
 	mutex_exit(&ds->ds_dir->dd_lock);
 
-	spa_history_log_internal(LOG_DS_REFRESERV,
-	    ds->ds_dir->dd_pool->dp_spa, tx, "%lld dataset = %llu",
-	    (longlong_t)effective_value, ds->ds_object);
+	spa_history_log_internal_ds(ds, "set refreservation", tx,
+	    "refreservation=%lld", (longlong_t)effective_value);
 }
 
 int
@@ -3629,7 +3621,7 @@ dsl_dataset_user_hold_check(void *arg1, 
 {
 	dsl_dataset_t *ds = arg1;
 	struct dsl_ds_holdarg *ha = arg2;
-	char *htag = ha->htag;
+	const char *htag = ha->htag;
 	objset_t *mos = ds->ds_dir->dd_pool->dp_meta_objset;
 	int error = 0;
 
@@ -3663,7 +3655,7 @@ dsl_dataset_user_hold_sync(void *arg1, v
 {
 	dsl_dataset_t *ds = arg1;
 	struct dsl_ds_holdarg *ha = arg2;
-	char *htag = ha->htag;
+	const char *htag = ha->htag;
 	dsl_pool_t *dp = ds->ds_dir->dd_pool;
 	objset_t *mos = dp->dp_meta_objset;

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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201207181051.q6IApBGk062334>