lkml.org 
[lkml]   [2015]   [Jul]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.1 54/56] fs/ufs: restore s_lock mutex
    Date
    4.1-stable review patch.  If anyone has any objections, please let me know.

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

    From: Fabian Frederick <fabf@skynet.be>

    commit cdd9eefdf905e92e7fc6cc393314efe68dc6ff66 upstream.

    Commit 0244756edc4b98c ("ufs: sb mutex merge + mutex_destroy") generated
    deadlocks in read/write mode on mkdir.

    This patch partially reverts it keeping fixes by Andrew Morton and
    mutex_destroy()

    [AV: fixed a missing bit in ufs_remount()]

    Signed-off-by: Fabian Frederick <fabf@skynet.be>
    Reported-by: Ian Campbell <ian.campbell@citrix.com>
    Suggested-by: Jan Kara <jack@suse.cz>
    Cc: Ian Campbell <ian.campbell@citrix.com>
    Cc: Evgeniy Dushistov <dushistov@mail.ru>
    Cc: Alexey Khoroshilov <khoroshilov@ispras.ru>
    Cc: Roger Pau Monne <roger.pau@citrix.com>
    Cc: Ian Jackson <Ian.Jackson@eu.citrix.com>
    Cc: Al Viro <viro@zeniv.linux.org.uk>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/ufs/balloc.c | 34 +++++++++++++++++-----------------
    fs/ufs/ialloc.c | 16 ++++++++--------
    fs/ufs/super.c | 10 ++++++++++
    fs/ufs/ufs.h | 1 +
    4 files changed, 36 insertions(+), 25 deletions(-)

    --- a/fs/ufs/balloc.c
    +++ b/fs/ufs/balloc.c
    @@ -51,8 +51,8 @@ void ufs_free_fragments(struct inode *in

    if (ufs_fragnum(fragment) + count > uspi->s_fpg)
    ufs_error (sb, "ufs_free_fragments", "internal error");
    -
    - lock_ufs(sb);
    +
    + mutex_lock(&UFS_SB(sb)->s_lock);

    cgno = ufs_dtog(uspi, fragment);
    bit = ufs_dtogd(uspi, fragment);
    @@ -115,13 +115,13 @@ void ufs_free_fragments(struct inode *in
    if (sb->s_flags & MS_SYNCHRONOUS)
    ubh_sync_block(UCPI_UBH(ucpi));
    ufs_mark_sb_dirty(sb);
    -
    - unlock_ufs(sb);
    +
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    UFSD("EXIT\n");
    return;

    failed:
    - unlock_ufs(sb);
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    UFSD("EXIT (FAILED)\n");
    return;
    }
    @@ -151,7 +151,7 @@ void ufs_free_blocks(struct inode *inode
    goto failed;
    }

    - lock_ufs(sb);
    + mutex_lock(&UFS_SB(sb)->s_lock);

    do_more:
    overflow = 0;
    @@ -211,12 +211,12 @@ do_more:
    }

    ufs_mark_sb_dirty(sb);
    - unlock_ufs(sb);
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    UFSD("EXIT\n");
    return;

    failed_unlock:
    - unlock_ufs(sb);
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    failed:
    UFSD("EXIT (FAILED)\n");
    return;
    @@ -357,7 +357,7 @@ u64 ufs_new_fragments(struct inode *inod
    usb1 = ubh_get_usb_first(uspi);
    *err = -ENOSPC;

    - lock_ufs(sb);
    + mutex_lock(&UFS_SB(sb)->s_lock);
    tmp = ufs_data_ptr_to_cpu(sb, p);

    if (count + ufs_fragnum(fragment) > uspi->s_fpb) {
    @@ -378,19 +378,19 @@ u64 ufs_new_fragments(struct inode *inod
    "fragment %llu, tmp %llu\n",
    (unsigned long long)fragment,
    (unsigned long long)tmp);
    - unlock_ufs(sb);
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    return INVBLOCK;
    }
    if (fragment < UFS_I(inode)->i_lastfrag) {
    UFSD("EXIT (ALREADY ALLOCATED)\n");
    - unlock_ufs(sb);
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    return 0;
    }
    }
    else {
    if (tmp) {
    UFSD("EXIT (ALREADY ALLOCATED)\n");
    - unlock_ufs(sb);
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    return 0;
    }
    }
    @@ -399,7 +399,7 @@ u64 ufs_new_fragments(struct inode *inod
    * There is not enough space for user on the device
    */
    if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(uspi, UFS_MINFREE) <= 0) {
    - unlock_ufs(sb);
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    UFSD("EXIT (FAILED)\n");
    return 0;
    }
    @@ -424,7 +424,7 @@ u64 ufs_new_fragments(struct inode *inod
    ufs_clear_frags(inode, result + oldcount,
    newcount - oldcount, locked_page != NULL);
    }
    - unlock_ufs(sb);
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    UFSD("EXIT, result %llu\n", (unsigned long long)result);
    return result;
    }
    @@ -439,7 +439,7 @@ u64 ufs_new_fragments(struct inode *inod
    fragment + count);
    ufs_clear_frags(inode, result + oldcount, newcount - oldcount,
    locked_page != NULL);
    - unlock_ufs(sb);
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    UFSD("EXIT, result %llu\n", (unsigned long long)result);
    return result;
    }
    @@ -477,7 +477,7 @@ u64 ufs_new_fragments(struct inode *inod
    *err = 0;
    UFS_I(inode)->i_lastfrag = max(UFS_I(inode)->i_lastfrag,
    fragment + count);
    - unlock_ufs(sb);
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    if (newcount < request)
    ufs_free_fragments (inode, result + newcount, request - newcount);
    ufs_free_fragments (inode, tmp, oldcount);
    @@ -485,7 +485,7 @@ u64 ufs_new_fragments(struct inode *inod
    return result;
    }

    - unlock_ufs(sb);
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    UFSD("EXIT (FAILED)\n");
    return 0;
    }
    --- a/fs/ufs/ialloc.c
    +++ b/fs/ufs/ialloc.c
    @@ -69,11 +69,11 @@ void ufs_free_inode (struct inode * inod

    ino = inode->i_ino;

    - lock_ufs(sb);
    + mutex_lock(&UFS_SB(sb)->s_lock);

    if (!((ino > 1) && (ino < (uspi->s_ncg * uspi->s_ipg )))) {
    ufs_warning(sb, "ufs_free_inode", "reserved inode or nonexistent inode %u\n", ino);
    - unlock_ufs(sb);
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    return;
    }

    @@ -81,7 +81,7 @@ void ufs_free_inode (struct inode * inod
    bit = ufs_inotocgoff (ino);
    ucpi = ufs_load_cylinder (sb, cg);
    if (!ucpi) {
    - unlock_ufs(sb);
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    return;
    }
    ucg = ubh_get_ucg(UCPI_UBH(ucpi));
    @@ -115,7 +115,7 @@ void ufs_free_inode (struct inode * inod
    ubh_sync_block(UCPI_UBH(ucpi));

    ufs_mark_sb_dirty(sb);
    - unlock_ufs(sb);
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    UFSD("EXIT\n");
    }

    @@ -193,7 +193,7 @@ struct inode *ufs_new_inode(struct inode
    sbi = UFS_SB(sb);
    uspi = sbi->s_uspi;

    - lock_ufs(sb);
    + mutex_lock(&sbi->s_lock);

    /*
    * Try to place the inode in its parent directory
    @@ -331,21 +331,21 @@ cg_found:
    sync_dirty_buffer(bh);
    brelse(bh);
    }
    - unlock_ufs(sb);
    + mutex_unlock(&sbi->s_lock);

    UFSD("allocating inode %lu\n", inode->i_ino);
    UFSD("EXIT\n");
    return inode;

    fail_remove_inode:
    - unlock_ufs(sb);
    + mutex_unlock(&sbi->s_lock);
    clear_nlink(inode);
    unlock_new_inode(inode);
    iput(inode);
    UFSD("EXIT (FAILED): err %d\n", err);
    return ERR_PTR(err);
    failed:
    - unlock_ufs(sb);
    + mutex_unlock(&sbi->s_lock);
    make_bad_inode(inode);
    iput (inode);
    UFSD("EXIT (FAILED): err %d\n", err);
    --- a/fs/ufs/super.c
    +++ b/fs/ufs/super.c
    @@ -694,6 +694,7 @@ static int ufs_sync_fs(struct super_bloc
    unsigned flags;

    lock_ufs(sb);
    + mutex_lock(&UFS_SB(sb)->s_lock);

    UFSD("ENTER\n");

    @@ -711,6 +712,7 @@ static int ufs_sync_fs(struct super_bloc
    ufs_put_cstotal(sb);

    UFSD("EXIT\n");
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    unlock_ufs(sb);

    return 0;
    @@ -1277,6 +1279,7 @@ static int ufs_remount (struct super_blo

    sync_filesystem(sb);
    lock_ufs(sb);
    + mutex_lock(&UFS_SB(sb)->s_lock);
    uspi = UFS_SB(sb)->s_uspi;
    flags = UFS_SB(sb)->s_flags;
    usb1 = ubh_get_usb_first(uspi);
    @@ -1290,6 +1293,7 @@ static int ufs_remount (struct super_blo
    new_mount_opt = 0;
    ufs_set_opt (new_mount_opt, ONERROR_LOCK);
    if (!ufs_parse_options (data, &new_mount_opt)) {
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    unlock_ufs(sb);
    return -EINVAL;
    }
    @@ -1297,12 +1301,14 @@ static int ufs_remount (struct super_blo
    new_mount_opt |= ufstype;
    } else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) {
    pr_err("ufstype can't be changed during remount\n");
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    unlock_ufs(sb);
    return -EINVAL;
    }

    if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
    UFS_SB(sb)->s_mount_opt = new_mount_opt;
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    unlock_ufs(sb);
    return 0;
    }
    @@ -1326,6 +1332,7 @@ static int ufs_remount (struct super_blo
    */
    #ifndef CONFIG_UFS_FS_WRITE
    pr_err("ufs was compiled with read-only support, can't be mounted as read-write\n");
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    unlock_ufs(sb);
    return -EINVAL;
    #else
    @@ -1335,11 +1342,13 @@ static int ufs_remount (struct super_blo
    ufstype != UFS_MOUNT_UFSTYPE_SUNx86 &&
    ufstype != UFS_MOUNT_UFSTYPE_UFS2) {
    pr_err("this ufstype is read-only supported\n");
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    unlock_ufs(sb);
    return -EINVAL;
    }
    if (!ufs_read_cylinder_structures(sb)) {
    pr_err("failed during remounting\n");
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    unlock_ufs(sb);
    return -EPERM;
    }
    @@ -1347,6 +1356,7 @@ static int ufs_remount (struct super_blo
    #endif
    }
    UFS_SB(sb)->s_mount_opt = new_mount_opt;
    + mutex_unlock(&UFS_SB(sb)->s_lock);
    unlock_ufs(sb);
    return 0;
    }
    --- a/fs/ufs/ufs.h
    +++ b/fs/ufs/ufs.h
    @@ -30,6 +30,7 @@ struct ufs_sb_info {
    int work_queued; /* non-zero if the delayed work is queued */
    struct delayed_work sync_work; /* FS sync delayed work */
    spinlock_t work_lock; /* protects sync_work and work_queued */
    + struct mutex s_lock;
    };

    struct ufs_inode_info {



    \
     
     \ /
      Last update: 2015-07-08 10:01    [W:4.564 / U:0.460 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site