--- a/usr/src/uts/common/fs/zfs/zvol.c Tue Apr 07 11:58:04 2009 -0700
+++ b/usr/src/uts/common/fs/zfs/zvol.c Tue Apr 07 13:03:48 2009 -0600
@@ -107,7 +107,7 @@
uint64_t zv_volblocksize; /* volume block size */
minor_t zv_minor; /* minor number */
uint8_t zv_min_bs; /* minimum addressable block shift */
- uint8_t zv_flags; /* readonly; dumpified */
+ uint8_t zv_flags; /* readonly, dumpified, etc. */
objset_t *zv_objset; /* objset handle */
uint32_t zv_mode; /* DS_MODE_* flags at open time */
uint32_t zv_open_count[OTYPCNT]; /* open counts */
@@ -123,6 +123,7 @@
#define ZVOL_RDONLY 0x1
#define ZVOL_DUMPIFIED 0x2
#define ZVOL_EXCL 0x4
+#define ZVOL_WCE 0x8
/*
* zvol maximum transfer in one DMU tx.
@@ -1165,7 +1166,8 @@
if ((bp->b_resid = resid) == bp->b_bcount)
bioerror(bp, off > volsize ? EINVAL : error);
- if (!(bp->b_flags & B_ASYNC) && !doread && !zil_disable && !is_dump)
+ if (!(bp->b_flags & B_ASYNC) && !doread && !zil_disable &&
+ !is_dump && !(zv->zv_flags & ZVOL_WCE))
zil_commit(zv->zv_zilog, UINT64_MAX, ZVOL_OBJ);
biodone(bp);
@@ -1324,7 +1326,7 @@
break;
}
zfs_range_unlock(rl);
- if (!zil_disable)
+ if (!zil_disable && !(zv->zv_flags & ZVOL_WCE))
zil_commit(zv->zv_zilog, UINT64_MAX, ZVOL_OBJ);
return (error);
}
@@ -1408,6 +1410,7 @@
mutex_exit(&zvol_state_lock);
return (ENXIO);
}
+ ASSERT(zv->zv_total_opens > 0);
switch (cmd) {
@@ -1444,12 +1447,40 @@
case DKIOCFLUSHWRITECACHE:
dkc = (struct dk_callback *)arg;
+ mutex_exit(&zvol_state_lock);
zil_commit(zv->zv_zilog, UINT64_MAX, ZVOL_OBJ);
if ((flag & FKIOCTL) && dkc != NULL && dkc->dkc_callback) {
(*dkc->dkc_callback)(dkc->dkc_cookie, error);
error = 0;
}
- break;
+ return (error);
+
+ case DKIOCGETWCE:
+ {
+ int wce = (zv->zv_flags & ZVOL_WCE) ? 1 : 0;
+ if (ddi_copyout(&wce, (void *)arg, sizeof (int),
+ flag))
+ error = EFAULT;
+ break;
+ }
+ case DKIOCSETWCE:
+ {
+ int wce;
+ if (ddi_copyin((void *)arg, &wce, sizeof (int),
+ flag)) {
+ error = EFAULT;
+ break;
+ }
+ if (wce) {
+ zv->zv_flags |= ZVOL_WCE;
+ mutex_exit(&zvol_state_lock);
+ } else {
+ zv->zv_flags &= ~ZVOL_WCE;
+ mutex_exit(&zvol_state_lock);
+ zil_commit(zv->zv_zilog, UINT64_MAX, ZVOL_OBJ);
+ }
+ return (0);
+ }
case DKIOCGGEOM:
case DKIOCGVTOC: