One fix for an NFS/RDMA crash.

-----BEGIN PGP SIGNATURE-----
 
 iQIcBAABAgAGBQJYLznTAAoJECebzXlCjuG+ThgP/0tQByIqOKGqUNcEE0MLT4/+
 E2/V/Basi3tnCIatAjYZiAN/rKnO5f4iuyh7PKG/bzlYluLv5MLq68HUia8EorN8
 LExNvZAwYhjEQwDTzhBSityLHWmCwy3G0yYsJQ1DnbUdh8wAKr7lj4R0sr8RGJc1
 GxgWnlhi2lAJSGYRa8tYHzh0tTXGOCoR8POKXFJ91PTx8gEO6VzULvbIQm0RLSow
 +LGW36ov/ChQtJzVJsfcW6Hf4wHFevrtVTPtLWckMEtRq/DJ7hS2btgc02hpqFZm
 MK7wywHT35LV+DvU6QPmwUUaf5IXJjWx0W7thOsjWbYMbAHC/0D3De8bgGaAI3B1
 nB+B96BpGrALyhTX2pXQiQxsavXBl37BOGl3Ft03WrAVI4aJsfkaWDRS2X1jxfXI
 zhGBN2vseoiJblie95hLIgvMtkRmOq4E44oNDiP9zKTwrIkISoz5jmvLHY/8Mj7E
 NCof2P+K6ays8ywD2DqHlJKmiGA7PdNT87ZeeS4ZFvEjWSd4S1pfa0R+jg5FVxZl
 Vl7QQX5D/Ep+sXszJin4dYQnl844+sVMVaj6CdQOK0udml81UZTRO5fvjNexs3e4
 4Zd/ymC/XGs6Hz3pbPeIkAd/MzXCK0zNojNAdZnicOMzQpG2sZ76SJRZQg0sTCFH
 EP6QTWxOog4lnDfML13E
 =F2DQ
 -----END PGP SIGNATURE-----

Merge tag 'nfsd-4.9-2' of git://linux-nfs.org/~bfields/linux

Pull nfsd bugfix from Bruce Fields:
 "Just one fix for an NFS/RDMA crash"

* tag 'nfsd-4.9-2' of git://linux-nfs.org/~bfields/linux:
  sunrpc: svc_age_temp_xprts_now should not call setsockopt non-tcp transports
This commit is contained in:
Linus Torvalds 2016-11-18 16:32:21 -08:00
commit aad931a30f
4 changed files with 29 additions and 10 deletions

View File

