From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752078Ab1LQV5A (ORCPT ); Sat, 17 Dec 2011 16:57:00 -0500 Received: from mail-ww0-f44.google.com ([74.125.82.44]:38241 "EHLO mail-ww0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750896Ab1LQV46 (ORCPT ); Sat, 17 Dec 2011 16:56:58 -0500 Date: Sun, 18 Dec 2011 00:53:33 +0300 From: Sergey Senozhatsky To: Jens Axboe Cc: Andrew Morton , Kay Sievers , Namhyung Kim , Lukas Czerner , linux-kernel@vger.kernel.org Subject: [PATCH] loop: fput() called in loop_clr_fd() may cause bd_mutex recursive locking Message-ID: <20111217215333.GA3313@swordfish> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Unmonting mounted with `-o loop' block device causes recursive bd_mutex locking. fput() calls blkdev_put() for bdev that issued disk->fops->release() (loop_clr_fd()) call: [23044.654647] umount/24442 is trying to acquire lock: [23044.654652] (&bdev->bd_mutex){+.+.+.}, at: [] blkdev_put+0x1f/0x131 [23044.654670] [23044.654672] but task is already holding lock: [23044.654677] (&bdev->bd_mutex){+.+.+.}, at: [] __blkdev_put+0x33/0x184 [23044.654690] [23044.654692] other info that might help us debug this: [23044.654697] Possible unsafe locking scenario: [23044.654727] [23044.654731] 1 lock held by umount/24442: [23044.654735] #0: (&bdev->bd_mutex){+.+.+.}, at: [] __blkdev_put+0x33/0x184 [23044.654748] [23044.654762] Call Trace: [23044.654773] [] __lock_acquire+0x15bf/0x1659 [23044.654784] [] ? inotify_free_group_priv+0x4f/0x4f [23044.654792] [] ? blkdev_put+0x1f/0x131 [23044.654799] [] lock_acquire+0x138/0x1b3 [23044.654807] [] ? blkdev_put+0x1f/0x131 [23044.654814] [] ? blkdev_put+0x1f/0x131 [23044.654824] [] mutex_lock_nested+0x5e/0x325 [23044.654831] [] ? blkdev_put+0x1f/0x131 [23044.654838] [] ? fsnotify+0x441/0x459 [23044.654846] [] blkdev_put+0x1f/0x131 [23044.654853] [] blkdev_close+0x20/0x22 [23044.654863] [] fput+0x117/0x1cf [23044.654874] [] loop_clr_fd+0x1f2/0x201 [loop] [23044.654882] [] lo_release+0x40/0x6f [loop] [23044.654890] [] __blkdev_put+0xd6/0x184 [23044.654898] [] blkdev_put+0x128/0x131 [23044.654906] [] kill_block_super+0x60/0x65 [23044.654914] [] deactivate_locked_super+0x32/0x63 [23044.654922] [] deactivate_super+0x3a/0x3e [23044.654931] [] mntput_no_expire+0xbf/0xc4 [23044.654939] [] sys_umount+0x2c5/0x2f3 [23044.654949] [] system_call_fastpath+0x16/0x1b Signed-off-by: Sergey Senozhatsky --- diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 1e888c9..b004779 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1028,6 +1028,15 @@ static int loop_clr_fd(struct loop_device *lo) * lock dependency possibility warning as fput can take * bd_mutex which is usually taken before lo_ctl_mutex. */ + /* + * Need to put file f_op, otherwise fput() may cause + * recursive locking on bd_mutex, calling blkdev_put() + * for bdev that issued disk->fops->release() call. + */ + if (bdev && bdev == bdev->bd_contains) { + fops_put(filp->f_op); + filp->f_op = NULL; + } fput(filp); return 0; }