/* This work queue function performs the blocking parts of socket shutdown. A few paths lead here. set_nn_state will trigger this callback if it sees an sc detached from the nn. state_change will also trigger this callback directly when it sees errors. In that case we need to call set_nn_state ourselves as state_change couldn't get the nn_lock and call set_nn_state itself.  */
static void o2net_shutdown_sc(struct work_struct *work)
/* This work queue function performs the blocking parts of socket shutdown. A few paths lead here. set_nn_state will trigger this callback if it sees an sc detached from the nn. state_change will also trigger this callback directly when it sees errors. In that case we need to call set_nn_state ourselves as state_change couldn't get the nn_lock and call set_nn_state itself.  */
static void o2net_shutdown_sc(struct work_struct *work)
{
	struct o2net_sock_container *sc =
		container_of(work, struct o2net_sock_container,
			     sc_shutdown_work);
	struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num);
	sclog(sc, "shutting down\n");
	if (o2net_unregister_callbacks(sc->sc_sock->sk, sc)) {
		del_timer_sync(&sc->sc_idle_timeout);
		o2net_sc_cancel_delayed_work(sc, &sc->sc_keepalive_work);
		sc_put(sc);
		kernel_sock_shutdown(sc->sc_sock, SHUT_RDWR);
	}
	o2net_ensure_shutdown(nn, sc, 0);
	sc_put(sc);
}