Date: Mon, 27 Feb 2012 19:43:38 GMT From: John Baldwin <jhb@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 206993 for review Message-ID: <201202271943.q1RJhcs9074208@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@206993?ac=10 Change 206993 by jhb@jhb_jhbbsd on 2012/02/27 19:43:20 Attempt to optimize for the common case of using NOREUSE with sequential access by tracking NOREUSE reads and if they are sequential, applying DONTNEED to the entire range that has been read so far. Also, make UFS restrict DONTNEED requests to block boundaries to avoid flushing partial blocks from RAM. Affected files ... .. //depot/projects/fadvise/sys/kern/vfs_syscalls.c#19 edit .. //depot/projects/fadvise/sys/kern/vfs_vnops.c#7 edit .. //depot/projects/fadvise/sys/sys/file.h#8 edit .. //depot/projects/fadvise/sys/ufs/ffs/ffs_vnops.c#4 edit Differences ... ==== //depot/projects/fadvise/sys/kern/vfs_syscalls.c#19 (text+ko) ==== @@ -4950,6 +4950,8 @@ new->fa_advice = advice; new->fa_start = offset; new->fa_end = end; + new->fa_prevstart = 0; + new->fa_prevend = 0; fp->f_advice = new; new = fa; } ==== //depot/projects/fadvise/sys/kern/vfs_vnops.c#7 (text+ko) ==== @@ -519,7 +519,7 @@ int error, ioflag; struct mtx *mtxp; int advice, vfslocked; - off_t offset; + off_t offset, start, end; KASSERT(uio->uio_td == td, ("uio_td %p is not td %p", uio->uio_td, td)); @@ -584,9 +584,38 @@ fp->f_nextoff = uio->uio_offset; VOP_UNLOCK(vp, 0); if (error == 0 && advice == POSIX_FADV_NOREUSE && - offset != uio->uio_offset) - error = VOP_ADVISE(vp, offset, uio->uio_offset - 1, - POSIX_FADV_DONTNEED); + offset != uio->uio_offset) { + /* + * Use POSIX_FADV_DONTNEED to flush clean pages and + * buffers for the backing file after a + * POSIX_FADV_NOREUSE read(2). To optimize the common + * case of using POSIX_FADV_NOREUSE with sequential + * access, track the previous implicit DONTNEED + * request and grow this request to include the + * current read(2) in addition to the previous + * DONTNEED. Withpurely sequential access this will + * cause the DONTNEED requests to continously grow to + * cover all of the previously read regions of the + * file. This allows filesystem blocks that are + * accessed by multiple calls to read(2) to be flushed + * once the last read(2) finishes. + */ + start = offset; + end = uio->uio_offset - 1; + mtx_lock(mtxp); + if (fp->f_advice != NULL && + fp->f_advice->fa_advice == POSIX_FADV_NOREUSE) { + if (start != 0 && fp->f_advice->fa_prevend + 1 == start) + start = fp->f_advice->fa_prevstart; + else if (fp->f_advice->fa_prevstart != 0 && + fp->f_advice->fa_prevstart == end + 1) + end = fp->f_advice->fa_prevend; + fp->f_advice->fa_prevstart = start; + fp->f_advice->fa_prevend = end; + } + mtx_unlock(mtxp); + error = VOP_ADVISE(vp, start, end, POSIX_FADV_DONTNEED); + } VFS_UNLOCK_GIANT(vfslocked); return (error); } ==== //depot/projects/fadvise/sys/sys/file.h#8 (text+ko) ==== @@ -126,6 +126,8 @@ int fa_advice; /* (f) FADV_* type. */ off_t fa_start; /* (f) Region start. */ off_t fa_end; /* (f) Region end. */ + off_t fa_prevstart; /* (f) Previous NOREUSE start. */ + off_t fa_prevend; /* (f) Previous NOREUSE end. */ }; struct file { ==== //depot/projects/fadvise/sys/ufs/ffs/ffs_vnops.c#4 (text+ko) ==== @@ -422,6 +422,43 @@ int xfersize; switch (ap->a_advice) { + case POSIX_FADV_DONTNEED: + /* + * Trim requests to only cover full blocks to avoid + * flushing partial blocks. + */ + vp = ap->a_vp; + start = ap->a_start; + end = ap->a_end; + vn_lock(vp, LK_SHARED | LK_RETRY); + if (vp->v_iflag & VI_DOOMED) { + VOP_UNLOCK(vp, 0); + return (EBADF); + } + KASSERT(vp->v_type == VREG, ("FADV_DONTNEED on bad vnode")); + ip = VTOI(vp); + if (start >= ip->i_size) { + VOP_UNLOCK(vp, 0); + return (0); + } + fs = ip->i_fs; + if (blkoffset(fs, start) != 0) { + size = blksize(fs, ip, lblkno(fs, start)); + start += size - blkoffset(fs, start); + KASSERT(blkoffset(fs, start) == 0, + ("failed to adjust range start to block boundary")); + } + if (end < ip->i_size && blkoffset(fs, end) != 0) { + end -= blkoffset(fs, end); + KASSERT(blkoffset(fs, end) == 0, + ("failed to adjust range end to block boundary")); + } + VOP_UNLOCK(vp, 0); + if (start > end) + return (0); + ap->a_start = start; + ap->a_end = end; + return (vop_stdadvise(ap)); case POSIX_FADV_WILLNEED: vp = ap->a_vp; start = ap->a_start;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201202271943.q1RJhcs9074208>