# HG changeset patch # User ek110237 # Date 1204054309 28800 # Node ID 23e77aa611b1388f10301e3de57b479f2780d381 # Parent 30337f24796be374a160b50112a408632747fd22 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 diff -r 30337f24796b -r 23e77aa611b1 usr/src/uts/common/fs/zfs/dmu_send.c --- a/usr/src/uts/common/fs/zfs/dmu_send.c Tue Feb 26 07:21:54 2008 -0800 +++ b/usr/src/uts/common/fs/zfs/dmu_send.c Tue Feb 26 11:31:49 2008 -0800 @@ -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 @@ 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 @@ 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 @@ * 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 @@ DS_MODE_PRIMARY, DS_MODE_EXCLUSIVE)) { lmode = DS_MODE_EXCLUSIVE; } else { - recv_abort_cleanup(drc); + dmu_recv_abort_cleanup(drc); return (EBUSY); } diff -r 30337f24796b -r 23e77aa611b1 usr/src/uts/common/fs/zfs/sys/dmu.h --- a/usr/src/uts/common/fs/zfs/sys/dmu.h Tue Feb 26 07:21:54 2008 -0800 +++ b/usr/src/uts/common/fs/zfs/sys/dmu.h Tue Feb 26 11:31:49 2008 -0800 @@ -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 @@ 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 -r 30337f24796b -r 23e77aa611b1 usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h --- a/usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h Tue Feb 26 07:21:54 2008 -0800 +++ b/usr/src/uts/common/fs/zfs/sys/zfs_vfsops.h Tue Feb 26 11:31:49 2008 -0800 @@ -74,7 +74,8 @@ 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 -r 30337f24796b -r 23e77aa611b1 usr/src/uts/common/fs/zfs/zfs_ioctl.c --- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c Tue Feb 26 07:21:54 2008 -0800 +++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c Tue Feb 26 11:31:49 2008 -0800 @@ -2186,11 +2186,17 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 -r 30337f24796b -r 23e77aa611b1 usr/src/uts/common/fs/zfs/zfs_vfsops.c --- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c Tue Feb 26 07:21:54 2008 -0800 +++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c Tue Feb 26 11:31:49 2008 -0800 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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 @@ /* * 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 @@ 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); }