diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2025-07-28 15:50:15 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2025-07-28 15:50:15 -0700 |
commit | 0965549d6f5f23e9250cd9c642f4ea5fd682eddb (patch) | |
tree | 554f0a7c94355afc2e401578ce060248b36d59fa | |
parent | 57fcb7d930d8f00f383e995aeebdcd2b416a187a (diff) | |
parent | d9c37a4904ec21ef7d45880fe023c11341869c28 (diff) |
Merge tag 'vfs-6.17-rc1.super' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
Pull superblock callback update from Christian Brauner:
"Currently all filesystems which implement super_operations::shutdown()
can not afford losing a device.
Thus fs_bdev_mark_dead() will just call the ->shutdown() callback for
the involved filesystem.
But it will no longer be the case, as multi-device filesystems like
btrfs can handle certain device loss without the need to shutdown the
whole filesystem.
To allow those multi-device filesystems to be integrated to use
fs_holder_ops:
- Add a new super_operations::remove_bdev() callback
- Try ->remove_bdev() callback first inside fs_bdev_mark_dead().
If the callback returned 0, meaning the fs can handling the device
loss, then exit without doing anything else.
If there is no such callback or the callback returned non-zero
value, continue to shutdown the filesystem as usual.
This means the new remove_bdev() should only do the check on whether
the operation can continue, and if so do the fs specific handlings.
The shutdown handling should still be handled by the existing
->shutdown() callback.
For all existing filesystems with shutdown callback, there is no
change to the code nor behavior.
Btrfs is going to implement both the ->remove_bdev() and ->shutdown()
callbacks soon"
* tag 'vfs-6.17-rc1.super' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
fs: add a new remove_bdev() callback
-rw-r--r-- | fs/super.c | 11 | ||||
-rw-r--r-- | include/linux/fs.h | 9 |
2 files changed, 20 insertions, 0 deletions
diff --git a/fs/super.c b/fs/super.c index 80418ca8e215..7f876f32343a 100644 --- a/fs/super.c +++ b/fs/super.c @@ -1459,6 +1459,17 @@ static void fs_bdev_mark_dead(struct block_device *bdev, bool surprise) if (!sb) return; + if (sb->s_op->remove_bdev) { + int ret; + + ret = sb->s_op->remove_bdev(sb, bdev); + if (!ret) { + super_unlock_shared(sb); + return; + } + /* Fallback to shutdown. */ + } + if (!surprise) sync_filesystem(sb); shrink_dcache_sb(sb); diff --git a/include/linux/fs.h b/include/linux/fs.h index 1f7aa7a14321..2ec4807d4ea8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2367,6 +2367,15 @@ struct super_operations { struct shrink_control *); long (*free_cached_objects)(struct super_block *, struct shrink_control *); + /* + * If a filesystem can support graceful removal of a device and + * continue read-write operations, implement this callback. + * + * Return 0 if the filesystem can continue read-write. + * Non-zero return value or no such callback means the fs will be shutdown + * as usual. + */ + int (*remove_bdev)(struct super_block *sb, struct block_device *bdev); void (*shutdown)(struct super_block *sb); }; |