Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 19 Mar 2014 12:30:44 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r263347 - projects/sendfile/sys/kern
Message-ID:  <201403191230.s2JCUikj024943@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: glebius
Date: Wed Mar 19 12:30:44 2014
New Revision: 263347
URL: http://svnweb.freebsd.org/changeset/base/263347

Log:
  Implement optional (default to 0) readahead for the new sendfile.
  
  If readahead is enabled, and vm_pager_has_page() hints us that we
  can do more pages in a single I/O than socket can consume, then
  we preload that much pages to memory.
  
  Sponsored by:	Netflix
  Sponsored by:	Nginx, Inc.

Modified:
  projects/sendfile/sys/kern/uipc_syscalls.c

Modified: projects/sendfile/sys/kern/uipc_syscalls.c
==============================================================================
--- projects/sendfile/sys/kern/uipc_syscalls.c	Wed Mar 19 12:29:20 2014	(r263346)
+++ projects/sendfile/sys/kern/uipc_syscalls.c	Wed Mar 19 12:30:44 2014	(r263347)
@@ -137,6 +137,10 @@ static int sfpgrabnowait = 0;
 SYSCTL_INT(_kern_ipc_sendfile, OID_AUTO, pgrabnowait, CTLFLAG_RW,
     &sfpgrabnowait, 0, "Use VM_ALLOC_NOWAIT when SF_NODISKIO is requested");
 
+static int sfreadahead = 0;
+SYSCTL_INT(_kern_ipc_sendfile, OID_AUTO, readahead, CTLFLAG_RW,
+    &sfreadahead, 0, "Read this more pages than socket buffer can accept");
+
 #ifdef	SFSYNC_DEBUG
 static int sf_sync_debug = 0;
 SYSCTL_INT(_debug, OID_AUTO, sf_sync_debug, CTLFLAG_RW,
@@ -2727,9 +2731,10 @@ sendfile_swapin(vm_object_t obj, struct 
 {
 	vm_page_t *pa = sfio->pa;
 	int npages = sfio->npages;
-	int nios, rv;
+	int nios, readahead;
 
 	nios = 0;
+	readahead = sfreadahead;
 	if (sfpgrabnowait && (flags & SF_NODISKIO))
 		flags = VM_ALLOC_NOWAIT;
 	else
@@ -2741,12 +2746,13 @@ sendfile_swapin(vm_object_t obj, struct 
 		    VM_ALLOC_WIRED | VM_ALLOC_NORMAL | flags);
 		if (pa[i] == NULL) {
 			npages = sfio->npages = i;
+			readahead = 0;
 			break;
 		}
 	}
 
 	for (int i = 0; i < npages; i++) {
-		int j, a;
+		int j, a, count, rv;
 
 		if (vm_page_is_valid(pa[i], vmoff(i, off) & PAGE_MASK,
 		    xfsize(i, npages, off, len))) {
@@ -2770,9 +2776,19 @@ sendfile_swapin(vm_object_t obj, struct 
 		if (i == j)
 			continue;
 
+		count = min(a + 1, npages + readahead - i);
+		for (j = npages; j < i + count; j++) {
+			pa[j] = vm_page_grab(obj, OFF_TO_IDX(vmoff(j, off)),
+			    VM_ALLOC_NORMAL | VM_ALLOC_NOWAIT);
+			if (pa[j] == NULL) {
+				count = j - i;
+				break;
+			}
+		}
+
 		refcount_acquire(&sfio->nios);
-		rv = vm_pager_get_pages_async(obj, pa + i,
-		    min(a + 1, npages - i), 0, &sf_io_done, sfio);
+		rv = vm_pager_get_pages_async(obj, pa + i, count, 0,
+		    &sf_io_done, sfio);
 
 		KASSERT(rv == VM_PAGER_OK, ("%s: pager fail obj %p page %p",
 		    __func__, obj, pa[i]));
@@ -2780,12 +2796,13 @@ sendfile_swapin(vm_object_t obj, struct 
 		SFSTAT_INC(sf_iocnt);
 		nios++;
 
-		i += a;
-		for (j = i - a; a > 0 && j < npages; a--, j++)
+		for (j = i; j < i + count; j++)
 			KASSERT(pa[j] == vm_page_lookup(obj,
 			    OFF_TO_IDX(vmoff(j, off))),
 			    ("pa[j] %p lookup %p\n", pa[j],
 			    vm_page_lookup(obj, OFF_TO_IDX(vmoff(j, off)))));
+
+		i += count - 1;
 	}
 
 	VM_OBJECT_WUNLOCK(obj);
@@ -3064,7 +3081,8 @@ retry_space:
 		else
 			npages = howmany(space, PAGE_SIZE);
 		sfio = malloc(sizeof(struct sf_io) +
-		    npages * sizeof(vm_page_t), M_TEMP, M_WAITOK);
+		    (sfreadahead + npages) * sizeof(vm_page_t),
+		    M_TEMP, M_WAITOK);
 		refcount_init(&sfio->nios, 1);
 		sfio->npages = npages;
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201403191230.s2JCUikj024943>