@@ -1454,7 +1454,16 @@ int freeze_super(struct super_block *sb)
sb_wait_write(sb, SB_FREEZE_PAGEFAULT);
/* All writers are done so after syncing there won't be dirty data */
- sync_filesystem(sb);
+ if (sb->s_op->freeze_data) {
+ ret = sb->s_op->freeze_data(sb);
+ if (ret) {
+ printk(KERN_ERR
+ "VFS:Filesystem data freeze failed\n");
+ goto freeze_fail;
+ }
+ } else {
+ sync_filesystem(sb);
+ }
/* Now wait for internal filesystem counter */
sb->s_writers.frozen = SB_FREEZE_FS;
@@ -1465,11 +1474,7 @@ int freeze_super(struct super_block *sb)
if (ret) {
printk(KERN_ERR
"VFS:Filesystem freeze failed\n");
- sb->s_writers.frozen = SB_UNFROZEN;
- sb_freeze_unlock(sb);
- wake_up(&sb->s_writers.wait_unfrozen);
- deactivate_locked_super(sb);
- return ret;
+ goto freeze_fail;
}
}
/*
@@ -1480,6 +1485,12 @@ int freeze_super(struct super_block *sb)
lockdep_sb_freeze_release(sb);
up_write(&sb->s_umount);
return 0;
+freeze_fail:
+ sb->s_writers.frozen = SB_UNFROZEN;
+ sb_freeze_unlock(sb);
+ wake_up(&sb->s_writers.wait_unfrozen);
+ deactivate_locked_super(sb);
+ return ret;
}
EXPORT_SYMBOL(freeze_super);
@@ -1408,6 +1408,26 @@ xfs_fs_remount(
}
/*
+ * First stage of a freeze. We need to sync all the dirty data and clean up
+ * all the leftover CoW mappings to make the filesystem as tidy as possible.
+ */
+STATIC int
+xfs_fs_freeze_data(
+ struct super_block *sb)
+{
+ struct xfs_mount *mp = XFS_M(sb);
+ int error;
+
+ error = sync_filesystem(sb);
+ if (error)
+ return error;
+
+ if (!xfs_sb_version_hasreflink(&mp->m_sb))
+ return 0;
+ return xfs_icache_free_cowblocks(mp, NULL);
+}
+
+/*
* Second stage of a freeze. The data is already frozen so we only
* need to take care of the metadata. Once that's done sync the superblock
* to the log to dirty it in case of a crash while frozen. This ensures that we
@@ -1780,6 +1800,7 @@ static const struct super_operations xfs_super_operations = {
.drop_inode = xfs_fs_drop_inode,
.put_super = xfs_fs_put_super,
.sync_fs = xfs_fs_sync_fs,
+ .freeze_data = xfs_fs_freeze_data,
.freeze_fs = xfs_fs_freeze,
.unfreeze_fs = xfs_fs_unfreeze,
.statfs = xfs_fs_statfs,
@@ -1811,6 +1811,7 @@ struct super_operations {
void (*put_super) (struct super_block *);
int (*sync_fs)(struct super_block *sb, int wait);
int (*freeze_super) (struct super_block *);
+ int (*freeze_data) (struct super_block *);
int (*freeze_fs) (struct super_block *);
int (*thaw_super) (struct super_block *);
int (*unfreeze_fs) (struct super_block *);