PSARC/2010/108 zil synchronicity
authorMark J Musante <Mark.Musante@Sun.COM>
Mon, 03 May 2010 09:07:08 -0600
changeset 12294 2a74b443e6b1
parent 12293 2286b8b6d071
child 12295 e16f396f04a1
PSARC/2010/108 zil synchronicity 6280630 zil synchronicity Contributed by Robert Milkowski <[email protected]>
usr/src/cmd/mdb/common/modules/zfs/zfs.c
usr/src/cmd/ztest/ztest.c
usr/src/common/zfs/zfs_prop.c
usr/src/uts/common/fs/zfs/dmu_objset.c
usr/src/uts/common/fs/zfs/sys/dmu.h
usr/src/uts/common/fs/zfs/sys/dmu_objset.h
usr/src/uts/common/fs/zfs/sys/zil.h
usr/src/uts/common/fs/zfs/sys/zil_impl.h
usr/src/uts/common/fs/zfs/zfs_vfsops.c
usr/src/uts/common/fs/zfs/zfs_vnops.c
usr/src/uts/common/fs/zfs/zil.c
usr/src/uts/common/fs/zfs/zvol.c
usr/src/uts/common/sys/fs/zfs.h
--- a/usr/src/cmd/mdb/common/modules/zfs/zfs.c	Mon May 03 04:17:29 2010 -0700
+++ b/usr/src/cmd/mdb/common/modules/zfs/zfs.c	Mon May 03 09:07:08 2010 -0600
@@ -19,10 +19,11 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
+/* Portions Copyright 2010 Robert Milkowski */
+
 #include <mdb/mdb_ctf.h>
 #include <sys/zfs_context.h>
 #include <sys/mdb_modapi.h>
@@ -329,8 +330,8 @@
 		"fzap_default_block_shift",
 		"zfs_immediate_write_sz",
 		"zfs_read_chunk_size",
-		"zil_disable",
 		"zfs_nocacheflush",
+		"zil_replay_disable",
 		"metaslab_gang_bang",
 		"metaslab_df_alloc_threshold",
 		"metaslab_df_free_pct",
--- a/usr/src/cmd/ztest/ztest.c	Mon May 03 04:17:29 2010 -0700
+++ b/usr/src/cmd/ztest/ztest.c	Mon May 03 09:07:08 2010 -0600
@@ -2820,6 +2820,21 @@
 	    DMU_OT_ZAP_OTHER, DMU_OT_NONE, 0, tx) == 0);
 }
 
+static int
+ztest_dataset_create(char *dsname)
+{
+	uint64_t zilset = ztest_random(100);
+	int err = dmu_objset_create(dsname, DMU_OST_OTHER, 0,
+	    ztest_objset_create_cb, NULL);
+
+	if (err || zilset < 80)
+		return (err);
+
+	(void) printf("Setting dataset %s to sync always\n", dsname);
+	return (ztest_dsl_prop_set_uint64(dsname, ZFS_PROP_SYNC,
+	    ZFS_SYNC_ALWAYS, B_FALSE));
+}
+
 /* ARGSUSED */
 static int
 ztest_objset_destroy_cb(const char *name, void *arg)
@@ -2929,8 +2944,7 @@
 	/*
 	 * Verify that we can create a new dataset.
 	 */
