This is btrfs' equivalent of XFS_IOC_GOINGDOWN or EXT4_IOC_SHUTDOWN, after entering the emergency shutdown state, all operations will return error (-EIO), and can not be bring back to normal state until unmount. We reuse the existing btrfs_handle_fs_error() function, which will mark the fs read-only and output an error message. This allows us to handle put_super() callback as usual, as the fs is already marked as error and RO, thus we need no special handling. The only extra thing is to set the EMERGENCY_SHUTDOWN flag to reject future operations with -EIO. Signed-off-by: Qu Wenruo <wqu@xxxxxxxx> --- fs/btrfs/fs.h | 18 ++++++++++++++++++ fs/btrfs/messages.c | 1 + 2 files changed, 19 insertions(+) diff --git a/fs/btrfs/fs.h b/fs/btrfs/fs.h index d90304d4e32c..8cc4468a9894 100644 --- a/fs/btrfs/fs.h +++ b/fs/btrfs/fs.h @@ -29,6 +29,7 @@ #include "extent-io-tree.h" #include "async-thread.h" #include "block-rsv.h" +#include "messages.h" struct inode; struct super_block; @@ -120,6 +121,12 @@ enum { /* No more delayed iput can be queued. */ BTRFS_FS_STATE_NO_DELAYED_IPUT, + /* + * Emergency shutdown, a step further than trans aborted by rejecting + * all operations. + */ + BTRFS_FS_STATE_EMERGENCY_SHUTDOWN, + BTRFS_FS_STATE_COUNT }; @@ -1100,6 +1107,17 @@ static inline void btrfs_wake_unfinished_drop(struct btrfs_fs_info *fs_info) (unlikely(test_bit(BTRFS_FS_STATE_LOG_CLEANUP_ERROR, \ &(fs_info)->fs_state))) +static inline bool btrfs_is_shutdown(struct btrfs_fs_info *fs_info) +{ + return test_bit(BTRFS_FS_STATE_EMERGENCY_SHUTDOWN, &fs_info->fs_state); +} + +static inline void btrfs_shutdown(struct btrfs_fs_info *fs_info) +{ + btrfs_handle_fs_error(fs_info, -EIO, "filesystem emergency shutdown"); + set_bit(BTRFS_FS_STATE_EMERGENCY_SHUTDOWN, &fs_info->fs_state); +} + /* * We use folio flag owner_2 to indicate there is an ordered extent with * unfinished IO. diff --git a/fs/btrfs/messages.c b/fs/btrfs/messages.c index 363fd28c0268..2bb4bcb7c2cd 100644 --- a/fs/btrfs/messages.c +++ b/fs/btrfs/messages.c @@ -23,6 +23,7 @@ static const char fs_state_chars[] = { [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) -- 2.49.0