From: Leon Romanovsky <leon@kernel.org>
To: ira.weiny@intel.com
Cc: dledford@redhat.com, linux-rdma@vger.kernel.org,
Mike Marciniszyn <mike.marciniszyn@intel.com>,
stable@vger.kernel.org
Subject: Re: [PATCH] IB/hfi1,IB/qib: Fix qp_stats sleep with rcu read lock held
Date: Tue, 9 Aug 2016 21:11:46 +0300 [thread overview]
Message-ID: <20160809181146.GE23921@leon.nu> (raw)
In-Reply-To: <1470755786-14054-1-git-send-email-ira.weiny@intel.com>
[-- Attachment #1: Type: text/plain, Size: 5494 bytes --]
On Tue, Aug 09, 2016 at 11:16:26AM -0400, ira.weiny@intel.com wrote:
> From: Mike Marciniszyn <mike.marciniszyn@intel.com>
>
> The qp init function does a kzalloc() while holding the RCU
> lock that encounters the following warning with a debug kernel
> when a cat of the qp_stats is done:
>
> [ 231.723948] rcu_scheduler_active = 1, debug_locks = 0
> [ 231.731939] 3 locks held by cat/11355:
> [ 231.736492] #0: (debugfs_srcu){......}, at: [<ffffffff813001a5>] debugfs_use_file_start+0x5/0x90
> [ 231.746955] #1: (&p->lock){+.+.+.}, at: [<ffffffff81289a6c>] seq_read+0x4c/0x3c0
> [ 231.755873] #2: (rcu_read_lock){......}, at: [<ffffffffa0a0c535>] _qp_stats_seq_start+0x5/0xd0 [hfi1]
> [ 231.766862]
>
> The init functions do an implicit next which requires the rcu read lock
> before the kzalloc().
>
> Fix for both drivers is to change the scope of the init function to only
> do the allocation and the initialization of the just allocated iter.
>
> The implict next is moved back into the respective start functions to fix
> the issue.
>
>
> Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
> Signed-off-by: Ira Weiny <ira.weiny@intel.com>
> CC: <stable@vger.kernel.org> # 4.6.x-
> ---
> drivers/infiniband/hw/hfi1/debugfs.c | 17 ++++++++++++-----
> drivers/infiniband/hw/hfi1/qp.c | 4 ----
> drivers/infiniband/hw/qib/qib_debugfs.c | 16 ++++++++++++----
> drivers/infiniband/hw/qib/qib_qp.c | 4 ----
> 4 files changed, 24 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/infiniband/hw/hfi1/debugfs.c b/drivers/infiniband/hw/hfi1/debugfs.c
> index dbab9d9cc288..c35bef8dd5aa 100644
> --- a/drivers/infiniband/hw/hfi1/debugfs.c
> +++ b/drivers/infiniband/hw/hfi1/debugfs.c
> @@ -223,28 +223,35 @@ DEBUGFS_SEQ_FILE_OPEN(ctx_stats)
> DEBUGFS_FILE_OPS(ctx_stats);
>
> static void *_qp_stats_seq_start(struct seq_file *s, loff_t *pos)
> -__acquires(RCU)
> + __acquires(RCU)
> {
> struct qp_iter *iter;
> loff_t n = *pos;
>
> - rcu_read_lock();
> iter = qp_iter_init(s->private);
> +
> + /* stop calls rcu_read_unlock */
> + rcu_read_lock();
IMHO, it should be placed after your if(!iter) check below.
> +
> if (!iter)
> return NULL;
>
> - while (n--) {
> + if (qp_iter_next(iter)) {
> + kfree(iter);
> + return NULL;
> + }
> + while (n--)
> if (qp_iter_next(iter)) {
> kfree(iter);
> return NULL;
> }
It looks like you forgot to remove the lines above.
> - }
>
> return iter;
> }
>
> static void *_qp_stats_seq_next(struct seq_file *s, void *iter_ptr,
> loff_t *pos)
> + __must_hold(RCU)
> {
> struct qp_iter *iter = iter_ptr;
>
> @@ -259,7 +266,7 @@ static void *_qp_stats_seq_next(struct seq_file *s, void *iter_ptr,
> }
>
> static void _qp_stats_seq_stop(struct seq_file *s, void *iter_ptr)
> -__releases(RCU)
> + __releases(RCU)
> {
> rcu_read_unlock();
> }
> diff --git a/drivers/infiniband/hw/hfi1/qp.c b/drivers/infiniband/hw/hfi1/qp.c
> index a5aa3517e7d5..4e4d8317c281 100644
> --- a/drivers/infiniband/hw/hfi1/qp.c
> +++ b/drivers/infiniband/hw/hfi1/qp.c
> @@ -656,10 +656,6 @@ struct qp_iter *qp_iter_init(struct hfi1_ibdev *dev)
>
> iter->dev = dev;
> iter->specials = dev->rdi.ibdev.phys_port_cnt * 2;
> - if (qp_iter_next(iter)) {
> - kfree(iter);
> - return NULL;
> - }
>
> return iter;
> }
> diff --git a/drivers/infiniband/hw/qib/qib_debugfs.c b/drivers/infiniband/hw/qib/qib_debugfs.c
> index 5e75b43c596b..07059c08c170 100644
> --- a/drivers/infiniband/hw/qib/qib_debugfs.c
> +++ b/drivers/infiniband/hw/qib/qib_debugfs.c
> @@ -189,27 +189,34 @@ static int _ctx_stats_seq_show(struct seq_file *s, void *v)
> DEBUGFS_FILE(ctx_stats)
>
> static void *_qp_stats_seq_start(struct seq_file *s, loff_t *pos)
> + __acquires(RCU)
> {
> struct qib_qp_iter *iter;
> loff_t n = *pos;
>
> - rcu_read_lock();
> iter = qib_qp_iter_init(s->private);
> +
> + /* stop calls rcu_read_unlock */
> + rcu_read_lock();
> +
The same
> if (!iter)
> return NULL;
>
> - while (n--) {
> + if (qib_qp_iter_next(iter)) {
> + kfree(iter);
> + return NULL;
> + }
> + while (n--)
> if (qib_qp_iter_next(iter)) {
> kfree(iter);
> return NULL;
> }
> - }
> -
The same
> return iter;
> }
>
> static void *_qp_stats_seq_next(struct seq_file *s, void *iter_ptr,
> loff_t *pos)
> + __must_hold(RCU)
> {
> struct qib_qp_iter *iter = iter_ptr;
>
> @@ -224,6 +231,7 @@ static void *_qp_stats_seq_next(struct seq_file *s, void *iter_ptr,
> }
>
> static void _qp_stats_seq_stop(struct seq_file *s, void *iter_ptr)
> + __releases(RCU)
> {
> rcu_read_unlock();
> }
> diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c
> index 9cc0aae1d781..f9b8cd2354d1 100644
> --- a/drivers/infiniband/hw/qib/qib_qp.c
> +++ b/drivers/infiniband/hw/qib/qib_qp.c
> @@ -573,10 +573,6 @@ struct qib_qp_iter *qib_qp_iter_init(struct qib_ibdev *dev)
> return NULL;
>
> iter->dev = dev;
> - if (qib_qp_iter_next(iter)) {
> - kfree(iter);
> - return NULL;
> - }
>
> return iter;
> }
> --
> 1.8.2
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
next prev parent reply other threads:[~2016-08-09 18:11 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-08-09 15:16 [PATCH] IB/hfi1,IB/qib: Fix qp_stats sleep with rcu read lock held ira.weiny
2016-08-09 18:11 ` Leon Romanovsky [this message]
2016-08-10 5:51 ` ira.weiny
[not found] ` <20160810055151.GB32695-W4f6Xiosr+yv7QzWx2u06xL4W9x8LtSr@public.gmane.org>
2016-08-10 8:24 ` Leon Romanovsky
2016-08-10 10:17 ` Leon Romanovsky
2016-08-22 18:21 ` Doug Ledford
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160809181146.GE23921@leon.nu \
--to=leon@kernel.org \
--cc=dledford@redhat.com \
--cc=ira.weiny@intel.com \
--cc=linux-rdma@vger.kernel.org \
--cc=mike.marciniszyn@intel.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox