FFS: allow sendfile(2) to work with block sizes greater than the page size

Implement ffs_getpages_async(), which when possible calls the asynchronous
flavor of the generic pager's getpages function. When the underlying
block size is larger than the system page size, however, it will invoke
the (synchronous) buffer cache pager, followed by a call to the client
completion routine. This retains true asynchronous completion in the most
common (block size <= page size) case, which is important for the performance
of the new sendfile(2). The behavior in the larger block size case mirrors
the default implementation of VOP_GETPAGES_ASYNC, which most other
filesystems use anyway as they do not override the getpages_async method.

PR:		235708
Reported by:	pho
Reviewed by:	kib, glebius
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D19340
This commit is contained in:
Jason A. Harmening 2019-02-26 04:56:10 +00:00
parent 40a5168449
commit 4775b07ebd
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=344562

View File

@ -111,6 +111,7 @@ extern int ffs_rawread(struct vnode *vp, struct uio *uio, int *workdone);
static vop_fdatasync_t ffs_fdatasync;
static vop_fsync_t ffs_fsync;
static vop_getpages_t ffs_getpages;
static vop_getpages_async_t ffs_getpages_async;
static vop_lock1_t ffs_lock;
static vop_read_t ffs_read;
static vop_write_t ffs_write;
@ -132,7 +133,7 @@ struct vop_vector ffs_vnodeops1 = {
.vop_fsync = ffs_fsync,
.vop_fdatasync = ffs_fdatasync,
.vop_getpages = ffs_getpages,
.vop_getpages_async = vnode_pager_local_getpages_async,
.vop_getpages_async = ffs_getpages_async,
.vop_lock1 = ffs_lock,
.vop_read = ffs_read,
.vop_reallocblks = ffs_reallocblks,
@ -154,7 +155,7 @@ struct vop_vector ffs_vnodeops2 = {
.vop_fsync = ffs_fsync,
.vop_fdatasync = ffs_fdatasync,
.vop_getpages = ffs_getpages,
.vop_getpages_async = vnode_pager_local_getpages_async,
.vop_getpages_async = ffs_getpages_async,
.vop_lock1 = ffs_lock,
.vop_read = ffs_read,
.vop_reallocblks = ffs_reallocblks,
@ -1742,3 +1743,25 @@ ffs_getpages(struct vop_getpages_args *ap)
return (vfs_bio_getpages(vp, ap->a_m, ap->a_count, ap->a_rbehind,
ap->a_rahead, ffs_gbp_getblkno, ffs_gbp_getblksz));
}
static int
ffs_getpages_async(struct vop_getpages_async_args *ap)
{
struct vnode *vp;
struct ufsmount *um;
int error;
vp = ap->a_vp;
um = VFSTOUFS(vp->v_mount);
if (um->um_devvp->v_bufobj.bo_bsize <= PAGE_SIZE)
return (vnode_pager_generic_getpages(vp, ap->a_m, ap->a_count,
ap->a_rbehind, ap->a_rahead, ap->a_iodone, ap->a_arg));
error = vfs_bio_getpages(vp, ap->a_m, ap->a_count, ap->a_rbehind,
ap->a_rahead, ffs_gbp_getblkno, ffs_gbp_getblksz);
ap->a_iodone(ap->a_arg, ap->a_m, ap->a_count, error);
return (error);
}