diff options
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_malloc.c | 36 | ||||
-rw-r--r-- | sys/kern/kern_physio.c | 8 | ||||
-rw-r--r-- | sys/kern/subr_rlist.c | 11 | ||||
-rw-r--r-- | sys/kern/sysv_shm.c | 3 | ||||
-rw-r--r-- | sys/kern/uipc_syscalls.c | 29 | ||||
-rw-r--r-- | sys/kern/uipc_usrreq.c | 9 | ||||
-rw-r--r-- | sys/kern/vfs_aio.c | 10 | ||||
-rw-r--r-- | sys/kern/vfs_bio.c | 119 | ||||
-rw-r--r-- | sys/kern/vfs_cluster.c | 10 | ||||
-rw-r--r-- | sys/kern/vfs_export.c | 46 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 46 |
11 files changed, 241 insertions, 86 deletions
diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c index a9776a5..be9f9d3 100644 --- a/sys/kern/kern_malloc.c +++ b/sys/kern/kern_malloc.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)kern_malloc.c 8.3 (Berkeley) 1/4/94 - * $Id: kern_malloc.c,v 1.50 1999/01/08 17:31:09 eivind Exp $ + * $Id: kern_malloc.c,v 1.51 1999/01/10 01:58:24 eivind Exp $ */ #include "opt_vm.h" @@ -101,7 +101,16 @@ struct freelist { #endif /* INVARIANTS */ /* - * Allocate a block of memory + * malloc: + * + * Allocate a block of memory. + * + * If M_NOWAIT is set, this routine will not block and return NULL if + * the allocation fails. + * + * If M_ASLEEP is set (M_NOWAIT must also be set), this routine + * will have the side effect of calling asleep() if it returns NULL, + * allowing the parent to await() at some future time. */ void * malloc(size, type, flags) @@ -122,13 +131,26 @@ malloc(size, type, flags) #endif register struct malloc_type *ksp = type; - if (!type->ks_next) + /* + * Must be at splmem() prior to initializing segment to handle + * potential initialization race. + */ + + s = splmem(); + + if (!type->ks_next) { malloc_init(type); + } indx = BUCKETINDX(size); kbp = &bucket[indx]; - s = splmem(); + while (ksp->ks_memuse >= ksp->ks_limit) { + if (flags & M_ASLEEP) { + if (ksp->ks_limblocks < 65535) + ksp->ks_limblocks++; + asleep((caddr_t)ksp, PSWP+2, type->ks_shortdesc, 0); + } if (flags & M_NOWAIT) { splx(s); return ((void *) NULL); @@ -239,7 +261,11 @@ out: } /* - * Free a block of memory allocated by malloc. + * free: + * + * Free a block of memory allocated by malloc. + * + * This routine may not block. */ void free(addr, type) diff --git a/sys/kern/kern_physio.c b/sys/kern/kern_physio.c index 441d95f..ad63a98 100644 --- a/sys/kern/kern_physio.c +++ b/sys/kern/kern_physio.c @@ -16,7 +16,7 @@ * 4. Modifications may be freely made to this file if the above conditions * are met. * - * $Id: kern_physio.c,v 1.28 1998/08/19 10:50:32 sos Exp $ + * $Id: kern_physio.c,v 1.29 1998/10/25 17:44:51 phk Exp $ */ #include <sys/param.h> @@ -147,7 +147,7 @@ physio(strategy, bp, dev, rw, minp, uio) doerror: - relpbuf(bpa); + relpbuf(bpa, NULL); if (!bp_alloc) { bp->b_flags &= ~(B_BUSY|B_PHYS); if( bp->b_flags & B_WANTED) { @@ -197,13 +197,13 @@ phygetvpbuf(dev_t dev, int resid) bdsw = cdevsw[major(dev)]; if ((bdsw == NULL) || (bdsw->d_bmaj == -1)) - return getpbuf(); + return getpbuf(NULL); maxio = bdsw->d_maxio; if (resid > maxio) resid = maxio; - return getpbuf(); + return getpbuf(NULL); } static void diff --git a/sys/kern/subr_rlist.c b/sys/kern/subr_rlist.c index d637ab4..810b87e 100644 --- a/sys/kern/subr_rlist.c +++ b/sys/kern/subr_rlist.c @@ -13,7 +13,7 @@ * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This software is a component of "386BSD" developed by - William F. Jolitz, TeleMuse. + * William F. Jolitz, TeleMuse. * 4. Neither the name of the developer nor the name "386BSD" * may be used to endorse or promote products derived from this software * without specific prior written permission. @@ -54,9 +54,13 @@ * functioning of this software, nor does the author assume any responsibility * for damages incurred with its use. * - * $Id: subr_rlist.c,v 1.28 1999/01/08 17:31:12 eivind Exp $ + * --------- DEPRECIATED --------- + * + * $Id: subr_rlist.c,v 1.29 1999/01/10 01:58:25 eivind Exp $ */ +#if 0 + #include <sys/param.h> #include <sys/systm.h> #include <sys/rlist.h> @@ -307,3 +311,6 @@ rlist_destroy (rlh) rlist_mfree(lp); } } + +#endif + diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c index edc74a7..a6c2dfe 100644 --- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -1,4 +1,4 @@ -/* $Id: sysv_shm.c,v 1.38 1998/08/24 08:39:38 dfr Exp $ */ +/* $Id: sysv_shm.c,v 1.39 1998/10/13 08:24:40 dg Exp $ */ /* $NetBSD: sysv_shm.c,v 1.23 1994/07/04 23:25:12 glass Exp $ */ /* @@ -52,6 +52,7 @@ #include <vm/pmap.h> #include <vm/vm_object.h> #include <vm/vm_map.h> +#include <vm/vm_page.h> #include <vm/vm_pager.h> #include <vm/vm_inherit.h> diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 6cc487a..1634681 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 - * $Id: uipc_syscalls.c,v 1.48 1998/12/03 12:35:47 dg Exp $ + * $Id: uipc_syscalls.c,v 1.49 1998/12/07 21:58:29 archie Exp $ */ #include "opt_compat.h" @@ -1543,7 +1543,13 @@ retry_lookup: VM_WAIT; goto retry_lookup; } - vm_page_flag_clear(pg, PG_BUSY); + /* + * don't just clear PG_BUSY manually - + * vm_page_alloc() should be considered opaque, + * use the VM routine provided to clear + * PG_BUSY. + */ + vm_page_wakeup(pg); } /* * Ensure that our page is still around when the I/O completes. @@ -1583,21 +1589,12 @@ retry_lookup: goto done; } } else { - if ((pg->flags & PG_BUSY) || pg->busy) { - s = splvm(); - if ((pg->flags & PG_BUSY) || pg->busy) { - /* - * Page is busy. Wait and retry. - */ - vm_page_flag_set(pg, PG_WANTED); - tsleep(pg, PVM, "sfpbsy", 0); - splx(s); - goto retry_lookup; - } - splx(s); - } + if (vm_page_sleep_busy(pg, TRUE, "sfpbsy")) + goto retry_lookup; + /* - * Protect from having the page ripped out from beneath us. + * Protect from having the page ripped out from + * beneath us. */ vm_page_wire(pg); } diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 93f6164..d528f5e 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94 - * $Id: uipc_usrreq.c,v 1.36 1998/07/15 02:32:12 bde Exp $ + * $Id: uipc_usrreq.c,v 1.37 1998/10/25 17:44:51 phk Exp $ */ #include <sys/param.h> @@ -1114,8 +1114,11 @@ unp_gc() /* * for each FD on our hit list, do the following two things */ - for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) - sorflush((struct socket *)(*fpp)->f_data); + for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) { + struct file *tfp = *fpp; + if (tfp->f_type == DTYPE_SOCKET && tfp->f_data != NULL) + sorflush((struct socket *)(tfp->f_data)); + } for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) closef(*fpp, (struct proc *) NULL); free((caddr_t)extra_ref, M_FILE); diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index c7c8aa9..c1af873 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -13,7 +13,7 @@ * bad that happens because of using this software isn't the responsibility * of the author. This software is distributed AS-IS. * - * $Id: vfs_aio.c,v 1.35 1998/11/27 01:14:21 tegge Exp $ + * $Id: vfs_aio.c,v 1.36 1998/12/15 17:38:33 des Exp $ */ /* @@ -386,7 +386,7 @@ aio_free_entry(struct aiocblist *aiocbe) splx(s); if (aiocbe->bp) { vunmapbuf(aiocbe->bp); - relpbuf(aiocbe->bp); + relpbuf(aiocbe->bp, NULL); aiocbe->bp = NULL; } } @@ -1035,7 +1035,7 @@ aio_qphysio(p, aiocbe) } /* create and build a buffer header for a transfer */ - bp = (struct buf *)getpbuf(); + bp = (struct buf *)getpbuf(NULL); /* * get a copy of the kva from the physical buffer @@ -1122,7 +1122,7 @@ doerror: lj->lioj_buffer_count--; } aiocbe->bp = NULL; - relpbuf(bp); + relpbuf(bp, NULL); return error; } @@ -1172,7 +1172,7 @@ aio_fphysio(p, iocb, flgwait) error = bp->b_error; } - relpbuf(bp); + relpbuf(bp, NULL); return (error); } diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 30018b5..3bb204e 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -11,7 +11,7 @@ * 2. Absolutely no warranty of function or purpose is made by the author * John S. Dyson. * - * $Id: vfs_bio.c,v 1.192 1999/01/12 11:59:34 eivind Exp $ + * $Id: vfs_bio.c,v 1.193 1999/01/19 08:00:51 dillon Exp $ */ /* @@ -562,7 +562,7 @@ brelse(struct buf * bp) int s; if (bp->b_flags & B_CLUSTER) { - relpbuf(bp); + relpbuf(bp, NULL); return; } @@ -1364,6 +1364,7 @@ vfs_setdirty(struct buf *bp) { break; } } + boffset = (i << PAGE_SHIFT) - (bp->b_offset & PAGE_MASK); if (boffset < bp->b_dirtyoff) { bp->b_dirtyoff = max(boffset, 0); @@ -1412,7 +1413,6 @@ loop: if ((bp = gbincore(vp, blkno))) { if (bp->b_flags & B_BUSY) { - bp->b_flags |= B_WANTED; if (bp->b_usecount < BUF_MAXUSE) ++bp->b_usecount; @@ -1429,16 +1429,13 @@ loop: bremfree(bp); /* - * check for size inconsistancies (note that they shouldn't - * happen but do when filesystems don't handle the size changes - * correctly.) We are conservative on metadata and don't just - * extend the buffer but write (if needed) and re-constitute it. + * check for size inconsistancies for non-VMIO case. */ if (bp->b_bcount != size) { - if ((bp->b_flags & B_VMIO) && (size <= bp->b_kvasize)) { - allocbuf(bp, size); - } else { + if ((bp->b_flags & B_VMIO) == 0 || + (size > bp->b_kvasize) + ) { if (bp->b_flags & B_DELWRI) { bp->b_flags |= B_NOCACHE; VOP_BWRITE(bp); @@ -1455,15 +1452,26 @@ loop: goto loop; } } + + /* + * If the size is inconsistant in the VMIO case, we can resize + * the buffer. This might lead to B_CACHE getting cleared. + */ + + if (bp->b_bcount != size) + allocbuf(bp, size); + KASSERT(bp->b_offset != NOOFFSET, ("getblk: no buffer offset")); + /* * Check that the constituted buffer really deserves for the * B_CACHE bit to be set. B_VMIO type buffers might not * contain fully valid pages. Normal (old-style) buffers - * should be fully valid. + * should be fully valid. This might also lead to B_CACHE + * getting clear. */ - if (bp->b_flags & B_VMIO) { + if ((bp->b_flags & B_VMIO|B_CACHE) == (B_VMIO|B_CACHE)) { int checksize = bp->b_bufsize; int poffset = bp->b_offset & PAGE_MASK; int resid; @@ -1479,6 +1487,19 @@ loop: } } + /* + * If B_DELWRI is set and B_CACHE got cleared ( or was + * already clear ), we have to commit the write and + * retry. The NFS code absolutely depends on this, + * and so might the FFS code. In anycase, it formalizes + * the B_CACHE rules. See sys/buf.h. + */ + + if ((bp->b_flags & (B_CACHE|B_DELWRI)) == B_DELWRI) { + VOP_BWRITE(bp); + goto loop; + } + if (bp->b_usecount < BUF_MAXUSE) ++bp->b_usecount; splx(s); @@ -1572,19 +1593,18 @@ geteblk(int size) /* * This code constitutes the buffer memory from either anonymous system * memory (in the case of non-VMIO operations) or from an associated - * VM object (in the case of VMIO operations). + * VM object (in the case of VMIO operations). This code is able to + * resize a buffer up or down. * * Note that this code is tricky, and has many complications to resolve - * deadlock or inconsistant data situations. Tread lightly!!! - * - * Modify the length of a buffer's underlying buffer storage without - * destroying information (unless, of course the buffer is shrinking). + * deadlock or inconsistant data situations. Tread lightly!!! + * There are B_CACHE and B_DELWRI interactions that must be dealt with by + * the caller. Calling this code willy nilly can result in the loss of data. */ + int -allocbuf(struct buf * bp, int size) +allocbuf(struct buf *bp, int size) { - - int s; int newbsize, mbsize; int i; @@ -1705,7 +1725,8 @@ allocbuf(struct buf * bp, int size) m = bp->b_pages[i]; KASSERT(m != bogus_page, ("allocbuf: bogus page found")); - vm_page_sleep(m, "biodep", &m->busy); + while (vm_page_sleep_busy(m, TRUE, "biodep")) + ; bp->b_pages[i] = NULL; vm_page_unwire(m, 0); @@ -1771,16 +1792,25 @@ allocbuf(struct buf * bp, int size) } vm_page_wire(m); - vm_page_flag_clear(m, PG_BUSY); + vm_page_wakeup(m); bp->b_flags &= ~B_CACHE; - } else if (m->flags & PG_BUSY) { - s = splvm(); - if (m->flags & PG_BUSY) { - vm_page_flag_set(m, PG_WANTED); - tsleep(m, PVM, "pgtblk", 0); - } - splx(s); + } else if (vm_page_sleep_busy(m, FALSE, "pgtblk")) { + /* + * If we had to sleep, retry. + * + * Also note that we only test + * PG_BUSY here, not m->busy. + * + * We cannot sleep on m->busy + * here because a vm_fault -> + * getpages -> cluster-read -> + * ...-> allocbuf sequence + * will convert PG_BUSY to + * m->busy so we have to let + * m->busy through if we do + * not want to deadlock. + */ goto doretry; } else { if ((curproc != pageproc) && @@ -2010,12 +2040,8 @@ biodone(register struct buf * bp) foff += resid; iosize -= resid; } - if (obj && - (obj->paging_in_progress == 0) && - (obj->flags & OBJ_PIPWNT)) { - vm_object_clear_flag(obj, OBJ_PIPWNT); - wakeup(obj); - } + if (obj) + vm_object_pip_wakeupn(obj, 0); } /* * For asynchronous completions, release the buffer now. The brelse @@ -2096,11 +2122,7 @@ vfs_unbusy_pages(struct buf * bp) vm_page_flag_clear(m, PG_ZERO); vm_page_io_finish(m); } - if (obj->paging_in_progress == 0 && - (obj->flags & OBJ_PIPWNT)) { - vm_object_clear_flag(obj, OBJ_PIPWNT); - wakeup(obj); - } + vm_object_pip_wakeupn(obj, 0); } } @@ -2109,6 +2131,8 @@ vfs_unbusy_pages(struct buf * bp) * of a page. If the consumer is not NFS, and the page is not * valid for the entire range, clear the B_CACHE flag to force * the consumer to re-read the page. + * + * B_CACHE interaction is especially tricky. */ static void vfs_buf_set_valid(struct buf *bp, @@ -2135,13 +2159,16 @@ vfs_buf_set_valid(struct buf *bp, } evalid = min(evalid, off + size); /* - * Make sure this range is contiguous with the range - * built up from previous pages. If not, then we will - * just use the range from the previous pages. + * We can only set b_validoff/end if this range is contiguous + * with the range built up already. If we cannot set + * b_validoff/end, we must clear B_CACHE to force an update + * to clean the bp up. */ if (svalid == bp->b_validend) { bp->b_validoff = min(bp->b_validoff, svalid); bp->b_validend = max(bp->b_validend, evalid); + } else { + bp->b_flags &= ~B_CACHE; } } else if (!vm_page_is_valid(m, (vm_offset_t) ((foff + off) & PAGE_MASK), @@ -2154,6 +2181,10 @@ vfs_buf_set_valid(struct buf *bp, * Set the valid bits in a page, taking care of the b_validoff, * b_validend fields which NFS uses to optimise small reads. Off is * the offset within the file and pageno is the page index within the buf. + * + * XXX we have to set the valid & clean bits for all page fragments + * touched by b_validoff/validend, even if the page fragment goes somewhat + * beyond b_validoff/validend due to alignment. */ static void vfs_page_set_valid(struct buf *bp, vm_ooffset_t off, int pageno, vm_page_t m) @@ -2208,7 +2239,7 @@ vfs_busy_pages(struct buf * bp, int clear_modify) retry: for (i = 0; i < bp->b_npages; i++) { vm_page_t m = bp->b_pages[i]; - if (vm_page_sleep(m, "vbpage", NULL)) + if (vm_page_sleep_busy(m, FALSE, "vbpage")) goto retry; } diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c index ce842ad..781508e 100644 --- a/sys/kern/vfs_cluster.c +++ b/sys/kern/vfs_cluster.c @@ -33,7 +33,7 @@ * SUCH DAMAGE. * * @(#)vfs_cluster.c 8.7 (Berkeley) 2/13/94 - * $Id: vfs_cluster.c,v 1.76 1999/01/08 17:31:15 eivind Exp $ + * $Id: vfs_cluster.c,v 1.77 1999/01/10 01:58:25 eivind Exp $ */ #include "opt_debug_cluster.h" @@ -68,6 +68,8 @@ static struct buf * extern vm_page_t bogus_page; +extern int cluster_pbuf_freecnt; + /* * Maximum number of blocks for read-ahead. */ @@ -336,7 +338,7 @@ cluster_rbuild(vp, filesize, lbn, blkno, size, run, fbp) ((tbp->b_flags & B_VMIO) == 0) || (run <= 1) ) return tbp; - bp = trypbuf(); + bp = trypbuf(&cluster_pbuf_freecnt); if (bp == 0) return tbp; @@ -475,7 +477,7 @@ cluster_callback(bp) tbp->b_dirtyoff = tbp->b_dirtyend = 0; biodone(tbp); } - relpbuf(bp); + relpbuf(bp, &cluster_pbuf_freecnt); } /* @@ -654,7 +656,7 @@ cluster_wbuild(vp, size, start_lbn, len) (tbp->b_bcount != tbp->b_bufsize) || (tbp->b_bcount != size) || (len == 1) || - ((bp = trypbuf()) == NULL)) { + ((bp = trypbuf(&cluster_pbuf_freecnt)) == NULL)) { totalwritten += tbp->b_bufsize; bawrite(tbp); ++start_lbn; diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c index 179ef78..44b1698 100644 --- a/sys/kern/vfs_export.c +++ b/sys/kern/vfs_export.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95 - * $Id: vfs_subr.c,v 1.181 1999/01/08 17:31:17 eivind Exp $ + * $Id: vfs_subr.c,v 1.182 1999/01/10 01:58:26 eivind Exp $ */ /* @@ -63,10 +63,13 @@ #include <machine/limits.h> #include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/vm_prot.h> #include <vm/vm_object.h> #include <vm/vm_extern.h> #include <vm/pmap.h> #include <vm/vm_map.h> +#include <vm/vm_page.h> #include <vm/vm_pager.h> #include <vm/vnode_pager.h> #include <vm/vm_zone.h> @@ -985,6 +988,10 @@ sched_sync(void) /* * Associate a p-buffer with a vnode. + * + * Also sets B_PAGING flag to indicate that vnode is not fully associated + * with the buffer. i.e. the bp has not been linked into the vnode or + * ref-counted. */ void pbgetvp(vp, bp) @@ -995,6 +1002,7 @@ pbgetvp(vp, bp) KASSERT(bp->b_vp == NULL, ("pbgetvp: not free")); bp->b_vp = vp; + bp->b_flags |= B_PAGING; if (vp->v_type == VBLK || vp->v_type == VCHR) bp->b_dev = vp->v_rdev; else @@ -1011,7 +1019,34 @@ pbrelvp(bp) KASSERT(bp->b_vp != NULL, ("pbrelvp: NULL")); +#if !defined(MAX_PERF) + /* XXX REMOVE ME */ + if (bp->b_vnbufs.tqe_next != NULL) { + panic( + "relpbuf(): b_vp was probably reassignbuf()d %p %x", + bp, + (int)bp->b_flags + ); + } +#endif bp->b_vp = (struct vnode *) 0; + bp->b_flags &= ~B_PAGING; +} + +void +pbreassignbuf(bp, newvp) + struct buf *bp; + struct vnode *newvp; +{ +#if !defined(MAX_PERF) + if ((bp->b_flags & B_PAGING) == 0) { + panic( + "pbreassignbuf() on non phys bp %p", + bp + ); + } +#endif + bp->b_vp = newvp; } /* @@ -1034,6 +1069,15 @@ reassignbuf(bp, newvp) return; } +#if !defined(MAX_PERF) + /* + * B_PAGING flagged buffers cannot be reassigned because their vp + * is not fully linked in. + */ + if (bp->b_flags & B_PAGING) + panic("cannot reassign paging buffer"); +#endif + s = splbio(); /* * Delete from old vnode list, if on one. diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 179ef78..44b1698 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95 - * $Id: vfs_subr.c,v 1.181 1999/01/08 17:31:17 eivind Exp $ + * $Id: vfs_subr.c,v 1.182 1999/01/10 01:58:26 eivind Exp $ */ /* @@ -63,10 +63,13 @@ #include <machine/limits.h> #include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/vm_prot.h> #include <vm/vm_object.h> #include <vm/vm_extern.h> #include <vm/pmap.h> #include <vm/vm_map.h> +#include <vm/vm_page.h> #include <vm/vm_pager.h> #include <vm/vnode_pager.h> #include <vm/vm_zone.h> @@ -985,6 +988,10 @@ sched_sync(void) /* * Associate a p-buffer with a vnode. + * + * Also sets B_PAGING flag to indicate that vnode is not fully associated + * with the buffer. i.e. the bp has not been linked into the vnode or + * ref-counted. */ void pbgetvp(vp, bp) @@ -995,6 +1002,7 @@ pbgetvp(vp, bp) KASSERT(bp->b_vp == NULL, ("pbgetvp: not free")); bp->b_vp = vp; + bp->b_flags |= B_PAGING; if (vp->v_type == VBLK || vp->v_type == VCHR) bp->b_dev = vp->v_rdev; else @@ -1011,7 +1019,34 @@ pbrelvp(bp) KASSERT(bp->b_vp != NULL, ("pbrelvp: NULL")); +#if !defined(MAX_PERF) + /* XXX REMOVE ME */ + if (bp->b_vnbufs.tqe_next != NULL) { + panic( + "relpbuf(): b_vp was probably reassignbuf()d %p %x", + bp, + (int)bp->b_flags + ); + } +#endif bp->b_vp = (struct vnode *) 0; + bp->b_flags &= ~B_PAGING; +} + +void +pbreassignbuf(bp, newvp) + struct buf *bp; + struct vnode *newvp; +{ +#if !defined(MAX_PERF) + if ((bp->b_flags & B_PAGING) == 0) { + panic( + "pbreassignbuf() on non phys bp %p", + bp + ); + } +#endif + bp->b_vp = newvp; } /* @@ -1034,6 +1069,15 @@ reassignbuf(bp, newvp) return; } +#if !defined(MAX_PERF) + /* + * B_PAGING flagged buffers cannot be reassigned because their vp + * is not fully linked in. + */ + if (bp->b_flags & B_PAGING) + panic("cannot reassign paging buffer"); +#endif + s = splbio(); /* * Delete from old vnode list, if on one. |