diff options
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/fs/ext2fs/ext2_vnops.c | 44 | ||||
| -rw-r--r-- | sys/kern/vfs_bio.c | 39 | ||||
| -rw-r--r-- | sys/sys/buf.h | 4 | ||||
| -rw-r--r-- | sys/sys/vnode.h | 1 | ||||
| -rw-r--r-- | sys/ufs/ffs/ffs_vnops.c | 97 | ||||
| -rw-r--r-- | sys/vm/vm_pageout.c | 4 | ||||
| -rw-r--r-- | sys/vm/vm_pager.h | 1 | ||||
| -rw-r--r-- | sys/vm/vnode_pager.c | 1 |
8 files changed, 62 insertions, 129 deletions
diff --git a/sys/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c index 7c4d3aeb3f10a..1a000653b01a0 100644 --- a/sys/fs/ext2fs/ext2_vnops.c +++ b/sys/fs/ext2fs/ext2_vnops.c @@ -1701,15 +1701,6 @@ ext2_ind_read(struct vop_read_args *ap) } /* - * If IO_DIRECT then set B_DIRECT for the buffer. This - * will cause us to attempt to release the buffer later on - * and will cause the buffer cache to attempt to free the - * underlying pages. - */ - if (ioflag & IO_DIRECT) - bp->b_flags |= B_DIRECT; - - /* * We should only get non-zero b_resid when an I/O error * has occurred, which should cause us to break above. * However, if the short read did not cause an error, @@ -1726,25 +1717,7 @@ ext2_ind_read(struct vop_read_args *ap) (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); - } + vfs_bio_brelse(bp, ioflag); } /* @@ -1753,14 +1726,8 @@ ext2_ind_read(struct vop_read_args *ap) * 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) + vfs_bio_brelse(bp, ioflag); if ((error == 0 || uio->uio_resid != orig_resid) && (vp->v_mount->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) == 0) @@ -2018,9 +1985,8 @@ ext2_write(struct vop_write_args *ap) if (error != 0 && (bp->b_flags & B_CACHE) == 0 && fs->e2fs_bsize == xfersize) vfs_bio_clrbuf(bp); - if (ioflag & (IO_VMIO|IO_DIRECT)) { - bp->b_flags |= B_RELBUF; - } + + vfs_bio_set_flags(bp, ioflag); /* * If IO_SYNC each buffer is written synchronously. Otherwise diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index bdd088adcf5a0..842447d1f6e36 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -4414,6 +4414,45 @@ vfs_bio_bzero_buf(struct buf *bp, int base, int size) } /* + * Update buffer flags based on I/O request parameters, optionally releasing the + * buffer. If it's VMIO or direct I/O, the buffer pages are released to the VM, + * where they may be placed on a page queue (VMIO) or freed immediately (direct + * I/O). Otherwise the buffer is released to the cache. + */ +static void +b_io_dismiss(struct buf *bp, int ioflag, bool release) +{ + + KASSERT((ioflag & IO_NOREUSE) == 0 || (ioflag & IO_VMIO) != 0, + ("buf %p non-VMIO noreuse", bp)); + + if ((ioflag & IO_DIRECT) != 0) + bp->b_flags |= B_DIRECT; + 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; + if (release) + brelse(bp); + } else if (release) + bqrelse(bp); +} + +void +vfs_bio_brelse(struct buf *bp, int ioflag) +{ + + b_io_dismiss(bp, ioflag, true); +} + +void +vfs_bio_set_flags(struct buf *bp, int ioflag) +{ + + b_io_dismiss(bp, ioflag, false); +} + +/* * vm_hold_load_pages and vm_hold_free_pages get pages into * a buffers address space. The pages are anonymous and are * not associated with a file object. diff --git a/sys/sys/buf.h b/sys/sys/buf.h index f1d08d728bf88..0528bec5f11a6 100644 --- a/sys/sys/buf.h +++ b/sys/sys/buf.h @@ -538,9 +538,11 @@ int cluster_read(struct vnode *, u_quad_t, daddr_t, long, struct ucred *, long, int, int, struct buf **); int cluster_wbuild(struct vnode *, long, daddr_t, int, int); void cluster_write(struct vnode *, struct buf *, u_quad_t, int, int); +void vfs_bio_brelse(struct buf *bp, int ioflags); void vfs_bio_bzero_buf(struct buf *bp, int base, int size); -void vfs_bio_set_valid(struct buf *, int base, int size); void vfs_bio_clrbuf(struct buf *); +void vfs_bio_set_flags(struct buf *bp, int ioflags); +void vfs_bio_set_valid(struct buf *, int base, int size); void vfs_busy_pages(struct buf *, int clear_modify); void vfs_unbusy_pages(struct buf *); int vmapbuf(struct buf *, int); diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index d6b8dcf8f6672..989af8bc13a4b 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -307,6 +307,7 @@ struct vattr { #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 */ diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index cfd4616a87af8..f5a45f1c17872 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -601,15 +601,6 @@ ffs_read(ap) } /* - * If IO_DIRECT then set B_DIRECT for the buffer. This - * will cause us to attempt to release the buffer later on - * and will cause the buffer cache to attempt to free the - * underlying pages. - */ - if (ioflag & IO_DIRECT) - bp->b_flags |= B_DIRECT; - - /* * We should only get non-zero b_resid when an I/O error * has occurred, which should cause us to break above. * However, if the short read did not cause an error, @@ -633,25 +624,7 @@ ffs_read(ap) 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); - } + vfs_bio_brelse(bp, ioflag); } /* @@ -660,15 +633,8 @@ ffs_read(ap) * 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) + vfs_bio_brelse(bp, ioflag); if ((error == 0 || uio->uio_resid != orig_resid) && (vp->v_mount->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) == 0 && @@ -786,8 +752,6 @@ ffs_write(ap) vnode_pager_setsize(vp, ip->i_size); break; } - if (ioflag & IO_DIRECT) - bp->b_flags |= B_DIRECT; if ((ioflag & (IO_SYNC|IO_INVAL)) == (IO_SYNC|IO_INVAL)) bp->b_flags |= B_NOCACHE; @@ -827,10 +791,8 @@ ffs_write(ap) 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))) { - bp->b_flags |= B_RELBUF; - } + + vfs_bio_set_flags(bp, ioflag); /* * If IO_SYNC each buffer is written synchronously. Otherwise @@ -978,15 +940,6 @@ ffs_extread(struct vnode *vp, struct uio *uio, int ioflag) } /* - * If IO_DIRECT then set B_DIRECT for the buffer. This - * will cause us to attempt to release the buffer later on - * and will cause the buffer cache to attempt to free the - * underlying pages. - */ - if (ioflag & IO_DIRECT) - bp->b_flags |= B_DIRECT; - - /* * We should only get non-zero b_resid when an I/O error * has occurred, which should cause us to break above. * However, if the short read did not cause an error, @@ -1004,26 +957,7 @@ ffs_extread(struct vnode *vp, struct uio *uio, int ioflag) (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); - } + vfs_bio_brelse(bp, ioflag); } /* @@ -1032,15 +966,8 @@ ffs_extread(struct vnode *vp, struct uio *uio, int ioflag) * 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) + vfs_bio_brelse(bp, ioflag); return (error); } @@ -1109,8 +1036,6 @@ ffs_extwrite(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *ucred) */ if ((bp->b_flags & B_CACHE) == 0 && fs->fs_bsize <= xfersize) vfs_bio_clrbuf(bp); - if (ioflag & IO_DIRECT) - bp->b_flags |= B_DIRECT; if (uio->uio_offset + xfersize > dp->di_extsize) dp->di_extsize = uio->uio_offset + xfersize; @@ -1121,10 +1046,8 @@ ffs_extwrite(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *ucred) error = uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio); - if ((ioflag & (IO_VMIO|IO_DIRECT)) && - (LIST_EMPTY(&bp->b_dep))) { - bp->b_flags |= B_RELBUF; - } + + vfs_bio_set_flags(bp, ioflag); /* * If IO_SYNC each buffer is written synchronously. Otherwise diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 6c2cefe6462ce..a62aebdd28e39 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -483,8 +483,8 @@ more: 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)); } /* diff --git a/sys/vm/vm_pager.h b/sys/vm/vm_pager.h index f73cd004425b4..d7c5adf4f3006 100644 --- a/sys/vm/vm_pager.h +++ b/sys/vm/vm_pager.h @@ -95,6 +95,7 @@ extern struct pagerops mgtdevicepagerops; #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 diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 0c55642d14c83..2d775061d049c 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -1280,6 +1280,7 @@ vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *ma, int bytecount, 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; |
