diff options
author | Jeff Mahoney <jeffm@suse.com> | 2012-03-01 11:24:58 -0500 |
---|---|---|
committer | David Sterba <dsterba@suse.cz> | 2012-03-21 20:45:40 -0400 |
commit | 49b25e0540904be0bf558b84475c69d72e4de66e (patch) | |
tree | 5a89b2f5d6e5bd8b1ff39bdb387071ec1cb2a615 /fs/btrfs/super.c | |
parent | 4da35113426d16673aa1fb0613c14ca2e419e7fd (diff) |
btrfs: enhance transaction abort infrastructure
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 74 |
1 files changed, 66 insertions, 8 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 7fe69eef7607..0517bd70b04c 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -119,6 +119,8 @@ static void btrfs_handle_error(struct btrfs_fs_info *fs_info) | |||
119 | if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { | 119 | if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { |
120 | sb->s_flags |= MS_RDONLY; | 120 | sb->s_flags |= MS_RDONLY; |
121 | printk(KERN_INFO "btrfs is forced readonly\n"); | 121 | printk(KERN_INFO "btrfs is forced readonly\n"); |
122 | __btrfs_scrub_cancel(fs_info); | ||
123 | // WARN_ON(1); | ||
122 | } | 124 | } |
123 | } | 125 | } |
124 | 126 | ||
@@ -198,6 +200,34 @@ void btrfs_printk(struct btrfs_fs_info *fs_info, const char *fmt, ...) | |||
198 | } | 200 | } |
199 | 201 | ||
200 | /* | 202 | /* |
203 | * We only mark the transaction aborted and then set the file system read-only. | ||
204 | * This will prevent new transactions from starting or trying to join this | ||
205 | * one. | ||
206 | * | ||
207 | * This means that error recovery at the call site is limited to freeing | ||
208 | * any local memory allocations and passing the error code up without | ||
209 | * further cleanup. The transaction should complete as it normally would | ||
210 | * in the call path but will return -EIO. | ||
211 | * | ||
212 | * We'll complete the cleanup in btrfs_end_transaction and | ||
213 | * btrfs_commit_transaction. | ||
214 | */ | ||
215 | void __btrfs_abort_transaction(struct btrfs_trans_handle *trans, | ||
216 | struct btrfs_root *root, const char *function, | ||
217 | unsigned int line, int errno) | ||
218 | { | ||
219 | WARN_ON_ONCE(1); | ||
220 | trans->aborted = errno; | ||
221 | /* Nothing used. The other threads that have joined this | ||
222 | * transaction may be able to continue. */ | ||
223 | if (!trans->blocks_used) { | ||
224 | btrfs_printk(root->fs_info, "Aborting unused transaction.\n"); | ||
225 | return; | ||
226 | } | ||
227 | trans->transaction->aborted = errno; | ||
228 | __btrfs_std_error(root->fs_info, function, line, errno, NULL); | ||
229 | } | ||
230 | /* | ||
201 | * __btrfs_panic decodes unexpected, fatal errors from the caller, | 231 | * __btrfs_panic decodes unexpected, fatal errors from the caller, |
202 | * issues an alert, and either panics or BUGs, depending on mount options. | 232 | * issues an alert, and either panics or BUGs, depending on mount options. |
203 | */ | 233 | */ |
@@ -295,6 +325,7 @@ static match_table_t tokens = { | |||
295 | /* | 325 | /* |
296 | * Regular mount options parser. Everything that is needed only when | 326 | * Regular mount options parser. Everything that is needed only when |
297 | * reading in a new superblock is parsed here. | 327 | * reading in a new superblock is parsed here. |
328 | * XXX JDM: This needs to be cleaned up for remount. | ||
298 | */ | 329 | */ |
299 | int btrfs_parse_options(struct btrfs_root *root, char *options) | 330 | int btrfs_parse_options(struct btrfs_root *root, char *options) |
300 | { | 331 | { |
@@ -1096,11 +1127,20 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) | |||
1096 | { | 1127 | { |
1097 | struct btrfs_fs_info *fs_info = btrfs_sb(sb); | 1128 | struct btrfs_fs_info *fs_info = btrfs_sb(sb); |
1098 | struct btrfs_root *root = fs_info->tree_root; | 1129 | struct btrfs_root *root = fs_info->tree_root; |
1130 | unsigned old_flags = sb->s_flags; | ||
1131 | unsigned long old_opts = fs_info->mount_opt; | ||
1132 | unsigned long old_compress_type = fs_info->compress_type; | ||
1133 | u64 old_max_inline = fs_info->max_inline; | ||
1134 | u64 old_alloc_start = fs_info->alloc_start; | ||
1135 | int old_thread_pool_size = fs_info->thread_pool_size; | ||
1136 | unsigned int old_metadata_ratio = fs_info->metadata_ratio; | ||
1099 | int ret; | 1137 | int ret; |
1100 | 1138 | ||
1101 | ret = btrfs_parse_options(root, data); | 1139 | ret = btrfs_parse_options(root, data); |
1102 | if (ret) | 1140 | if (ret) { |
1103 | return -EINVAL; | 1141 | ret = -EINVAL; |
1142 | goto restore; | ||
1143 | } | ||
1104 | 1144 | ||
1105 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) | 1145 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) |
1106 | return 0; | 1146 | return 0; |
@@ -1108,26 +1148,44 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) | |||
1108 | if (*flags & MS_RDONLY) { | 1148 | if (*flags & MS_RDONLY) { |
1109 | sb->s_flags |= MS_RDONLY; | 1149 | sb->s_flags |= MS_RDONLY; |
1110 | 1150 | ||
1111 | ret = btrfs_commit_super(root); | 1151 | ret = btrfs_commit_super(root); |
1112 | WARN_ON(ret); | 1152 | if (ret) |
1153 | goto restore; | ||
1113 | } else { | 1154 | } else { |
1114 | if (fs_info->fs_devices->rw_devices == 0) | 1155 | if (fs_info->fs_devices->rw_devices == 0) |
1115 | return -EACCES; | 1156 | ret = -EACCES; |
1157 | goto restore; | ||
1116 | 1158 | ||
1117 | if (btrfs_super_log_root(fs_info->super_copy) != 0) | 1159 | if (btrfs_super_log_root(fs_info->super_copy) != 0) |
1118 | return -EINVAL; | 1160 | ret = -EINVAL; |
1161 | goto restore; | ||
1119 | 1162 | ||
1120 | ret = btrfs_cleanup_fs_roots(fs_info); | 1163 | ret = btrfs_cleanup_fs_roots(fs_info); |
1121 | WARN_ON(ret); | 1164 | if (ret) |
1165 | goto restore; | ||
1122 | 1166 | ||
1123 | /* recover relocation */ | 1167 | /* recover relocation */ |
1124 | ret = btrfs_recover_relocation(root); | 1168 | ret = btrfs_recover_relocation(root); |
1125 | WARN_ON(ret); | 1169 | if (ret) |
1170 | goto restore; | ||
1126 | 1171 | ||
1127 | sb->s_flags &= ~MS_RDONLY; | 1172 | sb->s_flags &= ~MS_RDONLY; |
1128 | } | 1173 | } |
1129 | 1174 | ||
1130 | return 0; | 1175 | return 0; |
1176 | |||
1177 | restore: | ||
1178 | /* We've hit an error - don't reset MS_RDONLY */ | ||
1179 | if (sb->s_flags & MS_RDONLY) | ||
1180 | old_flags |= MS_RDONLY; | ||
1181 | sb->s_flags = old_flags; | ||
1182 | fs_info->mount_opt = old_opts; | ||
1183 | fs_info->compress_type = old_compress_type; | ||
1184 | fs_info->max_inline = old_max_inline; | ||
1185 | fs_info->alloc_start = old_alloc_start; | ||
1186 | fs_info->thread_pool_size = old_thread_pool_size; | ||
1187 | fs_info->metadata_ratio = old_metadata_ratio; | ||
1188 | return ret; | ||
1131 | } | 1189 | } |
1132 | 1190 | ||
1133 | /* Used to sort the devices by max_avail(descending sort) */ | 1191 | /* Used to sort the devices by max_avail(descending sort) */ |