Changeset View
Standalone View
sys/dev/md/md.c
Show First 20 Lines • Show All 869 Lines • ▼ Show 20 Lines | mdstart_vnode(struct md_s *sc, struct bio *bp) | ||||
struct uio auio; | struct uio auio; | ||||
struct iovec aiov; | struct iovec aiov; | ||||
struct iovec *piov; | struct iovec *piov; | ||||
struct mount *mp; | struct mount *mp; | ||||
struct vnode *vp; | struct vnode *vp; | ||||
struct buf *pb; | struct buf *pb; | ||||
bus_dma_segment_t *vlist; | bus_dma_segment_t *vlist; | ||||
struct thread *td; | struct thread *td; | ||||
off_t iolen, iostart, len, zerosize; | off_t iolen, iostart, off, len; | ||||
int ma_offs, npages; | int ma_offs, npages; | ||||
switch (bp->bio_cmd) { | switch (bp->bio_cmd) { | ||||
case BIO_READ: | case BIO_READ: | ||||
auio.uio_rw = UIO_READ; | auio.uio_rw = UIO_READ; | ||||
break; | break; | ||||
case BIO_WRITE: | case BIO_WRITE: | ||||
case BIO_DELETE: | |||||
auio.uio_rw = UIO_WRITE; | auio.uio_rw = UIO_WRITE; | ||||
markj: Harmless, but there's a missing `break` here. | |||||
break; | break; | ||||
case BIO_DELETE: | |||||
case BIO_FLUSH: | case BIO_FLUSH: | ||||
break; | break; | ||||
default: | default: | ||||
return (EOPNOTSUPP); | return (EOPNOTSUPP); | ||||
} | } | ||||
td = curthread; | td = curthread; | ||||
vp = sc->vnode; | vp = sc->vnode; | ||||
pb = NULL; | pb = NULL; | ||||
piov = NULL; | piov = NULL; | ||||
ma_offs = bp->bio_ma_offset; | ma_offs = bp->bio_ma_offset; | ||||
off = bp->bio_offset; | |||||
len = bp->bio_length; | len = bp->bio_length; | ||||
/* | /* | ||||
* VNODE I/O | * VNODE I/O | ||||
* | * | ||||
* If an error occurs, we set BIO_ERROR but we do not set | * If an error occurs, we set BIO_ERROR but we do not set | ||||
* B_INVAL because (for a write anyway), the buffer is | * B_INVAL because (for a write anyway), the buffer is | ||||
* still valid. | * still valid. | ||||
*/ | */ | ||||
if (bp->bio_cmd == BIO_FLUSH) { | if (bp->bio_cmd == BIO_FLUSH) { | ||||
(void) vn_start_write(vp, &mp, V_WAIT); | (void) vn_start_write(vp, &mp, V_WAIT); | ||||
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); | vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); | ||||
error = VOP_FSYNC(vp, MNT_WAIT, td); | error = VOP_FSYNC(vp, MNT_WAIT, td); | ||||
VOP_UNLOCK(vp); | VOP_UNLOCK(vp); | ||||
vn_finished_write(mp); | vn_finished_write(mp); | ||||
return (error); | return (error); | ||||
} else if (bp->bio_cmd == BIO_DELETE) { | |||||
error = vn_deallocate(vp, &off, &len, 0, | |||||
Done Inline ActionsLooks like there is no way to honour MD_SYNC? For writes it is translated to IO_SYNC, but here it looks like it would not be plumbed through VOP_DEALLOCATE. markj: Looks like there is no way to honour MD_SYNC? For writes it is translated to IO_SYNC, but here… | |||||
Done Inline ActionsFor the fallback part, do you think it is reasonable if we add a ioflg in VOP_DEALLOCATE that can accept IO_SYNC? Or do we just make it a vn_deallocate + VOP_FSYNC? On the other hand, posix_fallocate is another call that currently bypass IO_SYNC. khng: For the fallback part, do you think it is reasonable if we add a ioflg in VOP_DEALLOCATE that… | |||||
Done Inline ActionsI think that adding an additional parameter would be reasonable. Calling VOP_FSYNC() should also work but that seems like a hack, and it can in principle result in unnecessary I/O. I do not insist on fixing this for this review, but I would note it with an XXX comment or so. So posix_fallocate() does not respect O_SYNC, effectively, which is a bug IMO. markj: I think that adding an additional parameter would be reasonable. Calling VOP_FSYNC() should… | |||||
sc->flags & MD_ASYNC ? 0 : IO_SYNC, sc->cred, NOCRED); | |||||
bp->bio_resid = len; | |||||
Done Inline ActionsI believe we need to update bio->bp_resid as well. markj: I believe we need to update bio->bp_resid as well. | |||||
return (error); | |||||
} | } | ||||
auio.uio_offset = (vm_ooffset_t)bp->bio_offset; | auio.uio_offset = (vm_ooffset_t)bp->bio_offset; | ||||
auio.uio_resid = bp->bio_length; | auio.uio_resid = bp->bio_length; | ||||
auio.uio_segflg = UIO_SYSSPACE; | auio.uio_segflg = UIO_SYSSPACE; | ||||
auio.uio_td = td; | auio.uio_td = td; | ||||
if (bp->bio_cmd == BIO_DELETE) { | if ((bp->bio_flags & BIO_VLIST) != 0) { | ||||
/* | |||||
* Emulate BIO_DELETE by writing zeros. | |||||
*/ | |||||
zerosize = ZERO_REGION_SIZE - | |||||
(ZERO_REGION_SIZE % sc->sectorsize); | |||||
auio.uio_iovcnt = howmany(bp->bio_length, zerosize); | |||||
piov = malloc(sizeof(*piov) * auio.uio_iovcnt, M_MD, M_WAITOK); | |||||
auio.uio_iov = piov; | |||||
while (len > 0) { | |||||
piov->iov_base = __DECONST(void *, zero_region); | |||||
piov->iov_len = len; | |||||
if (len > zerosize) | |||||
piov->iov_len = zerosize; | |||||
len -= piov->iov_len; | |||||
piov++; | |||||
} | |||||
piov = auio.uio_iov; | |||||
} else if ((bp->bio_flags & BIO_VLIST) != 0) { | |||||
piov = malloc(sizeof(*piov) * bp->bio_ma_n, M_MD, M_WAITOK); | piov = malloc(sizeof(*piov) * bp->bio_ma_n, M_MD, M_WAITOK); | ||||
auio.uio_iov = piov; | auio.uio_iov = piov; | ||||
vlist = (bus_dma_segment_t *)bp->bio_data; | vlist = (bus_dma_segment_t *)bp->bio_data; | ||||
while (len > 0) { | while (len > 0) { | ||||
piov->iov_base = (void *)(uintptr_t)(vlist->ds_addr + | piov->iov_base = (void *)(uintptr_t)(vlist->ds_addr + | ||||
ma_offs); | ma_offs); | ||||
piov->iov_len = vlist->ds_len - ma_offs; | piov->iov_len = vlist->ds_len - ma_offs; | ||||
if (piov->iov_len > len) | if (piov->iov_len > len) | ||||
▲ Show 20 Lines • Show All 1,216 Lines • Show Last 20 Lines |
Harmless, but there's a missing break here.