Index: sys/fs/ext2fs/ext2_vnops.c =================================================================== --- sys/fs/ext2fs/ext2_vnops.c +++ sys/fs/ext2fs/ext2_vnops.c @@ -1602,6 +1602,19 @@ return (error); } +static void +ext2_rbufdone(struct buf *bp, int ioflag) +{ + + if ((ioflag & (IO_VMIO | IO_DIRECT)) != 0) { + bp->b_flags |= B_RELBUF; + if ((ioflag & IO_NOREUSE) != 0) + bp->b_flags |= B_NOREUSE; + brelse(bp); + } else + bqrelse(bp); +} + /* * Vnode op for reading. */ @@ -1726,25 +1739,7 @@ (int)xfersize, uio); if (error) break; - - if (ioflag & (IO_VMIO|IO_DIRECT)) { - /* - * If it's VMIO or direct I/O, then we don't - * need the buf, mark it available for - * freeing. If it's non-direct VMIO, the VM has - * the data. - */ - bp->b_flags |= B_RELBUF; - brelse(bp); - } else { - /* - * Otherwise let whoever - * made the request take care of - * freeing it. We just queue - * it onto another list. - */ - bqrelse(bp); - } + ext2_rbufdone(bp, ioflag); } /* @@ -1753,14 +1748,8 @@ * and on normal completion has not set a new value into it. * so it must have come from a 'break' statement */ - if (bp != NULL) { - if (ioflag & (IO_VMIO|IO_DIRECT)) { - bp->b_flags |= B_RELBUF; - brelse(bp); - } else { - bqrelse(bp); - } - } + if (bp != NULL) + ext2_rbufdone(bp, ioflag); if ((error == 0 || uio->uio_resid != orig_resid) && (vp->v_mount->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) == 0) @@ -2018,8 +2007,10 @@ if (error != 0 && (bp->b_flags & B_CACHE) == 0 && fs->e2fs_bsize == xfersize) vfs_bio_clrbuf(bp); - if (ioflag & (IO_VMIO|IO_DIRECT)) { + if ((ioflag & (IO_VMIO | IO_DIRECT)) != 0) { bp->b_flags |= B_RELBUF; + if ((ioflag & IO_NOREUSE) != 0) + bp->b_flags |= B_NOREUSE; } /* Index: sys/sys/vnode.h =================================================================== --- sys/sys/vnode.h +++ sys/sys/vnode.h @@ -307,6 +307,7 @@ #define IO_INVAL 0x0040 /* invalidate after I/O */ #define IO_SYNC 0x0080 /* do I/O synchronously */ #define IO_DIRECT 0x0100 /* attempt to bypass buffer cache */ +#define IO_NOREUSE 0x0200 /* VMIO data won't be reused */ #define IO_EXT 0x0400 /* operate on external attributes */ #define IO_NORMAL 0x0800 /* operate on regular data */ #define IO_NOMACCHECK 0x1000 /* MAC checks unnecessary */ Index: sys/ufs/ffs/ffs_vnops.c =================================================================== --- sys/ufs/ffs/ffs_vnops.c +++ sys/ufs/ffs/ffs_vnops.c @@ -457,6 +457,19 @@ #endif } +static void +ffs_rbufdone(struct buf *bp, int ioflag) +{ + + if ((ioflag & (IO_VMIO | IO_DIRECT)) != 0 && LIST_EMPTY(&bp->b_dep)) { + bp->b_flags |= B_RELBUF; + if ((ioflag & IO_NOREUSE) != 0) + bp->b_flags |= B_NOREUSE; + brelse(bp); + } else + bqrelse(bp); +} + /* * Vnode op for reading. */ @@ -632,26 +645,7 @@ } if (error) break; - - if ((ioflag & (IO_VMIO|IO_DIRECT)) && - (LIST_EMPTY(&bp->b_dep))) { - /* - * If there are no dependencies, and it's VMIO, - * then we don't need the buf, mark it available - * for freeing. For non-direct VMIO reads, the VM - * has the data. - */ - bp->b_flags |= B_RELBUF; - brelse(bp); - } else { - /* - * Otherwise let whoever - * made the request take care of - * freeing it. We just queue - * it onto another list. - */ - bqrelse(bp); - } + ffs_rbufdone(bp, ioflag); } /* @@ -660,15 +654,8 @@ * and on normal completion has not set a new value into it. * so it must have come from a 'break' statement */ - if (bp != NULL) { - if ((ioflag & (IO_VMIO|IO_DIRECT)) && - (LIST_EMPTY(&bp->b_dep))) { - bp->b_flags |= B_RELBUF; - brelse(bp); - } else { - bqrelse(bp); - } - } + if (bp != NULL) + ffs_rbufdone(bp, ioflag); if ((error == 0 || uio->uio_resid != orig_resid) && (vp->v_mount->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) == 0 && @@ -827,9 +814,11 @@ if (error != 0 && (bp->b_flags & B_CACHE) == 0 && fs->fs_bsize == xfersize) vfs_bio_clrbuf(bp); - if ((ioflag & (IO_VMIO|IO_DIRECT)) && - (LIST_EMPTY(&bp->b_dep))) { + if ((ioflag & (IO_VMIO | IO_DIRECT)) != 0 && + LIST_EMPTY(&bp->b_dep)) { bp->b_flags |= B_RELBUF; + if ((ioflag & IO_NOREUSE) != 0) + bp->b_flags |= B_NOREUSE; } /* @@ -1004,26 +993,7 @@ (int)xfersize, uio); if (error) break; - - if ((ioflag & (IO_VMIO|IO_DIRECT)) && - (LIST_EMPTY(&bp->b_dep))) { - /* - * If there are no dependencies, and it's VMIO, - * then we don't need the buf, mark it available - * for freeing. For non-direct VMIO reads, the VM - * has the data. - */ - bp->b_flags |= B_RELBUF; - brelse(bp); - } else { - /* - * Otherwise let whoever - * made the request take care of - * freeing it. We just queue - * it onto another list. - */ - bqrelse(bp); - } + ffs_rbufdone(bp, ioflag); } /* @@ -1032,15 +1002,8 @@ * and on normal completion has not set a new value into it. * so it must have come from a 'break' statement */ - if (bp != NULL) { - if ((ioflag & (IO_VMIO|IO_DIRECT)) && - (LIST_EMPTY(&bp->b_dep))) { - bp->b_flags |= B_RELBUF; - brelse(bp); - } else { - bqrelse(bp); - } - } + if (bp != NULL) + ffs_rbufdone(bp, ioflag); return (error); } @@ -1121,9 +1084,11 @@ error = uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio); - if ((ioflag & (IO_VMIO|IO_DIRECT)) && - (LIST_EMPTY(&bp->b_dep))) { + if ((ioflag & (IO_VMIO | IO_DIRECT)) != 0 && + LIST_EMPTY(&bp->b_dep)) { bp->b_flags |= B_RELBUF; + if ((ioflag & IO_NOREUSE) != 0) + bp->b_flags |= B_NOREUSE; } /* Index: sys/vm/vm_pageout.c =================================================================== --- sys/vm/vm_pageout.c +++ sys/vm/vm_pageout.c @@ -483,8 +483,8 @@ if (ib != 0 && pageout_count < vm_pageout_page_count) goto more; - return (vm_pageout_flush(&mc[page_base], pageout_count, 0, 0, NULL, - NULL)); + return (vm_pageout_flush(&mc[page_base], pageout_count, + VM_PAGER_PUT_NOREUSE, 0, NULL, NULL)); } /* Index: sys/vm/vm_pager.h =================================================================== --- sys/vm/vm_pager.h +++ sys/vm/vm_pager.h @@ -95,6 +95,7 @@ #define VM_PAGER_PUT_SYNC 0x0001 #define VM_PAGER_PUT_INVAL 0x0002 +#define VM_PAGER_PUT_NOREUSE 0x0004 #define VM_PAGER_CLUSTER_OK 0x0008 #ifdef _KERNEL Index: sys/vm/vnode_pager.c =================================================================== --- sys/vm/vnode_pager.c +++ sys/vm/vnode_pager.c @@ -1281,6 +1281,7 @@ else if ((flags & VM_PAGER_CLUSTER_OK) == 0) ioflags |= IO_ASYNC; ioflags |= (flags & VM_PAGER_PUT_INVAL) ? IO_INVAL: 0; + ioflags |= (flags & VM_PAGER_PUT_NOREUSE) ? IO_NOREUSE : 0; ioflags |= IO_SEQMAX << IO_SEQSHIFT; aiov.iov_base = (caddr_t) 0;