--- m/include/net/9p/client.h 2022-07-24 20:01:37.299820800 +0800 +++ n/include/net/9p/client.h 2022-07-24 20:30:41.400124300 +0800 @@ -11,6 +11,7 @@ #include #include +#include /* Number of requests per row */ #define P9_ROW_MAXTAG 255 @@ -64,6 +65,7 @@ enum p9_req_status_t { REQ_STATUS_ERROR, }; +struct p9_client; /** * struct p9_req_t - request slots * @status: status of this request slot @@ -81,6 +83,7 @@ struct p9_req_t { struct p9_fcall tc; struct p9_fcall rc; struct list_head req_list; + struct p9_client *client; }; /** @@ -106,6 +109,8 @@ struct p9_client { enum p9_trans_status status; void *trans; struct kmem_cache *fcall_cache; + atomic_t reqs; + struct completion destroy_compl; union { struct { --- m/net/9p/client.c 2022-07-24 20:02:17.111024400 +0800 +++ n/net/9p/client.c 2022-07-24 20:33:37.239483000 +0800 @@ -307,6 +307,8 @@ p9_tag_alloc(struct p9_client *c, int8_t */ refcount_set(&req->refcount.refcount, 2); + req->client = c; + atomic_inc(&c->reqs); return req; free: @@ -373,10 +375,14 @@ static int p9_tag_remove(struct p9_clien static void p9_req_free(struct kref *ref) { struct p9_req_t *r = container_of(ref, struct p9_req_t, refcount); + struct p9_client *c = r->client; p9_fcall_fini(&r->tc); p9_fcall_fini(&r->rc); kmem_cache_free(p9_req_cache, r); + + if (atomic_dec_and_test(&c->reqs)) + complete(&c->destroy_compl); } int p9_req_put(struct p9_req_t *r) @@ -1066,6 +1072,8 @@ struct p9_client *p9_client_create(const clnt->msize - (P9_HDRSZ + 4), NULL); + atomic_set(&clnt->reqs, 1); + init_completion(&clnt->destroy_compl); return clnt; close_trans: @@ -1097,6 +1105,9 @@ void p9_client_destroy(struct p9_client p9_tag_cleanup(clnt); + if (!atomic_dec_and_test(&clnt->reqs)) + wait_for_completion(&clnt->destroy_compl); + kmem_cache_destroy(clnt->fcall_cache); kfree(clnt); }