From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dmitry Monakhov Subject: [PATCH] fs: ioctl_fsthaw should use freeze_bdev if possible Date: Thu, 21 Mar 2013 16:26:56 +0400 Message-ID: <1363868816-11837-1-git-send-email-dmonakhov@openvz.org> Cc: viro@ZenIV.linux.org.uk, josef@redhat.com, Dmitry Monakhov To: linux-fsdevel@vger.kernel.org Return-path: Received: from mailhub.sw.ru ([195.214.232.25]:44265 "EHLO relay.sw.ru" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755580Ab3CUM1R (ORCPT ); Thu, 21 Mar 2013 08:27:17 -0400 Sender: linux-fsdevel-owner@vger.kernel.org List-ID: Commit: 18e9e5104fcd breaks connection between freeze_bdev()/thaw_bdev() and freeze_super()/thaw_super() In other workds: freeze_bdev()/thaw_bdev() may be called multiple times, but freeze_super()/thaw_super() only once (will resunt -EBUSY on second call) BUT user is still allowed to mix both interfaces: freeze_bdev () call it first time ->bdev->bd_fsfreeze_count++ ->freeze_super() return 0 freeze_super() second time ->bdev->bd_fsfreeze_count++ return 0 One can call ioctl_fsthaw( #xfs_freeze -u $MNT) ioctl_fsthaw ->thaw_super() -> fs is unfrozen now return 0 This leave bdev in broken state because: bd_fsfreeze_count > 0 but superblock is not frozen. Visiable effect: 0) Any freeze_bdev() will not call freeze_super() because (bdev->bd_fsfreeze_count > 0) 1) thaw_bdev() will fail because thaw_super() will return EINVAL (filesystem is not frozen) and bdev->bd_fsfreeze_count will not being decremented. 2) filesystem may not being mounted because mount_bdev will fail because (bdev->bd_fsfreeze_count > 0) #TEST_CASE: # Use xfstests 068'th test (while true ;do dmsetup suspend $SCRATCH_DEV ;dmsetup resume $SCRATCH_DEV;done)& pid=$! ./check 068 068 068 068 068 kill $pid wait $pid In order to fix that let's always use {freeze,thaw}_bdev() functions if super block has bdev, and directly call {freeze,thaw)_super() otherwise. Signed-off-by: Dmitry Monakhov --- fs/ioctl.c | 16 +++++++++++++--- 1 files changed, 13 insertions(+), 3 deletions(-) diff --git a/fs/ioctl.c b/fs/ioctl.c index 3bdad6d..ea47ccc 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -513,6 +513,7 @@ static int ioctl_fioasync(unsigned int fd, struct file *filp, static int ioctl_fsfreeze(struct file *filp) { struct super_block *sb = filp->f_path.dentry->d_inode->i_sb; + int ret = 0; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -521,8 +522,15 @@ static int ioctl_fsfreeze(struct file *filp) if (sb->s_op->freeze_fs == NULL) return -EOPNOTSUPP; - /* Freeze */ - return freeze_super(sb); + if (sb->s_bdev) { + struct super_block *fsb; + fsb = freeze_bdev(sb->s_bdev); + if (IS_ERR(fsb)) + ret = PTR_ERR(fsb); + } else { + ret = freeze_super(sb); + } + return ret; } static int ioctl_fsthaw(struct file *filp) @@ -532,7 +540,9 @@ static int ioctl_fsthaw(struct file *filp) if (!capable(CAP_SYS_ADMIN)) return -EPERM; - /* Thaw */ + if (sb->s_bdev) + return thaw_bdev(sb->s_bdev, sb); + return thaw_super(sb); } -- 1.7.1