Print this page
1631 kernel panic in tcp_input_data

*** 19,28 **** --- 19,29 ---- * CDDL HEADER END */ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ /* This file contains all TCP input processing functions. */ #include <sys/types.h>
*** 2228,2237 **** --- 2229,2346 ---- return (mp1); } } /* + * Dummy socket upcalls for if/when the conn_t gets detached from a + * direct-callback sonode via a user-driven close(). Easy to catch with + * DTrace FBT, and should be mostly harmless. + */ + + /* ARGSUSED */ + static sock_upper_handle_t + tcp_dummy_newconn(sock_upper_handle_t x, sock_lower_handle_t y, + sock_downcalls_t *z, cred_t *cr, pid_t pid, sock_upcalls_t **ignored) + { + ASSERT(0); /* Panic in debug, otherwise ignore. */ + return (NULL); + } + + /* ARGSUSED */ + static void + tcp_dummy_connected(sock_upper_handle_t x, sock_connid_t y, cred_t *cr, + pid_t pid) + { + ASSERT(x == NULL); + /* Normally we'd crhold(cr) and attach it to socket state. */ + /* LINTED */ + } + + /* ARGSUSED */ + static int + tcp_dummy_disconnected(sock_upper_handle_t x, sock_connid_t y, int blah) + { + ASSERT(0); /* Panic in debug, otherwise ignore. */ + return (-1); + } + + /* ARGSUSED */ + static void + tcp_dummy_opctl(sock_upper_handle_t x, sock_opctl_action_t y, uintptr_t blah) + { + ASSERT(x == NULL); + /* We really want this one to be a harmless NOP for now. */ + /* LINTED */ + } + + /* ARGSUSED */ + static ssize_t + tcp_dummy_recv(sock_upper_handle_t x, mblk_t *mp, size_t len, int flags, + int *error, boolean_t *push) + { + ASSERT(x == NULL); + + /* + * Consume the message, set ESHUTDOWN, and return an error. + * Nobody's home! + */ + freemsg(mp); + *error = ESHUTDOWN; + return (-1); + } + + /* ARGSUSED */ + static void + tcp_dummy_set_proto_props(sock_upper_handle_t x, struct sock_proto_props *y) + { + ASSERT(0); /* Panic in debug, otherwise ignore. */ + } + + /* ARGSUSED */ + static void + tcp_dummy_txq_full(sock_upper_handle_t x, boolean_t y) + { + ASSERT(0); /* Panic in debug, otherwise ignore. */ + } + + /* ARGSUSED */ + static void + tcp_dummy_signal_oob(sock_upper_handle_t x, ssize_t len) + { + ASSERT(x == NULL); + /* Otherwise, this would signal socket state about OOB data. */ + } + + /* ARGSUSED */ + static void + tcp_dummy_set_error(sock_upper_handle_t x, int err) + { + ASSERT(0); /* Panic in debug, otherwise ignore. */ + } + + /* ARGSUSED */ + static void + tcp_dummy_onearg(sock_upper_handle_t x) + { + ASSERT(0); /* Panic in debug, otherwise ignore. */ + } + + static sock_upcalls_t tcp_dummy_upcalls = { + tcp_dummy_newconn, + tcp_dummy_connected, + tcp_dummy_disconnected, + tcp_dummy_opctl, + tcp_dummy_recv, + tcp_dummy_set_proto_props, + tcp_dummy_txq_full, + tcp_dummy_signal_oob, + tcp_dummy_onearg, + tcp_dummy_set_error, + tcp_dummy_onearg + }; + + /* * Handle M_DATA messages from IP. Its called directly from IP via * squeue for received IP packets. * * The first argument is always the connp/tcp to which the mp belongs. * There are no exceptions to this rule. The caller has already put
*** 2269,2278 **** --- 2378,2388 ---- int mss; conn_t *connp = (conn_t *)arg; squeue_t *sqp = (squeue_t *)arg2; tcp_t *tcp = connp->conn_tcp; tcp_stack_t *tcps = tcp->tcp_tcps; + sock_upcalls_t *sockupcalls; /* * RST from fused tcp loopback peer should trigger an unfuse. */ if (tcp->tcp_fused) {
*** 2394,2403 **** --- 2504,2518 ---- mp->b_wptr = (uchar_t *)tcpha + TCP_HDR_LENGTH(tcpha); seg_len = 0; } } + sockupcalls = connp->conn_upcalls; + /* A conn_t may have belonged to a now-closed socket. Be careful. */ + if (sockupcalls == NULL) + sockupcalls = &tcp_dummy_upcalls; + switch (tcp->tcp_state) { case TCPS_SYN_SENT: if (connp->conn_final_sqp == NULL && tcp_outbound_squeue_switch && sqp != NULL) { ASSERT(connp->conn_initial_sqp == connp->conn_sqp);
*** 2605,2616 **** ira->ira_cred, ira->ira_cpid); } putnext(connp->conn_rq, mp1); } else { ! (*connp->conn_upcalls-> ! su_connected) (connp->conn_upper_handle, tcp->tcp_connid, ira->ira_cred, ira->ira_cpid); freemsg(mp1); --- 2720,2730 ---- ira->ira_cred, ira->ira_cpid); } putnext(connp->conn_rq, mp1); } else { ! (*sockupcalls->su_connected) (connp->conn_upper_handle, tcp->tcp_connid, ira->ira_cred, ira->ira_cpid); freemsg(mp1);
*** 2633,2643 **** mblk_setcred(mp1, ira->ira_cred, ira->ira_cpid); } putnext(connp->conn_rq, mp1); } else { ! (*connp->conn_upcalls->su_connected) (connp->conn_upper_handle, tcp->tcp_connid, ira->ira_cred, ira->ira_cpid); freemsg(mp1); } --- 2747,2757 ---- mblk_setcred(mp1, ira->ira_cred, ira->ira_cpid); } putnext(connp->conn_rq, mp1); } else { ! (*sockupcalls->su_connected) (connp->conn_upper_handle, tcp->tcp_connid, ira->ira_cred, ira->ira_cpid); freemsg(mp1); }
*** 3007,3018 **** if ((flags & TH_URG) && (!tcp->tcp_urp_last_valid || SEQ_GT(urp + seg_seq, tcp->tcp_urp_last))) { if (IPCL_IS_NONSTR(connp)) { if (!TCP_IS_DETACHED(tcp)) { ! (*connp->conn_upcalls-> ! su_signal_oob) (connp->conn_upper_handle, urp); } } else { mp1 = allocb(0, BPRI_MED); --- 3121,3131 ---- if ((flags & TH_URG) && (!tcp->tcp_urp_last_valid || SEQ_GT(urp + seg_seq, tcp->tcp_urp_last))) { if (IPCL_IS_NONSTR(connp)) { if (!TCP_IS_DETACHED(tcp)) { ! (*sockupcalls->su_signal_oob) (connp->conn_upper_handle, urp); } } else { mp1 = allocb(0, BPRI_MED);
*** 3286,3296 **** * Neither TH_SEND_URP_MARK nor TH_MARKNEXT_NEEDED * are used by non-STREAMS sockets. */ if (IPCL_IS_NONSTR(connp)) { if (!TCP_IS_DETACHED(tcp)) { ! (*connp->conn_upcalls->su_signal_oob) (connp->conn_upper_handle, urp); } } else { /* * If we haven't generated the signal yet for --- 3399,3409 ---- * Neither TH_SEND_URP_MARK nor TH_MARKNEXT_NEEDED * are used by non-STREAMS sockets. */ if (IPCL_IS_NONSTR(connp)) { if (!TCP_IS_DETACHED(tcp)) { ! (*sockupcalls->su_signal_oob) (connp->conn_upper_handle, urp); } } else { /* * If we haven't generated the signal yet for
*** 3445,3455 **** * have to allocate the T_exdata_ind, if we can. */ if (IPCL_IS_NONSTR(connp)) { int error; ! (*connp->conn_upcalls->su_recv) (connp->conn_upper_handle, mp, seg_len, MSG_OOB, &error, NULL); /* * We should never be in middle of a * fallback, the squeue guarantees that. --- 3558,3568 ---- * have to allocate the T_exdata_ind, if we can. */ if (IPCL_IS_NONSTR(connp)) { int error; ! (*sockupcalls->su_recv) (connp->conn_upper_handle, mp, seg_len, MSG_OOB, &error, NULL); /* * We should never be in middle of a * fallback, the squeue guarantees that.
*** 4624,4635 **** * Non-STREAMS socket */ boolean_t push = flags & (TH_PUSH|TH_FIN); int error; ! if ((*connp->conn_upcalls->su_recv)( ! connp->conn_upper_handle, mp, seg_len, 0, &error, &push) <= 0) { /* * We should never be in middle of a * fallback, the squeue guarantees that. */ --- 4737,4747 ---- * Non-STREAMS socket */ boolean_t push = flags & (TH_PUSH|TH_FIN); int error; ! if ((*sockupcalls->su_recv)(connp->conn_upper_handle, mp, seg_len, 0, &error, &push) <= 0) { /* * We should never be in middle of a * fallback, the squeue guarantees that. */
*** 4867,4878 **** ASSERT(!tcp->tcp_detached); if (IPCL_IS_NONSTR(connp)) { ASSERT(tcp->tcp_ordrel_mp == NULL); tcp->tcp_ordrel_done = B_TRUE; ! (*connp->conn_upcalls->su_opctl) ! (connp->conn_upper_handle, SOCK_OPCTL_SHUT_RECV, 0); goto done; } if (tcp->tcp_rcv_list != NULL) { /* --- 4979,4990 ---- ASSERT(!tcp->tcp_detached); if (IPCL_IS_NONSTR(connp)) { ASSERT(tcp->tcp_ordrel_mp == NULL); tcp->tcp_ordrel_done = B_TRUE; ! (*sockupcalls->su_opctl)(connp->conn_upper_handle, ! SOCK_OPCTL_SHUT_RECV, 0); goto done; } if (tcp->tcp_rcv_list != NULL) { /*