net/9p/client.c: fix misuse of spin_lock_irqsave for p9_client lock
PATCH v2 1/1 net/9p/client.c: fix misuse of spin_lock_irqsave for p9_client lock
In p9_read_work(), we use spin_lock for client->lock, but misuse spin_lock_irqsave for it in p9_fid_create(). As p9_client lock won't be locked in irq context, so spin_lock is enough. And that will improve the performance.
Rebased on 9p-next.
--- net/9p/client.c | 18 ++++++++---------- net/9p/trans_fd.c | 7 +++---- 2 files changed, 11 insertions(+), 14 deletions(-)
net/9p/client.c +8 -10
@@ -275,14 +275,14 @@ static struct p9_fcall *p9_fcall_alloc(int alloc_msize)INIT_LIST_HEAD (&req->req_list);idr_preload (GFP_NOFS ); -spin_lock_irq (&c->lock); +spin_lock (&c->lock);if (type ==P9_TVERSION ) tag =idr_alloc (&c->reqs, req,P9_NOTAG ,P9_NOTAG +1 ,GFP_NOWAIT );else tag =idr_alloc (&c->reqs, req,0 ,P9_NOTAG ,GFP_NOWAIT ); req->tc->tag = tag; -spin_unlock_irq (&c->lock); +spin_unlock (&c->lock);idr_preload_end ();if (tag <0 ) goto free;
@@ -328,13 +328,12 @@ struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)*/ static void p9_free_req (struct p9_client *c,struct p9_req_t *r) { -unsigned long flags;u16 tag = r->tc->tag;p9_debug (P9_DEBUG_MUX ,"clnt %p req %p tag: %d\n" , c, r, tag); -spin_lock_irqsave (&c->lock, flags); +spin_lock (&c->lock);idr_remove (&c->reqs, tag); -spin_unlock_irqrestore (&c->lock, flags); +spin_unlock (&c->lock);kfree (r->tc);kfree (r->rc);kmem_cache_free (p9_req_cache, r);
@@ -846,10 +845,10 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt) fid->fid =0 ;idr_preload (GFP_KERNEL ); -spin_lock_irq (&clnt->lock); +spin_lock (&clnt->lock); ret =idr_alloc_u32 (&clnt->fids, fid, &fid->fid,P9_NOFID -1 ,GFP_NOWAIT ); -spin_unlock_irq (&clnt->lock); +spin_unlock (&clnt->lock);idr_preload_end ();if (!ret)
@@ -862,13 +861,12 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt)static void p9_fid_destroy (struct p9_fid *fid) {struct p9_client *clnt; -unsigned long flags;p9_debug (P9_DEBUG_FID ,"fid %d\n" , fid->fid); clnt = fid->clnt; -spin_lock_irqsave (&clnt->lock, flags); +spin_lock (&clnt->lock);idr_remove (&clnt->fids, fid->fid); -spin_unlock_irqrestore (&clnt->lock, flags); +spin_unlock (&clnt->lock);kfree (fid->rdir);kfree (fid); }
net/9p/trans_fd.c +3 -4
@@ -197,15 +197,14 @@ static void p9_mux_poll_stop(struct p9_conn *m)static void p9_conn_cancel (struct p9_conn *m,int err) {struct p9_req_t *req, *rtmp; -unsigned long flags;LIST_HEAD (cancel_list);p9_debug (P9_DEBUG_ERROR ,"mux %p err %d\n" , m, err); -spin_lock_irqsave (&m->client->lock, flags); +spin_lock (&m->client->lock);if (m->err) { -spin_unlock_irqrestore (&m->client->lock, flags); +spin_unlock (&m->client->lock);return ; }
@@ -217,7 +216,7 @@ static void p9_conn_cancel(struct p9_conn *m, int err)list_for_each_entry_safe (req, rtmp, &m->unsent_req_list, req_list) {list_move (&req->req_list, &cancel_list); } -spin_unlock_irqrestore (&m->client->lock, flags); +spin_unlock (&m->client->lock);list_for_each_entry_safe (req, rtmp, &cancel_list, req_list) {p9_debug (P9_DEBUG_ERROR ,"call back req %p\n" , req);
Dominique Martinet
maintainerpiaojun wrote on Tue, Jul 17, 2018:
Quoted 4 lines
In
p9_read_work(), we usespin_lockforclient->lock, but misusespin_lock_irqsavefor it inp9_fid_create(). Asp9_clientlock won't be locked in irq context, sospin_lockis enough. And that will improve the performance.
(I didn't say in v1, but the commit message sounds a bit odd to me, if there is any other change to the patch could you please rephrase it a bit?)
Quoted 1 line
Rebased on 9p-next.
(Likewise, this should probably go below the '---' mark to not be in the final commit message, 9p-next does not make sense to linux as a whole)
Quoted 2 lines
Signed-off-by Jun Piao <[email protected]>
Nitpicks aside this still looks good to me, I'm not expert in locking but I believe the conn_cancel stuff in trans_fd is called either from user context or workqueue which also is process context, while the rest comes from user context only.
There *are* common functions called from interrupt context (I see:p9_tag_lookup, p9_client_cb, p9_parse_header) but luckily enough none of these take the lock.
I'll give this one a little bit of time for others to review before picking it up, just in case, but will do if no-one complains.
Quoted 103 lines
--- net/9p/client.c | 18 ++++++++---------- net/9p/trans_fd.c | 7 +++---- 2 files changed, 11 insertions(+), 14 deletions(-)net/9p/client.c +8
-10@@ -275,14 +275,14 @@ static struct p9_fcall *p9_fcall_alloc(int alloc_msize)INIT_LIST_HEAD (&req->req_list);idr_preload (GFP_NOFS ); -spin_lock_irq (&c->lock); +spin_lock (&c->lock);if (type ==P9_TVERSION ) tag =idr_alloc (&c->reqs, req,P9_NOTAG ,P9_NOTAG +1 ,GFP_NOWAIT );else tag =idr_alloc (&c->reqs, req,0 ,P9_NOTAG ,GFP_NOWAIT ); req->tc->tag = tag; -spin_unlock_irq (&c->lock); +spin_unlock (&c->lock);idr_preload_end ();if (tag <0 ) goto free;@@ -328,13 +328,12 @@ struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)*/ static void p9_free_req (struct p9_client *c,struct p9_req_t *r) { -unsigned long flags;u16 tag = r->tc->tag;p9_debug (P9_DEBUG_MUX ,"clnt %p req %p tag: %d\n" , c, r, tag); -spin_lock_irqsave (&c->lock, flags); +spin_lock (&c->lock);idr_remove (&c->reqs, tag); -spin_unlock_irqrestore (&c->lock, flags); +spin_unlock (&c->lock);kfree (r->tc);kfree (r->rc);kmem_cache_free (p9_req_cache, r);@@ -846,10 +845,10 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt) fid->fid =0 ;idr_preload (GFP_KERNEL ); -spin_lock_irq (&clnt->lock); +spin_lock (&clnt->lock); ret =idr_alloc_u32 (&clnt->fids, fid, &fid->fid,P9_NOFID -1 ,GFP_NOWAIT ); -spin_unlock_irq (&clnt->lock); +spin_unlock (&clnt->lock);idr_preload_end ();if (!ret)@@ -862,13 +861,12 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt)static void p9_fid_destroy (struct p9_fid *fid) {struct p9_client *clnt; -unsigned long flags;p9_debug (P9_DEBUG_FID ,"fid %d\n" , fid->fid); clnt = fid->clnt; -spin_lock_irqsave (&clnt->lock, flags); +spin_lock (&clnt->lock);idr_remove (&clnt->fids, fid->fid); -spin_unlock_irqrestore (&clnt->lock, flags); +spin_unlock (&clnt->lock);kfree (fid->rdir);kfree (fid); }net/9p/trans_fd.c +3
-4@@ -197,15 +197,14 @@ static void p9_mux_poll_stop(struct p9_conn *m)static void p9_conn_cancel (struct p9_conn *m,int err) {struct p9_req_t *req, *rtmp; -unsigned long flags;LIST_HEAD (cancel_list);p9_debug (P9_DEBUG_ERROR ,"mux %p err %d\n" , m, err); -spin_lock_irqsave (&m->client->lock, flags); +spin_lock (&m->client->lock);if (m->err) { -spin_unlock_irqrestore (&m->client->lock, flags); +spin_unlock (&m->client->lock);return ; }@@ -217,7 +216,7 @@ static void p9_conn_cancel(struct p9_conn *m, int err)list_for_each_entry_safe (req, rtmp, &m->unsent_req_list, req_list) {list_move (&req->req_list, &cancel_list); } -spin_unlock_irqrestore (&m->client->lock, flags); +spin_unlock (&m->client->lock);list_for_each_entry_safe (req, rtmp, &cancel_list, req_list) {p9_debug (P9_DEBUG_ERROR ,"call back req %p\n" , req);
Signature · 1 line
Dominique Martinet
Hi Dominique,
Quoted 9 lines · Dominique Martinet
piaojun wrote on Tue, Jul 17, 2018:
Quoted 4 lines
In
p9_read_work(), we usespin_lockforclient->lock, but misusespin_lock_irqsavefor it inp9_fid_create(). Asp9_clientlock won't be locked in irq context, sospin_lockis enough. And that will improve the performance.(I didn't say in v1, but the commit message sounds a bit odd to me, if there is any other change to the patch could you please rephrase it a bit?)
Yes, I will rephrase it if there is any change to the patch.
Quoted 6 lines
Quoted 2 lines
Rebased on 9p-next.
(Likewise, this should probably go below the '---' mark to not be in the final commit message, 9p-next does not make sense to linux as a whole)
Thanks for your suggestion.
Quoted 119 lines
Quoted 2 lines
Signed-off-by Jun Piao <[email protected]>Nitpicks aside this still looks good to me, I'm not expert in locking but I believe the
conn_cancelstuff intrans_fdis called either from user context or workqueue which also is process context, while the rest comes from user context only.There *are* common functions called from interrupt context (I see:
p9_tag_lookup,p9_client_cb,p9_parse_header) but luckily enough none of these take the lock.I'll give this one a little bit of time for others to review before picking it up, just in case, but will do if no-one complains.
Quoted 103 lines
--- net/9p/client.c | 18 ++++++++---------- net/9p/trans_fd.c | 7 +++---- 2 files changed, 11 insertions(+), 14 deletions(-)net/9p/client.c +8
-10@@ -275,14 +275,14 @@ static struct p9_fcall *p9_fcall_alloc(int alloc_msize)INIT_LIST_HEAD (&req->req_list);idr_preload (GFP_NOFS ); -spin_lock_irq (&c->lock); +spin_lock (&c->lock);if (type ==P9_TVERSION ) tag =idr_alloc (&c->reqs, req,P9_NOTAG ,P9_NOTAG +1 ,GFP_NOWAIT );else tag =idr_alloc (&c->reqs, req,0 ,P9_NOTAG ,GFP_NOWAIT ); req->tc->tag = tag; -spin_unlock_irq (&c->lock); +spin_unlock (&c->lock);idr_preload_end ();if (tag <0 ) goto free;@@ -328,13 +328,12 @@ struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag)*/ static void p9_free_req (struct p9_client *c,struct p9_req_t *r) { -unsigned long flags;u16 tag = r->tc->tag;p9_debug (P9_DEBUG_MUX ,"clnt %p req %p tag: %d\n" , c, r, tag); -spin_lock_irqsave (&c->lock, flags); +spin_lock (&c->lock);idr_remove (&c->reqs, tag); -spin_unlock_irqrestore (&c->lock, flags); +spin_unlock (&c->lock);kfree (r->tc);kfree (r->rc);kmem_cache_free (p9_req_cache, r);@@ -846,10 +845,10 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt) fid->fid =0 ;idr_preload (GFP_KERNEL ); -spin_lock_irq (&clnt->lock); +spin_lock (&clnt->lock); ret =idr_alloc_u32 (&clnt->fids, fid, &fid->fid,P9_NOFID -1 ,GFP_NOWAIT ); -spin_unlock_irq (&clnt->lock); +spin_unlock (&clnt->lock);idr_preload_end ();if (!ret)@@ -862,13 +861,12 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt)static void p9_fid_destroy (struct p9_fid *fid) {struct p9_client *clnt; -unsigned long flags;p9_debug (P9_DEBUG_FID ,"fid %d\n" , fid->fid); clnt = fid->clnt; -spin_lock_irqsave (&clnt->lock, flags); +spin_lock (&clnt->lock);idr_remove (&clnt->fids, fid->fid); -spin_unlock_irqrestore (&clnt->lock, flags); +spin_unlock (&clnt->lock);kfree (fid->rdir);kfree (fid); }net/9p/trans_fd.c +3
-4@@ -197,15 +197,14 @@ static void p9_mux_poll_stop(struct p9_conn *m)static void p9_conn_cancel (struct p9_conn *m,int err) {struct p9_req_t *req, *rtmp; -unsigned long flags;LIST_HEAD (cancel_list);p9_debug (P9_DEBUG_ERROR ,"mux %p err %d\n" , m, err); -spin_lock_irqsave (&m->client->lock, flags); +spin_lock (&m->client->lock);if (m->err) { -spin_unlock_irqrestore (&m->client->lock, flags); +spin_unlock (&m->client->lock);return ; }@@ -217,7 +216,7 @@ static void p9_conn_cancel(struct p9_conn *m, int err)list_for_each_entry_safe (req, rtmp, &m->unsent_req_list, req_list) {list_move (&req->req_list, &cancel_list); } -spin_unlock_irqrestore (&m->client->lock, flags); +spin_unlock (&m->client->lock);list_for_each_entry_safe (req, rtmp, &cancel_list, req_list) {p9_debug (P9_DEBUG_ERROR ,"call back req %p\n" , req);