-	error = dmu_objset_create(name, DMU_OST_OTHER, 0,
-	    ztest_objset_create_cb, NULL);
+	error = ztest_dataset_create(name);
 	if (error) {
 		if (error == ENOSPC) {
 			ztest_record_enospc(FTAG);
@@ -5019,8 +5033,7 @@
 
 	(void) rw_rdlock(&zs->zs_name_lock);
 
-	error = dmu_objset_create(name, DMU_OST_OTHER, 0,
-	    ztest_objset_create_cb, NULL);
+	error = ztest_dataset_create(name);
 	if (error == ENOSPC) {
 		(void) rw_unlock(&zs->zs_name_lock);
 		ztest_record_enospc(FTAG);
--- a/usr/src/common/zfs/zfs_prop.c	Mon May 03 04:17:29 2010 -0700
+++ b/usr/src/common/zfs/zfs_prop.c	Mon May 03 09:07:08 2010 -0600
@@ -22,6 +22,8 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
+/* Portions Copyright 2010 Robert Milkowski */
+
 #include <sys/zio.h>
 #include <sys/spa.h>
 #include <sys/u8_textprep.h>
@@ -176,7 +178,18 @@
 		{ NULL }
 	};
 
+	static zprop_index_t sync_table[] = {
+		{ "standard",	ZFS_SYNC_STANDARD },
+		{ "always",	ZFS_SYNC_ALWAYS },
+		{ "disabled",	ZFS_SYNC_DISABLED },
+		{ NULL }
+	};
+
 	/* inherit index properties */
+	zprop_register_index(ZFS_PROP_SYNC, "sync", ZFS_SYNC_STANDARD,
+	    PROP_INHERIT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
+	    "standard | always | disabled", "SYNC",
+	    sync_table);
 	zprop_register_index(ZFS_PROP_CHECKSUM, "checksum",
 	    ZIO_CHECKSUM_DEFAULT, PROP_INHERIT, ZFS_TYPE_FILESYSTEM |
 	    ZFS_TYPE_VOLUME,
--- a/usr/src/uts/common/fs/zfs/dmu_objset.c	Mon May 03 04:17:29 2010 -0700
+++ b/usr/src/uts/common/fs/zfs/dmu_objset.c	Mon May 03 09:07:08 2010 -0600
@@ -22,6 +22,8 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
+/* Portions Copyright 2010 Robert Milkowski */
+
 #include <sys/cred.h>
 #include <sys/zfs_context.h>
 #include <sys/dmu_objset.h>
@@ -92,6 +94,12 @@
 }
 
 uint64_t
+dmu_objset_syncprop(objset_t *os)
+{
+	return (os->os_sync);
+}
+
+uint64_t
 dmu_objset_logbias(objset_t *os)
 {
 	return (os->os_logbias);
@@ -184,6 +192,22 @@
 }
 
 static void
+sync_changed_cb(void *arg, uint64_t newval)
+{
+	objset_t *os = arg;
+
+	/*
+	 * Inheritance and range checking should have been done by now.
+	 */
+	ASSERT(newval == ZFS_SYNC_STANDARD || newval == ZFS_SYNC_ALWAYS ||
+	    newval == ZFS_SYNC_DISABLED);
+
+	os->os_sync = newval;
+	if (os->os_zil)
+		zil_set_sync(os->os_zil, newval);
+}
+
+static void
 logbias_changed_cb(void *arg, uint64_t newval)
 {
 	objset_t *os = arg;
@@ -303,6 +327,9 @@
 			if (err == 0)
 				err = dsl_prop_register(ds, "logbias",
 				    logbias_changed_cb, os);
+			if (err == 0)
+				err = dsl_prop_register(ds, "sync",
+				    sync_changed_cb, os);
 		}
 		if (err) {
 			VERIFY(arc_buf_remove_ref(os->os_phys_buf,
@@ -318,6 +345,7 @@
 		os->os_dedup_checksum = ZIO_CHECKSUM_OFF;
 		os->os_dedup_verify = 0;
 		os->os_logbias = 0;
+		os->os_sync = 0;
 		os->os_primary_cache = ZFS_CACHE_ALL;
 		os->os_secondary_cache = ZFS_CACHE_ALL;
 	}
@@ -493,6 +521,8 @@
 			    dedup_changed_cb, os));
 			VERIFY(0 == dsl_prop_unregister(ds, "logbias",
 			    logbias_changed_cb, os));
+			VERIFY(0 == dsl_prop_unregister(ds, "sync",
+			    sync_changed_cb, os));
 		}
 		VERIFY(0 == dsl_prop_unregister(ds, "primarycache",
 		    primary_cache_changed_cb, os));
--- a/usr/src/uts/common/fs/zfs/sys/dmu.h	Mon May 03 04:17:29 2010 -0700
+++ b/usr/src/uts/common/fs/zfs/sys/dmu.h	Mon May 03 09:07:08 2010 -0600
@@ -22,6 +22,8 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
+/* Portions Copyright 2010 Robert Milkowski */
+
 #ifndef	_SYS_DMU_H
 #define	_SYS_DMU_H
 
@@ -641,6 +643,7 @@
 extern void dmu_objset_name(objset_t *os, char *buf);
 extern dmu_objset_type_t dmu_objset_type(objset_t *os);
 extern uint64_t dmu_objset_id(objset_t *os);
+extern uint64_t dmu_objset_syncprop(objset_t *os);
 extern uint64_t dmu_objset_logbias(objset_t *os);
 extern int dmu_snapshot_list_next(objset_t *os, int namelen, char *name,
     uint64_t *id, uint64_t *offp, boolean_t *case_conflict);
--- a/usr/src/uts/common/fs/zfs/sys/dmu_objset.h	Mon May 03 04:17:29 2010 -0700
+++ b/usr/src/uts/common/fs/zfs/sys/dmu_objset.h	Mon May 03 09:07:08 2010 -0600
@@ -22,6 +22,8 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
+/* Portions Copyright 2010 Robert Milkowski */
+
 #ifndef	_SYS_DMU_OBJSET_H
 #define	_SYS_DMU_OBJSET_H
 
@@ -77,6 +79,7 @@
 	uint8_t os_logbias;
 	uint8_t os_primary_cache;
 	uint8_t os_secondary_cache;
+	uint8_t os_sync;
 
 	/* no lock needed: */
 	struct dmu_tx *os_synctx; /* XXX sketchy */
--- a/usr/src/uts/common/fs/zfs/sys/zil.h	Mon May 03 04:17:29 2010 -0700
+++ b/usr/src/uts/common/fs/zfs/sys/zil.h	Mon May 03 09:07:08 2010 -0600
@@ -19,10 +19,11 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
+/* Portions Copyright 2010 Robert Milkowski */
+
 #ifndef	_SYS_ZIL_H
 #define	_SYS_ZIL_H
 
@@ -417,9 +418,11 @@
 extern void	zil_add_block(zilog_t *zilog, const blkptr_t *bp);
 extern int	zil_bp_tree_add(zilog_t *zilog, const blkptr_t *bp);
 
+extern void	zil_set_sync(zilog_t *zilog, uint64_t syncval);
+
 extern void	zil_set_logbias(zilog_t *zilog, uint64_t slogval);
 
-extern int zil_disable;
+extern int zil_replay_disable;
 
 #ifdef	__cplusplus
 }
