diff options
Diffstat (limited to 'fs/sysv/inode.c')
-rw-r--r-- | fs/sysv/inode.c | 75 |
1 files changed, 40 insertions, 35 deletions
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index da20b48d350f..479923456a54 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c | |||
@@ -31,15 +31,13 @@ | |||
31 | #include <asm/byteorder.h> | 31 | #include <asm/byteorder.h> |
32 | #include "sysv.h" | 32 | #include "sysv.h" |
33 | 33 | ||
34 | /* This is only called on sync() and umount(), when s_dirt=1. */ | 34 | static int sysv_sync_fs(struct super_block *sb, int wait) |
35 | static void sysv_write_super(struct super_block *sb) | ||
36 | { | 35 | { |
37 | struct sysv_sb_info *sbi = SYSV_SB(sb); | 36 | struct sysv_sb_info *sbi = SYSV_SB(sb); |
38 | unsigned long time = get_seconds(), old_time; | 37 | unsigned long time = get_seconds(), old_time; |
39 | 38 | ||
39 | lock_super(sb); | ||
40 | lock_kernel(); | 40 | lock_kernel(); |
41 | if (sb->s_flags & MS_RDONLY) | ||
42 | goto clean; | ||
43 | 41 | ||
44 | /* | 42 | /* |
45 | * If we are going to write out the super block, | 43 | * If we are going to write out the super block, |
@@ -53,18 +51,30 @@ static void sysv_write_super(struct super_block *sb) | |||
53 | *sbi->s_sb_time = cpu_to_fs32(sbi, time); | 51 | *sbi->s_sb_time = cpu_to_fs32(sbi, time); |
54 | mark_buffer_dirty(sbi->s_bh2); | 52 | mark_buffer_dirty(sbi->s_bh2); |
55 | } | 53 | } |
56 | clean: | 54 | |
57 | sb->s_dirt = 0; | ||
58 | unlock_kernel(); | 55 | unlock_kernel(); |
56 | unlock_super(sb); | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static void sysv_write_super(struct super_block *sb) | ||
62 | { | ||
63 | if (!(sb->s_flags & MS_RDONLY)) | ||
64 | sysv_sync_fs(sb, 1); | ||
65 | else | ||
66 | sb->s_dirt = 0; | ||
59 | } | 67 | } |
60 | 68 | ||
61 | static int sysv_remount(struct super_block *sb, int *flags, char *data) | 69 | static int sysv_remount(struct super_block *sb, int *flags, char *data) |
62 | { | 70 | { |
63 | struct sysv_sb_info *sbi = SYSV_SB(sb); | 71 | struct sysv_sb_info *sbi = SYSV_SB(sb); |
72 | lock_super(sb); | ||
64 | if (sbi->s_forced_ro) | 73 | if (sbi->s_forced_ro) |
65 | *flags |= MS_RDONLY; | 74 | *flags |= MS_RDONLY; |
66 | if (!(*flags & MS_RDONLY)) | 75 | if (!(*flags & MS_RDONLY)) |
67 | sb->s_dirt = 1; | 76 | sb->s_dirt = 1; |
77 | unlock_super(sb); | ||
68 | return 0; | 78 | return 0; |
69 | } | 79 | } |
70 | 80 | ||
@@ -72,6 +82,11 @@ static void sysv_put_super(struct super_block *sb) | |||
72 | { | 82 | { |
73 | struct sysv_sb_info *sbi = SYSV_SB(sb); | 83 | struct sysv_sb_info *sbi = SYSV_SB(sb); |
74 | 84 | ||
85 | lock_kernel(); | ||
86 | |||
87 | if (sb->s_dirt) | ||
88 | sysv_write_super(sb); | ||
89 | |||
75 | if (!(sb->s_flags & MS_RDONLY)) { | 90 | if (!(sb->s_flags & MS_RDONLY)) { |
76 | /* XXX ext2 also updates the state here */ | 91 | /* XXX ext2 also updates the state here */ |
77 | mark_buffer_dirty(sbi->s_bh1); | 92 | mark_buffer_dirty(sbi->s_bh1); |
@@ -84,6 +99,8 @@ static void sysv_put_super(struct super_block *sb) | |||
84 | brelse(sbi->s_bh2); | 99 | brelse(sbi->s_bh2); |
85 | 100 | ||
86 | kfree(sbi); | 101 | kfree(sbi); |
102 | |||
103 | unlock_kernel(); | ||
87 | } | 104 | } |
88 | 105 | ||
89 | static int sysv_statfs(struct dentry *dentry, struct kstatfs *buf) | 106 | static int sysv_statfs(struct dentry *dentry, struct kstatfs *buf) |
@@ -236,7 +253,7 @@ bad_inode: | |||
236 | return ERR_PTR(-EIO); | 253 | return ERR_PTR(-EIO); |
237 | } | 254 | } |
238 | 255 | ||
239 | static struct buffer_head * sysv_update_inode(struct inode * inode) | 256 | int sysv_write_inode(struct inode *inode, int wait) |
240 | { | 257 | { |
241 | struct super_block * sb = inode->i_sb; | 258 | struct super_block * sb = inode->i_sb; |
242 | struct sysv_sb_info * sbi = SYSV_SB(sb); | 259 | struct sysv_sb_info * sbi = SYSV_SB(sb); |
@@ -244,19 +261,21 @@ static struct buffer_head * sysv_update_inode(struct inode * inode) | |||
244 | struct sysv_inode * raw_inode; | 261 | struct sysv_inode * raw_inode; |
245 | struct sysv_inode_info * si; | 262 | struct sysv_inode_info * si; |
246 | unsigned int ino, block; | 263 | unsigned int ino, block; |
264 | int err = 0; | ||
247 | 265 | ||
248 | ino = inode->i_ino; | 266 | ino = inode->i_ino; |
249 | if (!ino || ino > sbi->s_ninodes) { | 267 | if (!ino || ino > sbi->s_ninodes) { |
250 | printk("Bad inode number on dev %s: %d is out of range\n", | 268 | printk("Bad inode number on dev %s: %d is out of range\n", |
251 | inode->i_sb->s_id, ino); | 269 | inode->i_sb->s_id, ino); |
252 | return NULL; | 270 | return -EIO; |
253 | } | 271 | } |
254 | raw_inode = sysv_raw_inode(sb, ino, &bh); | 272 | raw_inode = sysv_raw_inode(sb, ino, &bh); |
255 | if (!raw_inode) { | 273 | if (!raw_inode) { |
256 | printk("unable to read i-node block\n"); | 274 | printk("unable to read i-node block\n"); |
257 | return NULL; | 275 | return -EIO; |
258 | } | 276 | } |
259 | 277 | ||
278 | lock_kernel(); | ||
260 | raw_inode->i_mode = cpu_to_fs16(sbi, inode->i_mode); | 279 | raw_inode->i_mode = cpu_to_fs16(sbi, inode->i_mode); |
261 | raw_inode->i_uid = cpu_to_fs16(sbi, fs_high2lowuid(inode->i_uid)); | 280 | raw_inode->i_uid = cpu_to_fs16(sbi, fs_high2lowuid(inode->i_uid)); |
262 | raw_inode->i_gid = cpu_to_fs16(sbi, fs_high2lowgid(inode->i_gid)); | 281 | raw_inode->i_gid = cpu_to_fs16(sbi, fs_high2lowgid(inode->i_gid)); |
@@ -272,38 +291,23 @@ static struct buffer_head * sysv_update_inode(struct inode * inode) | |||
272 | for (block = 0; block < 10+1+1+1; block++) | 291 | for (block = 0; block < 10+1+1+1; block++) |
273 | write3byte(sbi, (u8 *)&si->i_data[block], | 292 | write3byte(sbi, (u8 *)&si->i_data[block], |
274 | &raw_inode->i_data[3*block]); | 293 | &raw_inode->i_data[3*block]); |
294 | unlock_kernel(); | ||
275 | mark_buffer_dirty(bh); | 295 | mark_buffer_dirty(bh); |
276 | return bh; | 296 | if (wait) { |
277 | } | 297 | sync_dirty_buffer(bh); |
278 | 298 | if (buffer_req(bh) && !buffer_uptodate(bh)) { | |
279 | int sysv_write_inode(struct inode * inode, int wait) | 299 | printk ("IO error syncing sysv inode [%s:%08x]\n", |
280 | { | 300 | sb->s_id, ino); |
281 | struct buffer_head *bh; | 301 | err = -EIO; |
282 | lock_kernel(); | 302 | } |
283 | bh = sysv_update_inode(inode); | 303 | } |
284 | brelse(bh); | 304 | brelse(bh); |
285 | unlock_kernel(); | ||
286 | return 0; | 305 | return 0; |
287 | } | 306 | } |
288 | 307 | ||
289 | int sysv_sync_inode(struct inode * inode) | 308 | int sysv_sync_inode(struct inode *inode) |
290 | { | 309 | { |
291 | int err = 0; | 310 | return sysv_write_inode(inode, 1); |
292 | struct buffer_head *bh; | ||
293 | |||
294 | bh = sysv_update_inode(inode); | ||
295 | if (bh && buffer_dirty(bh)) { | ||
296 | sync_dirty_buffer(bh); | ||
297 | if (buffer_req(bh) && !buffer_uptodate(bh)) { | ||
298 | printk ("IO error syncing sysv inode [%s:%08lx]\n", | ||
299 | inode->i_sb->s_id, inode->i_ino); | ||
300 | err = -1; | ||
301 | } | ||
302 | } | ||
303 | else if (!bh) | ||
304 | err = -1; | ||
305 | brelse (bh); | ||
306 | return err; | ||
307 | } | 311 | } |
308 | 312 | ||
309 | static void sysv_delete_inode(struct inode *inode) | 313 | static void sysv_delete_inode(struct inode *inode) |
@@ -347,6 +351,7 @@ const struct super_operations sysv_sops = { | |||
347 | .delete_inode = sysv_delete_inode, | 351 | .delete_inode = sysv_delete_inode, |
348 | .put_super = sysv_put_super, | 352 | .put_super = sysv_put_super, |
349 | .write_super = sysv_write_super, | 353 | .write_super = sysv_write_super, |
354 | .sync_fs = sysv_sync_fs, | ||
350 | .remount_fs = sysv_remount, | 355 | .remount_fs = sysv_remount, |
351 | .statfs = sysv_statfs, | 356 | .statfs = sysv_statfs, |
352 | }; | 357 | }; |