svn commit: r207910 - in head: cddl/contrib/opensolaris/cmd/ztest sys/cddl/contrib/opensolaris/uts/common/fs/zfs

Martin Matuska mm at FreeBSD.org
Tue May 11 09:23:46 UTC 2010


Author: mm
Date: Tue May 11 09:23:46 2010
New Revision: 207910
URL: http://svn.freebsd.org/changeset/base/207910

Log:
  Fix possible panic with zfs destroy.
  
  OpenSolaris onnv revision:	8779:f164e0e90508
  
  PR:		kern/146471
  Approved by:	pjd, delphij (mentor)
  Obtained from:	OpenSolaris (Bug ID 6784924)
  MFC after:	3 days

Modified:
  head/cddl/contrib/opensolaris/cmd/ztest/ztest.c
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c

Modified: head/cddl/contrib/opensolaris/cmd/ztest/ztest.c
==============================================================================
--- head/cddl/contrib/opensolaris/cmd/ztest/ztest.c	Tue May 11 09:19:41 2010	(r207909)
+++ head/cddl/contrib/opensolaris/cmd/ztest/ztest.c	Tue May 11 09:23:46 2010	(r207910)
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -93,6 +93,7 @@
 #include <sys/vdev_file.h>
 #include <sys/spa_impl.h>
 #include <sys/dsl_prop.h>
+#include <sys/dsl_dataset.h>
 #include <sys/refcount.h>
 #include <stdio.h>
 #include <stdio_ext.h>
@@ -174,6 +175,7 @@ ztest_func_t ztest_traverse;
 ztest_func_t ztest_dsl_prop_get_set;
 ztest_func_t ztest_dmu_objset_create_destroy;
 ztest_func_t ztest_dmu_snapshot_create_destroy;
+ztest_func_t ztest_dsl_dataset_promote_busy;
 ztest_func_t ztest_spa_create_destroy;
 ztest_func_t ztest_fault_inject;
 ztest_func_t ztest_spa_rename;