@ -25,6 +25,7 @@ struct svc_xprt_ops {
void (*xpo_detach)(struct svc_xprt *); void (*xpo_detach)(struct svc_xprt *);
void (*xpo_free)(struct svc_xprt *); void (*xpo_free)(struct svc_xprt *);
int (*xpo_secure_port)(struct svc_rqst *); int (*xpo_secure_port)(struct svc_rqst *);
void (*xpo_kill_temp_xprt)(struct svc_xprt *);
}; };
struct svc_xprt_class { struct svc_xprt_class {

View File

@ -1002,14 +1002,8 @@ static void svc_age_temp_xprts(unsigned long closure)
void svc_age_temp_xprts_now(struct svc_serv *serv, struct sockaddr *server_addr) void svc_age_temp_xprts_now(struct svc_serv *serv, struct sockaddr *server_addr)
{ {
struct svc_xprt *xprt; struct svc_xprt *xprt;
struct svc_sock *svsk;
struct socket *sock;
struct list_head *le, *next; struct list_head *le, *next;
LIST_HEAD(to_be_closed); LIST_HEAD(to_be_closed);
struct linger no_linger = {
.l_onoff = 1,
.l_linger = 0,
};
spin_lock_bh(&serv->sv_lock); spin_lock_bh(&serv->sv_lock);
list_for_each_safe(le, next, &serv->sv_tempsocks) { list_for_each_safe(le, next, &serv->sv_tempsocks) {
@ -1027,10 +1021,7 @@ void svc_age_temp_xprts_now(struct svc_serv *serv, struct sockaddr *server_addr)
list_del_init(le); list_del_init(le);
xprt = list_entry(le, struct svc_xprt, xpt_list); xprt = list_entry(le, struct svc_xprt, xpt_list);
dprintk("svc_age_temp_xprts_now: closing %p\n", xprt); dprintk("svc_age_temp_xprts_now: closing %p\n", xprt);
svsk = container_of(xprt, struct svc_sock, sk_xprt); xprt->xpt_ops->xpo_kill_temp_xprt(xprt);
sock = svsk->sk_sock;
kernel_setsockopt(sock, SOL_SOCKET, SO_LINGER,
(char *)&no_linger, sizeof(no_linger));
svc_close_xprt(xprt); svc_close_xprt(xprt);
} }
} }

View File

@ -438,6 +438,21 @@ static int svc_tcp_has_wspace(struct svc_xprt *xprt)
return !test_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); return !test_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
} }
static void svc_tcp_kill_temp_xprt(struct svc_xprt *xprt)
{
struct svc_sock *svsk;
struct socket *sock;
struct linger no_linger = {
.l_onoff = 1,
.l_linger = 0,
};
svsk = container_of(xprt, struct svc_sock, sk_xprt);
sock = svsk->sk_sock;
kernel_setsockopt(sock, SOL_SOCKET, SO_LINGER,
(char *)&no_linger, sizeof(no_linger));
}
/* /*
* See net/ipv6/ip_sockglue.c : ip_cmsg_recv_pktinfo * See net/ipv6/ip_sockglue.c : ip_cmsg_recv_pktinfo
*/ */
@ -648,6 +663,10 @@ static struct svc_xprt *svc_udp_accept(struct svc_xprt *xprt)
return NULL; return NULL;
} }
static void svc_udp_kill_temp_xprt(struct svc_xprt *xprt)
{
}
static struct svc_xprt *svc_udp_create(struct svc_serv *serv, static struct svc_xprt *svc_udp_create(struct svc_serv *serv,
struct net *net, struct net *net,
struct sockaddr *sa, int salen, struct sockaddr *sa, int salen,
@ -667,6 +686,7 @@ static struct svc_xprt_ops svc_udp_ops = {
.xpo_has_wspace = svc_udp_has_wspace, .xpo_has_wspace = svc_udp_has_wspace,
.xpo_accept = svc_udp_accept, .xpo_accept = svc_udp_accept,
.xpo_secure_port = svc_sock_secure_port, .xpo_secure_port = svc_sock_secure_port,
.xpo_kill_temp_xprt = svc_udp_kill_temp_xprt,
}; };
static struct svc_xprt_class svc_udp_class = { static struct svc_xprt_class svc_udp_class = {
@ -1242,6 +1262,7 @@ static struct svc_xprt_ops svc_tcp_ops = {
.xpo_has_wspace = svc_tcp_has_wspace, .xpo_has_wspace = svc_tcp_has_wspace,
.xpo_accept = svc_tcp_accept, .xpo_accept = svc_tcp_accept,
.xpo_secure_port = svc_sock_secure_port, .xpo_secure_port = svc_sock_secure_port,
.xpo_kill_temp_xprt = svc_tcp_kill_temp_xprt,
}; };
static struct svc_xprt_class svc_tcp_class = { static struct svc_xprt_class svc_tcp_class = {

View File

@ -67,6 +67,7 @@ static void svc_rdma_detach(struct svc_xprt *xprt);
static void svc_rdma_free(struct svc_xprt *xprt); static void svc_rdma_free(struct svc_xprt *xprt);
static int svc_rdma_has_wspace(struct svc_xprt *xprt); static int svc_rdma_has_wspace(struct svc_xprt *xprt);
static int svc_rdma_secure_port(struct svc_rqst *); static int svc_rdma_secure_port(struct svc_rqst *);
static void svc_rdma_kill_temp_xprt(struct svc_xprt *);
static struct svc_xprt_ops svc_rdma_ops = { static struct svc_xprt_ops svc_rdma_ops = {
.xpo_create = svc_rdma_create, .xpo_create = svc_rdma_create,
@ -79,6 +80,7 @@ static struct svc_xprt_ops svc_rdma_ops = {
.xpo_has_wspace = svc_rdma_has_wspace, .xpo_has_wspace = svc_rdma_has_wspace,
.xpo_accept = svc_rdma_accept, .xpo_accept = svc_rdma_accept,
.xpo_secure_port = svc_rdma_secure_port, .xpo_secure_port = svc_rdma_secure_port,
.xpo_kill_temp_xprt = svc_rdma_kill_temp_xprt,
}; };
struct svc_xprt_class svc_rdma_class = { struct svc_xprt_class svc_rdma_class = {
@ -1317,6 +1319,10 @@ static int svc_rdma_secure_port(struct svc_rqst *rqstp)
return 1; return 1;
} }
static void svc_rdma_kill_temp_xprt(struct svc_xprt *xprt)
{
}
int svc_rdma_send(struct svcxprt_rdma *xprt, struct ib_send_wr *wr) int svc_rdma_send(struct svcxprt_rdma *xprt, struct ib_send_wr *wr)
{ {
struct ib_send_wr *bad_wr, *n_wr; struct ib_send_wr *bad_wr, *n_wr;