[BACK]Return to uipc_socket.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/kern/uipc_socket.c between version 1.129.2.1 and 1.132.2.3

version 1.129.2.1, 2007/05/13 21:23:47 version 1.132.2.3, 2007/03/24 14:56:06
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $NetBSD$        */
   
 /*-  /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.   * Copyright (c) 2002, 2007 The NetBSD Foundation, Inc.
  * All rights reserved.   * All rights reserved.
  *   *
  * This code is derived from software contributed to The NetBSD Foundation   * This code is derived from software contributed to The NetBSD Foundation
Line 92  __KERNEL_RCSID(0, "$NetBSD$");
Line 92  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/event.h>  #include <sys/event.h>
 #include <sys/poll.h>  #include <sys/poll.h>
 #include <sys/kauth.h>  #include <sys/kauth.h>
   #include <sys/mutex.h>
   #include <sys/condvar.h>
   
 #include <uvm/uvm.h>  #include <uvm/uvm.h>
   
 POOL_INIT(socket_pool, sizeof(struct socket), 0, 0, 0, "sockpl", NULL);  POOL_INIT(socket_pool, sizeof(struct socket), 0, 0, 0, "sockpl", NULL,
       IPL_SOFTNET);
   
 MALLOC_DEFINE(M_SOOPTS, "soopts", "socket options");  MALLOC_DEFINE(M_SOOPTS, "soopts", "socket options");
 MALLOC_DEFINE(M_SONAME, "soname", "socket name");  MALLOC_DEFINE(M_SONAME, "soname", "socket name");
Line 135  int sock_loan_thresh = -1;
Line 138  int sock_loan_thresh = -1;
 int sock_loan_thresh = 4096;  int sock_loan_thresh = 4096;
 #endif  #endif
   
 static struct simplelock so_pendfree_slock = SIMPLELOCK_INITIALIZER;  static kmutex_t so_pendfree_lock;
 static struct mbuf *so_pendfree;  static struct mbuf *so_pendfree;
   
 #ifndef SOMAXKVA  #ifndef SOMAXKVA
Line 143  static struct mbuf *so_pendfree;
Line 146  static struct mbuf *so_pendfree;
 #endif  #endif
 int somaxkva = SOMAXKVA;  int somaxkva = SOMAXKVA;
 static int socurkva;  static int socurkva;
 static int sokvawaiters;  static kcondvar_t socurkva_cv;
   
 #define SOCK_LOAN_CHUNK         65536  #define SOCK_LOAN_CHUNK         65536
   
Line 153  static size_t sodopendfreel(void);
Line 156  static size_t sodopendfreel(void);
 static vsize_t  static vsize_t
 sokvareserve(struct socket *so, vsize_t len)  sokvareserve(struct socket *so, vsize_t len)
 {  {
         int s;  
         int error;          int error;
   
         s = splvm();          mutex_enter(&so_pendfree_lock);
         simple_lock(&so_pendfree_slock);  
         while (socurkva + len > somaxkva) {          while (socurkva + len > somaxkva) {
                 size_t freed;                  size_t freed;
   
Line 175  sokvareserve(struct socket *so, vsize_t 
Line 176  sokvareserve(struct socket *so, vsize_t 
                         continue;                          continue;
   
                 SOSEND_COUNTER_INCR(&sosend_kvalimit);                  SOSEND_COUNTER_INCR(&sosend_kvalimit);
                 sokvawaiters++;                  error = cv_wait_sig(&socurkva_cv, &so_pendfree_lock);
                 error = ltsleep(&socurkva, PVM | PCATCH, "sokva", 0,  
                     &so_pendfree_slock);  
                 sokvawaiters--;  
                 if (error) {                  if (error) {
                         len = 0;                          len = 0;
                         break;                          break;
                 }                  }
         }          }
         socurkva += len;          socurkva += len;
         simple_unlock(&so_pendfree_slock);          mutex_exit(&so_pendfree_lock);
         splx(s);  
         return len;          return len;
 }  }
   
 static void  static void
 sokvaunreserve(vsize_t len)  sokvaunreserve(vsize_t len)
 {  {
         int s;  
   
         s = splvm();          mutex_enter(&so_pendfree_lock);
         simple_lock(&so_pendfree_slock);  
         socurkva -= len;          socurkva -= len;
         if (sokvawaiters)          cv_broadcast(&socurkva_cv);
                 wakeup(&socurkva);          mutex_exit(&so_pendfree_lock);
         simple_unlock(&so_pendfree_slock);  
         splx(s);  
 }  }
   
 /*  /*
Line 255  sokvafree(vaddr_t sva, vsize_t len)
Line 248  sokvafree(vaddr_t sva, vsize_t len)
 }  }
   
 static void  static void
 sodoloanfree(struct vm_page **pgs, caddr_t buf, size_t size)  sodoloanfree(struct vm_page **pgs, void *buf, size_t size)
 {  {
         vaddr_t va, sva, eva;          vaddr_t va, sva, eva;
         vsize_t len;          vsize_t len;
Line 271  sodoloanfree(struct vm_page **pgs, caddr
Line 264  sodoloanfree(struct vm_page **pgs, caddr
                 pgs = alloca(npgs * sizeof(*pgs));                  pgs = alloca(npgs * sizeof(*pgs));
   
                 for (i = 0, va = sva; va < eva; i++, va += PAGE_SIZE) {                  for (i = 0, va = sva; va < eva; i++, va += PAGE_SIZE) {
                         if (pmap_extract(pmap_kernel(), va, &pa) == FALSE)                          if (pmap_extract(pmap_kernel(), va, &pa) == false)
                                 panic("sodoloanfree: va 0x%lx not mapped", va);                                  panic("sodoloanfree: va 0x%lx not mapped", va);
                         pgs[i] = PHYS_TO_VM_PAGE(pa);                          pgs[i] = PHYS_TO_VM_PAGE(pa);
                 }                  }
Line 286  sodoloanfree(struct vm_page **pgs, caddr
Line 279  sodoloanfree(struct vm_page **pgs, caddr
 static size_t  static size_t
 sodopendfree()  sodopendfree()
 {  {
         int s;  
         size_t rv;          size_t rv;
   
         s = splvm();          mutex_enter(&so_pendfree_lock);
         simple_lock(&so_pendfree_slock);  
         rv = sodopendfreel();          rv = sodopendfreel();
         simple_unlock(&so_pendfree_slock);          mutex_exit(&so_pendfree_lock);
         splx(s);  
   
         return rv;          return rv;
 }  }
   
 /*  /*
  * sodopendfreel: free mbufs on "pendfree" list.   * sodopendfreel: free mbufs on "pendfree" list.
  * unlock and relock so_pendfree_slock when freeing mbufs.   * unlock and relock so_pendfree_lock when freeing mbufs.
  *   *
  * => called with so_pendfree_slock held.   * => called with so_pendfree_lock held.
  * => called at splvm.  
  */   */
   
 static size_t  static size_t
 sodopendfreel()  sodopendfreel()
 {  {
           struct mbuf *m, *next;
         size_t rv = 0;          size_t rv = 0;
           int s;
   
         LOCK_ASSERT(simple_lock_held(&so_pendfree_slock));          KASSERT(mutex_owned(&so_pendfree_lock));
   
         for (;;) {  
                 struct mbuf *m;  
                 struct mbuf *next;  
   
           while (so_pendfree != NULL) {
                 m = so_pendfree;                  m = so_pendfree;
                 if (m == NULL)  
                         break;  
                 so_pendfree = NULL;                  so_pendfree = NULL;
                 simple_unlock(&so_pendfree_slock);                  mutex_exit(&so_pendfree_lock);
                 /* XXX splx */  
   
                 for (; m != NULL; m = next) {                  for (; m != NULL; m = next) {
                         next = m->m_next;                          next = m->m_next;
Line 331  sodopendfreel()
Line 316  sodopendfreel()
                         sodoloanfree((m->m_flags & M_EXT_PAGES) ?                          sodoloanfree((m->m_flags & M_EXT_PAGES) ?
                             m->m_ext.ext_pgs : NULL, m->m_ext.ext_buf,                              m->m_ext.ext_pgs : NULL, m->m_ext.ext_buf,
                             m->m_ext.ext_size);                              m->m_ext.ext_size);
                           s = splvm();
                         pool_cache_put(&mbpool_cache, m);                          pool_cache_put(&mbpool_cache, m);
                           splx(s);
                 }                  }
   
                 /* XXX splvm */                  mutex_enter(&so_pendfree_lock);
                 simple_lock(&so_pendfree_slock);  
         }          }
   
         return (rv);          return (rv);
 }  }
   
 void  void
 soloanfree(struct mbuf *m, caddr_t buf, size_t size, void *arg)  soloanfree(struct mbuf *m, void *buf, size_t size, void *arg)
 {  {
         int s;  
   
         if (m == NULL) {          if (m == NULL) {
   
Line 363  soloanfree(struct mbuf *m, caddr_t buf, 
Line 348  soloanfree(struct mbuf *m, caddr_t buf, 
          * because we need to put kva back to kernel_map.           * because we need to put kva back to kernel_map.
          */           */
   
         s = splvm();          mutex_enter(&so_pendfree_lock);
         simple_lock(&so_pendfree_slock);  
         m->m_next = so_pendfree;          m->m_next = so_pendfree;
         so_pendfree = m;          so_pendfree = m;
         if (sokvawaiters)          cv_broadcast(&socurkva_cv);
                 wakeup(&socurkva);          mutex_exit(&so_pendfree_lock);
         simple_unlock(&so_pendfree_slock);  
         splx(s);  
 }  }
   
 static long  static long
Line 416  sosend_loan(struct socket *so, struct ui
Line 398  sosend_loan(struct socket *so, struct ui
   
         lva += (vaddr_t) iov->iov_base & PAGE_MASK;          lva += (vaddr_t) iov->iov_base & PAGE_MASK;
   
         MEXTADD(m, (caddr_t) lva, space, M_MBUF, soloanfree, so);          MEXTADD(m, (void *) lva, space, M_MBUF, soloanfree, so);
         m->m_flags |= M_EXT_PAGES | M_EXT_ROMAP;          m->m_flags |= M_EXT_PAGES | M_EXT_ROMAP;
   
         uio->uio_resid -= space;          uio->uio_resid -= space;
         /* uio_offset not updated, not set/used for write(2) */          /* uio_offset not updated, not set/used for write(2) */
         uio->uio_iov->iov_base = (caddr_t) uio->uio_iov->iov_base + space;          uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + space;
         uio->uio_iov->iov_len -= space;          uio->uio_iov->iov_len -= space;
         if (uio->uio_iov->iov_len == 0) {          if (uio->uio_iov->iov_len == 0) {
                 uio->uio_iov++;                  uio->uio_iov++;
Line 449  void
Line 431  void
 soinit(void)  soinit(void)
 {  {
   
           mutex_init(&so_pendfree_lock, MUTEX_DRIVER, IPL_VM);
           cv_init(&socurkva_cv, "sokva");
   
         /* Set the initial adjusted socket buffer size. */          /* Set the initial adjusted socket buffer size. */
         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);
Line 473  socreate(int dom, struct socket **aso, i
Line 458  socreate(int dom, struct socket **aso, i
         uid_t           uid;          uid_t           uid;
         int             error, s;          int             error, s;
   
         if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_SOCKET,          error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_SOCKET,
             KAUTH_REQ_NETWORK_SOCKET_OPEN, (void *)(u_long)dom,              KAUTH_REQ_NETWORK_SOCKET_OPEN, KAUTH_ARG(dom), KAUTH_ARG(type),
             (void *)(u_long)type, (void *)(u_long)proto) != 0)              KAUTH_ARG(proto));
                 return (EPERM);          if (error)
                   return (error);
   
         if (proto)          if (proto)
                 prp = pffindproto(dom, proto, type);                  prp = pffindproto(dom, proto, type);
Line 497  socreate(int dom, struct socket **aso, i
Line 483  socreate(int dom, struct socket **aso, i
                 return (EPROTOTYPE);                  return (EPROTOTYPE);
         s = splsoftnet();          s = splsoftnet();
         so = pool_get(&socket_pool, PR_WAITOK);          so = pool_get(&socket_pool, PR_WAITOK);
         memset((caddr_t)so, 0, sizeof(*so));          memset((void *)so, 0, sizeof(*so));
         TAILQ_INIT(&so->so_q0);          TAILQ_INIT(&so->so_q0);
         TAILQ_INIT(&so->so_q);          TAILQ_INIT(&so->so_q);
         so->so_type = type;          so->so_type = type;
Line 623  soclose(struct socket *so)
Line 609  soclose(struct socket *so)
                             (so->so_state & SS_NBIO))                              (so->so_state & SS_NBIO))
                                 goto drop;                                  goto drop;
                         while (so->so_state & SS_ISCONNECTED) {                          while (so->so_state & SS_ISCONNECTED) {
                                 error = tsleep((caddr_t)&so->so_timeo,                                  error = tsleep((void *)&so->so_timeo,
                                                PSOCK | PCATCH, netcls,                                                 PSOCK | PCATCH, netcls,
                                                so->so_linger * hz);                                                 so->so_linger * hz);
                                 if (error)                                  if (error)
Line 654  soclose(struct socket *so)
Line 640  soclose(struct socket *so)
 int  int
 soabort(struct socket *so)  soabort(struct socket *so)
 {  {
         int error;  
   
         KASSERT(so->so_head == NULL);          return (*so->so_proto->pr_usrreq)(so, PRU_ABORT, (struct mbuf *)0,
         error = (*so->so_proto->pr_usrreq)(so, PRU_ABORT, (struct mbuf *)0,  
             (struct mbuf *)0, (struct mbuf *)0, (struct lwp *)0);              (struct mbuf *)0, (struct mbuf *)0, (struct lwp *)0);
         if (error) {  
                 sofree(so);  
         }  
         return error;  
 }  }
   
 int  int
Line 897  sosend(struct socket *so, struct mbuf *a
Line 877  sosend(struct socket *so, struct mbuf *a
                                         if (atomic && top == 0 && len < mlen)                                          if (atomic && top == 0 && len < mlen)
                                                 MH_ALIGN(m, len);                                                  MH_ALIGN(m, len);
                                 }                                  }
                                 error = uiomove(mtod(m, caddr_t), (int)len,                                  error = uiomove(mtod(m, void *), (int)len,
                                     uio);                                      uio);
  have_data:   have_data:
                                 resid = uio->uio_resid;                                  resid = uio->uio_resid;
Line 1003  soreceive(struct socket *so, struct mbuf
Line 983  soreceive(struct socket *so, struct mbuf
                 if (error)                  if (error)
                         goto bad;                          goto bad;
                 do {                  do {
                         error = uiomove(mtod(m, caddr_t),                          error = uiomove(mtod(m, void *),
                             (int) 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 && error == 0 && m);                  } while (uio->uio_resid && error == 0 && m);
Line 1217  soreceive(struct socket *so, struct mbuf
Line 1197  soreceive(struct socket *so, struct mbuf
                         SBLASTRECORDCHK(&so->so_rcv, "soreceive uiomove");                          SBLASTRECORDCHK(&so->so_rcv, "soreceive uiomove");
                         SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove");                          SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove");
                         splx(s);                          splx(s);
                         error = uiomove(mtod(m, caddr_t) + moff, (int)len, uio);                          error = uiomove(mtod(m, char *) + moff, (int)len, uio);
                         s = splsoftnet();                          s = splsoftnet();
                         if (error) {                          if (error) {
                                 /*                                  /*
Line 1428  sosetopt(struct socket *so, int level, i
Line 1408  sosetopt(struct socket *so, int level, i
 {  {
         int             error;          int             error;
         struct mbuf     *m;          struct mbuf     *m;
           struct linger   *l;
   
         error = 0;          error = 0;
         m = m0;          m = m0;
Line 1444  sosetopt(struct socket *so, int level, i
Line 1425  sosetopt(struct socket *so, int level, i
                                 error = EINVAL;                                  error = EINVAL;
                                 goto bad;                                  goto bad;
                         }                          }
                         if (mtod(m, struct linger *)->l_linger < 0 ||                          l = mtod(m, struct linger *);
                             mtod(m, struct linger *)->l_linger > (INT_MAX / hz)) {                          if (l->l_linger < 0 || l->l_linger > USHRT_MAX ||
                               l->l_linger > (INT_MAX / hz)) {
                                 error = EDOM;                                  error = EDOM;
                                 goto bad;                                  goto bad;
                         }                          }
                         so->so_linger = mtod(m, struct linger *)->l_linger;                          so->so_linger = l->l_linger;
                         /* fall thru... */                          if (l->l_onoff)
                                   so->so_options |= SO_LINGER;
                           else
                                   so->so_options &= ~SO_LINGER;
                           break;
   
                 case SO_DEBUG:                  case SO_DEBUG:
                 case SO_KEEPALIVE:                  case SO_KEEPALIVE:
Line 1590  sogetopt(struct socket *so, int level, i
Line 1576  sogetopt(struct socket *so, int level, i
                 case SO_LINGER:                  case SO_LINGER:
                         m->m_len = sizeof(struct linger);                          m->m_len = sizeof(struct linger);
                         mtod(m, struct linger *)->l_onoff =                          mtod(m, struct linger *)->l_onoff =
                                 so->so_options & SO_LINGER;                              (so->so_options & SO_LINGER) ? 1 : 0;
                         mtod(m, struct linger *)->l_linger = so->so_linger;                          mtod(m, struct linger *)->l_linger = so->so_linger;
                         break;                          break;
   
Line 1603  sogetopt(struct socket *so, int level, i
Line 1589  sogetopt(struct socket *so, int level, i
                 case SO_BROADCAST:                  case SO_BROADCAST:
                 case SO_OOBINLINE:                  case SO_OOBINLINE:
                 case SO_TIMESTAMP:                  case SO_TIMESTAMP:
                         *mtod(m, int *) = so->so_options & optname;                          *mtod(m, int *) = (so->so_options & optname) ? 1 : 0;
                         break;                          break;
   
                 case SO_TYPE:                  case SO_TYPE:
Line 1793  sysctl_kern_somaxkva(SYSCTLFN_ARGS)
Line 1779  sysctl_kern_somaxkva(SYSCTLFN_ARGS)
 {  {
         int error, new_somaxkva;          int error, new_somaxkva;
         struct sysctlnode node;          struct sysctlnode node;
         int s;  
   
         new_somaxkva = somaxkva;          new_somaxkva = somaxkva;
         node = *rnode;          node = *rnode;
Line 1805  sysctl_kern_somaxkva(SYSCTLFN_ARGS)
Line 1790  sysctl_kern_somaxkva(SYSCTLFN_ARGS)
         if (new_somaxkva < (16 * 1024 * 1024)) /* sanity */          if (new_somaxkva < (16 * 1024 * 1024)) /* sanity */
                 return (EINVAL);                  return (EINVAL);
   
         s = splvm();          mutex_enter(&so_pendfree_lock);
         simple_lock(&so_pendfree_slock);  
         somaxkva = new_somaxkva;          somaxkva = new_somaxkva;
         wakeup(&socurkva);          cv_broadcast(&socurkva_cv);
         simple_unlock(&so_pendfree_slock);          mutex_exit(&so_pendfree_lock);
         splx(s);  
   
         return (error);          return (error);
 }  }

Legend:
Removed from v.1.129.2.1  
changed lines
  Added in v.1.132.2.3

CVSweb <webmaster@jp.NetBSD.org>