@@ -208,6 +210,7 @@ ztest_info_t ztest_info[] = {
 	{ ztest_dsl_prop_get_set,		1,	&zopt_sometimes	},
 	{ ztest_dmu_objset_create_destroy,	1,	&zopt_sometimes },
 	{ ztest_dmu_snapshot_create_destroy,	1,	&zopt_sometimes },
+	{ ztest_dsl_dataset_promote_busy,	1,	&zopt_sometimes },
 	{ ztest_spa_create_destroy,		1,	&zopt_sometimes },
 	{ ztest_fault_inject,			1,	&zopt_sometimes	},
 	{ ztest_spa_rename,			1,	&zopt_rarely	},
@@ -1591,6 +1594,109 @@ ztest_traverse(ztest_args_t *za)
 }
 
 /*
+ * Verify dsl_dataset_promote handles EBUSY
+ */
+void
+ztest_dsl_dataset_promote_busy(ztest_args_t *za)
+{
+	int error;
+	objset_t *os = za->za_os;
+	objset_t *clone;
+	dsl_dataset_t *ds;
+	char snap1name[100];
+	char clone1name[100];
+	char snap2name[100];
+	char clone2name[100];
+	char snap3name[100];
+	char osname[MAXNAMELEN];
+	static uint64_t uniq = 0;
+	uint64_t curval;
+
+	curval = atomic_add_64_nv(&uniq, 5) - 5;
+
+	(void) rw_rdlock(&ztest_shared->zs_name_lock);
+
+	dmu_objset_name(os, osname);
+	(void) snprintf(snap1name, 100, "%s at s1_%llu", osname, curval++);
+	(void) snprintf(clone1name, 100, "%s/c1_%llu", osname, curval++);
+	(void) snprintf(snap2name, 100, "%s at s2_%llu", clone1name, curval++);
+	(void) snprintf(clone2name, 100, "%s/c2_%llu", osname, curval++);
+	(void) snprintf(snap3name, 100, "%s at s3_%llu", clone1name, curval++);
+
+	error = dmu_objset_snapshot(osname, strchr(snap1name, '@')+1, FALSE);
+	if (error == ENOSPC)
+		ztest_record_enospc("dmu_take_snapshot");
+	else if (error != 0 && error != EEXIST)
+		fatal(0, "dmu_take_snapshot = %d", error);
+
+	error = dmu_objset_open(snap1name, DMU_OST_OTHER,
+	    DS_MODE_USER | DS_MODE_READONLY, &clone);
+	if (error)
+		fatal(0, "dmu_open_snapshot(%s) = %d", snap1name, error);
+
+	error = dmu_objset_create(clone1name, DMU_OST_OTHER, clone, 0,
+	    NULL, NULL);
+	if (error)
+		fatal(0, "dmu_objset_create(%s) = %d", clone1name, error);
+	dmu_objset_close(clone);
+
+	error = dmu_objset_snapshot(clone1name, strchr(snap2name, '@')+1,
+	    FALSE);
+	if (error == ENOSPC)
+		ztest_record_enospc("dmu_take_snapshot");
+	else if (error != 0 && error != EEXIST)
+		fatal(0, "dmu_take_snapshot = %d", error);
+
+	error = dmu_objset_snapshot(clone1name, strchr(snap3name, '@')+1,
+	    FALSE);
+	if (error == ENOSPC)
+		ztest_record_enospc("dmu_take_snapshot");
+	else if (error != 0 && error != EEXIST)
+		fatal(0, "dmu_take_snapshot = %d", error);
+
+	error = dmu_objset_open(snap3name, DMU_OST_OTHER,
+	    DS_MODE_USER | DS_MODE_READONLY, &clone);
+	if (error)
+		fatal(0, "dmu_open_snapshot(%s) = %d", snap3name, error);
+
+	error = dmu_objset_create(clone2name, DMU_OST_OTHER, clone, 0,
+	    NULL, NULL);
+	if (error)
+		fatal(0, "dmu_objset_create(%s) = %d", clone2name, error);
+	dmu_objset_close(clone);
+
+	error = dsl_dataset_own(snap1name, 0, FTAG, &ds);
+	if (error)
+		fatal(0, "dsl_dataset_own(%s) = %d", snap1name, error);
+	error = dsl_dataset_promote(clone2name);
+	if (error != EBUSY)
+		fatal(0, "dsl_dataset_promote(%s), %d, not EBUSY", clone2name,
+		    error);
+	dsl_dataset_disown(ds, FTAG);
+
+	error = dmu_objset_destroy(clone2name);
+	if (error)
+		fatal(0, "dmu_objset_destroy(%s) = %d", clone2name, error);
+
+	error = dmu_objset_destroy(snap3name);
+	if (error)
+		fatal(0, "dmu_objset_destroy(%s) = %d", snap2name, error);
+
+	error = dmu_objset_destroy(snap2name);
+	if (error)
+		fatal(0, "dmu_objset_destroy(%s) = %d", snap2name, error);
+
+	error = dmu_objset_destroy(clone1name);
+	if (error)
+		fatal(0, "dmu_objset_destroy(%s) = %d", clone1name, error);
+	error = dmu_objset_destroy(snap1name);
+	if (error)
+		fatal(0, "dmu_objset_destroy(%s) = %d", snap1name, error);
+
+	(void) rw_unlock(&ztest_shared->zs_name_lock);
+}
+
+/*
  * Verify that dmu_object_{alloc,free} work as expected.
  */
 void

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c	Tue May 11 09:19:41 2010	(r207909)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c	Tue May 11 09:23:46 2010	(r207910)
@@ -554,6 +554,7 @@ dsl_dataset_own_obj(dsl_pool_t *dp, uint
 		return (err);
 	if (!dsl_dataset_tryown(*dsp, DS_MODE_IS_INCONSISTENT(flags), owner)) {
 		dsl_dataset_rele(*dsp, owner);
+		*dsp = NULL;
 		return (EBUSY);
 	}
 	return (0);
@@ -2584,7 +2585,7 @@ snaplist_destroy(list_t *l, boolean_t ow
 {
 	struct promotenode *snap;
 
-	if (!list_link_active(&l->list_head))
+	if (!l || !list_link_active(&l->list_head))
 		return;
 
 	while ((snap = list_tail(l)) != NULL) {


More information about the svn-src-all mailing list