Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/kern/uipc_socket.c,v retrieving revision 1.205 retrieving revision 1.205.2.2 diff -u -p -r1.205 -r1.205.2.2 --- src/sys/kern/uipc_socket.c 2011/07/02 17:53:50 1.205 +++ src/sys/kern/uipc_socket.c 2012/10/30 17:22:37 1.205.2.2 @@ -1,4 +1,4 @@ -/* $NetBSD: uipc_socket.c,v 1.205 2011/07/02 17:53:50 bouyer Exp $ */ +/* $NetBSD: uipc_socket.c,v 1.205.2.2 2012/10/30 17:22:37 yamt Exp $ */ /*- * Copyright (c) 2002, 2007, 2008, 2009 The NetBSD Foundation, Inc. @@ -63,7 +63,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.205 2011/07/02 17:53:50 bouyer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.205.2.2 2012/10/30 17:22:37 yamt Exp $"); #include "opt_compat_netbsd.h" #include "opt_sock_counters.h" @@ -136,8 +136,6 @@ EVCNT_ATTACH_STATIC(sosend_kvalimit); #endif /* SOSEND_COUNTERS */ -static struct callback_entry sokva_reclaimerentry; - #if defined(SOSEND_NO_LOAN) || defined(MULTIPROCESSOR) int sock_loan_thresh = -1; #else @@ -162,7 +160,7 @@ static void sopendfree_thread(void *); static kcondvar_t pendfree_thread_cv; static lwp_t *sopendfree_lwp; -static void sysctl_kern_somaxkva_setup(void); +static void sysctl_kern_socket_setup(void); static struct sysctllog *socket_sysctllog; static vsize_t @@ -199,7 +197,7 @@ sokvaunreserve(vsize_t len) */ vaddr_t -sokvaalloc(vsize_t len, struct socket *so) +sokvaalloc(vaddr_t sva, vsize_t len, struct socket *so) { vaddr_t lva; @@ -214,7 +212,8 @@ sokvaalloc(vsize_t len, struct socket *s * allocate kva. */ - lva = uvm_km_alloc(kernel_map, len, 0, UVM_KMF_VAONLY | UVM_KMF_WAITVA); + lva = uvm_km_alloc(kernel_map, len, atop(sva) & uvmexp.colormask, + UVM_KMF_COLORMATCH | UVM_KMF_VAONLY | UVM_KMF_WAITVA); if (lva == 0) { sokvaunreserve(len); return (0); @@ -351,7 +350,7 @@ sosend_loan(struct socket *so, struct ui KASSERT(npgs <= M_EXT_MAXPAGES); - lva = sokvaalloc(len, so); + lva = sokvaalloc(sva, len, so); if (lva == 0) return 0; @@ -384,19 +383,6 @@ sosend_loan(struct socket *so, struct ui return (space); } -static int -sokva_reclaim_callback(struct callback_entry *ce, void *obj, void *arg) -{ - - KASSERT(ce == &sokva_reclaimerentry); - KASSERT(obj == NULL); - - if (!vm_map_starved_p(kernel_map)) { - return CALLBACK_CHAIN_ABORT; - } - return CALLBACK_CHAIN_CONTINUE; -} - struct mbuf * getsombuf(struct socket *so, int type) { @@ -467,7 +453,7 @@ void soinit(void) { - sysctl_kern_somaxkva_setup(); + sysctl_kern_socket_setup(); mutex_init(&so_pendfree_lock, MUTEX_DEFAULT, IPL_VM); softnet_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); @@ -479,9 +465,6 @@ soinit(void) if (sb_max_set(sb_max)) panic("bad initial sb_max value: %lu", sb_max); - callback_register(&vm_map_to_kernel(kernel_map)->vmk_reclaim_callback, - &sokva_reclaimerentry, NULL, sokva_reclaim_callback); - socket_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK, socket_listener_cb, NULL); } @@ -589,7 +572,8 @@ fsocreate(int domain, struct socket **so if ((error = fd_allocfile(&fp, &fd)) != 0) return error; fd_set_exclose(l, fd, (flags & SOCK_CLOEXEC) != 0); - fp->f_flag = FREAD|FWRITE|((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0); + fp->f_flag = FREAD|FWRITE|((flags & SOCK_NONBLOCK) ? FNONBLOCK : 0)| + ((flags & SOCK_NOSIGPIPE) ? FNOSIGPIPE : 0); fp->f_type = DTYPE_SOCKET; fp->f_ops = &socketops; error = socreate(domain, &so, type, protocol, l, NULL); @@ -638,7 +622,7 @@ solisten(struct socket *so, int backlog, if ((so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) != 0) { sounlock(so); - return (EOPNOTSUPP); + return (EINVAL); } error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, NULL, NULL, NULL, l); @@ -741,7 +725,8 @@ soclose(struct socket *so) goto drop; } if (so->so_options & SO_LINGER) { - if ((so->so_state & SS_ISDISCONNECTING) && so->so_nbio) + if ((so->so_state & (SS_ISDISCONNECTING|SS_NBIO)) == + (SS_ISDISCONNECTING|SS_NBIO)) goto drop; while (so->so_state & SS_ISCONNECTED) { error = sowait(so, true, so->so_linger * hz); @@ -961,7 +946,7 @@ sosend(struct socket *so, struct mbuf *a } if (space < resid + clen && (atomic || space < so->so_snd.sb_lowat || space < clen)) { - if (so->so_nbio) { + if ((so->so_state & SS_NBIO) || (flags & MSG_NBIO)) { error = EWOULDBLOCK; goto release; } @@ -1147,7 +1132,8 @@ soreceive(struct socket *so, struct mbuf { struct lwp *l = curlwp; struct mbuf *m, **mp, *mt; - int atomic, flags, len, error, s, offset, moff, type, orig_resid; + size_t len, offset, moff, orig_resid; + int atomic, flags, error, s, type; const struct protosw *pr; struct mbuf *nextrecord; int mbuf_removed = 0; @@ -1180,7 +1166,7 @@ soreceive(struct socket *so, struct mbuf goto bad; do { error = uiomove(mtod(m, void *), - (int) min(uio->uio_resid, m->m_len), uio); + MIN(uio->uio_resid, m->m_len), uio); m = m_free(m); } while (uio->uio_resid > 0 && error == 0 && m); bad: @@ -1257,7 +1243,8 @@ soreceive(struct socket *so, struct mbuf } if (uio->uio_resid == 0) goto release; - if (so->so_nbio || (flags & MSG_DONTWAIT)) { + if ((so->so_state & SS_NBIO) || + (flags & (MSG_DONTWAIT|MSG_NBIO))) { error = EWOULDBLOCK; goto release; } @@ -1433,7 +1420,7 @@ soreceive(struct socket *so, struct mbuf SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove"); sounlock(so); splx(s); - error = uiomove(mtod(m, char *) + moff, (int)len, uio); + error = uiomove(mtod(m, char *) + moff, len, uio); s = splsoftnet(); solock(so); if (error != 0) { @@ -1717,6 +1704,7 @@ sosetopt1(struct socket *so, const struc case SO_REUSEPORT: case SO_OOBINLINE: case SO_TIMESTAMP: + case SO_NOSIGPIPE: #ifdef SO_OTIMESTAMP case SO_OTIMESTAMP: #endif @@ -1917,6 +1905,7 @@ sogetopt1(struct socket *so, struct sock case SO_BROADCAST: case SO_OOBINLINE: case SO_TIMESTAMP: + case SO_NOSIGPIPE: #ifdef SO_OTIMESTAMP case SO_OTIMESTAMP: #endif @@ -2377,6 +2366,7 @@ sopoll(struct socket *so, int events) #include static int sysctl_kern_somaxkva(SYSCTLFN_PROTO); +static int sysctl_kern_sbmax(SYSCTLFN_PROTO); /* * sysctl helper routine for kern.somaxkva. ensures that the given @@ -2407,8 +2397,32 @@ sysctl_kern_somaxkva(SYSCTLFN_ARGS) return (error); } +/* + * sysctl helper routine for kern.sbmax. Basically just ensures that + * any new value is not too small. + */ +static int +sysctl_kern_sbmax(SYSCTLFN_ARGS) +{ + int error, new_sbmax; + struct sysctlnode node; + + new_sbmax = sb_max; + node = *rnode; + node.sysctl_data = &new_sbmax; + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (error || newp == NULL) + return (error); + + KERNEL_LOCK(1, NULL); + error = sb_max_set(new_sbmax); + KERNEL_UNLOCK_ONE(NULL); + + return (error); +} + static void -sysctl_kern_somaxkva_setup(void) +sysctl_kern_socket_setup(void) { KASSERT(socket_sysctllog == NULL); @@ -2425,4 +2439,11 @@ sysctl_kern_somaxkva_setup(void) "used for socket buffers"), sysctl_kern_somaxkva, 0, NULL, 0, CTL_KERN, KERN_SOMAXKVA, CTL_EOL); + + sysctl_createv(&socket_sysctllog, 0, NULL, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, + CTLTYPE_INT, "sbmax", + SYSCTL_DESCR("Maximum socket buffer size"), + sysctl_kern_sbmax, 0, NULL, 0, + CTL_KERN, KERN_SBMAX, CTL_EOL); }