All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alex Elder <alex.elder@linaro.org>
To: Josh Durgin <josh.durgin@inktank.com>, ceph-devel@vger.kernel.org
Subject: Re: [PATCH 1/2] rbd: move calls that may sleep out of spin lock range
Date: Tue, 01 Oct 2013 16:17:25 -0500	[thread overview]
Message-ID: <524B3BE5.5080406@linaro.org> (raw)
In-Reply-To: <1380604559-5331-2-git-send-email-josh.durgin@inktank.com>

On 10/01/2013 12:15 AM, Josh Durgin wrote:
> get_user() and set_disk_ro() may allocate memory, leading to a
> potential deadlock if theye are called while a spin lock is held.
> 
> Move the acquisition and release of rbd_dev->lock from rbd_ioctl()
> into rbd_ioctl_set_ro(), so it can occur between get_user() and
> set_disk_ro().

This fix looks good.  I have a couple small comments to consider.

Reviewed-by: Alex Elder <elder@linaro.org>

> Signed-off-by: Josh Durgin <josh.durgin@inktank.com>
> ---
>  drivers/block/rbd.c |   36 +++++++++++++++++++++++-------------
>  1 files changed, 23 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
> index 34bcdb7..b3b1b57 100644
> --- a/drivers/block/rbd.c
> +++ b/drivers/block/rbd.c
> @@ -510,23 +510,42 @@ static void rbd_release(struct gendisk *disk, fmode_t mode)
>  
>  static int rbd_ioctl_set_ro(struct rbd_device *rbd_dev, unsigned long arg)
>  {
> +	int ret = 0;
>  	int val;
>  	bool ro;
> +	bool ro_changed = false;
>  
> +	/* get_user() may sleep, so call it before taking rbd_dev->lock */
>  	if (get_user(val, (int __user *)(arg)))
>  		return -EFAULT;
>  
> +	spin_lock_irq(&rbd_dev->lock);
> +	/* prevent others open this device */
> +	if (rbd_dev->open_count > 1) {
> +		ret = -EBUSY;
> +		goto out;
> +	}

I like to do as little as possible inside spinlock protection.

> +
>  	ro = val ? true : false;

This assignment can be made outside the lock.

>  	/* Snapshot doesn't allow to write*/
> -	if (rbd_dev->spec->snap_id != CEPH_NOSNAP && !ro)
> -		return -EROFS;
> +	if (rbd_dev->spec->snap_id != CEPH_NOSNAP && !ro) {
> +		ret = -EROFS;
> +		goto out;
> +	}

This check can be too.

>  
>  	if (rbd_dev->mapping.read_only != ro) {
>  		rbd_dev->mapping.read_only = ro;
> -		set_disk_ro(rbd_dev->disk, ro ? 1 : 0);
> +		ro_changed = true;
>  	}
>  
> -	return 0;
> +out:
> +	spin_unlock_irq(&rbd_dev->lock);
> +	/* set_disk_ro() may sleep, so call it after releasing rbd_dev->lock */
> +	if (ret == 0 && ro_changed)
> +		set_disk_ro(rbd_dev->disk, ro ? 1 : 0);
> +

I like white space a lot, but this is one too many.

> +
> +	return ret;
>  }
>  
>  static int rbd_ioctl(struct block_device *bdev, fmode_t mode,
> @@ -535,13 +554,6 @@ static int rbd_ioctl(struct block_device *bdev, fmode_t mode,
>  	struct rbd_device *rbd_dev = bdev->bd_disk->private_data;
>  	int ret = 0;
>  
> -	spin_lock_irq(&rbd_dev->lock);
> -	/* prevent others open this device */
> -	if (rbd_dev->open_count > 1) {
> -		ret = -EBUSY;
> -		goto out;
> -	}
> -
>  	switch (cmd) {
>  	case BLKROSET:
>  		ret = rbd_ioctl_set_ro(rbd_dev, arg);
> @@ -550,8 +562,6 @@ static int rbd_ioctl(struct block_device *bdev, fmode_t mode,
>  		ret = -ENOTTY;
>  	}
>  
> -out:
> -	spin_unlock_irq(&rbd_dev->lock);
>  	return ret;
>  }
>  
> 


  reply	other threads:[~2013-10-01 21:17 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-09-24  3:25 [PATCH v4] rbd: add ioctl for rbd Guangliang Zhao
2013-10-01  5:15 ` [PATCH 0/2] clean up read only mode Josh Durgin
2013-10-08  3:40   ` Guangliang Zhao
2013-10-01  5:15 ` [PATCH 1/2] rbd: move calls that may sleep out of spin lock range Josh Durgin
2013-10-01 21:17   ` Alex Elder [this message]
2013-10-01  5:15 ` [PATCH 2/2] rbd: only set disk to read-only once Josh Durgin
2013-10-01 21:21   ` Alex Elder

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=524B3BE5.5080406@linaro.org \
    --to=alex.elder@linaro.org \
    --cc=ceph-devel@vger.kernel.org \
    --cc=josh.durgin@inktank.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.