svn commit: r292381 - in projects/sendfile: sys/kern sys/sys usr.bin/netstat
Gleb Smirnoff
glebius at FreeBSD.org
Wed Dec 16 22:48:34 UTC 2015
Author: glebius
Date: Wed Dec 16 22:48:32 2015
New Revision: 292381
URL: https://svnweb.freebsd.org/changeset/base/292381
Log:
Provide new behavior of SF_NODISKIO flag - abandon operation upon encounter
of a busy page. A retry after a short period of time is adviced. This behavior
is already documented in lib/libc/sys/sendfile.2 of this branch.
Modified:
projects/sendfile/sys/kern/uipc_syscalls.c
projects/sendfile/sys/sys/sf_buf.h
projects/sendfile/usr.bin/netstat/mbuf.c
Modified: projects/sendfile/sys/kern/uipc_syscalls.c
==============================================================================
--- projects/sendfile/sys/kern/uipc_syscalls.c Wed Dec 16 22:34:41 2015 (r292380)
+++ projects/sendfile/sys/kern/uipc_syscalls.c Wed Dec 16 22:48:32 2015 (r292381)
@@ -2138,21 +2138,28 @@ sf_iodone(void *arg, vm_page_t *pg, int
*/
static int
sendfile_swapin(vm_object_t obj, struct sf_io *sfio, off_t off, off_t len,
- int npages, int rhpages)
+ int npages, int rhpages, int flags)
{
vm_page_t *pa = sfio->pa;
int nios;
nios = 0;
- VM_OBJECT_WLOCK(obj);
+ flags = (flags & SF_NODISKIO) ? VM_ALLOC_NOWAIT : 0;
/*
* First grab all the pages and wire them. Note that we grab
* only required pages. Readahead pages are dealt with later.
*/
- for (int i = 0; i < npages; i++)
+ VM_OBJECT_WLOCK(obj);
+ for (int i = 0; i < npages; i++) {
pa[i] = vm_page_grab(obj, OFF_TO_IDX(vmoff(i, off)),
- VM_ALLOC_WIRED | VM_ALLOC_NORMAL);
+ VM_ALLOC_WIRED | VM_ALLOC_NORMAL | flags);
+ if (pa[i] == NULL) {
+ npages = i;
+ rhpages = 0;
+ break;
+ }
+ }
for (int i = 0; i < npages;) {
int j, a, count, rv;
@@ -2552,7 +2559,8 @@ retry_space:
refcount_init(&sfio->nios, 1);
sfio->error = 0;
- nios = sendfile_swapin(obj, sfio, off, space, npages, rhpages);
+ nios = sendfile_swapin(obj, sfio, off, space, npages, rhpages,
+ flags);
/*
* Loop and construct maximum sized mbuf chain to be bulk
@@ -2563,6 +2571,18 @@ retry_space:
struct mbuf *m0;
/*
+ * If a page wasn't grabbed successfully, then
+ * trim the array. Can happen only with SF_NODISKIO.
+ */
+ if (pa[i] == NULL) {
+ SFSTAT_INC(sf_busy);
+ fixspace(npages, i, off, &space);
+ npages = i;
+ softerr = EBUSY;
+ break;
+ }
+
+ /*
* Get a sendfile buf. When allocating the
* first buffer for mbuf chain, we usually
* wait as long as necessary, but this wait
Modified: projects/sendfile/sys/sys/sf_buf.h
==============================================================================
--- projects/sendfile/sys/sys/sf_buf.h Wed Dec 16 22:34:41 2015 (r292380)
+++ projects/sendfile/sys/sys/sf_buf.h Wed Dec 16 22:48:32 2015 (r292381)
@@ -38,6 +38,7 @@ struct sfstat { /* sendfile statistic
uint64_t sf_pages_valid; /* pages were valid for a request */
uint64_t sf_rhpages_requested; /* readahead pages requested */
uint64_t sf_rhpages_read; /* readahead pages read */
+ uint64_t sf_busy; /* times aborted on a busy page */
uint64_t sf_allocfail; /* times sfbuf allocation failed */
uint64_t sf_allocwait; /* times sfbuf allocation had to wait */
};
Modified: projects/sendfile/usr.bin/netstat/mbuf.c
==============================================================================
--- projects/sendfile/usr.bin/netstat/mbuf.c Wed Dec 16 22:34:41 2015 (r292380)
+++ projects/sendfile/usr.bin/netstat/mbuf.c Wed Dec 16 22:48:32 2015 (r292381)
@@ -346,6 +346,9 @@ mbpr(void *kvmd, u_long mbaddr)
xo_emit("{:sendfile-readahead/%ju} "
"{N:pages were read ahead by sendfile}\n",
(uintmax_t)sfstat.sf_rhpages_read);
+ xo_emit("{:sendfile-busy-encounters/%ju} "
+ "{N:times sendfile encountered an already busy page}\n",
+ (uintmax_t)sfstat.sf_busy);
xo_emit("{:sfbufs-alloc-failed/%ju} {N:requests for sfbufs denied}\n",
(uintmax_t)sfstat.sf_allocfail);
xo_emit("{:sfbufs-alloc-wait/%ju} {N:requests for sfbufs delayed}\n",
More information about the svn-src-projects
mailing list