summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_bio.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/vfs_bio.c')
-rw-r--r--sys/kern/vfs_bio.c124
1 files changed, 24 insertions, 100 deletions
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index ccde4b4..06e8625 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -1647,8 +1647,7 @@ vfs_vmio_release(struct buf *bp)
* no valid data. We also free the page if the
* buffer was used for direct I/O
*/
- if ((bp->b_flags & B_ASYNC) == 0 && !m->valid &&
- m->hold_count == 0) {
+ if ((bp->b_flags & B_ASYNC) == 0 && !m->valid) {
vm_page_free(m);
} else if (bp->b_flags & B_DIRECT) {
vm_page_try_to_free(m);
@@ -2235,7 +2234,7 @@ buf_daemon()
while (numdirtybuffers > lodirtybuffers) {
if (buf_do_flush(NULL) == 0)
break;
- uio_yield();
+ kern_yield(-1);
}
lodirtybuffers = lodirtysave;
@@ -2523,7 +2522,7 @@ vfs_setdirty_locked_object(struct buf *bp)
* We qualify the scan for modified pages on whether the
* object has been flushed yet.
*/
- if (object->flags & (OBJ_MIGHTBEDIRTY|OBJ_CLEANING)) {
+ if ((object->flags & OBJ_MIGHTBEDIRTY) != 0) {
vm_offset_t boffset;
vm_offset_t eoffset;
@@ -2831,11 +2830,6 @@ loop:
if (vmio) {
bp->b_flags |= B_VMIO;
-#if defined(VFS_BIO_DEBUG)
- if (vn_canvmio(vp) != TRUE)
- printf("getblk: VMIO on vnode type %d\n",
- vp->v_type);
-#endif
KASSERT(vp->v_object == bp->b_bufobj->bo_object,
("ARGH! different b_bufobj->bo_object %p %p %p\n",
bp, vp->v_object, bp->b_bufobj->bo_object));
@@ -3344,36 +3338,26 @@ bufdone_finish(struct buf *bp)
buf_complete(bp);
if (bp->b_flags & B_VMIO) {
- int i;
vm_ooffset_t foff;
vm_page_t m;
vm_object_t obj;
- int bogus, iosize;
- struct vnode *vp = bp->b_vp;
+ struct vnode *vp;
+ int bogus, i, iosize;
obj = bp->b_bufobj->bo_object;
+ KASSERT(obj->paging_in_progress >= bp->b_npages,
+ ("biodone_finish: paging in progress(%d) < b_npages(%d)",
+ obj->paging_in_progress, bp->b_npages));
-#if defined(VFS_BIO_DEBUG)
- mp_fixme("usecount and vflag accessed without locks.");
- if (vp->v_usecount == 0) {
- panic("biodone: zero vnode ref count");
- }
-
+ vp = bp->b_vp;
+ KASSERT(vp->v_holdcnt > 0,
+ ("biodone_finish: vnode %p has zero hold count", vp));
KASSERT(vp->v_object != NULL,
- ("biodone: vnode %p has no vm_object", vp));
-#endif
+ ("biodone_finish: vnode %p has no vm_object", vp));
foff = bp->b_offset;
KASSERT(bp->b_offset != NOOFFSET,
- ("biodone: no buffer offset"));
-
- VM_OBJECT_LOCK(obj);
-#if defined(VFS_BIO_DEBUG)
- if (obj->paging_in_progress < bp->b_npages) {
- printf("biodone: paging in progress(%d) < bp->b_npages(%d)\n",
- obj->paging_in_progress, bp->b_npages);
- }
-#endif
+ ("biodone_finish: bp %p has no buffer offset", bp));
/*
* Set B_CACHE if the op was a normal read and no error
@@ -3387,6 +3371,7 @@ bufdone_finish(struct buf *bp)
bp->b_flags |= B_CACHE;
}
bogus = 0;
+ VM_OBJECT_LOCK(obj);
for (i = 0; i < bp->b_npages; i++) {
int bogusflag = 0;
int resid;
@@ -3406,13 +3391,9 @@ bufdone_finish(struct buf *bp)
panic("biodone: page disappeared!");
bp->b_pages[i] = m;
}
-#if defined(VFS_BIO_DEBUG)
- if (OFF_TO_IDX(foff) != m->pindex) {
- printf(
-"biodone: foff(%jd)/m->pindex(%ju) mismatch\n",
- (intmax_t)foff, (uintmax_t)m->pindex);
- }
-#endif
+ KASSERT(OFF_TO_IDX(foff) == m->pindex,
+ ("biodone_finish: foff(%jd)/pindex(%ju) mismatch",
+ (intmax_t)foff, (uintmax_t)m->pindex));
/*
* In the write case, the valid and clean bits are
@@ -3426,31 +3407,6 @@ bufdone_finish(struct buf *bp)
vfs_page_set_valid(bp, foff, m);
}
- /*
- * when debugging new filesystems or buffer I/O methods, this
- * is the most common error that pops up. if you see this, you
- * have not set the page busy flag correctly!!!
- */
- if (m->busy == 0) {
- printf("biodone: page busy < 0, "
- "pindex: %d, foff: 0x(%x,%x), "
- "resid: %d, index: %d\n",
- (int) m->pindex, (int)(foff >> 32),
- (int) foff & 0xffffffff, resid, i);
- if (!vn_isdisk(vp, NULL))
- printf(" iosize: %jd, lblkno: %jd, flags: 0x%x, npages: %d\n",
- (intmax_t)bp->b_vp->v_mount->mnt_stat.f_iosize,
- (intmax_t) bp->b_lblkno,
- bp->b_flags, bp->b_npages);
- else
- printf(" VDEV, lblkno: %jd, flags: 0x%x, npages: %d\n",
- (intmax_t) bp->b_lblkno,
- bp->b_flags, bp->b_npages);
- printf(" valid: 0x%lx, dirty: 0x%lx, wired: %d\n",
- (u_long)m->valid, (u_long)m->dirty,
- m->wire_count);
- panic("biodone: page busy < 0\n");
- }
vm_page_io_finish(m);
vm_object_pip_subtract(obj, 1);
foff = (foff + PAGE_SIZE) & ~(off_t)PAGE_MASK;
@@ -3855,46 +3811,19 @@ vm_hold_free_pages(struct buf *bp, int newbsize)
int
vmapbuf(struct buf *bp)
{
- caddr_t addr, kva;
+ caddr_t kva;
vm_prot_t prot;
- int pidx, i;
- struct vm_page *m;
- struct pmap *pmap = &curproc->p_vmspace->vm_pmap;
+ int pidx;
if (bp->b_bufsize < 0)
return (-1);
prot = VM_PROT_READ;
if (bp->b_iocmd == BIO_READ)
prot |= VM_PROT_WRITE; /* Less backwards than it looks */
- for (addr = (caddr_t)trunc_page((vm_offset_t)bp->b_data), pidx = 0;
- addr < bp->b_data + bp->b_bufsize;
- addr += PAGE_SIZE, pidx++) {
- /*
- * Do the vm_fault if needed; do the copy-on-write thing
- * when reading stuff off device into memory.
- *
- * NOTE! Must use pmap_extract() because addr may be in
- * the userland address space, and kextract is only guarenteed
- * to work for the kernland address space (see: sparc64 port).
- */
-retry:
- if (vm_fault_quick(addr >= bp->b_data ? addr : bp->b_data,
- prot) < 0) {
- for (i = 0; i < pidx; ++i) {
- vm_page_lock(bp->b_pages[i]);
- vm_page_unhold(bp->b_pages[i]);
- vm_page_unlock(bp->b_pages[i]);
- bp->b_pages[i] = NULL;
- }
- return(-1);
- }
- m = pmap_extract_and_hold(pmap, (vm_offset_t)addr, prot);
- if (m == NULL)
- goto retry;
- bp->b_pages[pidx] = m;
- }
- if (pidx > btoc(MAXPHYS))
- panic("vmapbuf: mapped more than MAXPHYS");
+ if ((pidx = vm_fault_quick_hold_pages(&curproc->p_vmspace->vm_map,
+ (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;
@@ -3911,16 +3840,11 @@ retry:
void
vunmapbuf(struct buf *bp)
{
- int pidx;
int npages;
npages = bp->b_npages;
pmap_qremove(trunc_page((vm_offset_t)bp->b_data), npages);
- for (pidx = 0; pidx < npages; pidx++) {
- vm_page_lock(bp->b_pages[pidx]);
- vm_page_unhold(bp->b_pages[pidx]);
- vm_page_unlock(bp->b_pages[pidx]);
- }
+ vm_page_unhold_pages(bp->b_pages, npages);
bp->b_data = bp->b_saveaddr;
}
OpenPOWER on IntegriCloud