sunrpc: don't call sleeping functions from the notifier block callbacks
The inet6addr_chain is an atomic notifier chain, so we can't call
anything that might sleep (like lock_sock)... instead of closing the
socket from svc_age_temp_xprts_now (which is called by the notifier
function), just have the rpc service threads do it instead.
Cc: stable@vger.kernel.org
Fixes: c3d4879e01
"sunrpc: Add a function to close..."
Signed-off-by: Scott Mayhew <smayhew@redhat.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
Родитель
78794d1890
Коммит
546125d161
|
@ -66,6 +66,7 @@ struct svc_xprt {
|
||||||
#define XPT_LISTENER 10 /* listening endpoint */
|
#define XPT_LISTENER 10 /* listening endpoint */
|
||||||
#define XPT_CACHE_AUTH 11 /* cache auth info */
|
#define XPT_CACHE_AUTH 11 /* cache auth info */
|
||||||
#define XPT_LOCAL 12 /* connection from loopback interface */
|
#define XPT_LOCAL 12 /* connection from loopback interface */
|
||||||
|
#define XPT_KILL_TEMP 13 /* call xpo_kill_temp_xprt before closing */
|
||||||
|
|
||||||
struct svc_serv *xpt_server; /* service for transport */
|
struct svc_serv *xpt_server; /* service for transport */
|
||||||
atomic_t xpt_reserved; /* space on outq that is rsvd */
|
atomic_t xpt_reserved; /* space on outq that is rsvd */
|
||||||
|
|
|
@ -799,6 +799,8 @@ static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt)
|
||||||
|
|
||||||
if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
|
if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
|
||||||
dprintk("svc_recv: found XPT_CLOSE\n");
|
dprintk("svc_recv: found XPT_CLOSE\n");
|
||||||
|
if (test_and_clear_bit(XPT_KILL_TEMP, &xprt->xpt_flags))
|
||||||
|
xprt->xpt_ops->xpo_kill_temp_xprt(xprt);
|
||||||
svc_delete_xprt(xprt);
|
svc_delete_xprt(xprt);
|
||||||
/* Leave XPT_BUSY set on the dead xprt: */
|
/* Leave XPT_BUSY set on the dead xprt: */
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1020,9 +1022,11 @@ void svc_age_temp_xprts_now(struct svc_serv *serv, struct sockaddr *server_addr)
|
||||||
le = to_be_closed.next;
|
le = to_be_closed.next;
|
||||||
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);
|
set_bit(XPT_CLOSE, &xprt->xpt_flags);
|
||||||
xprt->xpt_ops->xpo_kill_temp_xprt(xprt);
|
set_bit(XPT_KILL_TEMP, &xprt->xpt_flags);
|
||||||
svc_close_xprt(xprt);
|
dprintk("svc_age_temp_xprts_now: queuing xprt %p for closing\n",
|
||||||
|
xprt);
|
||||||
|
svc_xprt_enqueue(xprt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(svc_age_temp_xprts_now);
|
EXPORT_SYMBOL_GPL(svc_age_temp_xprts_now);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче