Add flag SF_USER_READAHEAD to sendfile(2). When specified, the syscall won't

do any speculations about readahead, and use exactly the amount of readahead
specified by user.  E.g. setting SF_FLAGS(0, SF_USER_READAHEAD) will guarantee
that no readahead at all will be performed.
This commit is contained in:
Gleb Smirnoff 2016-11-17 21:36:18 +00:00
parent 5dba303d01
commit 00b5ffde8e
3 changed files with 44 additions and 14 deletions

View file

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd January 7, 2016
.Dd November 17, 2016
.Dt SENDFILE 2
.Os
.Sh NAME
@ -155,8 +155,33 @@ sleeps until the network stack no longer references the VM pages
of the file, making subsequent modifications to it safe.
Please note that this is not a guarantee that the data has actually
been sent.
.It Dv SF_USER_READAHEAD
.Nm
has some internal heuristics to do readahead when sending data.
This flag forces
.Nm
to override any heuristically calculated readahead and use exactly the
application specified readahead.
See
.Sx SETTING READAHEAD
for more details on readahead.
.El
.Pp
When using a socket marked for non-blocking I/O,
.Fn sendfile
may send fewer bytes than requested.
In this case, the number of bytes successfully
written is returned in
.Fa *sbytes
(if specified),
and the error
.Er EAGAIN
is returned.
.Sh SETTING READAHEAD
.Nm
uses internal heuristics based on request size and file system layout
to do readahead.
Additionally application may request extra readahead.
The most significant 16 bits of
.Fa flags
specify amount of pages that
@ -173,16 +198,13 @@ flag:
SF_FLAGS(16, SF_NOCACHE)
.Ed
.Pp
When using a socket marked for non-blocking I/O,
.Fn sendfile
may send fewer bytes than requested.
In this case, the number of bytes successfully
written is returned in
.Fa *sbytes
(if specified),
and the error
.Er EAGAIN
is returned.
.Nm
will use either application specified readahead or internally calculated,
whichever is bigger.
Setting flag
.Dv SF_USER_READAHEAD
would turn off any heuristics and set maximum possible readahead length to
the number of pages specified via flags.
.Sh IMPLEMENTATION NOTES
The
.Fx

View file

@ -706,13 +706,20 @@ retry_space:
/*
* Calculate maximum allowed number of pages for readahead
* at this iteration. First, we allow readahead up to "rem".
* at this iteration. If SF_USER_READAHEAD was set, we don't
* do any heuristics and use exactly the value supplied by
* application. Otherwise, we allow readahead up to "rem".
* If application wants more, let it be, but there is no
* reason to go above MAXPHYS. Also check against "obj_size",
* since vm_pager_has_page() can hint beyond EOF.
*/
rhpages = howmany(rem + (off & PAGE_MASK), PAGE_SIZE) - npages;
rhpages += SF_READAHEAD(flags);
if (flags & SF_USER_READAHEAD) {
rhpages = SF_READAHEAD(flags);
} else {
rhpages = howmany(rem + (off & PAGE_MASK), PAGE_SIZE) -
npages;
rhpages += SF_READAHEAD(flags);
}
rhpages = min(howmany(MAXPHYS, PAGE_SIZE), rhpages);
rhpages = min(howmany(obj_size - trunc_page(off), PAGE_SIZE) -
npages, rhpages);

View file

@ -590,6 +590,7 @@ struct sf_hdtr {
#define SF_NODISKIO 0x00000001
#define SF_MNOWAIT 0x00000002 /* obsolete */
#define SF_SYNC 0x00000004
#define SF_USER_READAHEAD 0x00000008
#define SF_NOCACHE 0x00000010
#define SF_FLAGS(rh, flags) (((rh) << 16) | (flags))