summaryrefslogtreecommitdiffstats
path: root/cddl
diff options
context:
space:
mode:
authormm <mm@FreeBSD.org>2011-07-30 19:00:31 +0000
committermm <mm@FreeBSD.org>2011-07-30 19:00:31 +0000
commitf2d210f70e11547907ab527221f98c5f32db7182 (patch)
tree23c9ef12e1030dbe2ac6fa22c4d2e1c5b670d84f /cddl
parent2f91b4a4bb5886422e47e5dcdc67ae52b12edd19 (diff)
downloadFreeBSD-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.c35
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);
}
/*
OpenPOWER on IntegriCloud