mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-01 06:33:07 +00:00
btrfs: store the error that turned the fs into error state
Currently when we turn the fs into an error state, typically after a transaction abort, we don't store the error anywhere, we just set a bit (BTRFS_FS_STATE_ERROR) at struct btrfs_fs_info::fs_state to signal the error state. There are cases where it would be useful to have access to the specific error in order to provide a more meaningful error to users/applications. This change adds a member to struct btrfs_fs_info to store the error and removes the BTRFS_FS_STATE_ERROR bit. When there's no error, the new member (fs_error) has a value of 0, otherwise its value is a negative errno value. Followup changes will make use of this new member. Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
1b6948acb8
commit
ae3364e521
3 changed files with 16 additions and 8 deletions
|
@ -3222,7 +3222,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
|
|||
|
||||
/* check FS state, whether FS is broken. */
|
||||
if (btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_ERROR)
|
||||
set_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state);
|
||||
WRITE_ONCE(fs_info->fs_error, -EUCLEAN);
|
||||
|
||||
/*
|
||||
* In the long term, we'll store the compression type in the super
|
||||
|
|
|
@ -46,8 +46,6 @@ static_assert(sizeof(struct btrfs_super_block) == BTRFS_SUPER_INFO_SIZE);
|
|||
* Runtime (in-memory) states of filesystem
|
||||
*/
|
||||
enum {
|
||||
/* Global indicator of serious filesystem errors */
|
||||
BTRFS_FS_STATE_ERROR,
|
||||
/*
|
||||
* Filesystem is being remounted, allow to skip some operations, like
|
||||
* defrag
|
||||
|
@ -686,6 +684,12 @@ struct btrfs_fs_info {
|
|||
bool qgroup_rescan_running;
|
||||
u8 qgroup_drop_subtree_thres;
|
||||
|
||||
/*
|
||||
* If this is not 0, then it indicates a serious filesystem error has
|
||||
* happened and it contains that error (negative errno value).
|
||||
*/
|
||||
int fs_error;
|
||||
|
||||
/* Filesystem state */
|
||||
unsigned long fs_state;
|
||||
|
||||
|
@ -962,8 +966,8 @@ static inline void btrfs_wake_unfinished_drop(struct btrfs_fs_info *fs_info)
|
|||
clear_and_wake_up_bit(BTRFS_FS_UNFINISHED_DROPS, &fs_info->flags);
|
||||
}
|
||||
|
||||
#define BTRFS_FS_ERROR(fs_info) (unlikely(test_bit(BTRFS_FS_STATE_ERROR, \
|
||||
&(fs_info)->fs_state)))
|
||||
#define BTRFS_FS_ERROR(fs_info) (READ_ONCE((fs_info)->fs_error))
|
||||
|
||||
#define BTRFS_FS_LOG_CLEANUP_ERROR(fs_info) \
|
||||
(unlikely(test_bit(BTRFS_FS_STATE_LOG_CLEANUP_ERROR, \
|
||||
&(fs_info)->fs_state)))
|
||||
|
|
|
@ -10,14 +10,13 @@
|
|||
#ifdef CONFIG_PRINTK
|
||||
|
||||
#define STATE_STRING_PREFACE ": state "
|
||||
#define STATE_STRING_BUF_LEN (sizeof(STATE_STRING_PREFACE) + BTRFS_FS_STATE_COUNT)
|
||||
#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_ERROR] = 'E',
|
||||
[BTRFS_FS_STATE_REMOUNTING] = 'M',
|
||||
[BTRFS_FS_STATE_RO] = 0,
|
||||
[BTRFS_FS_STATE_TRANS_ABORTED] = 'A',
|
||||
|
@ -37,6 +36,11 @@ static void btrfs_state_to_string(const struct btrfs_fs_info *info, char *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]) {
|
||||
|
@ -155,7 +159,7 @@ void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function
|
|||
* Today we only save the error info to memory. Long term we'll also
|
||||
* send it down to the disk.
|
||||
*/
|
||||
set_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state);
|
||||
WRITE_ONCE(fs_info->fs_error, errno);
|
||||
|
||||
/* Don't go through full error handling during mount. */
|
||||
if (!(sb->s_flags & SB_BORN))
|
||||
|
|
Loading…
Reference in a new issue