&ksocknal_data.ksnd_eager_ack, sizeof (int),
0644, NULL, &proc_dointvec},
#if SOCKNAL_ZC
- {SOCKNAL_SYSCTL_EAGER_ACK, "zero_copy",
+ {SOCKNAL_SYSCTL_ZERO_COPY, "zero_copy",
&ksocknal_data.ksnd_zc_min_frag, sizeof (int),
0644, NULL, &proc_dointvec},
#endif
int
ksocknal_api_shutdown(nal_t *nal, int ni)
{
- CDEBUG (D_NET, "closing all connections\n");
-
- ksocknal_del_route (PTL_NID_ANY, 0, 0, 0);
- ksocknal_close_matching_conns (PTL_NID_ANY, 0);
return PTL_OK;
}
INIT_LIST_HEAD (&peer->ksnp_routes);
INIT_LIST_HEAD (&peer->ksnp_tx_queue);
- /* Can't unload while peers exist; ensures all I/O has terminated
- * before unload attempts */
- PORTAL_MODULE_USE;
atomic_inc (&ksocknal_data.ksnd_npeers);
return (peer);
}
* that _all_ state to do with this peer has been cleaned up when
* its refcount drops to zero. */
atomic_dec (&ksocknal_data.ksnd_npeers);
- PORTAL_MODULE_UNUSE;
}
void
peer->ksnp_last_alive = jiffies;
peer->ksnp_error = 0;
+ /* Set the deadline for the outgoing HELLO to drain */
+ conn->ksnc_tx_deadline = jiffies +
+ ksocknal_data.ksnd_io_timeout * HZ;
+
list_add (&conn->ksnc_list, &peer->ksnp_conns);
atomic_inc (&conn->ksnc_refcount);
write_unlock_irqrestore (&ksocknal_data.ksnd_global_lock, flags);
if (rc != 0)
- CERROR ("Closed %d stale conns to "LPX64"\n", rc, nid);
+ CERROR ("Closed %d stale conns to nid "LPX64" ip %d.%d.%d.%d\n",
+ rc, conn->ksnc_peer->ksnp_nid,
+ HIPQUAD(conn->ksnc_ipaddr));
if (bind_irq) /* irq binding required */
ksocknal_bind_irq (irq);
ksocknal_data_ready (sock->sk, 0);
ksocknal_write_space (sock->sk);
- CDEBUG(D_IOCTL, "conn [%p] registered for nid "LPX64"\n",
- conn, conn->ksnc_peer->ksnp_nid);
+ CDEBUG(D_IOCTL, "conn [%p] registered for nid "LPX64" ip %d.%d.%d.%d\n",
+ conn, conn->ksnc_peer->ksnp_nid, HIPQUAD(conn->ksnc_ipaddr));
ksocknal_put_conn (conn);
return (0);
ksocknal_close_conn_locked (ksock_conn_t *conn, int error)
{
/* This just does the immmediate housekeeping, and queues the
- * connection for the reaper to terminate.
+ * connection for the reaper to terminate.
* Caller holds ksnd_global_lock exclusively in irq context */
ksock_peer_t *peer = conn->ksnc_peer;
ksock_route_t *route;
/* complete current receive if any */
switch (conn->ksnc_rx_state) {
case SOCKNAL_RX_BODY:
-#if 0
- lib_finalize (&ksocknal_lib, NULL, conn->ksnc_cookie);
-#else
- CERROR ("Refusing to complete a partial receive from "
- LPX64", ip %08x\n", conn->ksnc_peer->ksnp_nid,
- conn->ksnc_ipaddr);
- CERROR ("This may hang communications and "
- "prevent modules from unloading\n");
-#endif
+ CERROR("Completing partial receive from "LPX64
+ ", ip %d.%d.%d.%d:%d, with error\n",
+ conn->ksnc_peer->ksnp_nid,
+ HIPQUAD(conn->ksnc_ipaddr), conn->ksnc_port);
+ lib_finalize (&ksocknal_lib, NULL, conn->ksnc_cookie, PTL_FAIL);
break;
case SOCKNAL_RX_BODY_FWD:
ksocknal_fmb_callback (conn->ksnc_cookie, -ECONNABORTED);
/* fall through */
case SOCKNAL_INIT_PTL:
+ /* No more calls to ksocknal_cmd() to create new
+ * autoroutes/connections since we're being unloaded. */
PtlNIFini(ksocknal_ni);
+
+ /* Delete all autoroute entries */
+ ksocknal_del_route(PTL_NID_ANY, 0, 0, 0);
+
+ /* Delete all connections */
+ ksocknal_close_matching_conns (PTL_NID_ANY, 0);
+
+ /* Wait for all peer state to clean up */
+ i = 2;
+ while (atomic_read (&ksocknal_data.ksnd_npeers) != 0) {
+ i++;
+ CDEBUG(((i & (-i)) == i) ? D_WARNING : D_NET, /* power of 2? */
+ "waiting for %d peers to disconnect\n",
+ atomic_read (&ksocknal_data.ksnd_npeers));
+ set_current_state (TASK_UNINTERRUPTIBLE);
+ schedule_timeout (HZ);
+ }
+
+ /* Tell lib we've stopped calling into her. */
lib_fini(&ksocknal_lib);
/* fall through */