diff options
author | ek110237 <none@none> | 2008-02-26 11:31:49 -0800 |
---|---|---|
committer | ek110237 <none@none> | 2008-02-26 11:31:49 -0800 |
commit | 47f263f4211a47222fcc65b18b0cfa06d33f3c33 (patch) | |
tree | 7d63bbf540ef2768fcd436574701f5a6e4118a89 /usr/src | |
parent | d8ac9b2d669163fee52330a52017528035cacb4e (diff) | |
download | illumos-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.c | 19 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/sys/dmu.h | 3 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h | 3 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_ioctl.c | 54 | ||||
-rw-r--r-- | usr/src/uts/common/fs/zfs/zfs_vfsops.c | 34 |
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); } |