diff options
Diffstat (limited to 'sys/kern/vfs_bio.c')
-rw-r--r-- | sys/kern/vfs_bio.c | 124 |
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; } |