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>