Skip to content

Commit c067da8

Browse files
sweetteakdave
authored andcommitted
btrfs: add filesystems state details to error messages
When a filesystem goes read-only due to an error, multiple errors tend to be reported, some of which are knock-on failures. Logging fs_states, in btrfs_handle_fs_error() and btrfs_printk() helps distinguish the first error from subsequent messages which may only exist due to an error state. Under the new format, most initial errors will look like: `BTRFS: error (device loop0) in ...` while subsequent errors will begin with: `error (device loop0: state E) in ...` An initial transaction abort error will look like `error (device loop0: state A) in ...` and subsequent messages will contain `(device loop0: state EA) in ...` In addition to the error states we can also print other states that are temporary, like remounting, device replace, or indicate a global state that may affect functionality. Now implemented: E - filesystem error detected A - transaction aborted L - log tree errors M - remounting in progress R - device replace in progress C - data checksums not verified (mounted with ignoredatacsums) Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent b2d9f2d commit c067da8

2 files changed

Lines changed: 62 additions & 8 deletions

File tree

fs/btrfs/ctree.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ enum {
149149

150150
/* Indicates there was an error cleaning up a log tree. */
151151
BTRFS_FS_STATE_LOG_CLEANUP_ERROR,
152+
153+
BTRFS_FS_STATE_COUNT
152154
};
153155

154156
#define BTRFS_BACKREF_REV_MAX 256

fs/btrfs/super.c

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,52 @@ static struct file_system_type btrfs_root_fs_type;
6666

6767
static int btrfs_remount(struct super_block *sb, int *flags, char *data);
6868

69+
#ifdef CONFIG_PRINTK
70+
71+
#define STATE_STRING_PREFACE ": state "
72+
#define STATE_STRING_BUF_LEN (sizeof(STATE_STRING_PREFACE) + BTRFS_FS_STATE_COUNT)
73+
74+
/*
75+
* Characters to print to indicate error conditions or uncommon filesystem sate.
76+
* RO is not an error.
77+
*/
78+
static const char fs_state_chars[] = {
79+
[BTRFS_FS_STATE_ERROR] = 'E',
80+
[BTRFS_FS_STATE_REMOUNTING] = 'M',
81+
[BTRFS_FS_STATE_RO] = 0,
82+
[BTRFS_FS_STATE_TRANS_ABORTED] = 'A',
83+
[BTRFS_FS_STATE_DEV_REPLACING] = 'R',
84+
[BTRFS_FS_STATE_DUMMY_FS_INFO] = 0,
85+
[BTRFS_FS_STATE_NO_CSUMS] = 'C',
86+
[BTRFS_FS_STATE_LOG_CLEANUP_ERROR] = 'L',
87+
};
88+
89+
static void btrfs_state_to_string(const struct btrfs_fs_info *info, char *buf)
90+
{
91+
unsigned int bit;
92+
bool states_printed = false;
93+
unsigned long fs_state = READ_ONCE(info->fs_state);
94+
char *curr = buf;
95+
96+
memcpy(curr, STATE_STRING_PREFACE, sizeof(STATE_STRING_PREFACE));
97+
curr += sizeof(STATE_STRING_PREFACE) - 1;
98+
99+
for_each_set_bit(bit, &fs_state, sizeof(fs_state)) {
100+
WARN_ON_ONCE(bit >= BTRFS_FS_STATE_COUNT);
101+
if ((bit < BTRFS_FS_STATE_COUNT) && fs_state_chars[bit]) {
102+
*curr++ = fs_state_chars[bit];
103+
states_printed = true;
104+
}
105+
}
106+
107+
/* If no states were printed, reset the buffer */
108+
if (!states_printed)
109+
curr = buf;
110+
111+
*curr++ = 0;
112+
}
113+
#endif
114+
69115
/*
70116
* Generally the error codes correspond to their respective errors, but there
71117
* are a few special cases.
@@ -128,6 +174,7 @@ void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function
128174
{
129175
struct super_block *sb = fs_info->sb;
130176
#ifdef CONFIG_PRINTK
177+
char statestr[STATE_STRING_BUF_LEN];
131178
const char *errstr;
132179
#endif
133180

@@ -140,6 +187,7 @@ void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function
140187

141188
#ifdef CONFIG_PRINTK
142189
errstr = btrfs_decode_error(errno);
190+
btrfs_state_to_string(fs_info, statestr);
143191
if (fmt) {
144192
struct va_format vaf;
145193
va_list args;
@@ -148,12 +196,12 @@ void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function
148196
vaf.fmt = fmt;
149197
vaf.va = &args;
150198

151-
pr_crit("BTRFS: error (device %s) in %s:%d: errno=%d %s (%pV)\n",
152-
sb->s_id, function, line, errno, errstr, &vaf);
199+
pr_crit("BTRFS: error (device %s%s) in %s:%d: errno=%d %s (%pV)\n",
200+
sb->s_id, statestr, function, line, errno, errstr, &vaf);
153201
va_end(args);
154202
} else {
155-
pr_crit("BTRFS: error (device %s) in %s:%d: errno=%d %s\n",
156-
sb->s_id, function, line, errno, errstr);
203+
pr_crit("BTRFS: error (device %s%s) in %s:%d: errno=%d %s\n",
204+
sb->s_id, statestr, function, line, errno, errstr);
157205
}
158206
#endif
159207

@@ -240,11 +288,15 @@ void __cold btrfs_printk(const struct btrfs_fs_info *fs_info, const char *fmt, .
240288
vaf.va = &args;
241289

242290
if (__ratelimit(ratelimit)) {
243-
if (fs_info)
244-
printk("%sBTRFS %s (device %s): %pV\n", lvl, type,
245-
fs_info->sb->s_id, &vaf);
246-
else
291+
if (fs_info) {
292+
char statestr[STATE_STRING_BUF_LEN];
293+
294+
btrfs_state_to_string(fs_info, statestr);
295+
printk("%sBTRFS %s (device %s%s): %pV\n", lvl, type,
296+
fs_info->sb->s_id, statestr, &vaf);
297+
} else {
247298
printk("%sBTRFS %s: %pV\n", lvl, type, &vaf);
299+
}
248300
}
249301

250302
va_end(args);

0 commit comments

Comments
 (0)