Changeset View
Changeset View
Standalone View
Standalone View
sys/contrib/openzfs/module/os/freebsd/zfs/zvol_os.c
Show First 20 Lines • Show All 740 Lines • ▼ Show 20 Lines | else | ||||
biofinish(bp, NULL, error); | biofinish(bp, NULL, error); | ||||
} | } | ||||
/* | /* | ||||
* Character device mode implementation | * Character device mode implementation | ||||
*/ | */ | ||||
static int | static int | ||||
zvol_cdev_read(struct cdev *dev, struct uio *uio, int ioflag) | zvol_cdev_read(struct cdev *dev, struct uio *uio_s, int ioflag) | ||||
{ | { | ||||
zvol_state_t *zv; | zvol_state_t *zv; | ||||
uint64_t volsize; | uint64_t volsize; | ||||
zfs_locked_range_t *lr; | zfs_locked_range_t *lr; | ||||
int error = 0; | int error = 0; | ||||
zfs_uio_t uio; | |||||
zfs_uio_init(&uio, uio_s); | |||||
zv = dev->si_drv2; | zv = dev->si_drv2; | ||||
volsize = zv->zv_volsize; | volsize = zv->zv_volsize; | ||||
/* | /* | ||||
* uio_loffset == volsize isn't an error as | * uio_loffset == volsize isn't an error as | ||||
* its required for EOF processing. | * its required for EOF processing. | ||||
*/ | */ | ||||
if (uio->uio_resid > 0 && | if (zfs_uio_resid(&uio) > 0 && | ||||
(uio->uio_loffset < 0 || uio->uio_loffset > volsize)) | (zfs_uio_offset(&uio) < 0 || zfs_uio_offset(&uio) > volsize)) | ||||
return (SET_ERROR(EIO)); | return (SET_ERROR(EIO)); | ||||
lr = zfs_rangelock_enter(&zv->zv_rangelock, uio->uio_loffset, | lr = zfs_rangelock_enter(&zv->zv_rangelock, zfs_uio_offset(&uio), | ||||
uio->uio_resid, RL_READER); | zfs_uio_resid(&uio), RL_READER); | ||||
while (uio->uio_resid > 0 && uio->uio_loffset < volsize) { | while (zfs_uio_resid(&uio) > 0 && zfs_uio_offset(&uio) < volsize) { | ||||
uint64_t bytes = MIN(uio->uio_resid, DMU_MAX_ACCESS >> 1); | uint64_t bytes = MIN(zfs_uio_resid(&uio), DMU_MAX_ACCESS >> 1); | ||||
/* don't read past the end */ | /* don't read past the end */ | ||||
if (bytes > volsize - uio->uio_loffset) | if (bytes > volsize - zfs_uio_offset(&uio)) | ||||
bytes = volsize - uio->uio_loffset; | bytes = volsize - zfs_uio_offset(&uio); | ||||
error = dmu_read_uio_dnode(zv->zv_dn, uio, bytes); | error = dmu_read_uio_dnode(zv->zv_dn, &uio, bytes); | ||||
if (error) { | if (error) { | ||||
/* convert checksum errors into IO errors */ | /* convert checksum errors into IO errors */ | ||||
if (error == ECKSUM) | if (error == ECKSUM) | ||||
error = SET_ERROR(EIO); | error = SET_ERROR(EIO); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
zfs_rangelock_exit(lr); | zfs_rangelock_exit(lr); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
zvol_cdev_write(struct cdev *dev, struct uio *uio, int ioflag) | zvol_cdev_write(struct cdev *dev, struct uio *uio_s, int ioflag) | ||||
{ | { | ||||
zvol_state_t *zv; | zvol_state_t *zv; | ||||
uint64_t volsize; | uint64_t volsize; | ||||
zfs_locked_range_t *lr; | zfs_locked_range_t *lr; | ||||
int error = 0; | int error = 0; | ||||
boolean_t sync; | boolean_t sync; | ||||
zfs_uio_t uio; | |||||
zv = dev->si_drv2; | zv = dev->si_drv2; | ||||
volsize = zv->zv_volsize; | volsize = zv->zv_volsize; | ||||
if (uio->uio_resid > 0 && | zfs_uio_init(&uio, uio_s); | ||||
(uio->uio_loffset < 0 || uio->uio_loffset > volsize)) | |||||
if (zfs_uio_resid(&uio) > 0 && | |||||
(zfs_uio_offset(&uio) < 0 || zfs_uio_offset(&uio) > volsize)) | |||||
return (SET_ERROR(EIO)); | return (SET_ERROR(EIO)); | ||||
sync = (ioflag & IO_SYNC) || | sync = (ioflag & IO_SYNC) || | ||||
(zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS); | (zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS); | ||||
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); | ||||
lr = zfs_rangelock_enter(&zv->zv_rangelock, uio->uio_loffset, | lr = zfs_rangelock_enter(&zv->zv_rangelock, zfs_uio_offset(&uio), | ||||
uio->uio_resid, RL_WRITER); | zfs_uio_resid(&uio), RL_WRITER); | ||||
while (uio->uio_resid > 0 && uio->uio_loffset < volsize) { | while (zfs_uio_resid(&uio) > 0 && zfs_uio_offset(&uio) < volsize) { | ||||
uint64_t bytes = MIN(uio->uio_resid, DMU_MAX_ACCESS >> 1); | uint64_t bytes = MIN(zfs_uio_resid(&uio), DMU_MAX_ACCESS >> 1); | ||||
uint64_t off = uio->uio_loffset; | uint64_t off = zfs_uio_offset(&uio); | ||||
dmu_tx_t *tx = dmu_tx_create(zv->zv_objset); | dmu_tx_t *tx = dmu_tx_create(zv->zv_objset); | ||||
if (bytes > volsize - off) /* don't write past the end */ | if (bytes > volsize - off) /* don't write past the end */ | ||||
bytes = volsize - off; | bytes = volsize - off; | ||||
dmu_tx_hold_write_by_dnode(tx, zv->zv_dn, off, bytes); | dmu_tx_hold_write_by_dnode(tx, zv->zv_dn, off, bytes); | ||||
error = dmu_tx_assign(tx, TXG_WAIT); | error = dmu_tx_assign(tx, TXG_WAIT); | ||||
if (error) { | if (error) { | ||||
dmu_tx_abort(tx); | dmu_tx_abort(tx); | ||||
break; | break; | ||||
} | } | ||||
error = dmu_write_uio_dnode(zv->zv_dn, uio, bytes, tx); | error = dmu_write_uio_dnode(zv->zv_dn, &uio, bytes, tx); | ||||
if (error == 0) | if (error == 0) | ||||
zvol_log_write(zv, tx, off, bytes, sync); | zvol_log_write(zv, tx, off, bytes, sync); | ||||
dmu_tx_commit(tx); | dmu_tx_commit(tx); | ||||
if (error) | if (error) | ||||
break; | break; | ||||
} | } | ||||
zfs_rangelock_exit(lr); | zfs_rangelock_exit(lr); | ||||
▲ Show 20 Lines • Show All 683 Lines • Show Last 20 Lines |