On 2/7/12 4:37 PM, Jan Kara wrote: > This script causes a kernel deadlock: > set -e > DEVICE=/dev/vg1/linear > lvchange -ay $DEVICE > mkfs.ext3 $DEVICE > mount -t ext3 -o usrquota,grpquota $DEVICE /mnt/test > quotacheck -gu /mnt/test > umount /mnt/test > mount -t ext3 -o usrquota,grpquota $DEVICE /mnt/test > quotaon /mnt/test > dmsetup suspend $DEVICE > setquota -u root 1 2 3 4 /mnt/test & > sleep 1 > dmsetup resume $DEVICE > > setquota acquired semaphore s_umount for read and then tried to perform a > transaction (and waits because the device is suspended). dmsetup resume tries > to acquire s_umount for write before resuming the device (and waits for > setquota). > > Fix the deadlock by grabbing a thawed superblock for quota commands which need > it. > > Reported-by: Mikulas Patocka <mpatocka@xxxxxxxxxx> > Signed-off-by: Jan Kara <jack@xxxxxxx> Makes sense to me, thanks. Reviewed-by: Eric Sandeen <sandeen@xxxxxxxxxx> > --- > fs/quota/quota.c | 24 +++++++++++++++++++++--- > 1 files changed, 21 insertions(+), 3 deletions(-) > > diff --git a/fs/quota/quota.c b/fs/quota/quota.c > index 7898cd6..fc2c438 100644 > --- a/fs/quota/quota.c > +++ b/fs/quota/quota.c > @@ -292,11 +292,26 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, > } > } > > +/* Return 1 if 'cmd' will block on frozen filesystem */ > +static int quotactl_cmd_write(int cmd) > +{ > + switch (cmd) { > + case Q_GETFMT: > + case Q_GETINFO: > + case Q_SYNC: > + case Q_XGETQSTAT: > + case Q_XGETQUOTA: > + case Q_XQUOTASYNC: > + return 0; > + } > + return 1; > +} > + > /* > * look up a superblock on which quota ops will be performed > * - use the name of a block device to find the superblock thereon > */ > -static struct super_block *quotactl_block(const char __user *special) > +static struct super_block *quotactl_block(const char __user *special, int cmd) > { > #ifdef CONFIG_BLOCK > struct block_device *bdev; > @@ -309,7 +324,10 @@ static struct super_block *quotactl_block(const char __user *special) > putname(tmp); > if (IS_ERR(bdev)) > return ERR_CAST(bdev); > - sb = get_super(bdev); > + if (quotactl_cmd_write(cmd)) > + sb = get_super_thawed(bdev); > + else > + sb = get_super(bdev); > bdput(bdev); > if (!sb) > return ERR_PTR(-ENODEV); > @@ -361,7 +379,7 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special, > pathp = &path; > } > > - sb = quotactl_block(special); > + sb = quotactl_block(special, cmds); > if (IS_ERR(sb)) { > ret = PTR_ERR(sb); > goto out; -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html