Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Nov 2014 16:00:53 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r274514 - in projects/sendfile/sys: kern vm
Message-ID:  <201411141600.sAEG0rYD009060@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: glebius
Date: Fri Nov 14 16:00:53 2014
New Revision: 274514
URL: https://svnweb.freebsd.org/changeset/base/274514

Log:
  - Provide additonal "int error" argument to the callback function of
    VOP_GETPAGES_ASYNC(). It will be non-zero if vnode_pager_getpages()
    fails.
  - In sf_iodone() watch for errors. In case of I/O error, tear down
    the socket buffer, mark socket with error and available for write
    operation.
  
  Sponsored by:	Nginx, Inc.

Modified:
  projects/sendfile/sys/kern/uipc_syscalls.c
  projects/sendfile/sys/kern/vfs_default.c
  projects/sendfile/sys/kern/vnode_if.src
  projects/sendfile/sys/vm/vm_pager.h
  projects/sendfile/sys/vm/vnode_pager.c
  projects/sendfile/sys/vm/vnode_pager.h

Modified: projects/sendfile/sys/kern/uipc_syscalls.c
==============================================================================
--- projects/sendfile/sys/kern/uipc_syscalls.c	Fri Nov 14 15:55:56 2014	(r274513)
+++ projects/sendfile/sys/kern/uipc_syscalls.c	Fri Nov 14 16:00:53 2014	(r274514)
@@ -2057,6 +2057,7 @@ fixspace(int old, int new, off_t off, in
 
 struct sf_io {
 	u_int		nios;
+	u_int		error;
 	int		npages;
 	struct file	*sock_fp;
 	struct mbuf	*m;
@@ -2064,17 +2065,44 @@ struct sf_io {
 };
 
 static void
-sf_iodone(void *arg)
+sf_iodone(void *arg, int error)
 {
 	struct sf_io *sfio = arg;
 	struct socket *so;
 
+	if (error)
+		sfio->error = error;
+
 	if (!refcount_release(&sfio->nios))
 		return;
 
 	so = sfio->sock_fp->f_data;
 
-	(void)(so->so_proto->pr_usrreqs->pru_ready)(so, sfio->m, sfio->npages);
+	if (sfio->error) {
+		struct mbuf *m;
+
+		/*
+		 * I/O operation failed.  The state of data in the socket
+		 * is now inconsistent, and all what we can do is to tear
+		 * it down. sbflush() would free all ready mbufs and detach
+		 * not ready. We will free the mbufs corresponding to this
+		 * I/O manually.
+		 *
+		 * The socket would be marked with EIO and made available
+		 * for read, so that application receives EIO on next
+		 * syscall and eventually closes the socket.
+		 */
+		SOCKBUF_LOCK(&(so)->so_snd);
+		sbflush_locked(&so->so_snd);
+		so->so_error = EIO;
+		sowakeup((so), &(so)->so_snd);
+
+		m = sfio->m;
+		for (int i = 0; i < sfio->npages; i++)
+			m = m_free(m);
+	} else
+		(void )(so->so_proto->pr_usrreqs->pru_ready)(so, sfio->m,
+		    sfio->npages);
 
 	/* XXXGL: curthread */
 	fdrop(sfio->sock_fp, curthread);
@@ -2445,6 +2473,7 @@ retry_space:
 		sfio = malloc(sizeof(struct sf_io) +
 		    (rhpages + npages) * sizeof(vm_page_t), M_TEMP, M_WAITOK);
 		refcount_init(&sfio->nios, 1);
+		sfio->error = 0;
 
 		nios = sendfile_swapin(obj, sfio, off, space, npages, rhpages);
 
@@ -2564,7 +2593,7 @@ retry_space:
 			fhold(sock_fp);
 			error = (*so->so_proto->pr_usrreqs->pru_send)
 			    (so, PRUS_NOTREADY, m, NULL, NULL, td);
-			sf_iodone(sfio);
+			sf_iodone(sfio, 0);
 		}
 		CURVNET_RESTORE();
 

Modified: projects/sendfile/sys/kern/vfs_default.c
==============================================================================
--- projects/sendfile/sys/kern/vfs_default.c	Fri Nov 14 15:55:56 2014	(r274513)
+++ projects/sendfile/sys/kern/vfs_default.c	Fri Nov 14 16:00:53 2014	(r274514)
@@ -746,7 +746,7 @@ vop_stdgetpages_async_emulate(struct vop
 
 	error = VOP_GETPAGES(ap->a_vp, ap->a_m, ap->a_count, ap->a_reqpage);
 	vm_page_xunbusy(ap->a_m[ap->a_reqpage]);
-	ap->a_vop_getpages_iodone(ap->a_arg);
+	ap->a_vop_getpages_iodone(ap->a_arg, error);
 	return (error);
 }
 

Modified: projects/sendfile/sys/kern/vnode_if.src
==============================================================================
--- projects/sendfile/sys/kern/vnode_if.src	Fri Nov 14 15:55:56 2014	(r274513)
+++ projects/sendfile/sys/kern/vnode_if.src	Fri Nov 14 16:00:53 2014	(r274514)
@@ -484,7 +484,7 @@ vop_getpages_async {
 	IN int count;
 	IN int reqpage;
 	IN vm_ooffset_t offset;
-	IN void (*vop_getpages_iodone)(void *);
+	IN void (*vop_getpages_iodone)(void *, int);
 	IN void *arg;
 };
 

Modified: projects/sendfile/sys/vm/vm_pager.h
==============================================================================
--- projects/sendfile/sys/vm/vm_pager.h	Fri Nov 14 15:55:56 2014	(r274513)
+++ projects/sendfile/sys/vm/vm_pager.h	Fri Nov 14 16:00:53 2014	(r274514)
@@ -52,7 +52,7 @@ typedef vm_object_t pgo_alloc_t(void *, 
 typedef void pgo_dealloc_t(vm_object_t);
 typedef int pgo_getpages_t(vm_object_t, vm_page_t *, int, int);
 typedef int pgo_getpages_async_t(vm_object_t, vm_page_t *, int, int,
-    void(*)(void *), void *);
+    void(*)(void *, int), void *);
 typedef void pgo_putpages_t(vm_object_t, vm_page_t *, int, int, int *);
 typedef boolean_t pgo_haspage_t(vm_object_t, vm_pindex_t, int *, int *);
 typedef void pgo_pageunswapped_t(vm_page_t);
@@ -107,7 +107,7 @@ void vm_pager_bufferinit(void);
 void vm_pager_deallocate(vm_object_t);
 static __inline int vm_pager_get_pages(vm_object_t, vm_page_t *, int, int);
 static __inline int vm_pager_get_pages_async(vm_object_t, vm_page_t *, int,
-    int, void(*)(void *), void *);
+    int, void(*)(void *, int), void *);
 static __inline boolean_t vm_pager_has_page(vm_object_t, vm_pindex_t, int *, int *);
 void vm_pager_init(void);
 vm_object_t vm_pager_object_lookup(struct pagerlst *, void *);
@@ -140,7 +140,7 @@ vm_pager_get_pages(
 
 static __inline int
 vm_pager_get_pages_async(vm_object_t object, vm_page_t *m, int count,
-    int reqpage, void (*iodone)(void *), void *arg)
+    int reqpage, void (*iodone)(void *, int), void *arg)
 {
 	int r;
 
@@ -150,7 +150,7 @@ vm_pager_get_pages_async(vm_object_t obj
 		/* Emulate async operation. */
 		r = vm_pager_get_pages(object, m, count, reqpage);
 		VM_OBJECT_WUNLOCK(object);
-		(iodone)(arg);
+		(iodone)(arg, r);
 		VM_OBJECT_WLOCK(object);
 	} else
 		r = (*pagertab[object->type]->pgo_getpages_async)(object, m,

Modified: projects/sendfile/sys/vm/vnode_pager.c
==============================================================================
--- projects/sendfile/sys/vm/vnode_pager.c	Fri Nov 14 15:55:56 2014	(r274513)
+++ projects/sendfile/sys/vm/vnode_pager.c	Fri Nov 14 16:00:53 2014	(r274514)
@@ -83,10 +83,10 @@ static int vnode_pager_input_smlfs(vm_ob
 static int vnode_pager_input_old(vm_object_t object, vm_page_t m);
 static void vnode_pager_dealloc(vm_object_t);
 static int vnode_pager_local_getpages0(struct vnode *, vm_page_t *, int, int,
-    void (*)(void *), void *);
+    void (*)(void *, int), void *);
 static int vnode_pager_getpages(vm_object_t, vm_page_t *, int, int);
 static int vnode_pager_getpages_async(vm_object_t, vm_page_t *, int, int,
-    void(*)(void  *), void *);
+    void(*)(void  *, int), void *);
 static void vnode_pager_putpages(vm_object_t, vm_page_t *, int, int, int *);
 static boolean_t vnode_pager_haspage(vm_object_t, vm_pindex_t, int *, int *);
 static vm_object_t vnode_pager_alloc(void *, vm_ooffset_t, vm_prot_t,
@@ -671,7 +671,7 @@ vnode_pager_getpages(vm_object_t object,
 
 static int
 vnode_pager_getpages_async(vm_object_t object, vm_page_t *m, int count,
-    int reqpage, void (*iodone)(void *), void *arg)
+    int reqpage, void (*iodone)(void *, int), void *arg)
 {
 	int rtval;
 	struct vnode *vp;
@@ -696,7 +696,7 @@ struct getpages_softc {
 	int count;
 	int unmapped;
 	int reqpage;
-	void (*iodone)(void *);
+	void (*iodone)(void *, int);
 	void *arg;
 };
 
@@ -726,7 +726,7 @@ vnode_pager_local_getpages_async(struct 
 
 static int
 vnode_pager_local_getpages0(struct vnode *vp, vm_page_t *m, int bytecount,
-    int reqpage, void (*iodone)(void *), void *arg)
+    int reqpage, void (*iodone)(void *, int), void *arg)
 {
 	vm_page_t mreq;
 
@@ -748,7 +748,7 @@ vnode_pager_local_getpages0(struct vnode
 		vm_pager_free_nonreq(mreq->object, m, reqpage,
 		    round_page(bytecount) / PAGE_SIZE);
 		if (iodone != NULL)
-			iodone(arg);
+			iodone(arg, 0);
 		return (VM_PAGER_OK);
 	}
 
@@ -762,7 +762,7 @@ vnode_pager_local_getpages0(struct vnode
  */
 int
 vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m, int bytecount,
-    int reqpage, void (*iodone)(void *), void *arg)
+    int reqpage, void (*iodone)(void *, int), void *arg)
 {
 	vm_object_t object;
 	vm_offset_t kva;
@@ -1059,7 +1059,7 @@ vnode_pager_generic_getpages_done_async(
 
 	vm_page_xunbusy(sc->m[sc->reqpage]);
 
-	sc->iodone(sc->arg);
+	sc->iodone(sc->arg, error);
 
 	free(sc, M_TEMP);
 }

Modified: projects/sendfile/sys/vm/vnode_pager.h
==============================================================================
--- projects/sendfile/sys/vm/vnode_pager.h	Fri Nov 14 15:55:56 2014	(r274513)
+++ projects/sendfile/sys/vm/vnode_pager.h	Fri Nov 14 16:00:53 2014	(r274514)
@@ -41,7 +41,7 @@
 #ifdef _KERNEL
 
 int vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m,
-    int count, int reqpage, void (*iodone)(void *), void *arg);
+    int count, int reqpage, void (*iodone)(void *, int), void *arg);
 int vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *m,
 					  int count, boolean_t sync,
 					  int *rtvals);



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