fs: add freeze_super/thaw_super fs hooks
authorBenjamin Marzinski <bmarzins@redhat.com>
Fri, 14 Nov 2014 02:42:03 +0000 (20:42 -0600)
committerSteven Whitehouse <swhiteho@redhat.com>
Mon, 17 Nov 2014 10:35:17 +0000 (10:35 +0000)
Currently, freezing a filesystem involves calling freeze_super, which locks
sb->s_umount and then calls the fs-specific freeze_fs hook. This makes it
hard for gfs2 (and potentially other cluster filesystems) to use the vfs
freezing code to do freezes on all the cluster nodes.

In order to communicate that a freeze has been requested, and to make sure
that only one node is trying to freeze at a time, gfs2 uses a glock
(sd_freeze_gl). The problem is that there is no hook for gfs2 to acquire
this lock before calling freeze_super. This means that two nodes can
attempt to freeze the filesystem by both calling freeze_super, acquiring
the sb->s_umount lock, and then attempting to grab the cluster glock
sd_freeze_gl. Only one will succeed, and the other will be stuck in
freeze_super, making it impossible to finish freezing the node.

To solve this problem, this patch adds the freeze_super and thaw_super
hooks.  If a filesystem implements these hooks, they are called instead of
the vfs freeze_super and thaw_super functions. This means that every
filesystem that implements these hooks must call the vfs freeze_super and
thaw_super functions itself within the hook function to make use of the vfs
freezing code.

Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
fs/block_dev.c
fs/ioctl.c
include/linux/fs.h

index 1d9c9f3754f860b2f9ca19a61d1e89d3eaa9c47c..b48c41bf0f86755200808c1b33a82ce6c8066d71 100644 (file)
@@ -235,7 +235,10 @@ struct super_block *freeze_bdev(struct block_device *bdev)
        sb = get_active_super(bdev);
        if (!sb)
                goto out;
-       error = freeze_super(sb);
+       if (sb->s_op->freeze_super)
+               error = sb->s_op->freeze_super(sb);
+       else
+               error = freeze_super(sb);
        if (error) {
                deactivate_super(sb);
                bdev->bd_fsfreeze_count--;
@@ -272,7 +275,10 @@ int thaw_bdev(struct block_device *bdev, struct super_block *sb)
        if (!sb)
                goto out;
 
-       error = thaw_super(sb);
+       if (sb->s_op->thaw_super)
+               error = sb->s_op->thaw_super(sb);
+       else
+               error = thaw_super(sb);
        if (error) {
                bdev->bd_fsfreeze_count++;
                mutex_unlock(&bdev->bd_fsfreeze_mutex);
index 8ac3fad36192fb153b93e1be8c5d0e0ee110b463..77c9a7812542e0f7e4abe4cb013f22241988f238 100644 (file)
@@ -518,10 +518,12 @@ static int ioctl_fsfreeze(struct file *filp)
                return -EPERM;
 
        /* If filesystem doesn't support freeze feature, return. */
-       if (sb->s_op->freeze_fs == NULL)
+       if (sb->s_op->freeze_fs == NULL && sb->s_op->freeze_super == NULL)
                return -EOPNOTSUPP;
 
        /* Freeze */
+       if (sb->s_op->freeze_super)
+               return sb->s_op->freeze_super(sb);
        return freeze_super(sb);
 }
 
@@ -533,6 +535,8 @@ static int ioctl_fsthaw(struct file *filp)
                return -EPERM;
 
        /* Thaw */
+       if (sb->s_op->thaw_super)
+               return sb->s_op->thaw_super(sb);
        return thaw_super(sb);
 }
 
index 9ab779e8a63ccd7785637dd9017fc3bc69ff260f..b4a1d73c0d5d0952948df027b71df7e0618382a8 100644 (file)
@@ -1577,7 +1577,9 @@ struct super_operations {
        void (*evict_inode) (struct inode *);
        void (*put_super) (struct super_block *);
        int (*sync_fs)(struct super_block *sb, int wait);
+       int (*freeze_super) (struct super_block *);
        int (*freeze_fs) (struct super_block *);
+       int (*thaw_super) (struct super_block *);
        int (*unfreeze_fs) (struct super_block *);
        int (*statfs) (struct dentry *, struct kstatfs *);
        int (*remount_fs) (struct super_block *, int *, char *);
This page took 0.035118 seconds and 5 git commands to generate.