mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08: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
@ -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. */
|
/* check FS state, whether FS is broken. */
|
||||||
if (btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_ERROR)
|
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
|
* 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
|
* Runtime (in-memory) states of filesystem
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
/* Global indicator of serious filesystem errors */
|
|
||||||
BTRFS_FS_STATE_ERROR,
|
|
||||||
/*
|
/*
|
||||||
* Filesystem is being remounted, allow to skip some operations, like
|
* Filesystem is being remounted, allow to skip some operations, like
|
||||||
* defrag
|
* defrag
|
||||||
@ -686,6 +684,12 @@ struct btrfs_fs_info {
|
|||||||
bool qgroup_rescan_running;
|
bool qgroup_rescan_running;
|
||||||
u8 qgroup_drop_subtree_thres;
|
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 */
|
/* Filesystem state */
|
||||||
unsigned long fs_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);
|
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, \
|
#define BTRFS_FS_ERROR(fs_info) (READ_ONCE((fs_info)->fs_error))
|
||||||
&(fs_info)->fs_state)))
|
|
||||||
#define BTRFS_FS_LOG_CLEANUP_ERROR(fs_info) \
|
#define BTRFS_FS_LOG_CLEANUP_ERROR(fs_info) \
|
||||||
(unlikely(test_bit(BTRFS_FS_STATE_LOG_CLEANUP_ERROR, \
|
(unlikely(test_bit(BTRFS_FS_STATE_LOG_CLEANUP_ERROR, \
|
||||||
&(fs_info)->fs_state)))
|
&(fs_info)->fs_state)))
|
||||||
|
@ -10,14 +10,13 @@
|
|||||||
#ifdef CONFIG_PRINTK
|
#ifdef CONFIG_PRINTK
|
||||||
|
|
||||||
#define STATE_STRING_PREFACE ": state "
|
#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.
|
* Characters to print to indicate error conditions or uncommon filesystem state.
|
||||||
* RO is not an error.
|
* RO is not an error.
|
||||||
*/
|
*/
|
||||||
static const char fs_state_chars[] = {
|
static const char fs_state_chars[] = {
|
||||||
[BTRFS_FS_STATE_ERROR] = 'E',
|
|
||||||
[BTRFS_FS_STATE_REMOUNTING] = 'M',
|
[BTRFS_FS_STATE_REMOUNTING] = 'M',
|
||||||
[BTRFS_FS_STATE_RO] = 0,
|
[BTRFS_FS_STATE_RO] = 0,
|
||||||
[BTRFS_FS_STATE_TRANS_ABORTED] = 'A',
|
[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));
|
memcpy(curr, STATE_STRING_PREFACE, sizeof(STATE_STRING_PREFACE));
|
||||||
curr += sizeof(STATE_STRING_PREFACE) - 1;
|
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)) {
|
for_each_set_bit(bit, &fs_state, sizeof(fs_state)) {
|
||||||
WARN_ON_ONCE(bit >= BTRFS_FS_STATE_COUNT);
|
WARN_ON_ONCE(bit >= BTRFS_FS_STATE_COUNT);
|
||||||
if ((bit < BTRFS_FS_STATE_COUNT) && fs_state_chars[bit]) {
|
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
|
* Today we only save the error info to memory. Long term we'll also
|
||||||
* send it down to the disk.
|
* 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. */
|
/* Don't go through full error handling during mount. */
|
||||||
if (!(sb->s_flags & SB_BORN))
|
if (!(sb->s_flags & SB_BORN))
|
||||||
|
Loading…
Reference in New Issue
Block a user