lkml.org 
[lkml]   [2019]   [Jan]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 86/99] loop: Push loop_ctl_mutex down into loop_clr_fd()
    Date
    4.19-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Jan Kara <jack@suse.cz>

    commit 7ccd0791d98531df7cd59e92d55e4f063d48a070 upstream.

    loop_clr_fd() has a weird locking convention that is expects
    loop_ctl_mutex held, releases it on success and keeps it on failure.
    Untangle the mess by moving locking of loop_ctl_mutex into
    loop_clr_fd().

    Signed-off-by: Jan Kara <jack@suse.cz>
    Signed-off-by: Jens Axboe <axboe@kernel.dk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/block/loop.c | 49 +++++++++++++++++++++++++++++--------------------
    1 file changed, 29 insertions(+), 20 deletions(-)

    --- a/drivers/block/loop.c
    +++ b/drivers/block/loop.c
    @@ -1028,15 +1028,22 @@ loop_init_xfer(struct loop_device *lo, s

    static int __loop_clr_fd(struct loop_device *lo)
    {
    - struct file *filp = lo->lo_backing_file;
    + struct file *filp = NULL;
    gfp_t gfp = lo->old_gfp_mask;
    struct block_device *bdev = lo->lo_device;
    + int err = 0;

    - if (WARN_ON_ONCE(lo->lo_state != Lo_rundown))
    - return -ENXIO;
    + mutex_lock(&loop_ctl_mutex);
    + if (WARN_ON_ONCE(lo->lo_state != Lo_rundown)) {
    + err = -ENXIO;
    + goto out_unlock;
    + }

    - if (filp == NULL)
    - return -EINVAL;
    + filp = lo->lo_backing_file;
    + if (filp == NULL) {
    + err = -EINVAL;
    + goto out_unlock;
    + }

    /* freeze request queue during the transition */
    blk_mq_freeze_queue(lo->lo_queue);
    @@ -1083,6 +1090,7 @@ static int __loop_clr_fd(struct loop_dev
    if (!part_shift)
    lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN;
    loop_unprepare_queue(lo);
    +out_unlock:
    mutex_unlock(&loop_ctl_mutex);
    /*
    * Need not hold loop_ctl_mutex to fput backing file.
    @@ -1090,14 +1098,22 @@ static int __loop_clr_fd(struct loop_dev
    * lock dependency possibility warning as fput can take
    * bd_mutex which is usually taken before loop_ctl_mutex.
    */
    - fput(filp);
    - return 0;
    + if (filp)
    + fput(filp);
    + return err;
    }

    static int loop_clr_fd(struct loop_device *lo)
    {
    - if (lo->lo_state != Lo_bound)
    + int err;
    +
    + err = mutex_lock_killable_nested(&loop_ctl_mutex, 1);
    + if (err)
    + return err;
    + if (lo->lo_state != Lo_bound) {
    + mutex_unlock(&loop_ctl_mutex);
    return -ENXIO;
    + }
    /*
    * If we've explicitly asked to tear down the loop device,
    * and it has an elevated reference count, set it for auto-teardown when
    @@ -1114,6 +1130,7 @@ static int loop_clr_fd(struct loop_devic
    return 0;
    }
    lo->lo_state = Lo_rundown;
    + mutex_unlock(&loop_ctl_mutex);

    return __loop_clr_fd(lo);
    }
    @@ -1448,14 +1465,7 @@ static int lo_ioctl(struct block_device
    mutex_unlock(&loop_ctl_mutex);
    break;
    case LOOP_CLR_FD:
    - err = mutex_lock_killable_nested(&loop_ctl_mutex, 1);
    - if (err)
    - return err;
    - /* loop_clr_fd would have unlocked loop_ctl_mutex on success */
    - err = loop_clr_fd(lo);
    - if (err)
    - mutex_unlock(&loop_ctl_mutex);
    - break;
    + return loop_clr_fd(lo);
    case LOOP_SET_STATUS:
    err = -EPERM;
    if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) {
    @@ -1691,7 +1701,6 @@ out:
    static void lo_release(struct gendisk *disk, fmode_t mode)
    {
    struct loop_device *lo;
    - int err;

    mutex_lock(&loop_ctl_mutex);
    lo = disk->private_data;
    @@ -1702,13 +1711,13 @@ static void lo_release(struct gendisk *d
    if (lo->lo_state != Lo_bound)
    goto out_unlock;
    lo->lo_state = Lo_rundown;
    + mutex_unlock(&loop_ctl_mutex);
    /*
    * In autoclear mode, stop the loop thread
    * and remove configuration after last close.
    */
    - err = __loop_clr_fd(lo);
    - if (!err)
    - return;
    + __loop_clr_fd(lo);
    + return;
    } else if (lo->lo_state == Lo_bound) {
    /*
    * Otherwise keep thread (if running) and config,

    \
     
     \ /
      Last update: 2019-01-21 15:03    [W:2.389 / U:0.404 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site