diff options
author | J. Bruce Fields <bfields@redhat.com> | 2010-10-26 10:07:17 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2010-11-02 17:13:52 -0400 |
commit | 21b75b019983dfa5c2dda588f4b60b4ca69844a4 (patch) | |
tree | c1e0a8c4e136a0de35fc996a7ed6c5db1e6bb9cc /include | |
parent | c8ddb2713c624f432fa5fe3c7ecffcdda46ea0d4 (diff) |
nfsd4: fix 4.1 connection registration race
If a connection is closed just after a sequence or create_session
is sent over it, we could end up trying to register a callback that will
never get called since the xprt is already marked dead.
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/sunrpc/svc_xprt.h | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h index bbdb680ffbe9..aea0d438e3c7 100644 --- a/include/linux/sunrpc/svc_xprt.h +++ b/include/linux/sunrpc/svc_xprt.h | |||
@@ -82,18 +82,28 @@ struct svc_xprt { | |||
82 | struct net *xpt_net; | 82 | struct net *xpt_net; |
83 | }; | 83 | }; |
84 | 84 | ||
85 | static inline void register_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u) | 85 | static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u) |
86 | { | 86 | { |
87 | spin_lock(&xpt->xpt_lock); | 87 | spin_lock(&xpt->xpt_lock); |
88 | list_add(&u->list, &xpt->xpt_users); | 88 | list_del_init(&u->list); |
89 | spin_unlock(&xpt->xpt_lock); | 89 | spin_unlock(&xpt->xpt_lock); |
90 | } | 90 | } |
91 | 91 | ||
92 | static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u) | 92 | static inline int register_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u) |
93 | { | 93 | { |
94 | spin_lock(&xpt->xpt_lock); | 94 | spin_lock(&xpt->xpt_lock); |
95 | list_del_init(&u->list); | 95 | if (test_bit(XPT_CLOSE, &xpt->xpt_flags)) { |
96 | /* | ||
97 | * The connection is about to be deleted soon (or, | ||
98 | * worse, may already be deleted--in which case we've | ||
99 | * already notified the xpt_users). | ||
100 | */ | ||
101 | spin_unlock(&xpt->xpt_lock); | ||
102 | return -ENOTCONN; | ||
103 | } | ||
104 | list_add(&u->list, &xpt->xpt_users); | ||
96 | spin_unlock(&xpt->xpt_lock); | 105 | spin_unlock(&xpt->xpt_lock); |
106 | return 0; | ||
97 | } | 107 | } |
98 | 108 | ||
99 | int svc_reg_xprt_class(struct svc_xprt_class *); | 109 | int svc_reg_xprt_class(struct svc_xprt_class *); |