diff options
Diffstat (limited to 'fs/ocfs2/cluster/tcp.c')
| -rw-r--r-- | fs/ocfs2/cluster/tcp.c | 45 | 
1 files changed, 39 insertions, 6 deletions
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c index 681691bc233a..ea34952f9496 100644 --- a/fs/ocfs2/cluster/tcp.c +++ b/fs/ocfs2/cluster/tcp.c @@ -1480,6 +1480,14 @@ static int o2net_set_nodelay(struct socket *sock)  	return ret;  } +static int o2net_set_usertimeout(struct socket *sock) +{ +	int user_timeout = O2NET_TCP_USER_TIMEOUT; + +	return kernel_setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT, +				(char *)&user_timeout, sizeof(user_timeout)); +} +  static void o2net_initialize_handshake(void)  {  	o2net_hand->o2hb_heartbeat_timeout_ms = cpu_to_be32( @@ -1536,16 +1544,20 @@ static void o2net_idle_timer(unsigned long data)  #endif  	printk(KERN_NOTICE "o2net: Connection to " SC_NODEF_FMT " has been " -	       "idle for %lu.%lu secs, shutting it down.\n", SC_NODEF_ARGS(sc), -	       msecs / 1000, msecs % 1000); +	       "idle for %lu.%lu secs.\n", +	       SC_NODEF_ARGS(sc), msecs / 1000, msecs % 1000); -	/* -	 * Initialize the nn_timeout so that the next connection attempt -	 * will continue in o2net_start_connect. +	/* idle timerout happen, don't shutdown the connection, but +	 * make fence decision. Maybe the connection can recover before +	 * the decision is made.  	 */  	atomic_set(&nn->nn_timeout, 1); +	o2quo_conn_err(o2net_num_from_nn(nn)); +	queue_delayed_work(o2net_wq, &nn->nn_still_up, +			msecs_to_jiffies(O2NET_QUORUM_DELAY_MS)); + +	o2net_sc_reset_idle_timer(sc); -	o2net_sc_queue_work(sc, &sc->sc_shutdown_work);  }  static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc) @@ -1560,6 +1572,15 @@ static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc)  static void o2net_sc_postpone_idle(struct o2net_sock_container *sc)  { +	struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num); + +	/* clear fence decision since the connection recover from timeout*/ +	if (atomic_read(&nn->nn_timeout)) { +		o2quo_conn_up(o2net_num_from_nn(nn)); +		cancel_delayed_work(&nn->nn_still_up); +		atomic_set(&nn->nn_timeout, 0); +	} +  	/* Only push out an existing timer */  	if (timer_pending(&sc->sc_idle_timeout))  		o2net_sc_reset_idle_timer(sc); @@ -1650,6 +1671,12 @@ static void o2net_start_connect(struct work_struct *work)  		goto out;  	} +	ret = o2net_set_usertimeout(sock); +	if (ret) { +		mlog(ML_ERROR, "set TCP_USER_TIMEOUT failed with %d\n", ret); +		goto out; +	} +  	o2net_register_callbacks(sc->sc_sock->sk, sc);  	spin_lock(&nn->nn_lock); @@ -1831,6 +1858,12 @@ static int o2net_accept_one(struct socket *sock, int *more)  		goto out;  	} +	ret = o2net_set_usertimeout(new_sock); +	if (ret) { +		mlog(ML_ERROR, "set TCP_USER_TIMEOUT failed with %d\n", ret); +		goto out; +	} +  	slen = sizeof(sin);  	ret = new_sock->ops->getname(new_sock, (struct sockaddr *) &sin,  				       &slen, 1);  |