--- a/usr/src/uts/common/fs/zfs/sys/zil_impl.h	Mon May 03 04:17:29 2010 -0700
+++ b/usr/src/uts/common/fs/zfs/sys/zil_impl.h	Mon May 03 09:07:08 2010 -0600
@@ -19,10 +19,11 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
+/* Portions Copyright 2010 Robert Milkowski */
+
 #ifndef	_SYS_ZIL_IMPL_H
 #define	_SYS_ZIL_IMPL_H
 
@@ -86,6 +87,7 @@
 	uint8_t		zl_stop_sync;	/* for debugging */
 	uint8_t		zl_writer;	/* boolean: write setup in progress */
 	uint8_t		zl_logbias;	/* latency or throughput */
+	uint8_t		zl_sync;	/* synchronous or asynchronous */
 	int		zl_parse_error;	/* last zil_parse() error */
 	uint64_t	zl_parse_blk_seq; /* highest blk seq on last parse */
 	uint64_t	zl_parse_lr_seq; /* highest lr seq on last parse */
--- a/usr/src/uts/common/fs/zfs/zfs_vfsops.c	Mon May 03 04:17:29 2010 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_vfsops.c	Mon May 03 09:07:08 2010 -0600
@@ -22,6 +22,8 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
+/* Portions Copyright 2010 Robert Milkowski */
+
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -165,8 +167,7 @@
 
 		if (zfsvfs->z_log != NULL)
 			zil_commit(zfsvfs->z_log, UINT64_MAX, 0);
