diff options
Diffstat (limited to 'fs/ext2/super.c')
-rw-r--r-- | fs/ext2/super.c | 61 |
1 files changed, 44 insertions, 17 deletions
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 5c4afe652245..458999638c3d 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
@@ -42,6 +42,7 @@ static void ext2_sync_super(struct super_block *sb, | |||
42 | struct ext2_super_block *es); | 42 | struct ext2_super_block *es); |
43 | static int ext2_remount (struct super_block * sb, int * flags, char * data); | 43 | static int ext2_remount (struct super_block * sb, int * flags, char * data); |
44 | static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf); | 44 | static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf); |
45 | static int ext2_sync_fs(struct super_block *sb, int wait); | ||
45 | 46 | ||
46 | void ext2_error (struct super_block * sb, const char * function, | 47 | void ext2_error (struct super_block * sb, const char * function, |
47 | const char * fmt, ...) | 48 | const char * fmt, ...) |
@@ -114,6 +115,11 @@ static void ext2_put_super (struct super_block * sb) | |||
114 | int i; | 115 | int i; |
115 | struct ext2_sb_info *sbi = EXT2_SB(sb); | 116 | struct ext2_sb_info *sbi = EXT2_SB(sb); |
116 | 117 | ||
118 | lock_kernel(); | ||
119 | |||
120 | if (sb->s_dirt) | ||
121 | ext2_write_super(sb); | ||
122 | |||
117 | ext2_xattr_put_super(sb); | 123 | ext2_xattr_put_super(sb); |
118 | if (!(sb->s_flags & MS_RDONLY)) { | 124 | if (!(sb->s_flags & MS_RDONLY)) { |
119 | struct ext2_super_block *es = sbi->s_es; | 125 | struct ext2_super_block *es = sbi->s_es; |
@@ -135,7 +141,7 @@ static void ext2_put_super (struct super_block * sb) | |||
135 | kfree(sbi->s_blockgroup_lock); | 141 | kfree(sbi->s_blockgroup_lock); |
136 | kfree(sbi); | 142 | kfree(sbi); |
137 | 143 | ||
138 | return; | 144 | unlock_kernel(); |
139 | } | 145 | } |
140 | 146 | ||
141 | static struct kmem_cache * ext2_inode_cachep; | 147 | static struct kmem_cache * ext2_inode_cachep; |
@@ -304,6 +310,7 @@ static const struct super_operations ext2_sops = { | |||
304 | .delete_inode = ext2_delete_inode, | 310 | .delete_inode = ext2_delete_inode, |
305 | .put_super = ext2_put_super, | 311 | .put_super = ext2_put_super, |
306 | .write_super = ext2_write_super, | 312 | .write_super = ext2_write_super, |
313 | .sync_fs = ext2_sync_fs, | ||
307 | .statfs = ext2_statfs, | 314 | .statfs = ext2_statfs, |
308 | .remount_fs = ext2_remount, | 315 | .remount_fs = ext2_remount, |
309 | .clear_inode = ext2_clear_inode, | 316 | .clear_inode = ext2_clear_inode, |
@@ -1093,6 +1100,7 @@ failed_mount: | |||
1093 | brelse(bh); | 1100 | brelse(bh); |
1094 | failed_sbi: | 1101 | failed_sbi: |
1095 | sb->s_fs_info = NULL; | 1102 | sb->s_fs_info = NULL; |
1103 | kfree(sbi->s_blockgroup_lock); | ||
1096 | kfree(sbi); | 1104 | kfree(sbi); |
1097 | return ret; | 1105 | return ret; |
1098 | } | 1106 | } |
@@ -1126,25 +1134,36 @@ static void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es) | |||
1126 | * set s_state to EXT2_VALID_FS after some corrections. | 1134 | * set s_state to EXT2_VALID_FS after some corrections. |
1127 | */ | 1135 | */ |
1128 | 1136 | ||
1129 | void ext2_write_super (struct super_block * sb) | 1137 | static int ext2_sync_fs(struct super_block *sb, int wait) |
1130 | { | 1138 | { |
1131 | struct ext2_super_block * es; | 1139 | struct ext2_super_block *es = EXT2_SB(sb)->s_es; |
1140 | |||
1132 | lock_kernel(); | 1141 | lock_kernel(); |
1133 | if (!(sb->s_flags & MS_RDONLY)) { | 1142 | if (es->s_state & cpu_to_le16(EXT2_VALID_FS)) { |
1134 | es = EXT2_SB(sb)->s_es; | 1143 | ext2_debug("setting valid to 0\n"); |
1135 | 1144 | es->s_state &= cpu_to_le16(~EXT2_VALID_FS); | |
1136 | if (es->s_state & cpu_to_le16(EXT2_VALID_FS)) { | 1145 | es->s_free_blocks_count = |
1137 | ext2_debug ("setting valid to 0\n"); | 1146 | cpu_to_le32(ext2_count_free_blocks(sb)); |
1138 | es->s_state &= cpu_to_le16(~EXT2_VALID_FS); | 1147 | es->s_free_inodes_count = |
1139 | es->s_free_blocks_count = cpu_to_le32(ext2_count_free_blocks(sb)); | 1148 | cpu_to_le32(ext2_count_free_inodes(sb)); |
1140 | es->s_free_inodes_count = cpu_to_le32(ext2_count_free_inodes(sb)); | 1149 | es->s_mtime = cpu_to_le32(get_seconds()); |
1141 | es->s_mtime = cpu_to_le32(get_seconds()); | 1150 | ext2_sync_super(sb, es); |
1142 | ext2_sync_super(sb, es); | 1151 | } else { |
1143 | } else | 1152 | ext2_commit_super(sb, es); |
1144 | ext2_commit_super (sb, es); | ||
1145 | } | 1153 | } |
1146 | sb->s_dirt = 0; | 1154 | sb->s_dirt = 0; |
1147 | unlock_kernel(); | 1155 | unlock_kernel(); |
1156 | |||
1157 | return 0; | ||
1158 | } | ||
1159 | |||
1160 | |||
1161 | void ext2_write_super(struct super_block *sb) | ||
1162 | { | ||
1163 | if (!(sb->s_flags & MS_RDONLY)) | ||
1164 | ext2_sync_fs(sb, 1); | ||
1165 | else | ||
1166 | sb->s_dirt = 0; | ||
1148 | } | 1167 | } |
1149 | 1168 | ||
1150 | static int ext2_remount (struct super_block * sb, int * flags, char * data) | 1169 | static int ext2_remount (struct super_block * sb, int * flags, char * data) |
@@ -1156,6 +1175,8 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data) | |||
1156 | unsigned long old_sb_flags; | 1175 | unsigned long old_sb_flags; |
1157 | int err; | 1176 | int err; |
1158 | 1177 | ||
1178 | lock_kernel(); | ||
1179 | |||
1159 | /* Store the old options */ | 1180 | /* Store the old options */ |
1160 | old_sb_flags = sb->s_flags; | 1181 | old_sb_flags = sb->s_flags; |
1161 | old_opts.s_mount_opt = sbi->s_mount_opt; | 1182 | old_opts.s_mount_opt = sbi->s_mount_opt; |
@@ -1191,12 +1212,16 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data) | |||
1191 | sbi->s_mount_opt &= ~EXT2_MOUNT_XIP; | 1212 | sbi->s_mount_opt &= ~EXT2_MOUNT_XIP; |
1192 | sbi->s_mount_opt |= old_mount_opt & EXT2_MOUNT_XIP; | 1213 | sbi->s_mount_opt |= old_mount_opt & EXT2_MOUNT_XIP; |
1193 | } | 1214 | } |
1194 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) | 1215 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) { |
1216 | unlock_kernel(); | ||
1195 | return 0; | 1217 | return 0; |
1218 | } | ||
1196 | if (*flags & MS_RDONLY) { | 1219 | if (*flags & MS_RDONLY) { |
1197 | if (le16_to_cpu(es->s_state) & EXT2_VALID_FS || | 1220 | if (le16_to_cpu(es->s_state) & EXT2_VALID_FS || |
1198 | !(sbi->s_mount_state & EXT2_VALID_FS)) | 1221 | !(sbi->s_mount_state & EXT2_VALID_FS)) { |
1222 | unlock_kernel(); | ||
1199 | return 0; | 1223 | return 0; |
1224 | } | ||
1200 | /* | 1225 | /* |
1201 | * OK, we are remounting a valid rw partition rdonly, so set | 1226 | * OK, we are remounting a valid rw partition rdonly, so set |
1202 | * the rdonly flag and then mark the partition as valid again. | 1227 | * the rdonly flag and then mark the partition as valid again. |
@@ -1223,12 +1248,14 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data) | |||
1223 | sb->s_flags &= ~MS_RDONLY; | 1248 | sb->s_flags &= ~MS_RDONLY; |
1224 | } | 1249 | } |
1225 | ext2_sync_super(sb, es); | 1250 | ext2_sync_super(sb, es); |
1251 | unlock_kernel(); | ||
1226 | return 0; | 1252 | return 0; |
1227 | restore_opts: | 1253 | restore_opts: |
1228 | sbi->s_mount_opt = old_opts.s_mount_opt; | 1254 | sbi->s_mount_opt = old_opts.s_mount_opt; |
1229 | sbi->s_resuid = old_opts.s_resuid; | 1255 | sbi->s_resuid = old_opts.s_resuid; |
1230 | sbi->s_resgid = old_opts.s_resgid; | 1256 | sbi->s_resgid = old_opts.s_resgid; |
1231 | sb->s_flags = old_sb_flags; | 1257 | sb->s_flags = old_sb_flags; |
1258 | unlock_kernel(); | ||
1232 | return err; | 1259 | return err; |
1233 | } | 1260 | } |
1234 | 1261 | ||