if (bp->b_dirtyend == 0) { nbp->vb_buf.b_dirtyoff = 0; nbp->vb_buf.b_dirtyend = sz; } else { nbp->vb_buf.b_dirtyoff = max(0, bp->b_dirtyoff - (bp->b_bcount-resid)); nbp->vb_buf.b_dirtyend = min(sz, max(0, bp->b_dirtyend - (bp->b_bcount-resid))); } if (bp->b_validend == 0) { nbp->vb_buf.b_validoff = 0; nbp->vb_buf.b_validend = sz; } else { nbp->vb_buf.b_validoff = max(0, bp->b_validoff - (bp->b_bcount-resid)); nbp->vb_buf.b_validend = min(sz, max(0, bp->b_validend - (bp->b_bcount-resid))); }
sw_reg_strategy(sdp, bp, bn)	struct swapdev	*sdp;	struct buf	*bp;	int		bn;{	struct vnode	*vp;	struct vndxfer	*vnx;	daddr_t		nbn;	caddr_t		addr;	off_t		byteoff;	int		s, off, nra, error, sz, resid;	UVMHIST_FUNC("sw_reg_strategy"); UVMHIST_CALLED(pdhist);	/*	 * allocate a vndxfer head for this transfer and point it to	 * our buffer.	 */	getvndxfer(vnx);	vnx->vx_flags = VX_BUSY;	vnx->vx_error = 0;	vnx->vx_pending = 0;	vnx->vx_bp = bp;	vnx->vx_sdp = sdp;	/*	 * setup for main loop where we read filesystem blocks into	 * our buffer.	 */	error = 0;	bp->b_resid = bp->b_bcount;	/* nothing transferred yet! */	addr = bp->b_data;		/* current position in buffer */	byteoff = dbtob((u_int64_t)bn);	for (resid = bp->b_resid; resid; resid -= sz) {		struct vndbuf	*nbp;		/*		 * translate byteoffset into block number.  return values:		 *   vp = vnode of underlying device		 *  nbn = new block number (on underlying vnode dev)		 *  nra = num blocks we can read-ahead (excludes requested		 *	block)		 */		nra = 0;		error = VOP_BMAP(sdp->swd_vp, byteoff / sdp->swd_bsize,				 	&vp, &nbn, &nra);		if (error == 0 && nbn == (daddr_t)-1) {			/*			 * this used to just set error, but that doesn't			 * do the right thing.  Instead, it causes random			 * memory errors.  The panic() should remain until			 * this condition doesn't destabilize the system.			 */#if 1			panic("sw_reg_strategy: swap to sparse file");#else			error = EIO;	/* failure */#endif		}		/*		 * punt if there was an error or a hole in the file.		 * we must wait for any i/o ops we have already started		 * to finish before returning.		 *		 * XXX we could deal with holes here but it would be		 * a hassle (in the write case).		 */		if (error) {			s = splbio();			vnx->vx_error = error;	/* pass error up */			goto out;		}		/*		 * compute the size ("sz") of this transfer (in bytes).		 */		off = byteoff % sdp->swd_bsize;		sz = (1 + nra) * sdp->swd_bsize - off;		if (sz > resid)			sz = resid;		UVMHIST_LOG(pdhist, "sw_reg_strategy: "			    "vp %p/%p offset 0x%x/0x%x",			    sdp->swd_vp, vp, byteoff, nbn);		/*		 * now get a buf structure.   note that the vb_buf is		 * at the front of the nbp structure so that you can		 * cast pointers between the two structure easily.		 */		getvndbuf(nbp);		nbp->vb_buf.b_flags    = bp->b_flags | B_CALL;		nbp->vb_buf.b_bcount   = sz;		nbp->vb_buf.b_bufsize  = sz;		nbp->vb_buf.b_error    = 0;		nbp->vb_buf.b_data     = addr;		nbp->vb_buf.b_blkno    = nbn + btodb(off);		nbp->vb_buf.b_proc     = bp->b_proc;		nbp->vb_buf.b_iodone   = sw_reg_iodone;		nbp->vb_buf.b_vp       = NULLVP;		nbp->vb_buf.b_vnbufs.le_next = NOLIST;		LIST_INIT(&nbp->vb_buf.b_dep);		nbp->vb_xfer = vnx;	/* patch it back in to vnx */		/*		 * Just sort by block number		 */		nbp->vb_buf.b_cylinder = nbp->vb_buf.b_blkno;		s = splbio();		if (vnx->vx_error != 0) {			putvndbuf(nbp);			goto out;		}		vnx->vx_pending++;		/* assoc new buffer with underlying vnode */		bgetvp(vp, &nbp->vb_buf);		/* sort it in and start I/O if we are not over our limit */		disksort(&sdp->swd_tab, &nbp->vb_buf);		sw_reg_start(sdp);		splx(s);		/*		 * advance to the next I/O		 */		byteoff += sz;		addr += sz;	}	s = splbio();out: /* Arrive here at splbio */	vnx->vx_flags &= ~VX_BUSY;	if (vnx->vx_pending == 0) {		if (vnx->vx_error != 0) {			bp->b_error = vnx->vx_error;			bp->b_flags |= B_ERROR;		}		putvndxfer(vnx);		biodone(bp);	}	splx(s);}