public inbox for linux-rdma@vger.kernel.org
 help / color / mirror / Atom feed
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 --]

  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