mirror of
https://github.com/torvalds/linux.git
synced 2026-09-26 01:52:03 +02:00
erofs: open via dedicated fs bdev helpers
Route opens through fs_bdev_file_open_by_path() so each external device
is registered against the correct superblock, and convert the matching
releases.
Gao Xiang: I think typical immutable filesystems don't need .shutdown()
and .remove_bdev() for the following reasons:
- blk_mark_disk_dead() sets GD_DEAD in advance of fs_bdev_mark_dead()
so that the following bios will fail immediately; block_device
references are still valid so it seems overkill to handle dead
blockdevs in the deep filesystem I/O submission path.
- Immutable filesystems like EROFS don't have write paths and journals,
so they don't need to block writes (i.e., new dirty pages), metadata
changes, and abort journals.
- The comment above loop_change_fd() documents a valid read-only use
case we need to support anyway, but it calls disk_force_media_change()
which will call fs_bdev_mark_dead() later: we don't want loop_change_fd()
shutdowns the active filesystems and return -EIO unconditionally.
Currently I think the default behavior (shrink_dcache_sb + evict_inodes)
in fs_bdev_mark_dead() is enough for immutable filesystems, tried to
document in the commit here for later reference.
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Link: https://patch.msgid.link/20260616-work-super-bdev_holder_global-v2-14-7df6b864028e@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
This commit is contained in:
parent
7a7ef107b4
commit
69139a62a9
|
|
@ -147,8 +147,8 @@ static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb,
|
|||
if (!sbi->devs->flatdev) {
|
||||
file = erofs_is_fileio_mode(sbi) ?
|
||||
filp_open(dif->path, O_RDONLY | O_LARGEFILE, 0) :
|
||||
bdev_file_open_by_path(dif->path,
|
||||
BLK_OPEN_READ, sb->s_type, NULL);
|
||||
fs_bdev_file_open_by_path(dif->path,
|
||||
BLK_OPEN_READ, sb->s_type, sb);
|
||||
if (IS_ERR(file)) {
|
||||
if (file == ERR_PTR(-ENOTBLK))
|
||||
return -EINVAL;
|
||||
|
|
@ -799,28 +799,34 @@ static int erofs_fc_reconfigure(struct fs_context *fc)
|
|||
|
||||
static int erofs_release_device_info(int id, void *ptr, void *data)
|
||||
{
|
||||
struct super_block *sb = data;
|
||||
struct erofs_device_info *dif = ptr;
|
||||
|
||||
fs_put_dax(dif->dax_dev, NULL);
|
||||
if (dif->file)
|
||||
fput(dif->file);
|
||||
if (dif->file) {
|
||||
if (S_ISBLK(file_inode(dif->file)->i_mode))
|
||||
fs_bdev_file_release(dif->file, sb);
|
||||
else
|
||||
fput(dif->file);
|
||||
}
|
||||
kfree(dif->path);
|
||||
kfree(dif);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void erofs_free_dev_context(struct erofs_dev_context *devs)
|
||||
static void erofs_free_dev_context(struct erofs_dev_context *devs,
|
||||
struct super_block *sb)
|
||||
{
|
||||
if (!devs)
|
||||
return;
|
||||
idr_for_each(&devs->tree, &erofs_release_device_info, NULL);
|
||||
idr_for_each(&devs->tree, &erofs_release_device_info, sb);
|
||||
idr_destroy(&devs->tree);
|
||||
kfree(devs);
|
||||
}
|
||||
|
||||
static void erofs_sb_free(struct erofs_sb_info *sbi)
|
||||
static void erofs_sb_free(struct erofs_sb_info *sbi, struct super_block *sb)
|
||||
{
|
||||
erofs_free_dev_context(sbi->devs);
|
||||
erofs_free_dev_context(sbi->devs, sb);
|
||||
kfree_sensitive(sbi->domain_id);
|
||||
if (sbi->dif0.file)
|
||||
fput(sbi->dif0.file);
|
||||
|
|
@ -832,8 +838,13 @@ static void erofs_fc_free(struct fs_context *fc)
|
|||
{
|
||||
struct erofs_sb_info *sbi = fc->s_fs_info;
|
||||
|
||||
if (sbi) /* free here if an error occurs before transferring to sb */
|
||||
erofs_sb_free(sbi);
|
||||
/*
|
||||
* Freed here only if an error occurs before the sb is set up; at that
|
||||
* point no block-backed device has been claimed (that happens in
|
||||
* fill_super), so the NULL sb never reaches fs_bdev_file_release().
|
||||
*/
|
||||
if (sbi)
|
||||
erofs_sb_free(sbi, NULL);
|
||||
}
|
||||
|
||||
static const struct fs_context_operations erofs_context_ops = {
|
||||
|
|
@ -887,7 +898,7 @@ static void erofs_kill_sb(struct super_block *sb)
|
|||
kill_block_super(sb);
|
||||
erofs_drop_internal_inodes(sbi);
|
||||
fs_put_dax(sbi->dif0.dax_dev, NULL);
|
||||
erofs_sb_free(sbi);
|
||||
erofs_sb_free(sbi, sb);
|
||||
sb->s_fs_info = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -899,7 +910,7 @@ static void erofs_put_super(struct super_block *sb)
|
|||
erofs_shrinker_unregister(sb);
|
||||
erofs_xattr_prefixes_cleanup(sb);
|
||||
erofs_drop_internal_inodes(sbi);
|
||||
erofs_free_dev_context(sbi->devs);
|
||||
erofs_free_dev_context(sbi->devs, sb);
|
||||
sbi->devs = NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user