Skip to content

Commit e2154e2

Browse files
author
Malahal Naineni
committed
Prevent xprt refcount going up from zero.
svc_xprt_lookup() looks up in hash table, places a ref and passes to the caller. The xprt gets an additional initial refcount for being in the hash table itself. The caller will do SVC_RELEASE() once he is done with the xprt. SVC_DESTROY() gets called when the xprt gets an error which will eventually make the additional hash refcount go away, finally leading to zero refcount. The xprt is deleted only at the very end, before destroying. Once an SVC_DESTROY() is called, the refcount could go to zero, xprt gets deleted from hash table, then it gets destroyed. svc_xprt_lookup() can fairly assume that xprt memory won't be freed as long as it is in the hash table and it holds the hash lock. It should NOT access the xprt after releasing the hash lock if the refcount was bumped from zero. In such a case, we bailout and return failure. TODO: If we can delete the xprt from the hash table (RBT) as part of SVC_DESTROY() before decrementing the refcount, we will never have zero refcount xprt in the hash table, and this special code can be avoided.
1 parent 1ff6036 commit e2154e2

File tree

1 file changed

+21
-2
lines changed

1 file changed

+21
-2
lines changed

src/svc_xprt.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ svc_xprt_lookup(int fd, svc_xprt_setup_t setup)
143143
struct opr_rbtree_node *nv;
144144
SVCXPRT *xprt = NULL;
145145
uint16_t xp_flags;
146+
int32_t refcount;
146147

147148
if (svc_xprt_init_failure())
148149
return (NULL);
@@ -197,8 +198,26 @@ svc_xprt_lookup(int fd, svc_xprt_setup_t setup)
197198
rec = opr_containerof(nv, struct rpc_dplx_rec, fd_node);
198199
xprt = &rec->xprt;
199200

200-
/* lookup reference before unlock ensures shutdown cannot release */
201-
SVC_REF(xprt, SVC_REF_FLAG_NONE);
201+
/* lookup reference before unlock ensures shutdown cannot release
202+
*
203+
* The current implementation makes it possible to have 0
204+
* refcount xprts in the tree. The code would be easier if
205+
* destroy removes from the tree before decrementing the
206+
* refcount avoiding this possibility. It needs some code
207+
* re-org but easier to implement in the long run!
208+
*
209+
* For now, manually increment the refcnt and see if it indeed
210+
* was zero (1 now!). If so, bailout under tree lock as the xprt
211+
* might be freed as soon as we unlock!
212+
*
213+
* TODO: Need LTTng trace messages for these manual refcounts
214+
*/
215+
refcount = atomic_inc_int32_t(&xprt->xp_refcnt);
216+
if (refcount == 1) { /* proces of getting destroyed */
217+
atomic_dec_int32_t(&xprt->xp_refcnt);
218+
rwlock_unlock(&t->lock);
219+
return NULL;
220+
}
202221
rwlock_unlock(&t->lock);
203222

204223
/* unlocked window here permits shutdown to destroy without release;

0 commit comments

Comments
 (0)