aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Marzinski <bmarzins@redhat.com>2014-11-13 21:42:03 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2014-11-17 05:35:17 -0500
commit48b6bca6b7b8309697fc8a101793befe92d249d9 (patch)
tree2cec8b867e5058c6672e425e2ac9a0d25ae60cf1
parent98f1a696a1b2f6cf0c1ce6850b1516beda9c1269 (diff)
fs: add freeze_super/thaw_super fs hooks
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>
-rw-r--r--fs/block_dev.c10
-rw-r--r--fs/ioctl.c6
-rw-r--r--include/linux/fs.h2
3 files changed, 15 insertions, 3 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 1d9c9f3754f8..b48c41bf0f86 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -235,7 +235,10 @@ struct super_block *freeze_bdev(struct block_device *bdev)
235 sb = get_active_super(bdev); 235 sb = get_active_super(bdev);
236 if (!sb) 236 if (!sb)
237 goto out; 237 goto out;
238 error = freeze_super(sb); 238 if (sb->s_op->freeze_super)
239 error = sb->s_op->freeze_super(sb);
240 else
241 error = freeze_super(sb);
239 if (error) { 242 if (error) {
240 deactivate_super(sb); 243 deactivate_super(sb);
241 bdev->bd_fsfreeze_count--; 244 bdev->bd_fsfreeze_count--;
@@ -272,7 +275,10 @@ int thaw_bdev(struct block_device *bdev, struct super_block *sb)
272 if (!sb) 275 if (!sb)
273 goto out; 276 goto out;
274 277
275 error = thaw_super(sb); 278 if (sb->s_op->thaw_super)
279 error = sb->s_op->thaw_super(sb);
280 else
281 error = thaw_super(sb);
276 if (error) { 282 if (error) {
277 bdev->bd_fsfreeze_count++; 283 bdev->bd_fsfreeze_count++;
278 mutex_unlock(&bdev->bd_fsfreeze_mutex); 284 mutex_unlock(&bdev->bd_fsfreeze_mutex);
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 8ac3fad36192..77c9a7812542 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -518,10 +518,12 @@ static int ioctl_fsfreeze(struct file *filp)
518 return -EPERM; 518 return -EPERM;
519 519
520 /* If filesystem doesn't support freeze feature, return. */ 520 /* If filesystem doesn't support freeze feature, return. */
521 if (sb->s_op->freeze_fs == NULL) 521 if (sb->s_op->freeze_fs == NULL && sb->s_op->freeze_super == NULL)
522 return -EOPNOTSUPP; 522 return -EOPNOTSUPP;
523 523
524 /* Freeze */ 524 /* Freeze */
525 if (sb->s_op->freeze_super)
526 return sb->s_op->freeze_super(sb);
525 return freeze_super(sb); 527 return freeze_super(sb);
526} 528}
527 529
@@ -533,6 +535,8 @@ static int ioctl_fsthaw(struct file *filp)
533 return -EPERM; 535 return -EPERM;
534 536
535 /* Thaw */ 537 /* Thaw */
538 if (sb->s_op->thaw_super)
539 return sb->s_op->thaw_super(sb);
536 return thaw_super(sb); 540 return thaw_super(sb);
537} 541}
538 542
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 9ab779e8a63c..b4a1d73c0d5d 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1577,7 +1577,9 @@ struct super_operations {
1577 void (*evict_inode) (struct inode *); 1577 void (*evict_inode) (struct inode *);
1578 void (*put_super) (struct super_block *); 1578 void (*put_super) (struct super_block *);
1579 int (*sync_fs)(struct super_block *sb, int wait); 1579 int (*sync_fs)(struct super_block *sb, int wait);
1580 int (*freeze_super) (struct super_block *);
1580 int (*freeze_fs) (struct super_block *); 1581 int (*freeze_fs) (struct super_block *);
1582 int (*thaw_super) (struct super_block *);
1581 int (*unfreeze_fs) (struct super_block *); 1583 int (*unfreeze_fs) (struct super_block *);
1582 int (*statfs) (struct dentry *, struct kstatfs *); 1584 int (*statfs) (struct dentry *, struct kstatfs *);
1583 int (*remount_fs) (struct super_block *, int *, char *); 1585 int (*remount_fs) (struct super_block *, int *, char *);