lkml.org 
[lkml]   [2013]   [Jun]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[ 095/127] reiserfs: fix deadlock with nfs racing on create/lookup
    Date
    3.9-stable review patch.  If anyone has any objections, please let me know.

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

    From: Jeff Mahoney <jeffm@suse.com>

    commit a1457c0ce976bad1356b9b0437f2a5c3ab8a9cfc upstream.

    Reiserfs is currently able to be deadlocked by having two NFS clients
    where one has removed and recreated a file and another is accessing the
    file with an open file handle.

    If one client deletes and recreates a file with timing such that the
    recreated file obtains the same [dirid, objectid] pair as the original
    file while another client accesses the file via file handle, the create
    and lookup can race and deadlock if the lookup manages to create the
    in-memory inode first.

    The create thread, in insert_inode_locked4, will hold the write lock
    while waiting on the other inode to be unlocked. The lookup thread,
    anywhere in the iget path, will release and reacquire the write lock while
    it schedules. If it needs to reacquire the lock while the create thread
    has it, it will never be able to make forward progress because it needs
    to reacquire the lock before ultimately unlocking the inode.

    This patch drops the write lock across the insert_inode_locked4 call so
    that the ordering of inode_wait -> write lock is retained. Since this
    would have been the case before the BKL push-down, this is safe.

    Signed-off-by: Jeff Mahoney <jeffm@suse.com>
    Signed-off-by: Jan Kara <jack@suse.cz>
    Signed-off-by: Jonghwan Choi <jhbird.choi@samsung.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/reiserfs/inode.c | 9 +++++++--
    1 file changed, 7 insertions(+), 2 deletions(-)

    --- a/fs/reiserfs/inode.c
    +++ b/fs/reiserfs/inode.c
    @@ -1810,11 +1810,16 @@ int reiserfs_new_inode(struct reiserfs_t
    TYPE_STAT_DATA, SD_SIZE, MAX_US_INT);
    memcpy(INODE_PKEY(inode), &(ih.ih_key), KEY_SIZE);
    args.dirid = le32_to_cpu(ih.ih_key.k_dir_id);
    - if (insert_inode_locked4(inode, args.objectid,
    - reiserfs_find_actor, &args) < 0) {
    +
    + reiserfs_write_unlock(inode->i_sb);
    + err = insert_inode_locked4(inode, args.objectid,
    + reiserfs_find_actor, &args);
    + reiserfs_write_lock(inode->i_sb);
    + if (err) {
    err = -EINVAL;
    goto out_bad_inode;
    }
    +
    if (old_format_only(sb))
    /* not a perfect generation count, as object ids can be reused, but
    ** this is as good as reiserfs can do right now.



    \
     
     \ /
      Last update: 2013-06-06 03:41    [W:4.170 / U:0.220 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site