aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/super.c
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.com>2012-03-01 11:24:58 -0500
committerDavid Sterba <dsterba@suse.cz>2012-03-21 20:45:40 -0400
commit49b25e0540904be0bf558b84475c69d72e4de66e (patch)
tree5a89b2f5d6e5bd8b1ff39bdb387071ec1cb2a615 /fs/btrfs/super.c
parent4da35113426d16673aa1fb0613c14ca2e419e7fd (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.c74
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 */
215void __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 */
299int btrfs_parse_options(struct btrfs_root *root, char *options) 330int 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
1177restore:
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) */