diff options
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/fs/super.c b/fs/super.c index c248ac6a1a21..89afca5055ab 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -944,6 +944,96 @@ out: | |||
944 | 944 | ||
945 | EXPORT_SYMBOL_GPL(vfs_kern_mount); | 945 | EXPORT_SYMBOL_GPL(vfs_kern_mount); |
946 | 946 | ||
947 | /** | ||
948 | * freeze_super -- lock the filesystem and force it into a consistent state | ||
949 | * @super: the super to lock | ||
950 | * | ||
951 | * Syncs the super to make sure the filesystem is consistent and calls the fs's | ||
952 | * freeze_fs. Subsequent calls to this without first thawing the fs will return | ||
953 | * -EBUSY. | ||
954 | */ | ||
955 | int freeze_super(struct super_block *sb) | ||
956 | { | ||
957 | int ret; | ||
958 | |||
959 | atomic_inc(&sb->s_active); | ||
960 | down_write(&sb->s_umount); | ||
961 | if (sb->s_frozen) { | ||
962 | deactivate_locked_super(sb); | ||
963 | return -EBUSY; | ||
964 | } | ||
965 | |||
966 | if (sb->s_flags & MS_RDONLY) { | ||
967 | sb->s_frozen = SB_FREEZE_TRANS; | ||
968 | smp_wmb(); | ||
969 | up_write(&sb->s_umount); | ||
970 | return 0; | ||
971 | } | ||
972 | |||
973 | sb->s_frozen = SB_FREEZE_WRITE; | ||
974 | smp_wmb(); | ||
975 | |||
976 | sync_filesystem(sb); | ||
977 | |||
978 | sb->s_frozen = SB_FREEZE_TRANS; | ||
979 | smp_wmb(); | ||
980 | |||
981 | sync_blockdev(sb->s_bdev); | ||
982 | if (sb->s_op->freeze_fs) { | ||
983 | ret = sb->s_op->freeze_fs(sb); | ||
984 | if (ret) { | ||
985 | printk(KERN_ERR | ||
986 | "VFS:Filesystem freeze failed\n"); | ||
987 | sb->s_frozen = SB_UNFROZEN; | ||
988 | deactivate_locked_super(sb); | ||
989 | return ret; | ||
990 | } | ||
991 | } | ||
992 | up_write(&sb->s_umount); | ||
993 | return 0; | ||
994 | } | ||
995 | EXPORT_SYMBOL(freeze_super); | ||
996 | |||
997 | /** | ||
998 | * thaw_super -- unlock filesystem | ||
999 | * @sb: the super to thaw | ||
1000 | * | ||
1001 | * Unlocks the filesystem and marks it writeable again after freeze_super(). | ||
1002 | */ | ||
1003 | int thaw_super(struct super_block *sb) | ||
1004 | { | ||
1005 | int error; | ||
1006 | |||
1007 | down_write(&sb->s_umount); | ||
1008 | if (sb->s_frozen == SB_UNFROZEN) { | ||
1009 | up_write(&sb->s_umount); | ||
1010 | return -EINVAL; | ||
1011 | } | ||
1012 | |||
1013 | if (sb->s_flags & MS_RDONLY) | ||
1014 | goto out; | ||
1015 | |||
1016 | if (sb->s_op->unfreeze_fs) { | ||
1017 | error = sb->s_op->unfreeze_fs(sb); | ||
1018 | if (error) { | ||
1019 | printk(KERN_ERR | ||
1020 | "VFS:Filesystem thaw failed\n"); | ||
1021 | sb->s_frozen = SB_FREEZE_TRANS; | ||
1022 | up_write(&sb->s_umount); | ||
1023 | return error; | ||
1024 | } | ||
1025 | } | ||
1026 | |||
1027 | out: | ||
1028 | sb->s_frozen = SB_UNFROZEN; | ||
1029 | smp_wmb(); | ||
1030 | wake_up(&sb->s_wait_unfrozen); | ||
1031 | deactivate_locked_super(sb); | ||
1032 | |||
1033 | return 0; | ||
1034 | } | ||
1035 | EXPORT_SYMBOL(thaw_super); | ||
1036 | |||
947 | static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype) | 1037 | static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype) |
948 | { | 1038 | { |
949 | int err; | 1039 | int err; |