diff options
author | mm <mm@FreeBSD.org> | 2011-07-30 19:00:31 +0000 |
---|---|---|
committer | mm <mm@FreeBSD.org> | 2011-07-30 19:00:31 +0000 |
commit | f2d210f70e11547907ab527221f98c5f32db7182 (patch) | |
tree | 23c9ef12e1030dbe2ac6fa22c4d2e1c5b670d84f /cddl | |
parent | 2f91b4a4bb5886422e47e5dcdc67ae52b12edd19 (diff) | |
download | FreeBSD-src-f2d210f70e11547907ab527221f98c5f32db7182.zip FreeBSD-src-f2d210f70e11547907ab527221f98c5f32db7182.tar.gz |
Fix serious bug in ZIL that can lead to pool corruption
in the case of a held dataset during remount.
Detailed description is available at:
https://www.illumos.org/issues/883
illumos-gate revision: 13380:161b964a0e10
Reviewed by: pjd
Approved by: re (kib)
Obtained from: Illumos (Bug #883)
MFC after: 3 days
Diffstat (limited to 'cddl')
-rw-r--r-- | cddl/contrib/opensolaris/cmd/ztest/ztest.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/cddl/contrib/opensolaris/cmd/ztest/ztest.c b/cddl/contrib/opensolaris/cmd/ztest/ztest.c index 62c98f4..d90961e 100644 --- a/cddl/contrib/opensolaris/cmd/ztest/ztest.c +++ b/cddl/contrib/opensolaris/cmd/ztest/ztest.c @@ -205,6 +205,7 @@ typedef struct ztest_od { */ typedef struct ztest_ds { objset_t *zd_os; + rwlock_t zd_zilog_lock; zilog_t *zd_zilog; uint64_t zd_seq; ztest_od_t *zd_od; /* debugging aid */ @@ -238,6 +239,7 @@ ztest_func_t ztest_dmu_commit_callbacks; ztest_func_t ztest_zap; ztest_func_t ztest_zap_parallel; ztest_func_t ztest_zil_commit; +ztest_func_t ztest_zil_remount; ztest_func_t ztest_dmu_read_write_zcopy; ztest_func_t ztest_dmu_objset_create_destroy; ztest_func_t ztest_dmu_prealloc; @@ -273,6 +275,7 @@ ztest_info_t ztest_info[] = { { ztest_zap_parallel, 100, &zopt_always }, { ztest_split_pool, 1, &zopt_always }, { ztest_zil_commit, 1, &zopt_incessant }, + { ztest_zil_remount, 1, &zopt_sometimes }, { ztest_dmu_read_write_zcopy, 1, &zopt_often }, { ztest_dmu_objset_create_destroy, 1, &zopt_often }, { ztest_dsl_prop_get_set, 1, &zopt_often }, @@ -986,6 +989,7 @@ ztest_zd_init(ztest_ds_t *zd, objset_t *os) zd->zd_seq = 0; dmu_objset_name(os, zd->zd_name); + VERIFY(rwlock_init(&zd->zd_zilog_lock, USYNC_THREAD, NULL) == 0); VERIFY(_mutex_init(&zd->zd_dirobj_lock, USYNC_THREAD, NULL) == 0); for (int l = 0; l < ZTEST_OBJECT_LOCKS; l++) @@ -1965,6 +1969,8 @@ ztest_io(ztest_ds_t *zd, uint64_t object, uint64_t offset) if (ztest_random(2) == 0) io_type = ZTEST_IO_WRITE_TAG; + (void) rw_rdlock(&zd->zd_zilog_lock); + switch (io_type) { case ZTEST_IO_WRITE_TAG: @@ -2000,6 +2006,8 @@ ztest_io(ztest_ds_t *zd, uint64_t object, uint64_t offset) break; } + (void) rw_unlock(&zd->zd_zilog_lock); + umem_free(data, blocksize); } @@ -2054,6 +2062,8 @@ ztest_zil_commit(ztest_ds_t *zd, uint64_t id) { zilog_t *zilog = zd->zd_zilog; + (void) rw_rdlock(&zd->zd_zilog_lock); + zil_commit(zilog, ztest_random(ZTEST_OBJECTS)); /* @@ -2065,6 +2075,31 @@ ztest_zil_commit(ztest_ds_t *zd, uint64_t id) ASSERT(zd->zd_seq <= zilog->zl_commit_lr_seq); zd->zd_seq = zilog->zl_commit_lr_seq; mutex_exit(&zilog->zl_lock); + + (void) rw_unlock(&zd->zd_zilog_lock); +} + +/* + * This function is designed to simulate the operations that occur during a + * mount/unmount operation. We hold the dataset across these operations in an + * attempt to expose any implicit assumptions about ZIL management. + */ +/* ARGSUSED */ +void +ztest_zil_remount(ztest_ds_t *zd, uint64_t id) +{ + objset_t *os = zd->zd_os; + + (void) rw_wrlock(&zd->zd_zilog_lock); + + /* zfsvfs_teardown() */ + zil_close(zd->zd_zilog); + + /* zfsvfs_setup() */ + VERIFY(zil_open(os, ztest_get_data) == zd->zd_zilog); + zil_replay(os, zd, ztest_replay_vector); + + (void) rw_unlock(&zd->zd_zilog_lock); } /* |