version 1.205.2.3, 2014/05/22 11:41:03 |
version 1.206, 2011/12/20 23:56:28 |
Line 136 EVCNT_ATTACH_STATIC(sosend_kvalimit); |
|
Line 136 EVCNT_ATTACH_STATIC(sosend_kvalimit); |
|
|
|
#endif /* SOSEND_COUNTERS */ |
#endif /* SOSEND_COUNTERS */ |
|
|
|
static struct callback_entry sokva_reclaimerentry; |
|
|
#if defined(SOSEND_NO_LOAN) || defined(MULTIPROCESSOR) |
#if defined(SOSEND_NO_LOAN) || defined(MULTIPROCESSOR) |
int sock_loan_thresh = -1; |
int sock_loan_thresh = -1; |
#else |
#else |
Line 160 static void sopendfree_thread(void *); |
|
Line 162 static void sopendfree_thread(void *); |
|
static kcondvar_t pendfree_thread_cv; |
static kcondvar_t pendfree_thread_cv; |
static lwp_t *sopendfree_lwp; |
static lwp_t *sopendfree_lwp; |
|
|
static void sysctl_kern_socket_setup(void); |
static void sysctl_kern_somaxkva_setup(void); |
static struct sysctllog *socket_sysctllog; |
static struct sysctllog *socket_sysctllog; |
|
|
static vsize_t |
static vsize_t |
Line 197 sokvaunreserve(vsize_t len) |
|
Line 199 sokvaunreserve(vsize_t len) |
|
*/ |
*/ |
|
|
vaddr_t |
vaddr_t |
sokvaalloc(vaddr_t sva, vsize_t len, struct socket *so) |
sokvaalloc(vsize_t len, struct socket *so) |
{ |
{ |
vaddr_t lva; |
vaddr_t lva; |
|
|
Line 212 sokvaalloc(vaddr_t sva, vsize_t len, str |
|
Line 214 sokvaalloc(vaddr_t sva, vsize_t len, str |
|
* allocate kva. |
* allocate kva. |
*/ |
*/ |
|
|
lva = uvm_km_alloc(kernel_map, len, atop(sva) & uvmexp.colormask, |
lva = uvm_km_alloc(kernel_map, len, 0, UVM_KMF_VAONLY | UVM_KMF_WAITVA); |
UVM_KMF_COLORMATCH | UVM_KMF_VAONLY | UVM_KMF_WAITVA); |
|
if (lva == 0) { |
if (lva == 0) { |
sokvaunreserve(len); |
sokvaunreserve(len); |
return (0); |
return (0); |
Line 350 sosend_loan(struct socket *so, struct ui |
|
Line 351 sosend_loan(struct socket *so, struct ui |
|
|
|
KASSERT(npgs <= M_EXT_MAXPAGES); |
KASSERT(npgs <= M_EXT_MAXPAGES); |
|
|
lva = sokvaalloc(sva, len, so); |
lva = sokvaalloc(len, so); |
if (lva == 0) |
if (lva == 0) |
return 0; |
return 0; |
|
|
Line 383 sosend_loan(struct socket *so, struct ui |
|
Line 384 sosend_loan(struct socket *so, struct ui |
|
return (space); |
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 * |
struct mbuf * |
getsombuf(struct socket *so, int type) |
getsombuf(struct socket *so, int type) |
{ |
{ |
Line 416 socket_listener_cb(kauth_cred_t cred, ka |
|
Line 430 socket_listener_cb(kauth_cred_t cred, ka |
|
/* Normal users can only drop their own connections. */ |
/* Normal users can only drop their own connections. */ |
struct socket *so = (struct socket *)arg1; |
struct socket *so = (struct socket *)arg1; |
|
|
if (so->so_cred && proc_uidmatch(cred, so->so_cred) == 0) |
if (proc_uidmatch(cred, so->so_cred)) |
result = KAUTH_RESULT_ALLOW; |
result = KAUTH_RESULT_ALLOW; |
|
|
break; |
break; |
|
|
soinit(void) |
soinit(void) |
{ |
{ |
|
|
sysctl_kern_socket_setup(); |
sysctl_kern_somaxkva_setup(); |
|
|
mutex_init(&so_pendfree_lock, MUTEX_DEFAULT, IPL_VM); |
mutex_init(&so_pendfree_lock, MUTEX_DEFAULT, IPL_VM); |
softnet_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); |
softnet_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); |
|
|
if (sb_max_set(sb_max)) |
if (sb_max_set(sb_max)) |
panic("bad initial sb_max value: %lu", 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 = kauth_listen_scope(KAUTH_SCOPE_NETWORK, |
socket_listener_cb, NULL); |
socket_listener_cb, NULL); |
} |
} |
Line 538 socreate(int dom, struct socket **aso, i |
|
Line 555 socreate(int dom, struct socket **aso, i |
|
lock = lockso->so_lock; |
lock = lockso->so_lock; |
so->so_lock = lock; |
so->so_lock = lock; |
mutex_obj_hold(lock); |
mutex_obj_hold(lock); |
/* XXX Why is this not solock, to match sounlock? */ |
|
mutex_enter(lock); |
mutex_enter(lock); |
} else { |
} else { |
/* Lock assigned and taken during PRU_ATTACH. */ |
/* Lock assigned and taken during PRU_ATTACH. */ |
Line 573 fsocreate(int domain, struct socket **so |
|
Line 589 fsocreate(int domain, struct socket **so |
|
if ((error = fd_allocfile(&fp, &fd)) != 0) |
if ((error = fd_allocfile(&fp, &fd)) != 0) |
return error; |
return error; |
fd_set_exclose(l, fd, (flags & SOCK_CLOEXEC) != 0); |
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_type = DTYPE_SOCKET; |
fp->f_ops = &socketops; |
fp->f_ops = &socketops; |
error = socreate(domain, &so, type, protocol, l, NULL); |
error = socreate(domain, &so, type, protocol, l, NULL); |
Line 586 fsocreate(int domain, struct socket **so |
|
Line 601 fsocreate(int domain, struct socket **so |
|
fp->f_data = so; |
fp->f_data = so; |
fd_affix(curproc, fp, fd); |
fd_affix(curproc, fp, fd); |
*fdout = fd; |
*fdout = fd; |
if (flags & SOCK_NONBLOCK) |
|
so->so_state |= SS_NBIO; |
|
} |
} |
return error; |
return error; |
} |
} |
Line 625 solisten(struct socket *so, int backlog, |
|
Line 638 solisten(struct socket *so, int backlog, |
|
if ((so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING | |
if ((so->so_state & (SS_ISCONNECTED | SS_ISCONNECTING | |
SS_ISDISCONNECTING)) != 0) { |
SS_ISDISCONNECTING)) != 0) { |
sounlock(so); |
sounlock(so); |
return (EINVAL); |
return (EOPNOTSUPP); |
} |
} |
error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, NULL, |
error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN, NULL, |
NULL, NULL, l); |
NULL, NULL, l); |
Line 877 sosend(struct socket *so, struct mbuf *a |
|
Line 890 sosend(struct socket *so, struct mbuf *a |
|
struct mbuf *control, int flags, struct lwp *l) |
struct mbuf *control, int flags, struct lwp *l) |
{ |
{ |
struct mbuf **mp, *m; |
struct mbuf **mp, *m; |
|
struct proc *p; |
long space, len, resid, clen, mlen; |
long space, len, resid, clen, mlen; |
int error, s, dontroute, atomic; |
int error, s, dontroute, atomic; |
short wakeup_state = 0; |
short wakeup_state = 0; |
|
|
|
p = l->l_proc; |
clen = 0; |
clen = 0; |
|
|
/* |
/* |
Line 927 sosend(struct socket *so, struct mbuf *a |
|
Line 942 sosend(struct socket *so, struct mbuf *a |
|
} |
} |
if ((so->so_state & SS_ISCONNECTED) == 0) { |
if ((so->so_state & SS_ISCONNECTED) == 0) { |
if (so->so_proto->pr_flags & PR_CONNREQUIRED) { |
if (so->so_proto->pr_flags & PR_CONNREQUIRED) { |
if (resid || clen == 0) { |
if ((so->so_state & SS_ISCONFIRMING) == 0 && |
|
!(resid == 0 && clen != 0)) { |
error = ENOTCONN; |
error = ENOTCONN; |
goto release; |
goto release; |
} |
} |
Line 1132 soreceive(struct socket *so, struct mbuf |
|
Line 1148 soreceive(struct socket *so, struct mbuf |
|
{ |
{ |
struct lwp *l = curlwp; |
struct lwp *l = curlwp; |
struct mbuf *m, **mp, *mt; |
struct mbuf *m, **mp, *mt; |
size_t len, offset, moff, orig_resid; |
int atomic, flags, len, error, s, offset, moff, type, orig_resid; |
int atomic, flags, error, s, type; |
|
const struct protosw *pr; |
const struct protosw *pr; |
struct mbuf *nextrecord; |
struct mbuf *nextrecord; |
int mbuf_removed = 0; |
int mbuf_removed = 0; |
Line 1166 soreceive(struct socket *so, struct mbuf |
|
Line 1181 soreceive(struct socket *so, struct mbuf |
|
goto bad; |
goto bad; |
do { |
do { |
error = uiomove(mtod(m, void *), |
error = uiomove(mtod(m, void *), |
MIN(uio->uio_resid, m->m_len), uio); |
(int) min(uio->uio_resid, m->m_len), uio); |
m = m_free(m); |
m = m_free(m); |
} while (uio->uio_resid > 0 && error == 0 && m); |
} while (uio->uio_resid > 0 && error == 0 && m); |
bad: |
bad: |
Line 1184 soreceive(struct socket *so, struct mbuf |
|
Line 1199 soreceive(struct socket *so, struct mbuf |
|
*/ |
*/ |
s = splsoftnet(); |
s = splsoftnet(); |
solock(so); |
solock(so); |
|
if (so->so_state & SS_ISCONFIRMING && uio->uio_resid) |
|
(*pr->pr_usrreq)(so, PRU_RCVD, NULL, NULL, NULL, l); |
|
|
restart: |
restart: |
if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0) { |
if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0) { |
sounlock(so); |
sounlock(so); |
Line 1417 soreceive(struct socket *so, struct mbuf |
|
Line 1435 soreceive(struct socket *so, struct mbuf |
|
SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove"); |
SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove"); |
sounlock(so); |
sounlock(so); |
splx(s); |
splx(s); |
error = uiomove(mtod(m, char *) + moff, len, uio); |
error = uiomove(mtod(m, char *) + moff, (int)len, uio); |
s = splsoftnet(); |
s = splsoftnet(); |
solock(so); |
solock(so); |
if (error != 0) { |
if (error != 0) { |
Line 1664 sorflush(struct socket *so) |
|
Line 1682 sorflush(struct socket *so) |
|
static int |
static int |
sosetopt1(struct socket *so, const struct sockopt *sopt) |
sosetopt1(struct socket *so, const struct sockopt *sopt) |
{ |
{ |
int error = EINVAL, opt; |
int error = EINVAL, optval, opt; |
int optval = 0; /* XXX: gcc */ |
|
struct linger l; |
struct linger l; |
struct timeval tv; |
struct timeval tv; |
|
|
Line 1702 sosetopt1(struct socket *so, const struc |
|
Line 1719 sosetopt1(struct socket *so, const struc |
|
case SO_REUSEPORT: |
case SO_REUSEPORT: |
case SO_OOBINLINE: |
case SO_OOBINLINE: |
case SO_TIMESTAMP: |
case SO_TIMESTAMP: |
case SO_NOSIGPIPE: |
|
#ifdef SO_OTIMESTAMP |
#ifdef SO_OTIMESTAMP |
case SO_OTIMESTAMP: |
case SO_OTIMESTAMP: |
#endif |
#endif |
Line 1903 sogetopt1(struct socket *so, struct sock |
|
Line 1919 sogetopt1(struct socket *so, struct sock |
|
case SO_BROADCAST: |
case SO_BROADCAST: |
case SO_OOBINLINE: |
case SO_OOBINLINE: |
case SO_TIMESTAMP: |
case SO_TIMESTAMP: |
case SO_NOSIGPIPE: |
|
#ifdef SO_OTIMESTAMP |
#ifdef SO_OTIMESTAMP |
case SO_OTIMESTAMP: |
case SO_OTIMESTAMP: |
#endif |
#endif |
case SO_ACCEPTCONN: |
|
error = sockopt_setint(sopt, (so->so_options & opt) ? 1 : 0); |
error = sockopt_setint(sopt, (so->so_options & opt) ? 1 : 0); |
break; |
break; |
|
|
Line 2365 sopoll(struct socket *so, int events) |
|
Line 2379 sopoll(struct socket *so, int events) |
|
#include <sys/sysctl.h> |
#include <sys/sysctl.h> |
|
|
static int sysctl_kern_somaxkva(SYSCTLFN_PROTO); |
static int sysctl_kern_somaxkva(SYSCTLFN_PROTO); |
static int sysctl_kern_sbmax(SYSCTLFN_PROTO); |
|
|
|
/* |
/* |
* sysctl helper routine for kern.somaxkva. ensures that the given |
* sysctl helper routine for kern.somaxkva. ensures that the given |
Line 2396 sysctl_kern_somaxkva(SYSCTLFN_ARGS) |
|
Line 2409 sysctl_kern_somaxkva(SYSCTLFN_ARGS) |
|
return (error); |
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 |
static void |
sysctl_kern_socket_setup(void) |
sysctl_kern_somaxkva_setup(void) |
{ |
{ |
|
|
KASSERT(socket_sysctllog == NULL); |
KASSERT(socket_sysctllog == NULL); |
|
sysctl_createv(&socket_sysctllog, 0, NULL, NULL, |
|
CTLFLAG_PERMANENT, |
|
CTLTYPE_NODE, "kern", NULL, |
|
NULL, 0, NULL, 0, |
|
CTL_KERN, CTL_EOL); |
|
|
sysctl_createv(&socket_sysctllog, 0, NULL, NULL, |
sysctl_createv(&socket_sysctllog, 0, NULL, NULL, |
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
Line 2433 sysctl_kern_socket_setup(void) |
|
Line 2427 sysctl_kern_socket_setup(void) |
|
"used for socket buffers"), |
"used for socket buffers"), |
sysctl_kern_somaxkva, 0, NULL, 0, |
sysctl_kern_somaxkva, 0, NULL, 0, |
CTL_KERN, KERN_SOMAXKVA, CTL_EOL); |
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); |
|
} |
} |