>Number:         146471
>Category:       kern
>Synopsis:       [zfs] [patch] zfs bugfixes (6784757, 6784924, 6826861)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon May 10 15:50:01 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Martin Matuska
>Release:        FreeBSD 9-CURRENT amd64
>Organization:
>Environment:
>Description:
Fix OpenSolaris bugs #6784757, #6784924, #6826861

OpenSolaris revision 8517:41a0783dde17
6784757  zfs rename occasionally fails with ebusy

OpenSolaris revision 8779:f164e0e90508
6784924  panic while ludelete (zfs destroy)

OpenSolaris revision 9390:887948510f80
6826861  assertion failed in dsl_dataset_destroy_sync when "zfs destroy" old fs

Patch applies cleanly.

References:
http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6784757
http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6784924
http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6826861

>How-To-Repeat:
>Fix:
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c        
(revision 207846)
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c        
(working copy)
@@ -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.
  */
 
@@ -2205,6 +2205,12 @@
        err = dsl_dir_open(oldname, FTAG, &dd, &tail);
        if (err)
                return (err);
+       /*
+        * If there are more than 2 references there may be holds
+        * hanging around that haven't been cleared out yet.
+        */
+       if (dmu_buf_refcount(dd->dd_dbuf) > 2)
+               txg_wait_synced(dd->dd_pool, 0);
        if (tail == NULL) {
                int delta = strlen(newname) - strlen(oldname);
 
Index: cddl/contrib/opensolaris/cmd/ztest/ztest.c
===================================================================
--- cddl/contrib/opensolaris/cmd/ztest/ztest.c  (revision 207846)
+++ cddl/contrib/opensolaris/cmd/ztest/ztest.c  (working copy)
@@ -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_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_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 @@
 }
 
 /*
+ * 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, "%...@s1_%llu", osname, curval++);
+       (void) snprintf(clone1name, 100, "%s/c1_%llu", osname, curval++);
+       (void) snprintf(snap2name, 100, "%...@s2_%llu", clone1name, curval++);
+       (void) snprintf(clone2name, 100, "%s/c2_%llu", osname, curval++);
+       (void) snprintf(snap3name, 100, "%...@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
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c        
(revision 207846)
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c        
(working copy)
@@ -554,6 +554,7 @@
                return (err);
        if (!dsl_dataset_tryown(*dsp, DS_MODE_IS_INCONSISTENT(flags), owner)) {
                dsl_dataset_rele(*dsp, owner);
+               *dsp = NULL;
                return (EBUSY);
        }
        return (0);
@@ -2578,7 +2579,7 @@
 {
        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) {
Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c        
(revision 207846)
+++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c        
(working copy)
@@ -1267,8 +1267,7 @@
                (void) zio_wait(zio);
        }
 
-       ASSERT(!(ds->ds_phys->ds_flags & DS_FLAG_UNIQUE_ACCURATE) ||
-           ds->ds_phys->ds_unique_bytes == 0);
+       ASSERT(!DS_UNIQUE_IS_ACCURATE(ds) || ds->ds_phys->ds_unique_bytes == 0);
 
        if (ds->ds_prev && ds->ds_prev != ds->ds_dir->dd_pool->dp_origin_snap) {
                /* Change our contents to that of the prev snapshot */
@@ -1660,7 +1659,7 @@
                err = traverse_dsl_dataset(ds, ds->ds_phys->ds_prev_snap_txg,
                    ADVANCE_POST, kill_blkptr, &ka);
                ASSERT3U(err, ==, 0);
-               ASSERT(spa_version(dp->dp_spa) < SPA_VERSION_UNIQUE_ACCURATE ||
+               ASSERT(!DS_UNIQUE_IS_ACCURATE(ds) ||
                    ds->ds_phys->ds_unique_bytes == 0);
        }
 
>Release-Note:
>Audit-Trail:
>Unformatted:
_______________________________________________
freebsd-bugs@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"

Reply via email to