diff options
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 190 |
1 files changed, 171 insertions, 19 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 3ce97b217cbe..9db64165123a 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -76,6 +76,9 @@ static const char *btrfs_decode_error(struct btrfs_fs_info *fs_info, int errno, | |||
76 | case -EROFS: | 76 | case -EROFS: |
77 | errstr = "Readonly filesystem"; | 77 | errstr = "Readonly filesystem"; |
78 | break; | 78 | break; |
79 | case -EEXIST: | ||
80 | errstr = "Object already exists"; | ||
81 | break; | ||
79 | default: | 82 | default: |
80 | if (nbuf) { | 83 | if (nbuf) { |
81 | if (snprintf(nbuf, 16, "error %d", -errno) >= 0) | 84 | if (snprintf(nbuf, 16, "error %d", -errno) >= 0) |
@@ -116,6 +119,8 @@ static void btrfs_handle_error(struct btrfs_fs_info *fs_info) | |||
116 | if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { | 119 | if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) { |
117 | sb->s_flags |= MS_RDONLY; | 120 | sb->s_flags |= MS_RDONLY; |
118 | 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); | ||
119 | } | 124 | } |
120 | } | 125 | } |
121 | 126 | ||
@@ -124,25 +129,132 @@ static void btrfs_handle_error(struct btrfs_fs_info *fs_info) | |||
124 | * invokes the approciate error response. | 129 | * invokes the approciate error response. |
125 | */ | 130 | */ |
126 | void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function, | 131 | void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function, |
127 | unsigned int line, int errno) | 132 | unsigned int line, int errno, const char *fmt, ...) |
128 | { | 133 | { |
129 | struct super_block *sb = fs_info->sb; | 134 | struct super_block *sb = fs_info->sb; |
130 | char nbuf[16]; | 135 | char nbuf[16]; |
131 | const char *errstr; | 136 | const char *errstr; |
137 | va_list args; | ||
138 | va_start(args, fmt); | ||
132 | 139 | ||
133 | /* | 140 | /* |
134 | * Special case: if the error is EROFS, and we're already | 141 | * Special case: if the error is EROFS, and we're already |
135 | * under MS_RDONLY, then it is safe here. | 142 | * under MS_RDONLY, then it is safe here. |
136 | */ | 143 | */ |
137 | if (errno == -EROFS && (sb->s_flags & MS_RDONLY)) | 144 | if (errno == -EROFS && (sb->s_flags & MS_RDONLY)) |
145 | return; | ||
146 | |||
147 | errstr = btrfs_decode_error(fs_info, errno, nbuf); | ||
148 | if (fmt) { | ||
149 | struct va_format vaf = { | ||
150 | .fmt = fmt, | ||
151 | .va = &args, | ||
152 | }; | ||
153 | |||
154 | printk(KERN_CRIT "BTRFS error (device %s) in %s:%d: %s (%pV)\n", | ||
155 | sb->s_id, function, line, errstr, &vaf); | ||
156 | } else { | ||
157 | printk(KERN_CRIT "BTRFS error (device %s) in %s:%d: %s\n", | ||
158 | sb->s_id, function, line, errstr); | ||
159 | } | ||
160 | |||
161 | /* Don't go through full error handling during mount */ | ||
162 | if (sb->s_flags & MS_BORN) { | ||
163 | save_error_info(fs_info); | ||
164 | btrfs_handle_error(fs_info); | ||
165 | } | ||
166 | va_end(args); | ||
167 | } | ||
168 | |||
169 | const char *logtypes[] = { | ||
170 | "emergency", | ||
171 | "alert", | ||
172 | "critical", | ||
173 | "error", | ||
174 | "warning", | ||
175 | "notice", | ||
176 | "info", | ||
177 | "debug", | ||
178 | }; | ||
179 | |||
180 | void btrfs_printk(struct btrfs_fs_info *fs_info, const char *fmt, ...) | ||
181 | { | ||
182 | struct super_block *sb = fs_info->sb; | ||
183 | char lvl[4]; | ||
184 | struct va_format vaf; | ||
185 | va_list args; | ||
186 | const char *type = logtypes[4]; | ||
187 | |||
188 | va_start(args, fmt); | ||
189 | |||
190 | if (fmt[0] == '<' && isdigit(fmt[1]) && fmt[2] == '>') { | ||
191 | strncpy(lvl, fmt, 3); | ||
192 | fmt += 3; | ||
193 | type = logtypes[fmt[1] - '0']; | ||
194 | } else | ||
195 | *lvl = '\0'; | ||
196 | |||
197 | vaf.fmt = fmt; | ||
198 | vaf.va = &args; | ||
199 | printk("%sBTRFS %s (device %s): %pV", lvl, type, sb->s_id, &vaf); | ||
200 | } | ||
201 | |||
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_ONCE(1, KERN_DEBUG "btrfs: Transaction aborted"); | ||
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"); | ||
138 | return; | 225 | return; |
226 | } | ||
227 | trans->transaction->aborted = errno; | ||
228 | __btrfs_std_error(root->fs_info, function, line, errno, NULL); | ||
229 | } | ||
230 | /* | ||
231 | * __btrfs_panic decodes unexpected, fatal errors from the caller, | ||
232 | * issues an alert, and either panics or BUGs, depending on mount options. | ||
233 | */ | ||
234 | void __btrfs_panic(struct btrfs_fs_info *fs_info, const char *function, | ||
235 | unsigned int line, int errno, const char *fmt, ...) | ||
236 | { | ||
237 | char nbuf[16]; | ||
238 | char *s_id = "<unknown>"; | ||
239 | const char *errstr; | ||
240 | struct va_format vaf = { .fmt = fmt }; | ||
241 | va_list args; | ||
139 | 242 | ||
140 | errstr = btrfs_decode_error(fs_info, errno, nbuf); | 243 | if (fs_info) |
141 | printk(KERN_CRIT "BTRFS error (device %s) in %s:%d: %s\n", | 244 | s_id = fs_info->sb->s_id; |
142 | sb->s_id, function, line, errstr); | 245 | |
143 | save_error_info(fs_info); | 246 | va_start(args, fmt); |
247 | vaf.va = &args; | ||
144 | 248 | ||
145 | btrfs_handle_error(fs_info); | 249 | errstr = btrfs_decode_error(fs_info, errno, nbuf); |
250 | if (fs_info->mount_opt & BTRFS_MOUNT_PANIC_ON_FATAL_ERROR) | ||
251 | panic(KERN_CRIT "BTRFS panic (device %s) in %s:%d: %pV (%s)\n", | ||
252 | s_id, function, line, &vaf, errstr); | ||
253 | |||
254 | printk(KERN_CRIT "BTRFS panic (device %s) in %s:%d: %pV (%s)\n", | ||
255 | s_id, function, line, &vaf, errstr); | ||
256 | va_end(args); | ||
257 | /* Caller calls BUG() */ | ||
146 | } | 258 | } |
147 | 259 | ||
148 | static void btrfs_put_super(struct super_block *sb) | 260 | static void btrfs_put_super(struct super_block *sb) |
@@ -166,7 +278,7 @@ enum { | |||
166 | Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, Opt_inode_cache, | 278 | Opt_enospc_debug, Opt_subvolrootid, Opt_defrag, Opt_inode_cache, |
167 | Opt_no_space_cache, Opt_recovery, Opt_skip_balance, | 279 | Opt_no_space_cache, Opt_recovery, Opt_skip_balance, |
168 | Opt_check_integrity, Opt_check_integrity_including_extent_data, | 280 | Opt_check_integrity, Opt_check_integrity_including_extent_data, |
169 | Opt_check_integrity_print_mask, | 281 | Opt_check_integrity_print_mask, Opt_fatal_errors, |
170 | Opt_err, | 282 | Opt_err, |
171 | }; | 283 | }; |
172 | 284 | ||
@@ -206,12 +318,14 @@ static match_table_t tokens = { | |||
206 | {Opt_check_integrity, "check_int"}, | 318 | {Opt_check_integrity, "check_int"}, |
207 | {Opt_check_integrity_including_extent_data, "check_int_data"}, | 319 | {Opt_check_integrity_including_extent_data, "check_int_data"}, |
208 | {Opt_check_integrity_print_mask, "check_int_print_mask=%d"}, | 320 | {Opt_check_integrity_print_mask, "check_int_print_mask=%d"}, |
321 | {Opt_fatal_errors, "fatal_errors=%s"}, | ||
209 | {Opt_err, NULL}, | 322 | {Opt_err, NULL}, |
210 | }; | 323 | }; |
211 | 324 | ||
212 | /* | 325 | /* |
213 | * Regular mount options parser. Everything that is needed only when | 326 | * Regular mount options parser. Everything that is needed only when |
214 | * 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. | ||
215 | */ | 329 | */ |
216 | int btrfs_parse_options(struct btrfs_root *root, char *options) | 330 | int btrfs_parse_options(struct btrfs_root *root, char *options) |
217 | { | 331 | { |
@@ -438,6 +552,18 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
438 | ret = -EINVAL; | 552 | ret = -EINVAL; |
439 | goto out; | 553 | goto out; |
440 | #endif | 554 | #endif |
555 | case Opt_fatal_errors: | ||
556 | if (strcmp(args[0].from, "panic") == 0) | ||
557 | btrfs_set_opt(info->mount_opt, | ||
558 | PANIC_ON_FATAL_ERROR); | ||
559 | else if (strcmp(args[0].from, "bug") == 0) | ||
560 | btrfs_clear_opt(info->mount_opt, | ||
561 | PANIC_ON_FATAL_ERROR); | ||
562 | else { | ||
563 | ret = -EINVAL; | ||
564 | goto out; | ||
565 | } | ||
566 | break; | ||
441 | case Opt_err: | 567 | case Opt_err: |
442 | printk(KERN_INFO "btrfs: unrecognized mount option " | 568 | printk(KERN_INFO "btrfs: unrecognized mount option " |
443 | "'%s'\n", p); | 569 | "'%s'\n", p); |
@@ -766,6 +892,8 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry) | |||
766 | seq_puts(seq, ",inode_cache"); | 892 | seq_puts(seq, ",inode_cache"); |
767 | if (btrfs_test_opt(root, SKIP_BALANCE)) | 893 | if (btrfs_test_opt(root, SKIP_BALANCE)) |
768 | seq_puts(seq, ",skip_balance"); | 894 | seq_puts(seq, ",skip_balance"); |
895 | if (btrfs_test_opt(root, PANIC_ON_FATAL_ERROR)) | ||
896 | seq_puts(seq, ",fatal_errors=panic"); | ||
769 | return 0; | 897 | return 0; |
770 | } | 898 | } |
771 | 899 | ||
@@ -999,11 +1127,20 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) | |||
999 | { | 1127 | { |
1000 | struct btrfs_fs_info *fs_info = btrfs_sb(sb); | 1128 | struct btrfs_fs_info *fs_info = btrfs_sb(sb); |
1001 | 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; | ||
1002 | int ret; | 1137 | int ret; |
1003 | 1138 | ||
1004 | ret = btrfs_parse_options(root, data); | 1139 | ret = btrfs_parse_options(root, data); |
1005 | if (ret) | 1140 | if (ret) { |
1006 | return -EINVAL; | 1141 | ret = -EINVAL; |
1142 | goto restore; | ||
1143 | } | ||
1007 | 1144 | ||
1008 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) | 1145 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) |
1009 | return 0; | 1146 | return 0; |
@@ -1011,26 +1148,44 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) | |||
1011 | if (*flags & MS_RDONLY) { | 1148 | if (*flags & MS_RDONLY) { |
1012 | sb->s_flags |= MS_RDONLY; | 1149 | sb->s_flags |= MS_RDONLY; |
1013 | 1150 | ||
1014 | ret = btrfs_commit_super(root); | 1151 | ret = btrfs_commit_super(root); |
1015 | WARN_ON(ret); | 1152 | if (ret) |
1153 | goto restore; | ||
1016 | } else { | 1154 | } else { |
1017 | if (fs_info->fs_devices->rw_devices == 0) | 1155 | if (fs_info->fs_devices->rw_devices == 0) |
1018 | return -EACCES; | 1156 | ret = -EACCES; |
1157 | goto restore; | ||
1019 | 1158 | ||
1020 | if (btrfs_super_log_root(fs_info->super_copy) != 0) | 1159 | if (btrfs_super_log_root(fs_info->super_copy) != 0) |
1021 | return -EINVAL; | 1160 | ret = -EINVAL; |
1161 | goto restore; | ||
1022 | 1162 | ||
1023 | ret = btrfs_cleanup_fs_roots(fs_info); | 1163 | ret = btrfs_cleanup_fs_roots(fs_info); |
1024 | WARN_ON(ret); | 1164 | if (ret) |
1165 | goto restore; | ||
1025 | 1166 | ||
1026 | /* recover relocation */ | 1167 | /* recover relocation */ |
1027 | ret = btrfs_recover_relocation(root); | 1168 | ret = btrfs_recover_relocation(root); |
1028 | WARN_ON(ret); | 1169 | if (ret) |
1170 | goto restore; | ||
1029 | 1171 | ||
1030 | sb->s_flags &= ~MS_RDONLY; | 1172 | sb->s_flags &= ~MS_RDONLY; |
1031 | } | 1173 | } |
1032 | 1174 | ||
1033 | 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; | ||
1034 | } | 1189 | } |
1035 | 1190 | ||
1036 | /* Used to sort the devices by max_avail(descending sort) */ | 1191 | /* Used to sort the devices by max_avail(descending sort) */ |
@@ -1360,9 +1515,7 @@ static int __init init_btrfs_fs(void) | |||
1360 | if (err) | 1515 | if (err) |
1361 | return err; | 1516 | return err; |
1362 | 1517 | ||
1363 | err = btrfs_init_compress(); | 1518 | btrfs_init_compress(); |
1364 | if (err) | ||
1365 | goto free_sysfs; | ||
1366 | 1519 | ||
1367 | err = btrfs_init_cachep(); | 1520 | err = btrfs_init_cachep(); |
1368 | if (err) | 1521 | if (err) |
@@ -1403,7 +1556,6 @@ free_cachep: | |||
1403 | btrfs_destroy_cachep(); | 1556 | btrfs_destroy_cachep(); |
1404 | free_compress: | 1557 | free_compress: |
1405 | btrfs_exit_compress(); | 1558 | btrfs_exit_compress(); |
1406 | free_sysfs: | ||
1407 | btrfs_exit_sysfs(); | 1559 | btrfs_exit_sysfs(); |
1408 | return err; | 1560 | return err; |
1409 | } | 1561 | } |