FreeBSD: Simplify zvol and fix locking
zvol_geom_bio_strategy should handle its own use of the zvol suspend reader lock and ensure the zilog exists when needed. A few other places using the zvol zilog should use the suspend reader lock as well. Simplify consumers of zvol_geom_bio_strategy, fix the locking, and while in here, use the boolean_t constants with doread. Reviewed-by: Matt Macy <mmacy@FreeBSD.org> Reviewed-by: Alexander Motin <mav@FreeBSD.org> Signed-off-by: Ryan Moeller <ryan@iXsystems.com> Closes #10381
This commit is contained in:
parent
a9dcfac51c
commit
c0eb5c35ef
|
@ -199,7 +199,6 @@ static int zvol_geom_access(struct g_provider *pp, int acr, int acw, int ace);
|
||||||
static void zvol_geom_worker(void *arg);
|
static void zvol_geom_worker(void *arg);
|
||||||
static void zvol_geom_bio_start(struct bio *bp);
|
static void zvol_geom_bio_start(struct bio *bp);
|
||||||
static int zvol_geom_bio_getattr(struct bio *bp);
|
static int zvol_geom_bio_getattr(struct bio *bp);
|
||||||
static void zvol_geom_bio_check_zilog(struct bio *bp);
|
|
||||||
/* static d_strategy_t zvol_geom_bio_strategy; (declared elsewhere) */
|
/* static d_strategy_t zvol_geom_bio_strategy; (declared elsewhere) */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -487,23 +486,7 @@ zvol_geom_worker(void *arg)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
mtx_unlock(&zsg->zsg_queue_mtx);
|
mtx_unlock(&zsg->zsg_queue_mtx);
|
||||||
rw_enter(&zv->zv_suspend_lock, ZVOL_RW_READER);
|
|
||||||
zvol_geom_bio_check_zilog(bp);
|
|
||||||
switch (bp->bio_cmd) {
|
|
||||||
case BIO_FLUSH:
|
|
||||||
zil_commit(zv->zv_zilog, ZVOL_OBJ);
|
|
||||||
g_io_deliver(bp, 0);
|
|
||||||
break;
|
|
||||||
case BIO_READ:
|
|
||||||
case BIO_WRITE:
|
|
||||||
case BIO_DELETE:
|
|
||||||
zvol_geom_bio_strategy(bp);
|
zvol_geom_bio_strategy(bp);
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_io_deliver(bp, EOPNOTSUPP);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
rw_exit(&zv->zv_suspend_lock);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,24 +512,8 @@ zvol_geom_bio_start(struct bio *bp)
|
||||||
wakeup_one(&zsg->zsg_queue);
|
wakeup_one(&zsg->zsg_queue);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rw_enter(&zv->zv_suspend_lock, ZVOL_RW_READER);
|
|
||||||
zvol_geom_bio_check_zilog(bp);
|
|
||||||
|
|
||||||
switch (bp->bio_cmd) {
|
|
||||||
case BIO_FLUSH:
|
|
||||||
zil_commit(zv->zv_zilog, ZVOL_OBJ);
|
|
||||||
g_io_deliver(bp, 0);
|
|
||||||
break;
|
|
||||||
case BIO_READ:
|
|
||||||
case BIO_WRITE:
|
|
||||||
case BIO_DELETE:
|
|
||||||
zvol_geom_bio_strategy(bp);
|
zvol_geom_bio_strategy(bp);
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_io_deliver(bp, EOPNOTSUPP);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
rw_exit(&zv->zv_suspend_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -586,24 +553,6 @@ zvol_geom_bio_getattr(struct bio *bp)
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
zvol_geom_bio_check_zilog(struct bio *bp)
|
|
||||||
{
|
|
||||||
zvol_state_t *zv;
|
|
||||||
|
|
||||||
zv = bp->bio_to->private;
|
|
||||||
ASSERT(zv != NULL);
|
|
||||||
|
|
||||||
switch (bp->bio_cmd) {
|
|
||||||
case BIO_FLUSH:
|
|
||||||
case BIO_WRITE:
|
|
||||||
case BIO_DELETE:
|
|
||||||
zvol_ensure_zilog(zv);
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
zvol_geom_bio_strategy(struct bio *bp)
|
zvol_geom_bio_strategy(struct bio *bp)
|
||||||
{
|
{
|
||||||
|
@ -614,7 +563,7 @@ zvol_geom_bio_strategy(struct bio *bp)
|
||||||
objset_t *os;
|
objset_t *os;
|
||||||
zfs_locked_range_t *lr;
|
zfs_locked_range_t *lr;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
boolean_t doread = 0;
|
boolean_t doread = B_FALSE;
|
||||||
boolean_t is_dumpified;
|
boolean_t is_dumpified;
|
||||||
boolean_t sync;
|
boolean_t sync;
|
||||||
|
|
||||||
|
@ -628,22 +577,26 @@ zvol_geom_bio_strategy(struct bio *bp)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bp->bio_cmd != BIO_READ && (zv->zv_flags & ZVOL_RDONLY)) {
|
rw_enter(&zv->zv_suspend_lock, ZVOL_RW_READER);
|
||||||
error = SET_ERROR(EROFS);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (bp->bio_cmd) {
|
switch (bp->bio_cmd) {
|
||||||
case BIO_FLUSH:
|
|
||||||
goto sync;
|
|
||||||
case BIO_READ:
|
case BIO_READ:
|
||||||
doread = 1;
|
doread = B_TRUE;
|
||||||
|
break;
|
||||||
case BIO_WRITE:
|
case BIO_WRITE:
|
||||||
|
case BIO_FLUSH:
|
||||||
case BIO_DELETE:
|
case BIO_DELETE:
|
||||||
|
if (zv->zv_flags & ZVOL_RDONLY) {
|
||||||
|
error = SET_ERROR(EROFS);
|
||||||
|
goto resume;
|
||||||
|
}
|
||||||
|
zvol_ensure_zilog(zv);
|
||||||
|
if (bp->bio_cmd == BIO_FLUSH)
|
||||||
|
goto sync;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error = EOPNOTSUPP;
|
error = EOPNOTSUPP;
|
||||||
goto out;
|
goto resume;
|
||||||
}
|
}
|
||||||
|
|
||||||
off = bp->bio_offset;
|
off = bp->bio_offset;
|
||||||
|
@ -657,7 +610,7 @@ zvol_geom_bio_strategy(struct bio *bp)
|
||||||
|
|
||||||
if (resid > 0 && (off < 0 || off >= volsize)) {
|
if (resid > 0 && (off < 0 || off >= volsize)) {
|
||||||
error = SET_ERROR(EIO);
|
error = SET_ERROR(EIO);
|
||||||
goto out;
|
goto resume;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_dumpified = B_FALSE;
|
is_dumpified = B_FALSE;
|
||||||
|
@ -723,6 +676,8 @@ unlock:
|
||||||
sync:
|
sync:
|
||||||
zil_commit(zv->zv_zilog, ZVOL_OBJ);
|
zil_commit(zv->zv_zilog, ZVOL_OBJ);
|
||||||
}
|
}
|
||||||
|
resume:
|
||||||
|
rw_exit(&zv->zv_suspend_lock);
|
||||||
out:
|
out:
|
||||||
if (bp->bio_to)
|
if (bp->bio_to)
|
||||||
g_io_deliver(bp, error);
|
g_io_deliver(bp, error);
|
||||||
|
@ -797,7 +752,6 @@ zvol_cdev_write(struct cdev *dev, struct uio *uio, int ioflag)
|
||||||
|
|
||||||
rw_enter(&zv->zv_suspend_lock, ZVOL_RW_READER);
|
rw_enter(&zv->zv_suspend_lock, ZVOL_RW_READER);
|
||||||
zvol_ensure_zilog(zv);
|
zvol_ensure_zilog(zv);
|
||||||
rw_exit(&zv->zv_suspend_lock);
|
|
||||||
|
|
||||||
lr = zfs_rangelock_enter(&zv->zv_rangelock, uio->uio_loffset,
|
lr = zfs_rangelock_enter(&zv->zv_rangelock, uio->uio_loffset,
|
||||||
uio->uio_resid, RL_WRITER);
|
uio->uio_resid, RL_WRITER);
|
||||||
|
@ -826,6 +780,7 @@ zvol_cdev_write(struct cdev *dev, struct uio *uio, int ioflag)
|
||||||
zfs_rangelock_exit(lr);
|
zfs_rangelock_exit(lr);
|
||||||
if (sync)
|
if (sync)
|
||||||
zil_commit(zv->zv_zilog, ZVOL_OBJ);
|
zil_commit(zv->zv_zilog, ZVOL_OBJ);
|
||||||
|
rw_exit(&zv->zv_suspend_lock);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1015,8 +970,10 @@ zvol_cdev_ioctl(struct cdev *dev, ulong_t cmd, caddr_t data,
|
||||||
*(off_t *)data = zv->zv_volsize;
|
*(off_t *)data = zv->zv_volsize;
|
||||||
break;
|
break;
|
||||||
case DIOCGFLUSH:
|
case DIOCGFLUSH:
|
||||||
|
rw_enter(&zv->zv_suspend_lock, ZVOL_RW_READER);
|
||||||
if (zv->zv_zilog != NULL)
|
if (zv->zv_zilog != NULL)
|
||||||
zil_commit(zv->zv_zilog, ZVOL_OBJ);
|
zil_commit(zv->zv_zilog, ZVOL_OBJ);
|
||||||
|
rw_exit(&zv->zv_suspend_lock);
|
||||||
break;
|
break;
|
||||||
case DIOCGDELETE:
|
case DIOCGDELETE:
|
||||||
if (!zvol_unmap_enabled)
|
if (!zvol_unmap_enabled)
|
||||||
|
@ -1121,8 +1078,10 @@ zvol_ensure_zilog(zvol_state_t *zv)
|
||||||
* additional lock in this path.
|
* additional lock in this path.
|
||||||
*/
|
*/
|
||||||
if (zv->zv_zilog == NULL) {
|
if (zv->zv_zilog == NULL) {
|
||||||
|
if (!rw_tryupgrade(&zv->zv_suspend_lock)) {
|
||||||
rw_exit(&zv->zv_suspend_lock);
|
rw_exit(&zv->zv_suspend_lock);
|
||||||
rw_enter(&zv->zv_suspend_lock, RW_WRITER);
|
rw_enter(&zv->zv_suspend_lock, RW_WRITER);
|
||||||
|
}
|
||||||
if (zv->zv_zilog == NULL) {
|
if (zv->zv_zilog == NULL) {
|
||||||
zv->zv_zilog = zil_open(zv->zv_objset,
|
zv->zv_zilog = zil_open(zv->zv_objset,
|
||||||
zvol_get_data);
|
zvol_get_data);
|
||||||
|
|
Loading…
Reference in New Issue