diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2010-07-05 08:15:00 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-08-09 16:48:51 -0400 |
commit | 7435d50611b04c1155a939a9f373154a53606592 (patch) | |
tree | 5800b04dbaf99dfc6958bb777c39d98e7de94593 /fs/affs | |
parent | 669d5f1f608f7de29bb467bb239517a414e43777 (diff) |
AFFS: wait for sb synchronization when needed
AFFS does not ever wait for superblock synchronization in
->put_super(), ->write_super, and ->sync_fs().
However, it should wait for synchronization in ->put_super() because
it is about to be unmounted, in ->write_super() because this is
periodic SB synchronization performed from a separate kernel thread,
and in ->sync_fs() it should respect the 'wait' flag. This patch fixes
the situation.
Also, in ->put_super(), do not write the SB if it is not dirty.
Tested-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/affs')
-rw-r--r-- | fs/affs/super.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/fs/affs/super.c b/fs/affs/super.c index fde3b9ae700f..33c4e7eef470 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c | |||
@@ -26,7 +26,7 @@ static int affs_statfs(struct dentry *dentry, struct kstatfs *buf); | |||
26 | static int affs_remount (struct super_block *sb, int *flags, char *data); | 26 | static int affs_remount (struct super_block *sb, int *flags, char *data); |
27 | 27 | ||
28 | static void | 28 | static void |
29 | affs_commit_super(struct super_block *sb, int clean) | 29 | affs_commit_super(struct super_block *sb, int wait, int clean) |
30 | { | 30 | { |
31 | struct affs_sb_info *sbi = AFFS_SB(sb); | 31 | struct affs_sb_info *sbi = AFFS_SB(sb); |
32 | struct buffer_head *bh = sbi->s_root_bh; | 32 | struct buffer_head *bh = sbi->s_root_bh; |
@@ -36,6 +36,8 @@ affs_commit_super(struct super_block *sb, int clean) | |||
36 | secs_to_datestamp(get_seconds(), &tail->disk_change); | 36 | secs_to_datestamp(get_seconds(), &tail->disk_change); |
37 | affs_fix_checksum(sb, bh); | 37 | affs_fix_checksum(sb, bh); |
38 | mark_buffer_dirty(bh); | 38 | mark_buffer_dirty(bh); |
39 | if (wait) | ||
40 | sync_dirty_buffer(bh); | ||
39 | } | 41 | } |
40 | 42 | ||
41 | static void | 43 | static void |
@@ -46,8 +48,8 @@ affs_put_super(struct super_block *sb) | |||
46 | 48 | ||
47 | lock_kernel(); | 49 | lock_kernel(); |
48 | 50 | ||
49 | if (!(sb->s_flags & MS_RDONLY)) | 51 | if (!(sb->s_flags & MS_RDONLY) && sb->s_dirt) |
50 | affs_commit_super(sb, 1); | 52 | affs_commit_super(sb, 1, 1); |
51 | 53 | ||
52 | kfree(sbi->s_prefix); | 54 | kfree(sbi->s_prefix); |
53 | affs_free_bitmap(sb); | 55 | affs_free_bitmap(sb); |
@@ -63,7 +65,7 @@ affs_write_super(struct super_block *sb) | |||
63 | { | 65 | { |
64 | lock_super(sb); | 66 | lock_super(sb); |
65 | if (!(sb->s_flags & MS_RDONLY)) | 67 | if (!(sb->s_flags & MS_RDONLY)) |
66 | affs_commit_super(sb, 2); | 68 | affs_commit_super(sb, 1, 2); |
67 | sb->s_dirt = 0; | 69 | sb->s_dirt = 0; |
68 | unlock_super(sb); | 70 | unlock_super(sb); |
69 | 71 | ||
@@ -74,7 +76,7 @@ static int | |||
74 | affs_sync_fs(struct super_block *sb, int wait) | 76 | affs_sync_fs(struct super_block *sb, int wait) |
75 | { | 77 | { |
76 | lock_super(sb); | 78 | lock_super(sb); |
77 | affs_commit_super(sb, 2); | 79 | affs_commit_super(sb, wait, 2); |
78 | sb->s_dirt = 0; | 80 | sb->s_dirt = 0; |
79 | unlock_super(sb); | 81 | unlock_super(sb); |
80 | return 0; | 82 | return 0; |