-		else
-			txg_wait_synced(dp, 0);
+
 		ZFS_EXIT(zfsvfs);
 	} else {
 		/*
@@ -1024,10 +1025,6 @@
 	mutex_exit(&zfsvfs->z_os->os_user_ptr_lock);
 
 	zfsvfs->z_log = zil_open(zfsvfs->z_os, zfs_get_data);
-	if (zil_disable) {
-		zil_destroy(zfsvfs->z_log, B_FALSE);
-		zfsvfs->z_log = NULL;
-	}
 
 	/*
 	 * If we are not mounting (ie: online recv), then we don't
@@ -1047,34 +1044,36 @@
 		else
 			zfs_unlinked_drain(zfsvfs);
 
-		if (zfsvfs->z_log) {
-			/*
-			 * Parse and replay the intent log.
-			 *
-			 * Because of ziltest, this must be done after
-			 * zfs_unlinked_drain().  (Further note: ziltest
-			 * doesn't use readonly mounts, where
-			 * zfs_unlinked_drain() isn't called.)  This is because
-			 * ziltest causes spa_sync() to think it's committed,
-			 * but actually it is not, so the intent log contains
-			 * many txg's worth of changes.
-			 *
-			 * In particular, if object N is in the unlinked set in
-			 * the last txg to actually sync, then it could be
-			 * actually freed in a later txg and then reallocated
-			 * in a yet later txg.  This would write a "create
-			 * object N" record to the intent log.  Normally, this
-			 * would be fine because the spa_sync() would have
-			 * written out the fact that object N is free, before
-			 * we could write the "create object N" intent log
-			 * record.
-			 *
-			 * But when we are in ziltest mode, we advance the "open
-			 * txg" without actually spa_sync()-ing the changes to
-			 * disk.  So we would see that object N is still
-			 * allocated and in the unlinked set, and there is an
-			 * intent log record saying to allocate it.
-			 */
+		/*
+		 * Parse and replay the intent log.
+		 *
+		 * Because of ziltest, this must be done after
+		 * zfs_unlinked_drain().  (Further note: ziltest
+		 * doesn't use readonly mounts, where
+		 * zfs_unlinked_drain() isn't called.)  This is because
+		 * ziltest causes spa_sync() to think it's committed,
+		 * but actually it is not, so the intent log contains
+		 * many txg's worth of changes.
+		 *
+		 * In particular, if object N is in the unlinked set in
+		 * the last txg to actually sync, then it could be
+		 * actually freed in a later txg and then reallocated
+		 * in a yet later txg.  This would write a "create
+		 * object N" record to the intent log.  Normally, this
+		 * would be fine because the spa_sync() would have
+		 * written out the fact that object N is free, before
+		 * we could write the "create object N" intent log
+		 * record.
+		 *
+		 * But when we are in ziltest mode, we advance the "open
+		 * txg" without actually spa_sync()-ing the changes to
+		 * disk.  So we would see that object N is still
+		 * allocated and in the unlinked set, and there is an
+		 * intent log record saying to allocate it.
+		 */
+		if (zil_replay_disable) {
+			zil_destroy(zfsvfs->z_log, B_FALSE);
+		} else {
 			zfsvfs->z_replay = B_TRUE;
 			zil_replay(zfsvfs->z_os, zfsvfs, zfs_replay_vector);
 			zfsvfs->z_replay = B_FALSE;
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c	Mon May 03 04:17:29 2010 -0700
+++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c	Mon May 03 09:07:08 2010 -0600
@@ -23,6 +23,7 @@
  */
 
 /* Portions Copyright 2007 Jeremy Teo */
+/* Portions Copyright 2010 Robert Milkowski */
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -56,6 +57,7 @@
 #include <sys/zfs_ioctl.h>
 #include <sys/fs/zfs.h>
 #include <sys/dmu.h>
+#include <sys/dmu_objset.h>
 #include <sys/spa.h>
 #include <sys/txg.h>
 #include <sys/dbuf.h>
@@ -487,7 +489,7 @@
 	/*
 	 * If we're in FRSYNC mode, sync out this znode before reading it.
 	 */
-	if (ioflag & FRSYNC)
+	if (ioflag & FRSYNC || zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
 		zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id);
 
 	/*
@@ -913,7 +915,8 @@
 		return (error);
 	}
 
-	if (ioflag & (FSYNC | FDSYNC))
+	if (ioflag & (FSYNC | FDSYNC) ||
+	    zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
 		zil_commit(zilog, zp->z_last_itx, zp->z_id);
 
 	ZFS_EXIT(zfsvfs);
@@ -1489,6 +1492,9 @@
 		error = specvp_check(vpp, cr);
 	}
 
+	if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+		zil_commit(zilog, UINT64_MAX, 0);
+
 	ZFS_EXIT(zfsvfs);
 	return (error);
 }
@@ -1704,6 +1710,9 @@
 	if (xzp)
 		VN_RELE(ZTOV(xzp));
 
+	if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+		zil_commit(zilog, UINT64_MAX, 0);
+
 	ZFS_EXIT(zfsvfs);
 	return (error);
 }
@@ -1877,6 +1886,9 @@
 
 	zfs_dirent_unlock(dl);
 
+	if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+		zil_commit(zilog, UINT64_MAX, 0);
+
 	ZFS_EXIT(zfsvfs);
 	return (0);
 }
@@ -2002,6 +2014,9 @@
 
 	VN_RELE(vp);
 
+	if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+		zil_commit(zilog, UINT64_MAX, 0);
+
 	ZFS_EXIT(zfsvfs);
 	return (error);
 }
@@ -2316,10 +2331,12 @@
 
 	(void) tsd_set(zfs_fsyncer_key, (void *)zfs_fsync_sync_cnt);
 
-	ZFS_ENTER(zfsvfs);
-	ZFS_VERIFY_ZP(zp);
-	zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id);
-	ZFS_EXIT(zfsvfs);
+	if (zfsvfs->z_os->os_sync != ZFS_SYNC_DISABLED) {
+		ZFS_ENTER(zfsvfs);
+		ZFS_VERIFY_ZP(zp);
+		zil_commit(zfsvfs->z_log, zp->z_last_itx, zp->z_id);
+		ZFS_EXIT(zfsvfs);
+	}
 	return (0);
 }
 
@@ -3117,6 +3134,9 @@
 
 
 out2:
+	if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+		zil_commit(zilog, UINT64_MAX, 0);
+
 	ZFS_EXIT(zfsvfs);
 	return (err);
 }
@@ -3547,6 +3567,9 @@
 	if (tzp)
 		VN_RELE(ZTOV(tzp));
 
+	if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+		zil_commit(zilog, UINT64_MAX, 0);
+
 	ZFS_EXIT(zfsvfs);
 	return (error);
 }
@@ -3687,6 +3710,9 @@
 
 	VN_RELE(ZTOV(zp));
 
+	if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+		zil_commit(zilog, UINT64_MAX, 0);
+
 	ZFS_EXIT(zfsvfs);
 	return (error);
 }
@@ -3877,6 +3903,9 @@
 		vnevent_link(svp, ct);
 	}
 
+	if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+		zil_commit(zilog, UINT64_MAX, 0);
+
 	ZFS_EXIT(zfsvfs);
 	return (error);
 }
@@ -4109,7 +4138,7 @@
 	}
 out:
 	zfs_range_unlock(rl);
-	if ((flags & B_ASYNC) == 0)
+	if ((flags & B_ASYNC) == 0 || zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
 		zil_commit(zfsvfs->z_log, UINT64_MAX, zp->z_id);
 	ZFS_EXIT(zfsvfs);
 	return (error);
@@ -4757,10 +4786,16 @@
 	zfsvfs_t *zfsvfs = zp->z_zfsvfs;
 	int error;
 	boolean_t skipaclchk = (flag & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE;
+	zilog_t	*zilog = zfsvfs->z_log;
 
 	ZFS_ENTER(zfsvfs);
 	ZFS_VERIFY_ZP(zp);
+
 	error = zfs_setacl(zp, vsecp, skipaclchk, cr);
+
+	if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+		zil_commit(zilog, UINT64_MAX, 0);
+
 	ZFS_EXIT(zfsvfs);
 	return (error);
 }
--- a/usr/src/uts/common/fs/zfs/zil.c	Mon May 03 04:17:29 2010 -0700
+++ b/usr/src/uts/common/fs/zfs/zil.c	Mon May 03 09:07:08 2010 -0600
@@ -19,10 +19,11 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
+/* Portions Copyright 2010 Robert Milkowski */
+
 #include <sys/zfs_context.h>
 #include <sys/spa.h>
 #include <sys/dmu.h>
@@ -65,7 +66,7 @@
 /*
  * This global ZIL switch affects all pools
  */
-int zil_disable = 0;	/* disable intent logging */
+int zil_replay_disable = 0;    /* disable intent logging replay */
 
 /*
  * Tunable parameter for debugging or performance analysis.  Setting
@@ -1266,7 +1267,7 @@
 void
 zil_commit(zilog_t *zilog, uint64_t seq, uint64_t foid)
 {
-	if (zilog == NULL || seq == 0)
+	if (zilog->zl_sync == ZFS_SYNC_DISABLED || seq == 0)
 		return;
 
 	mutex_enter(&zilog->zl_lock);
@@ -1398,6 +1399,12 @@
 }
 
 void
+zil_set_sync(zilog_t *zilog, uint64_t sync)
+{
+	zilog->zl_sync = sync;
+}
+
+void
 zil_set_logbias(zilog_t *zilog, uint64_t logbias)
 {
 	zilog->zl_logbias = logbias;
@@ -1416,6 +1423,7 @@
 	zilog->zl_dmu_pool = dmu_objset_pool(os);
 	zilog->zl_destroy_txg = TXG_INITIAL - 1;
 	zilog->zl_logbias = dmu_objset_logbias(os);
+	zilog->zl_sync = dmu_objset_syncprop(os);
 
 	mutex_init(&zilog->zl_lock, NULL, MUTEX_DEFAULT, NULL);
 
@@ -1721,7 +1729,7 @@
 boolean_t
 zil_replaying(zilog_t *zilog, dmu_tx_t *tx)
 {
-	if (zilog == NULL)
+	if (zilog->zl_sync == ZFS_SYNC_DISABLED)
 		return (B_TRUE);
 
 	if (zilog->zl_replay) {
--- a/usr/src/uts/common/fs/zfs/zvol.c	Mon May 03 04:17:29 2010 -0700
+++ b/usr/src/uts/common/fs/zfs/zvol.c	Mon May 03 09:07:08 2010 -0600
@@ -22,6 +22,8 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
+/* Portions Copyright 2010 Robert Milkowski */
+
 /*
  * ZFS volume emulation driver.
  *
@@ -525,7 +527,10 @@
 	ASSERT(error == 0);
 	zv->zv_volblocksize = doi.doi_data_block_size;
 
-	zil_replay(os, zv, zvol_replay_vector);
+	if (zil_replay_disable)
+		zil_destroy(dmu_objset_zil(os), B_FALSE);
+	else
+		zil_replay(os, zv, zvol_replay_vector);
 	dmu_objset_disown(os, zvol_tag);
 	zv->zv_objset = NULL;
 
@@ -988,9 +993,6 @@
 	boolean_t slogging;
 	ssize_t immediate_write_sz;
 
-	if (zil_disable)
-		return;
-
 	if (zil_replaying(zilog, tx))
 		return;
 
@@ -1182,8 +1184,10 @@
 	}
 
 	is_dump = zv->zv_flags & ZVOL_DUMPIFIED;
-	sync = !(bp->b_flags & B_ASYNC) && !doread && !is_dump &&
-	    !(zv->zv_flags & ZVOL_WCE) && !zil_disable;
+	sync = ((!(bp->b_flags & B_ASYNC) &&
+	    !(zv->zv_flags & ZVOL_WCE)) ||
+	    (zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS)) &&
+	    !doread && !is_dump;
 
 	/*
 	 * There must be no buffer changes when doing a dmu_sync() because
@@ -1363,7 +1367,8 @@
 		return (error);
 	}
 
-	sync = !(zv->zv_flags & ZVOL_WCE) && !zil_disable;
+	sync = !(zv->zv_flags & ZVOL_WCE) ||
+	    (zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS);
 
 	rl = zfs_range_lock(&zv->zv_znode, uio->uio_loffset, uio->uio_resid,
 	    RL_WRITER);
--- a/usr/src/uts/common/sys/fs/zfs.h	Mon May 03 04:17:29 2010 -0700
+++ b/usr/src/uts/common/sys/fs/zfs.h	Mon May 03 09:07:08 2010 -0600
@@ -23,6 +23,8 @@
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
+/* Portions Copyright 2010 Robert Milkowski */
+
 #ifndef	_SYS_FS_ZFS_H
 #define	_SYS_FS_ZFS_H
 
@@ -119,6 +121,7 @@
 	ZFS_PROP_OBJSETID,		/* not exposed to the user */
 	ZFS_PROP_DEDUP,
 	ZFS_PROP_MLSLABEL,
+	ZFS_PROP_SYNC,
 	ZFS_NUM_PROPS
 } zfs_prop_t;
 
@@ -296,6 +299,12 @@
 	ZFS_CACHE_ALL = 2
 } zfs_cache_type_t;
 
+typedef enum {
+	ZFS_SYNC_STANDARD = 0,
+	ZFS_SYNC_ALWAYS = 1,
+	ZFS_SYNC_DISABLED = 2
+} zfs_sync_type_t;
+
 
 /*
  * On-disk version number.