+#define LFS_CHUNKSIZE (56 * 1024)
+ ch_per_blk = LFS_CHUNKSIZE / fs->lfs_bsize;
+ for (bpp = sp->bpp, i = nblocks; i;) {
+ num = ch_per_blk;
+ if (num > i)
+ num = i;
+ i -= num;
+ size = num * fs->lfs_bsize;
+
+ cbp = lfs_newbuf(VTOI(fs->lfs_ivnode)->i_devvp,
+ (*bpp)->b_blkno, size);
+ cbp->b_dev = i_dev;
+ cbp->b_flags |= B_ASYNC | B_BUSY;
+
+ s = splbio();
+ ++fs->lfs_iocount;
+ for (p = cbp->b_un.b_addr; num--;) {
+ bp = *bpp++;
+ /*
+ * Fake buffers from the cleaner are marked as B_INVAL.
+ * We need to copy the data from user space rather than
+ * from the buffer indicated.
+ * XXX == what do I do on an error?
+ */
+ if (bp->b_flags & B_INVAL) {
+ if (copyin(bp->b_saveaddr, p, bp->b_bcount))
+ panic("lfs_writeseg: copyin failed");
+ } else
+ bcopy(bp->b_un.b_addr, p, bp->b_bcount);
+ p += bp->b_bcount;
+ if (bp->b_flags & B_LOCKED)
+ --locked_queue_count;
+ bp->b_flags &= ~(B_ERROR | B_READ | B_DELWRI |
+ B_LOCKED | B_GATHERED);
+ if (bp->b_flags & B_CALL) {
+ /* if B_CALL, it was created with newbuf */
+ brelvp(bp);
+ free(bp, M_SEGMENT);
+ } else {
+ bremfree(bp);
+ reassignbuf(bp, bp->b_vp);
+ brelse(bp);
+ }
+ }
+ ++cbp->b_vp->v_numoutput;
+ splx(s);
+ cbp->b_bcount = p - cbp->b_un.b_addr;
+ /*
+ * XXXX This is a gross and disgusting hack. Since these
+ * buffers are physically addressed, they hang off the
+ * device vnode (devvp). As a result, they have no way
+ * of getting to the LFS superblock or lfs structure to
+ * keep track of the number of I/O's pending. So, I am
+ * going to stuff the fs into the saveaddr field of
+ * the buffer (yuk).
+ */
+ cbp->b_saveaddr = (caddr_t)fs;
+ vop_strategy_a.a_desc = VDESC(vop_strategy);
+ vop_strategy_a.a_bp = cbp;
+ (strategy)(&vop_strategy_a);
+ }
+ return (do_again);
+}