Author: kib Date: Tue Sep 15 22:06:36 2020 New Revision: 365785 URL: https://svnweb.freebsd.org/changeset/base/365785
Log: Convert page cache read to VOP. There are several negative side-effects of not calling into VOP layer at all for page cache reads. The biggest is the missed activation of EVFILT_READ knotes. Also, it allows filesystem to make more fine grained decision to refuse read from page cache. Keep VIRF_PGREAD flag around, it is still useful for nullfs, and for asserts. Reviewed by: markj Tested by: pho Discussed with: mjg Sponsored by: The FreeBSD Foundation Differential revision: https://reviews.freebsd.org/D26346 Modified: head/sys/kern/vfs_default.c head/sys/kern/vfs_subr.c head/sys/kern/vfs_vnops.c head/sys/kern/vnode_if.src head/sys/sys/vnode.h head/sys/ufs/ufs/ufs_vnops.c Modified: head/sys/kern/vfs_default.c ============================================================================== --- head/sys/kern/vfs_default.c Tue Sep 15 22:00:58 2020 (r365784) +++ head/sys/kern/vfs_default.c Tue Sep 15 22:06:36 2020 (r365785) @@ -90,6 +90,7 @@ static int vop_stdadd_writecount(struct vop_add_writec static int vop_stdcopy_file_range(struct vop_copy_file_range_args *ap); static int vop_stdfdatasync(struct vop_fdatasync_args *ap); static int vop_stdgetpages_async(struct vop_getpages_async_args *ap); +static int vop_stdread_pgcache(struct vop_read_pgcache_args *ap); static int vop_stdstat(struct vop_stat_args *ap); /* @@ -135,6 +136,7 @@ struct vop_vector default_vnodeops = { .vop_poll = vop_nopoll, .vop_putpages = vop_stdputpages, .vop_readlink = VOP_EINVAL, + .vop_read_pgcache = vop_stdread_pgcache, .vop_rename = vop_norename, .vop_revoke = VOP_PANIC, .vop_strategy = vop_nostrategy, @@ -1574,4 +1576,10 @@ vop_stdstat(struct vop_stat_args *a) sb->st_gen = vap->va_gen; out: return (vop_stat_helper_post(a, error)); +} + +static int +vop_stdread_pgcache(struct vop_read_pgcache_args *ap __unused) +{ + return (EJUSTRETURN); } Modified: head/sys/kern/vfs_subr.c ============================================================================== --- head/sys/kern/vfs_subr.c Tue Sep 15 22:00:58 2020 (r365784) +++ head/sys/kern/vfs_subr.c Tue Sep 15 22:06:36 2020 (r365785) @@ -5839,6 +5839,15 @@ vop_read_post(void *ap, int rc) } void +vop_read_pgcache_post(void *ap, int rc) +{ + struct vop_read_pgcache_args *a = ap; + + if (!rc) + VFS_KNOTE_UNLOCKED(a->a_vp, NOTE_READ); +} + +void vop_readdir_post(void *ap, int rc) { struct vop_readdir_args *a = ap; Modified: head/sys/kern/vfs_vnops.c ============================================================================== --- head/sys/kern/vfs_vnops.c Tue Sep 15 22:00:58 2020 (r365784) +++ head/sys/kern/vfs_vnops.c Tue Sep 15 22:06:36 2020 (r365785) @@ -951,15 +951,6 @@ out_pip: return (uio->uio_resid == 0 ? 0 : EJUSTRETURN); } -static bool -do_vn_read_from_pgcache(struct vnode *vp, struct uio *uio, struct file *fp) -{ - return ((vp->v_irflag & (VIRF_DOOMED | VIRF_PGREAD)) == VIRF_PGREAD && - !mac_vnode_check_read_enabled() && - uio->uio_resid <= ptoa(io_hold_cnt) && uio->uio_offset >= 0 && - (fp->f_flag & O_DIRECT) == 0 && vn_io_pgcache_read_enable); -} - /* * File table vnode read routine. */ @@ -976,8 +967,19 @@ vn_read(struct file *fp, struct uio *uio, struct ucred uio->uio_td, td)); KASSERT(flags & FOF_OFFSET, ("No FOF_OFFSET")); vp = fp->f_vnode; - if (do_vn_read_from_pgcache(vp, uio, fp)) { - error = vn_read_from_obj(vp, uio); + ioflag = 0; + if (fp->f_flag & FNONBLOCK) + ioflag |= IO_NDELAY; + if (fp->f_flag & O_DIRECT) + ioflag |= IO_DIRECT; + + /* + * Try to read from page cache. VIRF_DOOMED check is racy but + * allows us to avoid unneeded work outright. + */ + if (vn_io_pgcache_read_enable && !mac_vnode_check_read_enabled() && + (vp->v_irflag & (VIRF_DOOMED | VIRF_PGREAD)) == VIRF_PGREAD) { + error = VOP_READ_PGCACHE(vp, uio, ioflag, fp->f_cred); if (error == 0) { fp->f_nextoff[UIO_READ] = uio->uio_offset; return (0); @@ -985,11 +987,7 @@ vn_read(struct file *fp, struct uio *uio, struct ucred if (error != EJUSTRETURN) return (error); } - ioflag = 0; - if (fp->f_flag & FNONBLOCK) - ioflag |= IO_NDELAY; - if (fp->f_flag & O_DIRECT) - ioflag |= IO_DIRECT; + advice = get_advice(fp, uio); vn_lock(vp, LK_SHARED | LK_RETRY); Modified: head/sys/kern/vnode_if.src ============================================================================== --- head/sys/kern/vnode_if.src Tue Sep 15 22:00:58 2020 (r365784) +++ head/sys/kern/vnode_if.src Tue Sep 15 22:06:36 2020 (r365785) @@ -225,6 +225,17 @@ vop_read { }; +%% read_pgcache vp - - - +%! read_pgcache post vop_read_pgcache_post + +vop_read_pgcache { + IN struct vnode *vp; + INOUT struct uio *uio; + IN int ioflag; + IN struct ucred *cred; +}; + + %% write vp L L L %! write pre VOP_WRITE_PRE %! write post VOP_WRITE_POST Modified: head/sys/sys/vnode.h ============================================================================== --- head/sys/sys/vnode.h Tue Sep 15 22:00:58 2020 (r365784) +++ head/sys/sys/vnode.h Tue Sep 15 22:06:36 2020 (r365785) @@ -852,6 +852,7 @@ void vop_mknod_pre(void *a); void vop_mknod_post(void *a, int rc); void vop_open_post(void *a, int rc); void vop_read_post(void *a, int rc); +void vop_read_pgcache_post(void *ap, int rc); void vop_readdir_post(void *a, int rc); void vop_reclaim_post(void *a, int rc); void vop_remove_pre(void *a); Modified: head/sys/ufs/ufs/ufs_vnops.c ============================================================================== --- head/sys/ufs/ufs/ufs_vnops.c Tue Sep 15 22:00:58 2020 (r365784) +++ head/sys/ufs/ufs/ufs_vnops.c Tue Sep 15 22:06:36 2020 (r365785) @@ -2874,6 +2874,22 @@ ufs_ioctl(struct vop_ioctl_args *ap) } } +static int +ufs_read_pgcache(struct vop_read_pgcache_args *ap) +{ + struct uio *uio; + struct vnode *vp; + + uio = ap->a_uio; + vp = ap->a_vp; + MPASS((vp->v_irflag & VIRF_PGREAD) != 0); + + if (uio->uio_resid > ptoa(io_hold_cnt) || uio->uio_offset < 0 || + (ap->a_ioflag & IO_DIRECT) != 0) + return (EJUSTRETURN); + return (vn_read_from_obj(vp, uio)); +} + /* Global vfs data structures for ufs. */ struct vop_vector ufs_vnodeops = { .vop_default = &default_vnodeops, @@ -2901,6 +2917,7 @@ struct vop_vector ufs_vnodeops = { .vop_pathconf = ufs_pathconf, .vop_poll = vop_stdpoll, .vop_print = ufs_print, + .vop_read_pgcache = ufs_read_pgcache, .vop_readdir = ufs_readdir, .vop_readlink = ufs_readlink, .vop_reclaim = ufs_reclaim, _______________________________________________ svn-src-head@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"