Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933691AbYBMRr1 (ORCPT ); Wed, 13 Feb 2008 12:47:27 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753911AbYBMRrL (ORCPT ); Wed, 13 Feb 2008 12:47:11 -0500 Received: from twin.jikos.cz ([213.151.79.26]:47610 "EHLO twin.jikos.cz" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1764187AbYBMRrJ (ORCPT ); Wed, 13 Feb 2008 12:47:09 -0500 Date: Wed, 13 Feb 2008 18:47:05 +0100 (CET) From: Jiri Kosina X-X-Sender: jikos@twin.jikos.cz To: Zdenek Kabelac cc: linux-kernel@vger.kernel.org Subject: Re: losetup INFO: possible circular locking dependency detected In-Reply-To: Message-ID: References: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3331 Lines: 91 On Wed, 13 Feb 2008, Zdenek Kabelac wrote: > ======================================================= > [ INFO: possible circular locking dependency detected ] > 2.6.25-rc1 #29 > ------------------------------------------------------- > losetup/26595 is trying to acquire lock: > (&bdev->bd_mutex){--..}, at: [] __blkdev_put+0x38/0x1e0 > but task is already holding lock: > (&lo->lo_ctl_mutex){--..}, at: [] lo_ioctl+0x4e/0xaf0 [loop] > which lock already depends on the new lock. Seems to me that this is valid and there indeed is a AB-BA deadlock in loop code. (BTW when looking at this, there seem to be other locking problems in loop.c, the code for example doesn't seem to be consistent whether accessing lo->lo_state needs to be protected by lo->lo_lock or not). What about this ugly fix? From: Jiri Kosina loop - fix deadlock against block A: B: bdev_open() for ino X (locks bd_mutex for bdev Y) lo_ioctl(LOOP_CLR_FD) for ino X (locks lo_ctl_mutex) fput() __fput() blkdev_close() (hangs on bd_mutex for bdev Y) lo_open() (hangs on lo_ctl_mutex) Fix this by letting releasing the lock inside loop_clr_fd() after the loopback structure has been completely deinitialized, but before calling final fput(). Signed-off-by: Jiri Kosina diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 91ebb00..eb9e091 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -881,6 +881,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) struct file *filp = lo->lo_backing_file; gfp_t gfp = lo->old_gfp_mask; + mutex_lock(&lo->lo_ctl_mutex); if (lo->lo_state != Lo_bound) return -ENXIO; @@ -916,6 +917,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) bd_set_size(bdev, 0); mapping_set_gfp_mask(filp->f_mapping, gfp); lo->lo_state = Lo_unbound; + mutex_unlock(&lo->lo_ctl_mutex); fput(filp); /* This is safe: open() is still holding a reference. */ module_put(THIS_MODULE); @@ -1143,8 +1145,11 @@ static int lo_ioctl(struct inode * inode, struct file * file, err = loop_change_fd(lo, file, inode->i_bdev, arg); break; case LOOP_CLR_FD: + /* loop_clr_fd must do the locking itself, so that it + * doesn't deadlock with bdev */ + mutex_unlock(&lo->lo_ctl_mutex); err = loop_clr_fd(lo, inode->i_bdev); - break; + goto out_unlocked; case LOOP_SET_STATUS: err = loop_set_status_old(lo, (struct loop_info __user *) arg); break; @@ -1160,6 +1165,7 @@ static int lo_ioctl(struct inode * inode, struct file * file, default: err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; } +out_unlocked: mutex_unlock(&lo->lo_ctl_mutex); return err; } -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/