Merge branch 'vfs-7.3.super' into vfs.all

This commit is contained in:
Christian Brauner
2026-07-31 12:59:51 +02:00
27 changed files with 880 additions and 304 deletions
+99 -26
View File
@@ -304,7 +304,12 @@ int bdev_freeze(struct block_device *bdev)
mutex_lock(&bdev->bd_fsfreeze_mutex);
if (atomic_inc_return(&bdev->bd_fsfreeze_count) > 1) {
/* A device being removed from its filesystem refuses freezes. */
if (!atomic_inc_unless_negative(&bdev->bd_fsfreeze_count)) {
mutex_unlock(&bdev->bd_fsfreeze_mutex);
return -EBUSY;
}
if (atomic_read(&bdev->bd_fsfreeze_count) > 1) {
mutex_unlock(&bdev->bd_fsfreeze_mutex);
return 0;
}
@@ -340,18 +345,18 @@ int bdev_thaw(struct block_device *bdev)
mutex_lock(&bdev->bd_fsfreeze_mutex);
/*
* If this returns < 0 it means that @bd_fsfreeze_count was
* already 0 and no decrement was performed.
*/
nr_freeze = atomic_dec_if_positive(&bdev->bd_fsfreeze_count);
if (nr_freeze < 0)
/* <= 0: not frozen (0) or a freeze deny is held (< 0); leave it. */
nr_freeze = atomic_read(&bdev->bd_fsfreeze_count);
if (nr_freeze <= 0)
goto out;
error = 0;
if (nr_freeze > 0)
if (nr_freeze > 1) {
atomic_dec(&bdev->bd_fsfreeze_count);
goto out;
}
/* Keep the count positive across the thaw so a deny is refused. */
mutex_lock(&bdev->bd_holder_lock);
if (bdev->bd_holder_ops && bdev->bd_holder_ops->thaw) {
error = bdev->bd_holder_ops->thaw(bdev);
@@ -360,14 +365,52 @@ int bdev_thaw(struct block_device *bdev)
mutex_unlock(&bdev->bd_holder_lock);
}
if (error)
atomic_inc(&bdev->bd_fsfreeze_count);
if (!error)
atomic_dec(&bdev->bd_fsfreeze_count);
out:
mutex_unlock(&bdev->bd_fsfreeze_mutex);
return error;
}
EXPORT_SYMBOL(bdev_thaw);
/**
* bdev_deny_freeze - make a block device unfreezable
* @bdev: block device
*
* Reserve @bdev against bdev_freeze() the way deny_write_access() reserves a
* file against writers. bd_fsfreeze_count is sign-encoded: > 0 counts active
* freezes, < 0 counts deniers, so a deny succeeds only while no freeze is in
* progress. While held, bdev_freeze() returns -EBUSY. Pair with
* bdev_allow_freeze().
*
* A filesystem removing, adding or replacing a member device denies freezes on
* it for the duration, so a claim a freeze walk might act on is never torn down
* behind the freezer's back. The deny is device-scoped, not (device,
* superblock)-scoped: a device shared by several superblocks is refused for all
* of them. No in-tree filesystem removes a shared claim from a live superblock.
*
* Return: 0, or -EBUSY if the device is currently frozen.
*/
int bdev_deny_freeze(struct block_device *bdev)
{
return atomic_dec_unless_positive(&bdev->bd_fsfreeze_count) ? 0 : -EBUSY;
}
EXPORT_SYMBOL_GPL(bdev_deny_freeze);
/**
* bdev_allow_freeze - allow freezing a block device again
* @bdev: block device
*
* Undo one bdev_deny_freeze().
*/
void bdev_allow_freeze(struct block_device *bdev)
{
/* A deny must be held, i.e. the count must be negative. */
WARN_ON_ONCE(atomic_read(&bdev->bd_fsfreeze_count) >= 0);
atomic_inc(&bdev->bd_fsfreeze_count);
}
EXPORT_SYMBOL_GPL(bdev_allow_freeze);
/*
* pseudo-fs
*/
@@ -1152,6 +1195,39 @@ put_no_open:
blkdev_put_no_open(bdev);
}
/**
* bdev_yield_claim - give up the holder claim on an open block device
* @bdev_file: open block device
*
* Yield the holder and any write access for @bdev_file without closing it, so
* the caller can still act on the device - e.g. bdev_allow_freeze() it - before
* the final bdev_fput(). bdev_fput() yields too, so calling it afterwards is
* safe.
*/
void bdev_yield_claim(struct file *bdev_file)
{
struct block_device *bdev;
struct gendisk *disk;
if (!bdev_file->private_data)
return;
bdev = file_bdev(bdev_file);
disk = bdev->bd_disk;
mutex_lock(&disk->open_mutex);
bdev_yield_write_access(bdev_file);
bd_yield_claim(bdev_file);
/*
* Tell release we already gave up our hold on the
* device and if write restrictions are available that
* we already gave up write access to the device.
*/
bdev_file->private_data = BDEV_I(bdev_file->f_mapping->host);
mutex_unlock(&disk->open_mutex);
}
EXPORT_SYMBOL_GPL(bdev_yield_claim);
/**
* bdev_fput - yield claim to the block device and put the file
* @bdev_file: open block device
@@ -1165,22 +1241,7 @@ void bdev_fput(struct file *bdev_file)
if (WARN_ON_ONCE(bdev_file->f_op != &def_blk_fops))
return;
if (bdev_file->private_data) {
struct block_device *bdev = file_bdev(bdev_file);
struct gendisk *disk = bdev->bd_disk;
mutex_lock(&disk->open_mutex);
bdev_yield_write_access(bdev_file);
bd_yield_claim(bdev_file);
/*
* Tell release we already gave up our hold on the
* device and if write restrictions are available that
* we already gave up write access to the device.
*/
bdev_file->private_data = BDEV_I(bdev_file->f_mapping->host);
mutex_unlock(&disk->open_mutex);
}
bdev_yield_claim(bdev_file);
fput(bdev_file);
}
EXPORT_SYMBOL(bdev_fput);
@@ -1217,6 +1278,18 @@ int lookup_bdev(const char *pathname, dev_t *dev)
if (!may_open_dev(&path))
goto out_path_put;
/*
* Reject a block device inode with i_rdev == 0. A dev_t of 0 is
* never valid for a block device: no real block device driver
* registers major 0. Fake block device inodes (e.g. fuse with
* rootmode=S_IFBLK) can expose i_rdev == 0, and letting that
* propagate would confuse superblock lookup and trigger warnings
* in the device-to-superblock table (super_dev_register).
*/
error = -ENODEV;
if (!inode->i_rdev)
goto out_path_put;
*dev = inode->i_rdev;
error = 0;
out_path_put:
+58 -7
View File
@@ -247,8 +247,8 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
return -EINVAL;
}
bdev_file = bdev_file_open_by_path(device_path, BLK_OPEN_WRITE,
fs_info->sb, &fs_holder_ops);
/* Unfreezable for the whole replace; see btrfs_dev_replace_start(). */
bdev_file = btrfs_open_device_deny_freeze(device_path, fs_info->sb);
if (IS_ERR(bdev_file)) {
btrfs_err(fs_info, "target device %s is invalid!", device_path);
return PTR_ERR(bdev_file);
@@ -327,7 +327,8 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
return 0;
error:
bdev_fput(bdev_file);
/* Undo the open-time freeze deny. */
btrfs_release_device_allow_freeze(bdev_file);
return ret;
}
@@ -624,6 +625,15 @@ static int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
if (ret)
return ret;
/* Deny the source before mark, so every 'leave' unwinds both denied. */
if (src_device->bdev) {
ret = bdev_deny_freeze(src_device->bdev);
if (ret) {
btrfs_destroy_dev_replace_tgtdev(tgt_device, true);
return ret;
}
}
ret = mark_block_group_to_copy(fs_info, src_device);
if (ret)
return ret;
@@ -708,7 +718,9 @@ static int btrfs_dev_replace_start(struct btrfs_fs_info *fs_info,
return ret;
leave:
btrfs_destroy_dev_replace_tgtdev(tgt_device);
if (src_device->bdev)
bdev_allow_freeze(src_device->bdev);
btrfs_destroy_dev_replace_tgtdev(tgt_device, true);
return ret;
}
@@ -889,6 +901,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
*/
ret = btrfs_start_delalloc_roots(fs_info, LONG_MAX, false);
if (ret) {
/* Stays started/resumable; keep both denied. */
mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
return ret;
}
@@ -902,6 +915,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
while (1) {
trans = btrfs_start_transaction(root, 0);
if (IS_ERR(trans)) {
/* Stays started/resumable; keep both denied. */
mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
return PTR_ERR(trans);
}
@@ -954,7 +968,10 @@ error:
mutex_unlock(&fs_devices->device_list_mutex);
btrfs_rm_dev_replace_blocked(fs_info);
if (tgt_device)
btrfs_destroy_dev_replace_tgtdev(tgt_device);
btrfs_destroy_dev_replace_tgtdev(tgt_device, true);
/* The source stays a member; re-allow freezing it. */
if (src_device->bdev)
bdev_allow_freeze(src_device->bdev);
btrfs_rm_dev_replace_unblocked(fs_info);
mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
@@ -1027,6 +1044,8 @@ error:
mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
/* The target is now a member; the source is freed (allow + release). */
bdev_allow_freeze(tgt_device->bdev);
btrfs_rm_dev_replace_free_srcdev(src_device);
return 0;
@@ -1155,8 +1174,9 @@ int btrfs_dev_replace_cancel(struct btrfs_fs_info *fs_info)
btrfs_dev_name(src_device), src_device->devid,
btrfs_dev_name(tgt_device));
/* A suspended replace never re-denied freezing; do not allow. */
if (tgt_device)
btrfs_destroy_dev_replace_tgtdev(tgt_device);
btrfs_destroy_dev_replace_tgtdev(tgt_device, false);
break;
default:
up_write(&dev_replace->rwsem);
@@ -1186,6 +1206,11 @@ void btrfs_dev_replace_suspend_for_unmount(struct btrfs_fs_info *fs_info)
dev_replace->time_stopped = ktime_get_real_seconds();
dev_replace->item_needs_writeback = 1;
btrfs_info(fs_info, "suspending dev_replace for unmount");
/* Reopened freezable next mount; resume re-denies. */
if (dev_replace->srcdev && dev_replace->srcdev->bdev)
bdev_allow_freeze(dev_replace->srcdev->bdev);
if (dev_replace->tgtdev && dev_replace->tgtdev->bdev)
bdev_allow_freeze(dev_replace->tgtdev->bdev);
break;
}
@@ -1198,6 +1223,7 @@ int btrfs_resume_dev_replace_async(struct btrfs_fs_info *fs_info)
{
struct task_struct *task;
struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
int ret = 0;
down_write(&dev_replace->rwsem);
@@ -1241,8 +1267,33 @@ int btrfs_resume_dev_replace_async(struct btrfs_fs_info *fs_info)
return 0;
}
/* Re-deny for the resumed replace; stay suspended if frozen now. */
if (dev_replace->srcdev->bdev &&
bdev_deny_freeze(dev_replace->srcdev->bdev))
goto suspend;
if (bdev_deny_freeze(dev_replace->tgtdev->bdev)) {
if (dev_replace->srcdev->bdev)
bdev_allow_freeze(dev_replace->srcdev->bdev);
goto suspend;
}
task = kthread_run(btrfs_dev_replace_kthread, fs_info, "btrfs-devrepl");
return PTR_ERR_OR_ZERO(task);
if (IS_ERR(task)) {
bdev_allow_freeze(dev_replace->tgtdev->bdev);
if (dev_replace->srcdev->bdev)
bdev_allow_freeze(dev_replace->srcdev->bdev);
/* Undo the deny and suspend, but still fail the mount. */
ret = PTR_ERR(task);
goto suspend;
}
return 0;
suspend:
btrfs_exclop_finish(fs_info);
down_write(&dev_replace->rwsem);
dev_replace->replace_state = BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED;
up_write(&dev_replace->rwsem);
return ret;
}
static int btrfs_dev_replace_kthread(void *data)
+2 -2
View File
@@ -2629,7 +2629,7 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg)
err_drop:
mnt_drop_write_file(file);
if (bdev_file)
bdev_fput(bdev_file);
btrfs_release_device_allow_freeze(bdev_file);
out:
btrfs_put_dev_args_from_path(&args);
return ret;
@@ -2679,7 +2679,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
mnt_drop_write_file(file);
if (bdev_file)
bdev_fput(bdev_file);
btrfs_release_device_allow_freeze(bdev_file);
out:
btrfs_put_dev_args_from_path(&args);
return ret;
+89 -16
View File
@@ -481,7 +481,12 @@ btrfs_get_bdev_and_sb(const char *device_path, blk_mode_t flags, void *holder,
struct block_device *bdev;
int ret;
*bdev_file = bdev_file_open_by_path(device_path, flags, holder, &fs_holder_ops);
if (holder)
*bdev_file = fs_bdev_file_open_by_path(device_path, flags,
holder, holder);
else
*bdev_file = bdev_file_open_by_path(device_path, flags, NULL,
NULL);
if (IS_ERR(*bdev_file)) {
ret = PTR_ERR(*bdev_file);
@@ -496,7 +501,7 @@ btrfs_get_bdev_and_sb(const char *device_path, blk_mode_t flags, void *holder,
if (holder) {
ret = set_blocksize(*bdev_file, BTRFS_BDEV_BLOCKSIZE);
if (ret) {
bdev_fput(*bdev_file);
fs_bdev_file_release(*bdev_file, holder);
goto error;
}
}
@@ -504,7 +509,10 @@ btrfs_get_bdev_and_sb(const char *device_path, blk_mode_t flags, void *holder,
*disk_super = btrfs_read_disk_super(bdev, 0, false);
if (IS_ERR(*disk_super)) {
ret = PTR_ERR(*disk_super);
bdev_fput(*bdev_file);
if (holder)
fs_bdev_file_release(*bdev_file, holder);
else
bdev_fput(*bdev_file);
goto error;
}
@@ -728,7 +736,7 @@ static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices,
error_free_page:
btrfs_release_disk_super(disk_super);
bdev_fput(bdev_file);
fs_bdev_file_release(bdev_file, holder);
return -EINVAL;
}
@@ -1088,7 +1096,7 @@ static void __btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices,
continue;
if (device->bdev_file) {
bdev_fput(device->bdev_file);
fs_bdev_file_release(device->bdev_file, device->bdev_file->private_data);
device->bdev = NULL;
device->bdev_file = NULL;
fs_devices->open_devices--;
@@ -1125,7 +1133,18 @@ void btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices)
mutex_unlock(&uuid_mutex);
}
static void btrfs_close_bdev(struct btrfs_device *device)
/* Release a device that was made unfreezable for a membership change. */
void btrfs_release_device_allow_freeze(struct file *bdev_file)
{
struct super_block *sb = bdev_file->private_data;
/* Unregister before re-allowing (strand-safe); file still open (UAF-safe). */
fs_bdev_unregister(bdev_file, sb);
bdev_allow_freeze(file_bdev(bdev_file));
bdev_fput(bdev_file);
}
static void btrfs_close_bdev(struct btrfs_device *device, bool allow_freeze)
{
if (!device->bdev)
return;
@@ -1135,7 +1154,12 @@ static void btrfs_close_bdev(struct btrfs_device *device)
invalidate_bdev(device->bdev);
}
bdev_fput(device->bdev_file);
/* @allow_freeze undoes a replace-time deny; unmount-close was never denied. */
if (allow_freeze)
btrfs_release_device_allow_freeze(device->bdev_file);
else
fs_bdev_file_release(device->bdev_file,
device->bdev_file->private_data);
}
static void btrfs_close_one_device(struct btrfs_device *device)
@@ -1156,7 +1180,7 @@ static void btrfs_close_one_device(struct btrfs_device *device)
fs_devices->missing_devices--;
}
btrfs_close_bdev(device);
btrfs_close_bdev(device, false);
if (device->bdev) {
fs_devices->open_devices--;
device->bdev = NULL;
@@ -2382,6 +2406,13 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info,
fs_info->fs_devices->rw_devices == 1)
return BTRFS_ERROR_DEV_ONLY_WRITABLE;
/* Removal and freezing are mutually exclusive; refuse if frozen now. */
if (device->bdev) {
ret = bdev_deny_freeze(device->bdev);
if (ret)
return ret;
}
if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) {
mutex_lock(&fs_info->chunk_mutex);
list_del_init(&device->dev_alloc_list);
@@ -2408,6 +2439,8 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info,
device->devid, ret);
btrfs_abort_transaction(trans, ret);
btrfs_end_transaction(trans);
if (device->bdev)
bdev_allow_freeze(device->bdev);
return ret;
}
@@ -2499,6 +2532,8 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info,
return btrfs_commit_transaction(trans);
error_undo:
if (device->bdev)
bdev_allow_freeze(device->bdev);
if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) {
mutex_lock(&fs_info->chunk_mutex);
list_add(&device->dev_alloc_list,
@@ -2543,7 +2578,8 @@ void btrfs_rm_dev_replace_free_srcdev(struct btrfs_device *srcdev)
mutex_lock(&uuid_mutex);
btrfs_close_bdev(srcdev);
/* The source was made unfreezable for the replace; undo it. */
btrfs_close_bdev(srcdev, true);
synchronize_rcu();
btrfs_free_device(srcdev);
@@ -2564,7 +2600,8 @@ void btrfs_rm_dev_replace_free_srcdev(struct btrfs_device *srcdev)
mutex_unlock(&uuid_mutex);
}
void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev)
void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev,
bool allow_freeze)
{
struct btrfs_fs_devices *fs_devices = tgtdev->fs_info->fs_devices;
@@ -2585,7 +2622,7 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev)
btrfs_scratch_superblocks(tgtdev->fs_info, tgtdev);
btrfs_close_bdev(tgtdev);
btrfs_close_bdev(tgtdev, allow_freeze);
synchronize_rcu();
btrfs_free_device(tgtdev);
}
@@ -2854,6 +2891,37 @@ next_slot:
return 0;
}
/*
* Open @path for @sb with freezing denied before the holder claim is published,
* so a racing bdev_freeze() can never reach a claim a device add or replace may
* still abort. The deny is taken on a throwaway non-holder probe open, then the
* holder is opened by the probe's dev_t. Balanced by the caller.
*/
struct file *btrfs_open_device_deny_freeze(const char *path,
struct super_block *sb)
{
struct file *probe_file, *bdev_file;
int ret;
/* WRITE so bdev_file_open_by_path() rejects a read-only device. */
probe_file = bdev_file_open_by_path(path, BLK_OPEN_WRITE, NULL, NULL);
if (IS_ERR(probe_file))
return probe_file;
ret = bdev_deny_freeze(file_bdev(probe_file));
if (ret) {
bdev_fput(probe_file);
return ERR_PTR(ret);
}
bdev_file = fs_bdev_file_open_by_dev(file_bdev(probe_file)->bd_dev,
BLK_OPEN_WRITE, sb, sb);
if (IS_ERR(bdev_file))
bdev_allow_freeze(file_bdev(probe_file));
bdev_fput(probe_file);
return bdev_file;
}
int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path)
{
struct btrfs_root *root = fs_info->dev_root;
@@ -2872,8 +2940,8 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
if (sb_rdonly(sb) && !fs_devices->seeding)
return -EROFS;
bdev_file = bdev_file_open_by_path(device_path, BLK_OPEN_WRITE,
fs_info->sb, &fs_holder_ops);
/* Forbid freezing until the device is a committed member (or unwound). */
bdev_file = btrfs_open_device_deny_freeze(device_path, fs_info->sb);
if (IS_ERR(bdev_file))
return PTR_ERR(bdev_file);
@@ -3044,8 +3112,10 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
up_write(&sb->s_umount);
locked = false;
if (ret) /* transaction commit */
if (ret) { /* transaction commit */
bdev_allow_freeze(file_bdev(bdev_file));
return ret;
}
ret = btrfs_relocate_sys_chunks(fs_info);
if (ret < 0)
@@ -3053,8 +3123,10 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
"Failed to relocate sys chunks after device initialization. This can be fixed using the \"btrfs balance\" command.");
trans = btrfs_attach_transaction(root);
if (IS_ERR(trans)) {
if (PTR_ERR(trans) == -ENOENT)
if (PTR_ERR(trans) == -ENOENT) {
bdev_allow_freeze(file_bdev(bdev_file));
return 0;
}
ret = PTR_ERR(trans);
trans = NULL;
goto error_sysfs;
@@ -3074,6 +3146,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
/* Update ctime/mtime for blkid or udev */
update_dev_time(device_path);
bdev_allow_freeze(file_bdev(bdev_file));
return ret;
error_sysfs:
@@ -3103,7 +3176,7 @@ error_free_zone:
error_free_device:
btrfs_free_device(device);
error:
bdev_fput(bdev_file);
btrfs_release_device_allow_freeze(bdev_file);
if (locked) {
mutex_unlock(&uuid_mutex);
up_write(&sb->s_umount);
+5 -1
View File
@@ -744,6 +744,7 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
struct btrfs_device *btrfs_scan_one_device(const char *path, bool mount_arg_dev);
int btrfs_forget_devices(dev_t devt);
void btrfs_close_devices(struct btrfs_fs_devices *fs_devices);
void btrfs_release_device_allow_freeze(struct file *bdev_file);
void btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices);
void btrfs_assign_next_active_device(struct btrfs_device *device,
struct btrfs_device *this_dev);
@@ -768,6 +769,8 @@ struct btrfs_device *btrfs_find_device(const struct btrfs_fs_devices *fs_devices
const struct btrfs_dev_lookup_args *args);
int btrfs_shrink_device(struct btrfs_device *device, u64 new_size);
int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *path);
struct file *btrfs_open_device_deny_freeze(const char *path,
struct super_block *sb);
int btrfs_balance(struct btrfs_fs_info *fs_info,
struct btrfs_balance_control *bctl,
struct btrfs_ioctl_balance_args *bargs);
@@ -788,7 +791,8 @@ int btrfs_init_writeback_bio_size(struct btrfs_fs_info *fs_info);
int btrfs_run_dev_stats(struct btrfs_trans_handle *trans);
void btrfs_rm_dev_replace_remove_srcdev(struct btrfs_device *srcdev);
void btrfs_rm_dev_replace_free_srcdev(struct btrfs_device *srcdev);
void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev);
void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev,
bool allow_freeze);
unsigned long btrfs_full_stripe_len(struct btrfs_fs_info *fs_info,
u64 logical);
u64 btrfs_calc_stripe_length(const struct btrfs_chunk_map *map);
+1 -1
View File
@@ -504,7 +504,7 @@ static void cramfs_kill_sb(struct super_block *sb)
sb->s_mtd = NULL;
} else if (IS_ENABLED(CONFIG_CRAMFS_BLOCKDEV) && sb->s_bdev) {
sync_blockdev(sb->s_bdev);
bdev_fput(sb->s_bdev_file);
fs_bdev_file_release(sb->s_bdev_file, sb);
}
kfree(sbi);
}
+23 -12
View File
@@ -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;
@@ -790,28 +790,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);
@@ -823,8 +829,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 = {
@@ -878,7 +889,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;
}
@@ -890,7 +901,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;
}
+2 -7
View File
@@ -126,11 +126,6 @@ struct kunit_ext_test_param {
struct kunit_ext_data_state exp_data_state[3];
};
static void ext_kill_sb(struct super_block *sb)
{
generic_shutdown_super(sb);
}
static int ext_init_fs_context(struct fs_context *fc)
{
return 0;
@@ -138,13 +133,13 @@ static int ext_init_fs_context(struct fs_context *fc)
static int ext_set(struct super_block *sb, struct fs_context *fc)
{
return 0;
return set_anon_super_fc(sb, fc);
}
static struct file_system_type ext_fs_type = {
.name = "extents test",
.init_fs_context = ext_init_fs_context,
.kill_sb = ext_kill_sb,
.kill_sb = kill_anon_super,
};
static void extents_kunit_exit(struct kunit *test)
+2 -7
View File
@@ -59,11 +59,6 @@ static const struct super_operations mbt_sops = {
.free_inode = mbt_free_inode,
};
static void mbt_kill_sb(struct super_block *sb)
{
generic_shutdown_super(sb);
}
static int mbt_init_fs_context(struct fs_context *fc)
{
return 0;
@@ -72,7 +67,7 @@ static int mbt_init_fs_context(struct fs_context *fc)
static struct file_system_type mbt_fs_type = {
.name = "mballoc test",
.init_fs_context = mbt_init_fs_context,
.kill_sb = mbt_kill_sb,
.kill_sb = kill_anon_super,
};
static int mbt_mb_init(struct super_block *sb)
@@ -136,7 +131,7 @@ static void mbt_mb_release(struct super_block *sb)
static int mbt_set(struct super_block *sb, struct fs_context *fc)
{
return 0;
return set_anon_super_fc(sb, fc);
}
static struct super_block *mbt_ext4_alloc_super_block(void)
+6 -6
View File
@@ -5797,7 +5797,7 @@ failed_mount:
brelse(sbi->s_sbh);
if (sbi->s_journal_bdev_file) {
invalidate_bdev(file_bdev(sbi->s_journal_bdev_file));
bdev_fput(sbi->s_journal_bdev_file);
fs_bdev_file_release(sbi->s_journal_bdev_file, sb);
}
out_fail:
invalidate_bdev(sb->s_bdev);
@@ -5981,9 +5981,9 @@ static struct file *ext4_get_journal_blkdev(struct super_block *sb,
struct ext4_super_block *es;
int errno;
bdev_file = bdev_file_open_by_dev(j_dev,
bdev_file = fs_bdev_file_open_by_dev(j_dev,
BLK_OPEN_READ | BLK_OPEN_WRITE | BLK_OPEN_RESTRICT_WRITES,
sb, &fs_holder_ops);
sb, sb);
if (IS_ERR(bdev_file)) {
ext4_msg(sb, KERN_ERR,
"failed to open journal device unknown-block(%u,%u) %pe",
@@ -6043,7 +6043,7 @@ static struct file *ext4_get_journal_blkdev(struct super_block *sb,
out_bh:
brelse(bh);
out_bdev:
bdev_fput(bdev_file);
fs_bdev_file_release(bdev_file, sb);
return ERR_PTR(errno);
}
@@ -6082,7 +6082,7 @@ static journal_t *ext4_open_dev_journal(struct super_block *sb,
out_journal:
ext4_journal_destroy(EXT4_SB(sb), journal);
out_bdev:
bdev_fput(bdev_file);
fs_bdev_file_release(bdev_file, sb);
return ERR_PTR(errno);
}
@@ -7499,7 +7499,7 @@ static void ext4_kill_sb(struct super_block *sb)
kill_block_super(sb);
if (bdev_file)
bdev_fput(bdev_file);
fs_bdev_file_release(bdev_file, sb);
}
static struct file_system_type ext4_fs_type = {
+3 -3
View File
@@ -1971,7 +1971,7 @@ static void destroy_device_list(struct f2fs_sb_info *sbi)
for (i = 0; i < sbi->s_ndevs; i++) {
if (i > 0)
bdev_fput(FDEV(i).bdev_file);
fs_bdev_file_release(FDEV(i).bdev_file, sbi->sb);
#ifdef CONFIG_BLK_DEV_ZONED
kvfree(FDEV(i).blkz_seq);
#endif
@@ -4901,8 +4901,8 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi)
FDEV(i).end_blk = FDEV(i).start_blk +
SEGS_TO_BLKS(sbi,
FDEV(i).total_segments) - 1;
FDEV(i).bdev_file = bdev_file_open_by_path(
FDEV(i).path, mode, sbi->sb, NULL);
FDEV(i).bdev_file = fs_bdev_file_open_by_path(
FDEV(i).path, mode, sbi->sb, sbi->sb);
}
}
if (IS_ERR(FDEV(i).bdev_file))
+1
View File
@@ -137,6 +137,7 @@ extern int reconfigure_super(struct fs_context *);
extern bool super_trylock_shared(struct super_block *sb);
struct super_block *user_get_super(dev_t, bool excl);
void put_super(struct super_block *sb);
void __init super_dev_init(void);
extern bool mount_capable(struct fs_context *);
/*
+2
View File
@@ -6270,6 +6270,8 @@ void __init mnt_init(void)
HASH_ZERO,
&mp_hash_shift, &mp_hash_mask, 0, 0);
super_dev_init();
kernfs_init();
err = sysfs_init();
-1
View File
@@ -1882,7 +1882,6 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
ocfs2_delete_osb(osb);
kfree(osb);
sb->s_dev = 0;
sb->s_fs_info = NULL;
}
+1 -1
View File
@@ -595,7 +595,7 @@ static void romfs_kill_sb(struct super_block *sb)
#ifdef CONFIG_ROMFS_ON_BLOCK
if (sb->s_bdev) {
sync_blockdev(sb->s_bdev);
bdev_fput(sb->s_bdev_file);
fs_bdev_file_release(sb->s_bdev_file, sb);
}
#endif
}
+426 -194
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1631,7 +1631,7 @@ xfs_free_buftarg(
fs_put_dax(btp->bt_daxdev, btp->bt_mount);
/* the main block device is closed by kill_block_super */
if (btp->bt_bdev != btp->bt_mount->m_super->s_bdev)
bdev_fput(btp->bt_file);
fs_bdev_file_release(btp->bt_file, btp->bt_mount->m_super);
kfree(btp);
}
+5 -5
View File
@@ -400,8 +400,8 @@ xfs_blkdev_get(
blk_mode_t mode;
mode = sb_open_mode(mp->m_super->s_flags);
*bdev_filep = bdev_file_open_by_path(name, mode,
mp->m_super, &fs_holder_ops);
*bdev_filep = fs_bdev_file_open_by_path(name, mode,
mp->m_super, mp->m_super);
if (IS_ERR(*bdev_filep)) {
error = PTR_ERR(*bdev_filep);
*bdev_filep = NULL;
@@ -526,7 +526,7 @@ xfs_open_devices(
mp->m_logdev_targp = mp->m_ddev_targp;
/* Handle won't be used, drop it */
if (logdev_file)
bdev_fput(logdev_file);
fs_bdev_file_release(logdev_file, mp->m_super);
}
return 0;
@@ -541,10 +541,10 @@ xfs_open_devices(
mp->m_ddev_targp = NULL;
out_close_rtdev:
if (rtdev_file)
bdev_fput(rtdev_file);
fs_bdev_file_release(rtdev_file, mp->m_super);
out_close_logdev:
if (logdev_file)
bdev_fput(logdev_file);
fs_bdev_file_release(logdev_file, mp->m_super);
return error;
}
+1 -1
View File
@@ -66,7 +66,7 @@ struct block_device {
int bd_holders;
struct kobject *bd_holder_dir;
atomic_t bd_fsfreeze_count; /* number of freeze requests */
atomic_t bd_fsfreeze_count; /* >0 freeze requests, <0 freeze deniers */
struct mutex bd_fsfreeze_mutex; /* serialize freeze/thaw */
struct partition_meta_info *bd_meta_info;
+3 -9
View File
@@ -126,8 +126,6 @@ struct blk_integrity {
unsigned char pi_tuple_size;
};
typedef unsigned int __bitwise blk_mode_t;
/* open for reading */
#define BLK_OPEN_READ ((__force blk_mode_t)(1 << 0))
/* open for writing */
@@ -1770,13 +1768,6 @@ struct blk_holder_ops {
__releases(&bdev->bd_holder_lock);
};
/*
* For filesystems using @fs_holder_ops, the @holder argument passed to
* helpers used to open and claim block devices via
* bd_prepare_to_claim() must point to a superblock.
*/
extern const struct blk_holder_ops fs_holder_ops;
/*
* Return the correct open flags for blkdev_get_by_* for super block flags
* as stored in sb->s_flags.
@@ -1837,7 +1828,10 @@ static inline int early_lookup_bdev(const char *pathname, dev_t *dev)
int bdev_freeze(struct block_device *bdev);
int bdev_thaw(struct block_device *bdev);
int bdev_deny_freeze(struct block_device *bdev);
void bdev_allow_freeze(struct block_device *bdev);
void bdev_fput(struct file *bdev_file);
void bdev_yield_claim(struct file *bdev_file);
struct io_comp_batch {
struct rq_list req_list;

Some files were not shown because too many files have changed in this diff Show More