diff options
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r-- | fs/ext4/super.c | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 8f7e0be8ab1b..e5f06a5f045e 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -51,7 +51,7 @@ struct proc_dir_entry *ext4_proc_root; | |||
51 | 51 | ||
52 | static int ext4_load_journal(struct super_block *, struct ext4_super_block *, | 52 | static int ext4_load_journal(struct super_block *, struct ext4_super_block *, |
53 | unsigned long journal_devnum); | 53 | unsigned long journal_devnum); |
54 | static void ext4_commit_super(struct super_block *sb, | 54 | static int ext4_commit_super(struct super_block *sb, |
55 | struct ext4_super_block *es, int sync); | 55 | struct ext4_super_block *es, int sync); |
56 | static void ext4_mark_recovery_complete(struct super_block *sb, | 56 | static void ext4_mark_recovery_complete(struct super_block *sb, |
57 | struct ext4_super_block *es); | 57 | struct ext4_super_block *es); |
@@ -62,9 +62,9 @@ static const char *ext4_decode_error(struct super_block *sb, int errno, | |||
62 | char nbuf[16]); | 62 | char nbuf[16]); |
63 | static int ext4_remount(struct super_block *sb, int *flags, char *data); | 63 | static int ext4_remount(struct super_block *sb, int *flags, char *data); |
64 | static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf); | 64 | static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf); |
65 | static void ext4_unlockfs(struct super_block *sb); | 65 | static int ext4_unfreeze(struct super_block *sb); |
66 | static void ext4_write_super(struct super_block *sb); | 66 | static void ext4_write_super(struct super_block *sb); |
67 | static void ext4_write_super_lockfs(struct super_block *sb); | 67 | static int ext4_freeze(struct super_block *sb); |
68 | 68 | ||
69 | 69 | ||
70 | ext4_fsblk_t ext4_block_bitmap(struct super_block *sb, | 70 | ext4_fsblk_t ext4_block_bitmap(struct super_block *sb, |
@@ -978,8 +978,8 @@ static const struct super_operations ext4_sops = { | |||
978 | .put_super = ext4_put_super, | 978 | .put_super = ext4_put_super, |
979 | .write_super = ext4_write_super, | 979 | .write_super = ext4_write_super, |
980 | .sync_fs = ext4_sync_fs, | 980 | .sync_fs = ext4_sync_fs, |
981 | .write_super_lockfs = ext4_write_super_lockfs, | 981 | .freeze_fs = ext4_freeze, |
982 | .unlockfs = ext4_unlockfs, | 982 | .unfreeze_fs = ext4_unfreeze, |
983 | .statfs = ext4_statfs, | 983 | .statfs = ext4_statfs, |
984 | .remount_fs = ext4_remount, | 984 | .remount_fs = ext4_remount, |
985 | .clear_inode = ext4_clear_inode, | 985 | .clear_inode = ext4_clear_inode, |
@@ -2888,13 +2888,14 @@ static int ext4_load_journal(struct super_block *sb, | |||
2888 | return 0; | 2888 | return 0; |
2889 | } | 2889 | } |
2890 | 2890 | ||
2891 | static void ext4_commit_super(struct super_block *sb, | 2891 | static int ext4_commit_super(struct super_block *sb, |
2892 | struct ext4_super_block *es, int sync) | 2892 | struct ext4_super_block *es, int sync) |
2893 | { | 2893 | { |
2894 | struct buffer_head *sbh = EXT4_SB(sb)->s_sbh; | 2894 | struct buffer_head *sbh = EXT4_SB(sb)->s_sbh; |
2895 | int error = 0; | ||
2895 | 2896 | ||
2896 | if (!sbh) | 2897 | if (!sbh) |
2897 | return; | 2898 | return error; |
2898 | if (buffer_write_io_error(sbh)) { | 2899 | if (buffer_write_io_error(sbh)) { |
2899 | /* | 2900 | /* |
2900 | * Oh, dear. A previous attempt to write the | 2901 | * Oh, dear. A previous attempt to write the |
@@ -2918,14 +2919,19 @@ static void ext4_commit_super(struct super_block *sb, | |||
2918 | BUFFER_TRACE(sbh, "marking dirty"); | 2919 | BUFFER_TRACE(sbh, "marking dirty"); |
2919 | mark_buffer_dirty(sbh); | 2920 | mark_buffer_dirty(sbh); |
2920 | if (sync) { | 2921 | if (sync) { |
2921 | sync_dirty_buffer(sbh); | 2922 | error = sync_dirty_buffer(sbh); |
2922 | if (buffer_write_io_error(sbh)) { | 2923 | if (error) |
2924 | return error; | ||
2925 | |||
2926 | error = buffer_write_io_error(sbh); | ||
2927 | if (error) { | ||
2923 | printk(KERN_ERR "EXT4-fs: I/O error while writing " | 2928 | printk(KERN_ERR "EXT4-fs: I/O error while writing " |
2924 | "superblock for %s.\n", sb->s_id); | 2929 | "superblock for %s.\n", sb->s_id); |
2925 | clear_buffer_write_io_error(sbh); | 2930 | clear_buffer_write_io_error(sbh); |
2926 | set_buffer_uptodate(sbh); | 2931 | set_buffer_uptodate(sbh); |
2927 | } | 2932 | } |
2928 | } | 2933 | } |
2934 | return error; | ||
2929 | } | 2935 | } |
2930 | 2936 | ||
2931 | 2937 | ||
@@ -3058,12 +3064,14 @@ static int ext4_sync_fs(struct super_block *sb, int wait) | |||
3058 | * LVM calls this function before a (read-only) snapshot is created. This | 3064 | * LVM calls this function before a (read-only) snapshot is created. This |
3059 | * gives us a chance to flush the journal completely and mark the fs clean. | 3065 | * gives us a chance to flush the journal completely and mark the fs clean. |
3060 | */ | 3066 | */ |
3061 | static void ext4_write_super_lockfs(struct super_block *sb) | 3067 | static int ext4_freeze(struct super_block *sb) |
3062 | { | 3068 | { |
3069 | int error = 0; | ||
3070 | journal_t *journal; | ||
3063 | sb->s_dirt = 0; | 3071 | sb->s_dirt = 0; |
3064 | 3072 | ||
3065 | if (!(sb->s_flags & MS_RDONLY)) { | 3073 | if (!(sb->s_flags & MS_RDONLY)) { |
3066 | journal_t *journal = EXT4_SB(sb)->s_journal; | 3074 | journal = EXT4_SB(sb)->s_journal; |
3067 | 3075 | ||
3068 | if (journal) { | 3076 | if (journal) { |
3069 | /* Now we set up the journal barrier. */ | 3077 | /* Now we set up the journal barrier. */ |
@@ -3073,21 +3081,29 @@ static void ext4_write_super_lockfs(struct super_block *sb) | |||
3073 | * We don't want to clear needs_recovery flag when we | 3081 | * We don't want to clear needs_recovery flag when we |
3074 | * failed to flush the journal. | 3082 | * failed to flush the journal. |
3075 | */ | 3083 | */ |
3076 | if (jbd2_journal_flush(journal) < 0) | 3084 | error = jbd2_journal_flush(journal); |
3077 | return; | 3085 | if (error < 0) |
3086 | goto out; | ||
3078 | } | 3087 | } |
3079 | 3088 | ||
3080 | /* Journal blocked and flushed, clear needs_recovery flag. */ | 3089 | /* Journal blocked and flushed, clear needs_recovery flag. */ |
3081 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 3090 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); |
3082 | ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1); | 3091 | ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1); |
3092 | error = ext4_commit_super(sb, EXT4_SB(sb)->s_es, 1); | ||
3093 | if (error) | ||
3094 | goto out; | ||
3083 | } | 3095 | } |
3096 | return 0; | ||
3097 | out: | ||
3098 | jbd2_journal_unlock_updates(journal); | ||
3099 | return error; | ||
3084 | } | 3100 | } |
3085 | 3101 | ||
3086 | /* | 3102 | /* |
3087 | * Called by LVM after the snapshot is done. We need to reset the RECOVER | 3103 | * Called by LVM after the snapshot is done. We need to reset the RECOVER |
3088 | * flag here, even though the filesystem is not technically dirty yet. | 3104 | * flag here, even though the filesystem is not technically dirty yet. |
3089 | */ | 3105 | */ |
3090 | static void ext4_unlockfs(struct super_block *sb) | 3106 | static int ext4_unfreeze(struct super_block *sb) |
3091 | { | 3107 | { |
3092 | if (EXT4_SB(sb)->s_journal && !(sb->s_flags & MS_RDONLY)) { | 3108 | if (EXT4_SB(sb)->s_journal && !(sb->s_flags & MS_RDONLY)) { |
3093 | lock_super(sb); | 3109 | lock_super(sb); |
@@ -3097,6 +3113,7 @@ static void ext4_unlockfs(struct super_block *sb) | |||
3097 | unlock_super(sb); | 3113 | unlock_super(sb); |
3098 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | 3114 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); |
3099 | } | 3115 | } |
3116 | return 0; | ||
3100 | } | 3117 | } |
3101 | 3118 | ||
3102 | static int ext4_remount(struct super_block *sb, int *flags, char *data) | 3119 | static int ext4_remount(struct super_block *sb, int *flags, char *data) |