diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index bd9365d375f9d748d1b23ffecfbae602db5ccdfc..9543f59b7b25a832fe242a44518f40b3cd3a3ab7 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -429,6 +429,7 @@ cifs_reconnect(struct TCP_Server_Info *server) server->ssocket->state, server->ssocket->flags); sock_release(server->ssocket); server->ssocket = NULL; + put_net(cifs_net_ns(server)); } server->sequence_number = 0; server->session_estab = false; @@ -811,6 +812,9 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) if (server->ssocket) { sock_release(server->ssocket); server->ssocket = NULL; + + /* Release netns reference for the socket. */ + put_net(cifs_net_ns(server)); } if (!list_empty(&server->pending_mid_q)) { @@ -859,6 +863,7 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) */ } + /* Release netns reference for this server. */ put_net(cifs_net_ns(server)); kfree(server->hostname); kfree(server); @@ -2526,6 +2531,8 @@ cifs_get_tcp_session(struct smb_vol *volume_info) tcp_ses->ops = volume_info->ops; tcp_ses->vals = volume_info->vals; + + /* Grab netns reference for this server. */ cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns)); tcp_ses->hostname = extract_hostname(volume_info->UNC); if (IS_ERR(tcp_ses->hostname)) { @@ -2627,14 +2634,17 @@ cifs_get_tcp_session(struct smb_vol *volume_info) out_err_crypto_release: cifs_crypto_secmech_release(tcp_ses); + /* Release netns reference for this server. */ put_net(cifs_net_ns(tcp_ses)); out_err: if (tcp_ses) { if (!IS_ERR(tcp_ses->hostname)) kfree(tcp_ses->hostname); - if (tcp_ses->ssocket) + if (tcp_ses->ssocket) { sock_release(tcp_ses->ssocket); + put_net(cifs_net_ns(tcp_ses)); + } kfree(tcp_ses); } return ERR_PTR(rc); @@ -3629,22 +3639,26 @@ generic_ip_connect(struct TCP_Server_Info *server) if (socket == NULL) { struct net *net = cifs_net_ns(server); - struct sock *sk; - rc = __sock_create(net, sfamily, SOCK_STREAM, - IPPROTO_TCP, &socket, 1); + rc = sock_create_kern(net, sfamily, SOCK_STREAM, + IPPROTO_TCP, &socket); if (rc < 0) { cifs_dbg(VFS, "Error %d creating socket\n", rc); server->ssocket = NULL; return rc; } - sk = socket->sk; - sk->sk_net_refcnt = 1; + /* + * Grab netns reference for the socket. + * + * This reference will be released in several situations: + * - In the failure path before the cifsd is started + * - In the all place where server->socket is released, it is + * also set to NULL. + * - Ultimately in clean_demultiplex_info(), during the final + * teardown. + */ get_net(net); -#ifdef CONFIG_PROC_FS - this_cpu_add(*net->core.sock_inuse, 1); -#endif /* BB other socket options to set KEEPALIVE, NODELAY? */ cifs_dbg(FYI, "Socket created\n"); @@ -3692,6 +3706,7 @@ generic_ip_connect(struct TCP_Server_Info *server) rc = socket->ops->connect(socket, saddr, slen, 0); if (rc < 0) { cifs_dbg(FYI, "Error %d connecting to server\n", rc); + put_net(cifs_net_ns(server)); sock_release(socket); server->ssocket = NULL; return rc;