* Get a socket structure from our zone, and initialize it. Note that it * would probably be better to allocate socket and PCB at the same time, but * I'm not convinced that all the protocols can be easily modified to do * this. * * soalloc() returns a socket with a ref count of 0. */
| 393 | * soalloc() returns a socket with a ref count of 0. |
| 394 | */ |
| 395 | static struct socket * |
| 396 | soalloc(struct vnet *vnet) |
| 397 | { |
| 398 | struct socket *so; |
| 399 | |
| 400 | so = uma_zalloc(socket_zone, M_NOWAIT | M_ZERO); |
| 401 | if (so == NULL) |
| 402 | return (NULL); |
| 403 | #ifdef MAC |
| 404 | if (mac_socket_init(so, M_NOWAIT) != 0) { |
| 405 | uma_zfree(socket_zone, so); |
| 406 | return (NULL); |
| 407 | } |
| 408 | #endif |
| 409 | if (khelp_init_osd(HELPER_CLASS_SOCKET, &so->osd)) { |
| 410 | uma_zfree(socket_zone, so); |
| 411 | return (NULL); |
| 412 | } |
| 413 | |
| 414 | /* |
| 415 | * The socket locking protocol allows to lock 2 sockets at a time, |
| 416 | * however, the first one must be a listening socket. WITNESS lacks |
| 417 | * a feature to change class of an existing lock, so we use DUPOK. |
| 418 | */ |
| 419 | mtx_init(&so->so_lock, "socket", NULL, MTX_DEF | MTX_DUPOK); |
| 420 | SOCKBUF_LOCK_INIT(&so->so_snd, "so_snd"); |
| 421 | SOCKBUF_LOCK_INIT(&so->so_rcv, "so_rcv"); |
| 422 | so->so_rcv.sb_sel = &so->so_rdsel; |
| 423 | so->so_snd.sb_sel = &so->so_wrsel; |
| 424 | sx_init(&so->so_snd.sb_sx, "so_snd_sx"); |
| 425 | sx_init(&so->so_rcv.sb_sx, "so_rcv_sx"); |
| 426 | TAILQ_INIT(&so->so_snd.sb_aiojobq); |
| 427 | TAILQ_INIT(&so->so_rcv.sb_aiojobq); |
| 428 | #ifndef FSTACK |
| 429 | TASK_INIT(&so->so_snd.sb_aiotask, 0, soaio_snd, so); |
| 430 | TASK_INIT(&so->so_rcv.sb_aiotask, 0, soaio_rcv, so); |
| 431 | #endif |
| 432 | #ifdef VIMAGE |
| 433 | VNET_ASSERT(vnet != NULL, ("%s:%d vnet is NULL, so=%p", |
| 434 | __func__, __LINE__, so)); |
| 435 | so->so_vnet = vnet; |
| 436 | #endif |
| 437 | /* We shouldn't need the so_global_mtx */ |
| 438 | if (hhook_run_socket(so, NULL, HHOOK_SOCKET_CREATE)) { |
| 439 | /* Do we need more comprehensive error returns? */ |
| 440 | uma_zfree(socket_zone, so); |
| 441 | return (NULL); |
| 442 | } |
| 443 | mtx_lock(&so_global_mtx); |
| 444 | so->so_gencnt = ++so_gencnt; |
| 445 | ++numopensockets; |
| 446 | #ifdef VIMAGE |
| 447 | vnet->vnet_sockcnt++; |
| 448 | #endif |
| 449 | mtx_unlock(&so_global_mtx); |
| 450 | |
| 451 | return (so); |
| 452 | } |
no test coverage detected