| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- // SPDX-License-Identifier: GPL-2.0
- #include "fs.h"
- #include "messages.h"
- #include "discard.h"
- #include "super.h"
- #ifdef CONFIG_PRINTK
- #define STATE_STRING_PREFACE " state "
- #define STATE_STRING_BUF_LEN (sizeof(STATE_STRING_PREFACE) + BTRFS_FS_STATE_COUNT + 1)
- /*
- * Characters to print to indicate error conditions or uncommon filesystem state.
- * RO is not an error.
- */
- static const char fs_state_chars[] = {
- [BTRFS_FS_STATE_REMOUNTING] = 'M',
- [BTRFS_FS_STATE_RO] = 0,
- [BTRFS_FS_STATE_TRANS_ABORTED] = 'A',
- [BTRFS_FS_STATE_LOG_REPLAY_ABORTED] = 'O',
- [BTRFS_FS_STATE_DEV_REPLACING] = 'R',
- [BTRFS_FS_STATE_DUMMY_FS_INFO] = 0,
- [BTRFS_FS_STATE_NO_DATA_CSUMS] = 'C',
- [BTRFS_FS_STATE_SKIP_META_CSUMS] = 'S',
- [BTRFS_FS_STATE_LOG_CLEANUP_ERROR] = 'L',
- [BTRFS_FS_STATE_EMERGENCY_SHUTDOWN] = 'E',
- };
- static void btrfs_state_to_string(const struct btrfs_fs_info *info, char *buf)
- {
- unsigned int bit;
- bool states_printed = false;
- unsigned long fs_state = READ_ONCE(info->fs_state);
- char *curr = buf;
- memcpy(curr, STATE_STRING_PREFACE, sizeof(STATE_STRING_PREFACE));
- curr += sizeof(STATE_STRING_PREFACE) - 1;
- if (BTRFS_FS_ERROR(info)) {
- *curr++ = 'E';
- states_printed = true;
- }
- for_each_set_bit(bit, &fs_state, sizeof(fs_state)) {
- WARN_ON_ONCE(bit >= BTRFS_FS_STATE_COUNT);
- if ((bit < BTRFS_FS_STATE_COUNT) && fs_state_chars[bit]) {
- *curr++ = fs_state_chars[bit];
- states_printed = true;
- }
- }
- /* If no states were printed, reset the buffer */
- if (!states_printed)
- curr = buf;
- *curr++ = 0;
- }
- #endif
- /*
- * Generally the error codes correspond to their respective errors, but there
- * are a few special cases.
- *
- * EUCLEAN: Any sort of corruption that we encounter. The tree-checker for
- * instance will return EUCLEAN if any of the blocks are corrupted in
- * a way that is problematic. We want to reserve EUCLEAN for these
- * sort of corruptions.
- *
- * EROFS: If we check BTRFS_FS_STATE_ERROR and fail out with a return error, we
- * need to use EROFS for this case. We will have no idea of the
- * original failure, that will have been reported at the time we tripped
- * over the error. Each subsequent error that doesn't have any context
- * of the original error should use EROFS when handling BTRFS_FS_STATE_ERROR.
- */
- const char * __attribute_const__ btrfs_decode_error(int error)
- {
- char *errstr = "unknown";
- switch (error) {
- case -ENOENT: /* -2 */
- errstr = "No such entry";
- break;
- case -EIO: /* -5 */
- errstr = "IO failure";
- break;
- case -ENOMEM: /* -12*/
- errstr = "Out of memory";
- break;
- case -EEXIST: /* -17 */
- errstr = "Object already exists";
- break;
- case -ENOSPC: /* -28 */
- errstr = "No space left";
- break;
- case -EROFS: /* -30 */
- errstr = "Readonly filesystem";
- break;
- case -EOPNOTSUPP: /* -95 */
- errstr = "Operation not supported";
- break;
- case -EUCLEAN: /* -117 */
- errstr = "Filesystem corrupted";
- break;
- case -EDQUOT: /* -122 */
- errstr = "Quota exceeded";
- break;
- }
- return errstr;
- }
- /*
- * Decodes expected errors from the caller and invokes the appropriate error
- * response.
- */
- __cold
- void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function,
- unsigned int line, int error, const char *fmt, ...)
- {
- struct super_block *sb = fs_info->sb;
- #ifdef CONFIG_PRINTK
- char statestr[STATE_STRING_BUF_LEN];
- const char *errstr;
- #endif
- #ifdef CONFIG_PRINTK_INDEX
- printk_index_subsys_emit(
- "BTRFS: error (device %s%s) in %s:%d: errno=%d %s", KERN_CRIT, fmt);
- #endif
- /*
- * Special case: if the error is EROFS, and we're already under
- * SB_RDONLY, then it is safe here.
- */
- if (error == -EROFS && sb_rdonly(sb))
- return;
- #ifdef CONFIG_PRINTK
- errstr = btrfs_decode_error(error);
- btrfs_state_to_string(fs_info, statestr);
- if (fmt) {
- struct va_format vaf;
- va_list args;
- va_start(args, fmt);
- vaf.fmt = fmt;
- vaf.va = &args;
- pr_crit("BTRFS: error (device %s%s) in %s:%d: errno=%d %s (%pV)\n",
- sb->s_id, statestr, function, line, error, errstr, &vaf);
- va_end(args);
- } else {
- pr_crit("BTRFS: error (device %s%s) in %s:%d: errno=%d %s\n",
- sb->s_id, statestr, function, line, error, errstr);
- }
- #endif
- /*
- * Today we only save the error info to memory. Long term we'll also
- * send it down to the disk.
- */
- WRITE_ONCE(fs_info->fs_error, error);
- /* Don't go through full error handling during mount. */
- if (!(sb->s_flags & SB_BORN))
- return;
- if (sb_rdonly(sb))
- return;
- btrfs_discard_stop(fs_info);
- /* Handle error by forcing the filesystem readonly. */
- btrfs_set_sb_rdonly(sb);
- btrfs_info(fs_info, "forced readonly");
- /*
- * Note that a running device replace operation is not canceled here
- * although there is no way to update the progress. It would add the
- * risk of a deadlock, therefore the canceling is omitted. The only
- * penalty is that some I/O remains active until the procedure
- * completes. The next time when the filesystem is mounted writable
- * again, the device replace operation continues.
- */
- }
- #ifdef CONFIG_PRINTK
- static const char * const logtypes[] = {
- "emergency",
- "alert",
- "critical",
- "error",
- "warning",
- "notice",
- "info",
- "debug",
- };
- /*
- * Use one ratelimit state per log level so that a flood of less important
- * messages doesn't cause more important ones to be dropped.
- */
- static struct ratelimit_state printk_limits[] = {
- RATELIMIT_STATE_INIT(printk_limits[0], DEFAULT_RATELIMIT_INTERVAL, 100),
- RATELIMIT_STATE_INIT(printk_limits[1], DEFAULT_RATELIMIT_INTERVAL, 100),
- RATELIMIT_STATE_INIT(printk_limits[2], DEFAULT_RATELIMIT_INTERVAL, 100),
- RATELIMIT_STATE_INIT(printk_limits[3], DEFAULT_RATELIMIT_INTERVAL, 100),
- RATELIMIT_STATE_INIT(printk_limits[4], DEFAULT_RATELIMIT_INTERVAL, 100),
- RATELIMIT_STATE_INIT(printk_limits[5], DEFAULT_RATELIMIT_INTERVAL, 100),
- RATELIMIT_STATE_INIT(printk_limits[6], DEFAULT_RATELIMIT_INTERVAL, 100),
- RATELIMIT_STATE_INIT(printk_limits[7], DEFAULT_RATELIMIT_INTERVAL, 100),
- };
- __printf(3, 4) __cold
- void _btrfs_printk(const struct btrfs_fs_info *fs_info, unsigned int level, const char *fmt, ...)
- {
- struct va_format vaf;
- va_list args;
- const char *type = logtypes[level];
- struct ratelimit_state *ratelimit = &printk_limits[level];
- #ifdef CONFIG_PRINTK_INDEX
- printk_index_subsys_emit("%sBTRFS %s (device %s): ", NULL, fmt);
- #endif
- va_start(args, fmt);
- vaf.fmt = fmt;
- vaf.va = &args;
- /* Do not ratelimit if CONFIG_BTRFS_DEBUG is enabled. */
- if (IS_ENABLED(CONFIG_BTRFS_DEBUG) || __ratelimit(ratelimit)) {
- if (fs_info) {
- char statestr[STATE_STRING_BUF_LEN];
- btrfs_state_to_string(fs_info, statestr);
- _printk(KERN_SOH "%dBTRFS %s (device %s%s): %pV\n", level, type,
- fs_info->sb->s_id, statestr, &vaf);
- } else {
- _printk(KERN_SOH "%dBTRFS %s: %pV\n", level, type, &vaf);
- }
- }
- va_end(args);
- }
- #endif
- #if BITS_PER_LONG == 32
- void __cold btrfs_warn_32bit_limit(struct btrfs_fs_info *fs_info)
- {
- if (!test_and_set_bit(BTRFS_FS_32BIT_WARN, &fs_info->flags)) {
- btrfs_warn(fs_info, "reaching 32bit limit for logical addresses");
- btrfs_warn(fs_info,
- "due to page cache limit on 32bit systems, btrfs can't access metadata at or beyond %lluT",
- BTRFS_32BIT_MAX_FILE_SIZE >> 40);
- btrfs_warn(fs_info,
- "please consider upgrading to 64bit kernel/hardware");
- }
- }
- void __cold btrfs_err_32bit_limit(struct btrfs_fs_info *fs_info)
- {
- if (!test_and_set_bit(BTRFS_FS_32BIT_ERROR, &fs_info->flags)) {
- btrfs_err(fs_info, "reached 32bit limit for logical addresses");
- btrfs_err(fs_info,
- "due to page cache limit on 32bit systems, metadata beyond %lluT can't be accessed",
- BTRFS_32BIT_MAX_FILE_SIZE >> 40);
- btrfs_err(fs_info,
- "please consider upgrading to 64bit kernel/hardware");
- }
- }
- #endif
- /*
- * Decode unexpected, fatal errors from the caller, issue an alert, and either
- * panic or BUGs, depending on mount options.
- */
- __cold
- void __btrfs_panic(const struct btrfs_fs_info *fs_info, const char *function,
- unsigned int line, int error, const char *fmt, ...)
- {
- char *s_id = "<unknown>";
- const char *errstr;
- struct va_format vaf = { .fmt = fmt };
- va_list args;
- if (fs_info)
- s_id = fs_info->sb->s_id;
- va_start(args, fmt);
- vaf.va = &args;
- errstr = btrfs_decode_error(error);
- if (fs_info && (btrfs_test_opt(fs_info, PANIC_ON_FATAL_ERROR)))
- panic(KERN_CRIT "BTRFS panic (device %s) in %s:%d: %pV (errno=%d %s)\n",
- s_id, function, line, &vaf, error, errstr);
- btrfs_crit(fs_info, "panic in %s:%d: %pV (errno=%d %s)",
- function, line, &vaf, error, errstr);
- va_end(args);
- /* Caller calls BUG() */
- }
|