summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorek110237 <none@none>2008-02-26 11:31:49 -0800
committerek110237 <none@none>2008-02-26 11:31:49 -0800
commit47f263f4211a47222fcc65b18b0cfa06d33f3c33 (patch)
tree7d63bbf540ef2768fcd436574701f5a6e4118a89 /usr/src
parentd8ac9b2d669163fee52330a52017528035cacb4e (diff)
downloadillumos-joyent-47f263f4211a47222fcc65b18b0cfa06d33f3c33.tar.gz
6655963 Panic: 0 == zap_add(mos, pds->dd_phys->dd_child_dir_zapobj, name, sizeof (uint64_t), 1, &ddobj, tx)
6661137 simultaneous rollbacks can panic the system 6662714 panic: rrw_held(&zfsvfs->z_teardown_lock, RW_WRITER), file: ../../common/fs/zfs/zfs_vfsops.c
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/fs/zfs/dmu_send.c19
-rw-r--r--usr/src/uts/common/fs/zfs/sys/dmu.h3
-rw-r--r--usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h3
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_ioctl.c54
-rw-r--r--usr/src/uts/common/fs/zfs/zfs_vfsops.c34
5 files changed, 78 insertions, 35 deletions
diff --git a/usr/src/uts/common/fs/zfs/dmu_send.c b/usr/src/uts/common/fs/zfs/dmu_send.c
index 9ff2917fcb..7afbe38ee8 100644
--- a/usr/src/uts/common/fs/zfs/dmu_send.c
+++ b/usr/src/uts/common/fs/zfs/dmu_send.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -467,6 +467,15 @@ recv_incremental_check(void *arg1, void *arg2, dmu_tx_t *tx)
if (ds->ds_prev->ds_phys->ds_guid != rbsa->fromguid)
return (ENODEV);
+ /* temporary clone name must not exist */
+ err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset,
+ ds->ds_dir->dd_phys->dd_child_dir_zapobj,
+ rbsa->clonelastname, 8, 1, &val);
+ if (err == 0)
+ return (EEXIST);
+ if (err != ENOENT)
+ return (err);
+
/* new snapshot name must not exist */
err = zap_lookup(ds->ds_dir->dd_pool->dp_meta_objset,
ds->ds_phys->ds_snapnames_zapobj, rbsa->tosnap, 8, 1, &val);
@@ -963,8 +972,8 @@ restore_free(struct restorearg *ra, objset_t *os,
return (err);
}
-static void
-recv_abort_cleanup(dmu_recv_cookie_t *drc)
+void
+dmu_recv_abort_cleanup(dmu_recv_cookie_t *drc)
{
if (drc->drc_newfs || drc->drc_real_ds != drc->drc_logical_ds) {
/*
@@ -1124,7 +1133,7 @@ out:
* leave it in the restoring state.
*/
txg_wait_synced(drc->drc_real_ds->ds_dir->dd_pool, 0);
- recv_abort_cleanup(drc);
+ dmu_recv_abort_cleanup(drc);
}
kmem_free(ra.buf, ra.bufsize);
@@ -1182,7 +1191,7 @@ dmu_recv_end(dmu_recv_cookie_t *drc)
DS_MODE_PRIMARY, DS_MODE_EXCLUSIVE)) {
lmode = DS_MODE_EXCLUSIVE;
} else {
- recv_abort_cleanup(drc);
+ dmu_recv_abort_cleanup(drc);
return (EBUSY);
}
diff --git a/usr/src/uts/common/fs/zfs/sys/dmu.h b/usr/src/uts/common/fs/zfs/sys/dmu.h
index 216a906984..8391a09e42 100644
--- a/usr/src/uts/common/fs/zfs/sys/dmu.h
+++ b/usr/src/uts/common/fs/zfs/sys/dmu.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -605,6 +605,7 @@ int dmu_recv_begin(char *tofs, char *tosnap, struct drr_begin *,
boolean_t force, objset_t *origin, boolean_t online, dmu_recv_cookie_t *);
int dmu_recv_stream(dmu_recv_cookie_t *drc, struct vnode *vp, offset_t *voffp);
int dmu_recv_end(dmu_recv_cookie_t *drc);
+void dmu_recv_abort_cleanup(dmu_recv_cookie_t *drc);
/* CRC64 table */
#define ZFS_CRC64_POLY 0xC96C5795D7870F42ULL /* ECMA-182, reflected form */
diff --git a/usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h b/usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h
index 502e4f218b..87b75e6e75 100644
--- a/usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h
+++ b/usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h
@@ -74,7 +74,8 @@ struct zfsvfs {
boolean_t z_issnap; /* true if this is a snapshot */
boolean_t z_vscan; /* virus scan on/off */
boolean_t z_use_fuids; /* version allows fuids */
- uint64_t z_version;
+ kmutex_t z_online_recv_lock; /* recv in prog grabs as WRITER */
+ uint64_t z_version; /* ZPL version */
#define ZFS_OBJ_MTX_SZ 64
kmutex_t z_hold_mtx[ZFS_OBJ_MTX_SZ]; /* znode hold locks */
};
diff --git a/usr/src/uts/common/fs/zfs/zfs_ioctl.c b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
index 42b908f5a5..b5f8b87a83 100644
--- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c
+++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c
@@ -2186,11 +2186,17 @@ zfs_ioc_rollback(zfs_cmd_t *zc)
char osname[MAXNAMELEN];
int mode;
- VERIFY3U(0, ==, zfs_suspend_fs(zfsvfs, osname, &mode));
- ASSERT(strcmp(osname, zc->zc_name) == 0);
- error = dmu_objset_rollback(os);
- VERIFY3U(0, ==, zfs_resume_fs(zfsvfs, osname, mode));
+ error = zfs_suspend_fs(zfsvfs, osname, &mode);
+ if (error == 0) {
+ int resume_err;
+ ASSERT(strcmp(osname, zc->zc_name) == 0);
+ error = dmu_objset_rollback(os);
+ resume_err = zfs_resume_fs(zfsvfs, osname, mode);
+ error = error ? error : resume_err;
+ } else {
+ dmu_objset_close(os);
+ }
VFS_RELE(zfsvfs->z_vfs);
} else {
error = dmu_objset_rollback(os);
@@ -2294,9 +2300,19 @@ zfs_ioc_recv(zfs_cmd_t *zc)
if (!error) {
mutex_enter(&os->os->os_user_ptr_lock);
zfsvfs = dmu_objset_get_user(os);
- if (zfsvfs != NULL)
+ if (zfsvfs != NULL) {
VFS_HOLD(zfsvfs->z_vfs);
- mutex_exit(&os->os->os_user_ptr_lock);
+ mutex_exit(&os->os->os_user_ptr_lock);
+ if (!mutex_tryenter(&zfsvfs->z_online_recv_lock)) {
+ VFS_RELE(zfsvfs->z_vfs);
+ dmu_objset_close(os);
+ nvlist_free(props);
+ releasef(fd);
+ return (EBUSY);
+ }
+ } else {
+ mutex_exit(&os->os->os_user_ptr_lock);
+ }
dmu_objset_close(os);
}
@@ -2304,8 +2320,10 @@ zfs_ioc_recv(zfs_cmd_t *zc)
error = dmu_objset_open(zc->zc_string, DMU_OST_ANY,
DS_MODE_STANDARD | DS_MODE_READONLY, &origin);
if (error) {
- if (zfsvfs != NULL)
+ if (zfsvfs != NULL) {
+ mutex_exit(&zfsvfs->z_online_recv_lock);
VFS_RELE(zfsvfs->z_vfs);
+ }
nvlist_free(props);
releasef(fd);
return (error);
@@ -2317,8 +2335,10 @@ zfs_ioc_recv(zfs_cmd_t *zc)
if (origin)
dmu_objset_close(origin);
if (error) {
- if (zfsvfs != NULL)
+ if (zfsvfs != NULL) {
+ mutex_exit(&zfsvfs->z_online_recv_lock);
VFS_RELE(zfsvfs->z_vfs);
+ }
nvlist_free(props);
releasef(fd);
return (error);
@@ -2372,15 +2392,25 @@ zfs_ioc_recv(zfs_cmd_t *zc)
char osname[MAXNAMELEN];
int mode;
- (void) zfs_suspend_fs(zfsvfs, osname, &mode);
- error = dmu_recv_end(&drc);
- error |= zfs_resume_fs(zfsvfs, osname, mode);
+ error = zfs_suspend_fs(zfsvfs, osname, &mode);
+ if (error == 0) {
+ int resume_err;
+
+ error = dmu_recv_end(&drc);
+ resume_err = zfs_resume_fs(zfsvfs,
+ osname, mode);
+ error = error ? error : resume_err;
+ } else {
+ dmu_recv_abort_cleanup(&drc);
+ }
} else {
error = dmu_recv_end(&drc);
}
}
- if (zfsvfs != NULL)
+ if (zfsvfs != NULL) {
+ mutex_exit(&zfsvfs->z_online_recv_lock);
VFS_RELE(zfsvfs->z_vfs);
+ }
zc->zc_cookie = off - fp->f_offset;
if (VOP_SEEK(fp->f_vnode, fp->f_offset, &off, NULL) == 0)
diff --git a/usr/src/uts/common/fs/zfs/zfs_vfsops.c b/usr/src/uts/common/fs/zfs/zfs_vfsops.c
index d55dee5ae3..78cadaeff4 100644
--- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c
+++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -624,6 +624,18 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting)
return (0);
}
+static void
+zfs_freezfsvfs(zfsvfs_t *zfsvfs)
+{
+ mutex_destroy(&zfsvfs->z_znodes_lock);
+ mutex_destroy(&zfsvfs->z_online_recv_lock);
+ list_destroy(&zfsvfs->z_all_znodes);
+ rrw_destroy(&zfsvfs->z_teardown_lock);
+ rw_destroy(&zfsvfs->z_teardown_inactive_lock);
+ rw_destroy(&zfsvfs->z_fuid_lock);
+ kmem_free(zfsvfs, sizeof (zfsvfs_t));
+}
+
static int
zfs_domount(vfs_t *vfsp, char *osname, cred_t *cr)
{
@@ -650,6 +662,7 @@ zfs_domount(vfs_t *vfsp, char *osname, cred_t *cr)
zfsvfs->z_show_ctldir = ZFS_SNAPDIR_VISIBLE;
mutex_init(&zfsvfs->z_znodes_lock, NULL, MUTEX_DEFAULT, NULL);
+ mutex_init(&zfsvfs->z_online_recv_lock, NULL, MUTEX_DEFAULT, NULL);
list_create(&zfsvfs->z_all_znodes, sizeof (znode_t),
offsetof(znode_t, z_link_node));
rrw_init(&zfsvfs->z_teardown_lock);
@@ -738,12 +751,7 @@ out:
if (error) {
if (zfsvfs->z_os)
dmu_objset_close(zfsvfs->z_os);
- mutex_destroy(&zfsvfs->z_znodes_lock);
- list_destroy(&zfsvfs->z_all_znodes);
- rrw_destroy(&zfsvfs->z_teardown_lock);
- rw_destroy(&zfsvfs->z_teardown_inactive_lock);
- rw_destroy(&zfsvfs->z_fuid_lock);
- kmem_free(zfsvfs, sizeof (zfsvfs_t));
+ zfs_freezfsvfs(zfsvfs);
} else {
atomic_add_32(&zfs_active_fs_count, 1);
}
@@ -1145,7 +1153,6 @@ zfs_root(vfs_t *vfsp, vnode_t **vpp)
static int
zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
{
- objset_t *os = zfsvfs->z_os;
znode_t *zp;
rrw_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG);
@@ -1225,9 +1232,9 @@ zfsvfs_teardown(zfsvfs_t *zfsvfs, boolean_t unmounting)
/*
* Evict cached data
*/
- if (dmu_objset_evict_dbufs(os)) {
+ if (dmu_objset_evict_dbufs(zfsvfs->z_os)) {
txg_wait_synced(dmu_objset_pool(zfsvfs->z_os), 0);
- (void) dmu_objset_evict_dbufs(os);
+ (void) dmu_objset_evict_dbufs(zfsvfs->z_os);
}
return (0);
@@ -1482,13 +1489,8 @@ zfs_freevfs(vfs_t *vfsp)
for (i = 0; i != ZFS_OBJ_MTX_SZ; i++)
mutex_destroy(&zfsvfs->z_hold_mtx[i]);
- mutex_destroy(&zfsvfs->z_znodes_lock);
- list_destroy(&zfsvfs->z_all_znodes);
- rrw_destroy(&zfsvfs->z_teardown_lock);
- rw_destroy(&zfsvfs->z_teardown_inactive_lock);
zfs_fuid_destroy(zfsvfs);
- rw_destroy(&zfsvfs->z_fuid_lock);
- kmem_free(zfsvfs, sizeof (zfsvfs_t));
+ zfs_freezfsvfs(zfsvfs);
atomic_add_32(&zfs_active_fs_count, -1);
}