summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2013-03-19 14:43:57 +0000
committerkib <kib@FreeBSD.org>2013-03-19 14:43:57 +0000
commite5332ab95582db8a564780b7e76fea59e30335a1 (patch)
treee048114eb9989a7f49051ebcc4027da6e0a571e4
parent2ace051956132678a2275297973eb6d294b4c8d5 (diff)
downloadFreeBSD-src-e5332ab95582db8a564780b7e76fea59e30335a1.zip
FreeBSD-src-e5332ab95582db8a564780b7e76fea59e30335a1.tar.gz
Do not remap usermode pages into KVA for physio.
Sponsored by: The FreeBSD Foundation Tested by: pho
-rw-r--r--sys/cam/cam_periph.c2
-rw-r--r--sys/kern/kern_physio.c2
-rw-r--r--sys/kern/vfs_aio.c2
-rw-r--r--sys/kern/vfs_bio.c24
-rw-r--r--sys/sys/buf.h2
-rw-r--r--sys/ufs/ffs/ffs_rawread.c4
6 files changed, 23 insertions, 13 deletions
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index 9ef359c..fa4fa04 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -850,7 +850,7 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
* into a larger area of VM, or if userland races against
* vmapbuf() after the useracc() check.
*/
- if (vmapbuf(mapinfo->bp[i]) < 0) {
+ if (vmapbuf(mapinfo->bp[i], 1) < 0) {
for (j = 0; j < i; ++j) {
*data_ptrs[j] = mapinfo->bp[j]->b_saveaddr;
vunmapbuf(mapinfo->bp[j]);
diff --git a/sys/kern/kern_physio.c b/sys/kern/kern_physio.c
index 34072f3..922ebb6 100644
--- a/sys/kern/kern_physio.c
+++ b/sys/kern/kern_physio.c
@@ -92,7 +92,7 @@ physio(struct cdev *dev, struct uio *uio, int ioflag)
bp->b_blkno = btodb(bp->b_offset);
if (uio->uio_segflg == UIO_USERSPACE)
- if (vmapbuf(bp) < 0) {
+ if (vmapbuf(bp, 0) < 0) {
error = EFAULT;
goto doerror;
}
diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c
index cafe440..4facd97 100644
--- a/sys/kern/vfs_aio.c
+++ b/sys/kern/vfs_aio.c
@@ -1323,7 +1323,7 @@ aio_qphysio(struct proc *p, struct aiocblist *aiocbe)
/*
* Bring buffer into kernel space.
*/
- if (vmapbuf(bp) < 0) {
+ if (vmapbuf(bp, 1) < 0) {
error = EFAULT;
goto doerror;
}
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 6f790d2..19eb895 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -4279,7 +4279,7 @@ vm_hold_free_pages(struct buf *bp, int newbsize)
* check the return value.
*/
int
-vmapbuf(struct buf *bp)
+vmapbuf(struct buf *bp, int mapbuf)
{
caddr_t kva;
vm_prot_t prot;
@@ -4294,12 +4294,19 @@ vmapbuf(struct buf *bp)
(vm_offset_t)bp->b_data, bp->b_bufsize, prot, bp->b_pages,
btoc(MAXPHYS))) < 0)
return (-1);
- pmap_qenter((vm_offset_t)bp->b_saveaddr, bp->b_pages, pidx);
-
- kva = bp->b_saveaddr;
bp->b_npages = pidx;
- bp->b_saveaddr = bp->b_data;
- bp->b_data = kva + (((vm_offset_t) bp->b_data) & PAGE_MASK);
+ if (mapbuf || !unmapped_buf_allowed) {
+ pmap_qenter((vm_offset_t)bp->b_saveaddr, bp->b_pages, pidx);
+ kva = bp->b_saveaddr;
+ bp->b_saveaddr = bp->b_data;
+ bp->b_data = kva + (((vm_offset_t)bp->b_data) & PAGE_MASK);
+ bp->b_flags &= ~B_UNMAPPED;
+ } else {
+ bp->b_flags |= B_UNMAPPED;
+ bp->b_offset = ((vm_offset_t)bp->b_data) & PAGE_MASK;
+ bp->b_saveaddr = bp->b_data;
+ bp->b_data = unmapped_buf;
+ }
return(0);
}
@@ -4313,7 +4320,10 @@ vunmapbuf(struct buf *bp)
int npages;
npages = bp->b_npages;
- pmap_qremove(trunc_page((vm_offset_t)bp->b_data), npages);
+ if (bp->b_flags & B_UNMAPPED)
+ bp->b_flags &= ~B_UNMAPPED;
+ else
+ pmap_qremove(trunc_page((vm_offset_t)bp->b_data), npages);
vm_page_unhold_pages(bp->b_pages, npages);
bp->b_data = bp->b_saveaddr;
diff --git a/sys/sys/buf.h b/sys/sys/buf.h
index d7025b0..0c7a6f4 100644
--- a/sys/sys/buf.h
+++ b/sys/sys/buf.h
@@ -524,7 +524,7 @@ void vfs_bio_set_valid(struct buf *, int base, int size);
void vfs_bio_clrbuf(struct buf *);
void vfs_busy_pages(struct buf *, int clear_modify);
void vfs_unbusy_pages(struct buf *);
-int vmapbuf(struct buf *);
+int vmapbuf(struct buf *, int);
void vunmapbuf(struct buf *);
void relpbuf(struct buf *, int *);
void brelvp(struct buf *);
diff --git a/sys/ufs/ffs/ffs_rawread.c b/sys/ufs/ffs/ffs_rawread.c
index cfdee3a..1c8aaec 100644
--- a/sys/ufs/ffs/ffs_rawread.c
+++ b/sys/ufs/ffs/ffs_rawread.c
@@ -241,7 +241,7 @@ ffs_rawread_readahead(struct vnode *vp,
bp->b_bcount = bsize - blockoff * DEV_BSIZE;
bp->b_bufsize = bp->b_bcount;
- if (vmapbuf(bp) < 0)
+ if (vmapbuf(bp, 1) < 0)
return EFAULT;
maybe_yield();
@@ -260,7 +260,7 @@ ffs_rawread_readahead(struct vnode *vp,
bp->b_bcount = bsize * (1 + bforwards) - blockoff * DEV_BSIZE;
bp->b_bufsize = bp->b_bcount;
- if (vmapbuf(bp) < 0)
+ if (vmapbuf(bp, 1) < 0)
return EFAULT;
BO_STRATEGY(&dp->v_bufobj, bp);
OpenPOWER on IntegriCloud