* [PATCH 1/3 RFC] btrfs: wrap rdonly check into btrfs_fs_is_rdonly
2022-04-06 13:57 [PATCH 0/3] cleanup rdonly flag and BTRFS_FS_OPEN flag Anand Jain
@ 2022-04-06 13:57 ` Anand Jain
2022-04-06 13:57 ` [PATCH 2/3] btrfs: wrap check for BTRFS_FS_OPEN flag into function Anand Jain
2022-04-06 13:57 ` [PATCH 3/3] btrfs: set BTRFS_FS_OPEN flag for both rdonly and rw Anand Jain
2 siblings, 0 replies; 4+ messages in thread
From: Anand Jain @ 2022-04-06 13:57 UTC (permalink / raw)
To: linux-btrfs; +Cc: dsterba
Check for rdonly is a little bit inconsistent. At most of the places we
use sb_rdonly(fs_info->sb) however in btrfs_need_cleaner_sleep() it
used the test_bit(BTRFS_FS_STATE_RO....).
As per the comment of btrfs_need_cleaner_sleep(), it needs to use
BTRFS_FS_STATE_RO state for the atomic purpose.
BTRFS_FS_OPEN flag is true if the filesystem open is complete and
read-write-able (not rdonly). In preparatory to take out the rdonly/rw
part in the above flag, consolidate the check for filesystem rdonly into
the function btrfs_fs_is_rdonly(). It makes either way migration easier.
Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
fs/btrfs/block-group.c | 2 +-
fs/btrfs/ctree.h | 13 +++++++++++--
fs/btrfs/dev-replace.c | 2 +-
fs/btrfs/disk-io.c | 11 ++++++-----
fs/btrfs/extent_io.c | 4 ++--
fs/btrfs/inode.c | 2 +-
fs/btrfs/ioctl.c | 2 +-
fs/btrfs/super.c | 12 ++++++------
fs/btrfs/sysfs.c | 4 ++--
fs/btrfs/tree-checker.c | 2 +-
fs/btrfs/volumes.c | 4 ++--
11 files changed, 34 insertions(+), 24 deletions(-)
diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
index 7bf10afab89c..94345316cc92 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
@@ -2571,7 +2571,7 @@ int btrfs_inc_block_group_ro(struct btrfs_block_group *cache,
* In that case we should not start a new transaction on read-only fs.
* Thus here we skip all chunk allocations.
*/
- if (sb_rdonly(fs_info->sb)) {
+ if (btrfs_fs_is_rdonly(fs_info)) {
mutex_lock(&fs_info->ro_block_group_mutex);
ret = inc_block_group_ro(cache, 0);
mutex_unlock(&fs_info->ro_block_group_mutex);
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 4af340c32986..21b1e9698b19 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3112,6 +3112,16 @@ static inline int btrfs_fs_closing(struct btrfs_fs_info *fs_info)
return 0;
}
+static inline bool btrfs_fs_is_rdonly(const struct btrfs_fs_info *fs_info)
+{
+ bool rdonly = sb_rdonly(fs_info->sb);
+ bool fs_rdonly = test_bit(BTRFS_FS_STATE_RO, &fs_info->fs_state);
+
+ BUG_ON(rdonly != fs_rdonly);
+
+ return rdonly;
+}
+
/*
* If we remount the fs to be R/O or umount the fs, the cleaner needn't do
* anything except sleeping. This function is used to check the status of
@@ -3122,8 +3132,7 @@ static inline int btrfs_fs_closing(struct btrfs_fs_info *fs_info)
*/
static inline int btrfs_need_cleaner_sleep(struct btrfs_fs_info *fs_info)
{
- return test_bit(BTRFS_FS_STATE_RO, &fs_info->fs_state) ||
- btrfs_fs_closing(fs_info);
+ return btrfs_fs_is_rdonly(fs_info) || btrfs_fs_closing(fs_info);
}
static inline void btrfs_set_sb_rdonly(struct super_block *sb)
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index 677b99e66c21..1a9b2d7eedad 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -1074,7 +1074,7 @@ int btrfs_dev_replace_cancel(struct btrfs_fs_info *fs_info)
int result;
int ret;
- if (sb_rdonly(fs_info->sb))
+ if (btrfs_fs_is_rdonly(fs_info))
return -EROFS;
mutex_lock(&dev_replace->lock_finishing_cancel_unmount);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index dfec67e8a78c..552dc49e2948 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2590,7 +2590,7 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
return ret;
}
- if (sb_rdonly(fs_info->sb)) {
+ if (btrfs_fs_is_rdonly(fs_info)) {
ret = btrfs_commit_super(fs_info);
if (ret)
return ret;
@@ -3668,7 +3668,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
features = btrfs_super_compat_ro_flags(disk_super) &
~BTRFS_FEATURE_COMPAT_RO_SUPP;
- if (!sb_rdonly(sb) && features) {
+ if (!btrfs_fs_is_rdonly(fs_info) && features) {
btrfs_err(fs_info,
"cannot mount read-write because of unsupported optional features (%llx)",
features);
@@ -3838,7 +3838,8 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
btrfs_free_zone_cache(fs_info);
- if (!sb_rdonly(sb) && fs_info->fs_devices->missing_devices &&
+ if (!btrfs_fs_is_rdonly(fs_info) &&
+ fs_info->fs_devices->missing_devices &&
!btrfs_check_rw_degradable(fs_info, NULL)) {
btrfs_warn(fs_info,
"writable mount is not allowed due to too many missing devices");
@@ -3905,7 +3906,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
goto fail_qgroup;
}
- if (sb_rdonly(sb))
+ if (btrfs_fs_is_rdonly(fs_info))
goto clear_oneshot;
ret = btrfs_start_pre_rw_mount(fs_info);
@@ -4694,7 +4695,7 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
/* Cancel or finish ongoing discard work */
btrfs_discard_cleanup(fs_info);
- if (!sb_rdonly(fs_info->sb)) {
+ if (!btrfs_fs_is_rdonly(fs_info)) {
/*
* The cleaner kthread is stopped, so do one final pass over
* unused block groups.
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 9f2ada809dea..20916748a3b2 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -2391,7 +2391,7 @@ int btrfs_repair_eb_io_failure(const struct extent_buffer *eb, int mirror_num)
int i, num_pages = num_extent_pages(eb);
int ret = 0;
- if (sb_rdonly(fs_info->sb))
+ if (btrfs_fs_is_rdonly(fs_info))
return -EROFS;
for (i = 0; i < num_pages; i++) {
@@ -2434,7 +2434,7 @@ int clean_io_failure(struct btrfs_fs_info *fs_info,
BUG_ON(!failrec->this_mirror);
- if (sb_rdonly(fs_info->sb))
+ if (btrfs_fs_is_rdonly(fs_info))
goto out;
spin_lock(&io_tree->lock);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 7d91166d90bf..a1dcc656dd63 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -5755,7 +5755,7 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
if (!IS_ERR(inode) && root != sub_root) {
down_read(&fs_info->cleanup_work_sem);
- if (!sb_rdonly(inode->i_sb))
+ if (!btrfs_fs_is_rdonly(fs_info))
ret = btrfs_orphan_cleanup(sub_root);
up_read(&fs_info->cleanup_work_sem);
if (ret) {
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 7a6974e877f4..2332b9226735 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -4132,7 +4132,7 @@ static long btrfs_ioctl_dev_replace(struct btrfs_fs_info *fs_info,
switch (p->cmd) {
case BTRFS_IOCTL_DEV_REPLACE_CMD_START:
- if (sb_rdonly(fs_info->sb)) {
+ if (btrfs_fs_is_rdonly(fs_info)) {
ret = -EROFS;
goto out;
}
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 1857636b84df..0df155f88c14 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -183,7 +183,7 @@ void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function
* Special case: if the error is EROFS, and we're already
* under SB_RDONLY, then it is safe here.
*/
- if (errno == -EROFS && sb_rdonly(sb))
+ if (errno == -EROFS && btrfs_fs_is_rdonly(fs_info))
return;
#ifdef CONFIG_PRINTK
@@ -216,7 +216,7 @@ void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function
if (!(sb->s_flags & SB_BORN))
return;
- if (sb_rdonly(sb))
+ if (btrfs_fs_is_rdonly(fs_info))
return;
btrfs_discard_stop(fs_info);
@@ -1941,9 +1941,9 @@ static inline void btrfs_remount_cleanup(struct btrfs_fs_info *fs_info,
* close or the filesystem is read only.
*/
if (btrfs_raw_test_opt(old_opts, AUTO_DEFRAG) &&
- (!btrfs_raw_test_opt(fs_info->mount_opt, AUTO_DEFRAG) || sb_rdonly(fs_info->sb))) {
+ (!btrfs_raw_test_opt(fs_info->mount_opt, AUTO_DEFRAG) ||
+ btrfs_fs_is_rdonly(fs_info)))
btrfs_cleanup_defrag_inodes(fs_info);
- }
/* If we toggled discard async */
if (!btrfs_raw_test_opt(old_opts, DISCARD_ASYNC) &&
@@ -1993,7 +1993,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
if ((bool)btrfs_test_opt(fs_info, FREE_SPACE_TREE) !=
(bool)btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE) &&
- (!sb_rdonly(sb) || (*flags & SB_RDONLY))) {
+ (!btrfs_fs_is_rdonly(fs_info) || (*flags & SB_RDONLY))) {
btrfs_warn(fs_info,
"remount supports changing free space tree only from ro to rw");
/* Make sure free space cache options match the state on disk */
@@ -2007,7 +2007,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
}
}
- if ((bool)(*flags & SB_RDONLY) == sb_rdonly(sb))
+ if ((bool)(*flags & SB_RDONLY) == btrfs_fs_is_rdonly(fs_info))
goto out;
if (*flags & SB_RDONLY) {
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index 366424222b4f..19f7ffd26480 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -194,7 +194,7 @@ static ssize_t btrfs_feature_attr_store(struct kobject *kobj,
if (!fs_info)
return -EPERM;
- if (sb_rdonly(fs_info->sb))
+ if (btrfs_fs_is_rdonly(fs_info))
return -EROFS;
ret = kstrtoul(skip_spaces(buf), 0, &val);
@@ -824,7 +824,7 @@ static ssize_t btrfs_label_store(struct kobject *kobj,
if (!fs_info)
return -EPERM;
- if (sb_rdonly(fs_info->sb))
+ if (btrfs_fs_is_rdonly(fs_info))
return -EROFS;
/*
diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
index 9e0e0ae2288c..24aa0e00bf5a 100644
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -1104,7 +1104,7 @@ static int check_inode_item(struct extent_buffer *leaf,
"unknown incompat flags detected: 0x%x", flags);
return -EUCLEAN;
}
- if (unlikely(!sb_rdonly(fs_info->sb) &&
+ if (unlikely(!btrfs_fs_is_rdonly(fs_info) &&
(ro_flags & ~BTRFS_INODE_RO_FLAG_MASK))) {
inode_item_err(leaf, slot,
"unknown ro-compat flags detected on writeable mount: 0x%x",
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 26ada24890a5..e206cb0df6a1 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -2597,7 +2597,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
bool seeding_dev = false;
bool locked = false;
- if (sb_rdonly(sb) && !fs_devices->seeding)
+ if (btrfs_fs_is_rdonly(fs_info) && !fs_devices->seeding)
return -EROFS;
bdev = blkdev_get_by_path(device_path, FMODE_WRITE | FMODE_EXCL,
@@ -4587,7 +4587,7 @@ int btrfs_cancel_balance(struct btrfs_fs_info *fs_info)
* mount time if the mount is read-write. Otherwise it's still paused
* and we must not allow cancelling as it deletes the item.
*/
- if (sb_rdonly(fs_info->sb)) {
+ if (btrfs_fs_is_rdonly(fs_info)) {
mutex_unlock(&fs_info->balance_mutex);
return -EROFS;
}
--
2.33.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/3] btrfs: wrap check for BTRFS_FS_OPEN flag into function
2022-04-06 13:57 [PATCH 0/3] cleanup rdonly flag and BTRFS_FS_OPEN flag Anand Jain
2022-04-06 13:57 ` [PATCH 1/3 RFC] btrfs: wrap rdonly check into btrfs_fs_is_rdonly Anand Jain
@ 2022-04-06 13:57 ` Anand Jain
2022-04-06 13:57 ` [PATCH 3/3] btrfs: set BTRFS_FS_OPEN flag for both rdonly and rw Anand Jain
2 siblings, 0 replies; 4+ messages in thread
From: Anand Jain @ 2022-04-06 13:57 UTC (permalink / raw)
To: linux-btrfs; +Cc: dsterba
2nd patch in preparation to make the BTRFS_FS_OPEN flag work irrespective
of the type of mount (rdonly or read-write-able). Bring the check for the
BTRFS_FS_OPEN flag into an inline function btrfs_fs_state_is_open_rw().
Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
fs/btrfs/block-group.c | 4 ++--
fs/btrfs/ctree.h | 5 +++++
fs/btrfs/disk-io.c | 2 +-
fs/btrfs/volumes.c | 2 +-
4 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
index 94345316cc92..3b10669b413b 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
@@ -1295,7 +1295,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
const bool async_trim_enabled = btrfs_test_opt(fs_info, DISCARD_ASYNC);
int ret = 0;
- if (!test_bit(BTRFS_FS_OPEN, &fs_info->flags))
+ if (!btrfs_fs_state_is_open_rw(fs_info))
return;
/*
@@ -1526,7 +1526,7 @@ void btrfs_reclaim_bgs_work(struct work_struct *work)
struct btrfs_block_group *bg;
struct btrfs_space_info *space_info;
- if (!test_bit(BTRFS_FS_OPEN, &fs_info->flags))
+ if (!btrfs_fs_state_is_open_rw(fs_info))
return;
if (!btrfs_should_reclaim(fs_info))
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 21b1e9698b19..9d21f4b9d3dd 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -4026,6 +4026,11 @@ static inline bool btrfs_is_data_reloc_root(const struct btrfs_root *root)
return root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID;
}
+static inline bool btrfs_fs_state_is_open_rw(const struct btrfs_fs_info *fs_info)
+{
+ return test_bit(BTRFS_FS_OPEN, &fs_info->flags);
+}
+
/*
* We use page status Private2 to indicate there is an ordered extent with
* unfinished IO.
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 552dc49e2948..1f9613d733ab 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2000,7 +2000,7 @@ static int cleaner_kthread(void *arg)
* Do not do anything if we might cause open_ctree() to block
* before we have finished mounting the filesystem.
*/
- if (!test_bit(BTRFS_FS_OPEN, &fs_info->flags))
+ if (!btrfs_fs_state_is_open_rw(fs_info))
goto sleep;
if (!mutex_trylock(&fs_info->cleaner_mutex))
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index e206cb0df6a1..64ff39274f32 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -7589,7 +7589,7 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
* and at this point there can't be any concurrent task modifying the
* chunk tree, to keep it simple, just skip locking on the chunk tree.
*/
- ASSERT(!test_bit(BTRFS_FS_OPEN, &fs_info->flags));
+ ASSERT(!btrfs_fs_state_is_open_rw(fs_info));
path->skip_locking = 1;
/*
--
2.33.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/3] btrfs: set BTRFS_FS_OPEN flag for both rdonly and rw
2022-04-06 13:57 [PATCH 0/3] cleanup rdonly flag and BTRFS_FS_OPEN flag Anand Jain
2022-04-06 13:57 ` [PATCH 1/3 RFC] btrfs: wrap rdonly check into btrfs_fs_is_rdonly Anand Jain
2022-04-06 13:57 ` [PATCH 2/3] btrfs: wrap check for BTRFS_FS_OPEN flag into function Anand Jain
@ 2022-04-06 13:57 ` Anand Jain
2 siblings, 0 replies; 4+ messages in thread
From: Anand Jain @ 2022-04-06 13:57 UTC (permalink / raw)
To: linux-btrfs; +Cc: dsterba
It is good to have the BTRFS_FS_OPEN flag set irrespective of rdonly or rw
mount. Setting the BTRFS_FS_OPEN flag only for the rw-mount does not make
sense as it lessens its utility. Besides, we have the BTRFS_FS_STATE_RO
state for mount type rdonly or rw-able.
Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
fs/btrfs/ctree.h | 3 ++-
fs/btrfs/disk-io.c | 39 ++++++++++++++++++++-------------------
fs/btrfs/super.c | 2 --
3 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 9d21f4b9d3dd..092efa9392e5 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -4028,7 +4028,8 @@ static inline bool btrfs_is_data_reloc_root(const struct btrfs_root *root)
static inline bool btrfs_fs_state_is_open_rw(const struct btrfs_fs_info *fs_info)
{
- return test_bit(BTRFS_FS_OPEN, &fs_info->flags);
+ return test_bit(BTRFS_FS_OPEN, &fs_info->flags) &&
+ !btrfs_fs_is_rdonly(fs_info);
}
/*
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 1f9613d733ab..0624f9636497 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -3906,36 +3906,37 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
goto fail_qgroup;
}
- if (btrfs_fs_is_rdonly(fs_info))
- goto clear_oneshot;
-
- ret = btrfs_start_pre_rw_mount(fs_info);
- if (ret) {
- close_ctree(fs_info);
- return ret;
- }
- btrfs_discard_resume(fs_info);
-
- if (fs_info->uuid_root &&
- (btrfs_test_opt(fs_info, RESCAN_UUID_TREE) ||
- fs_info->generation != btrfs_super_uuid_tree_generation(disk_super))) {
- btrfs_info(fs_info, "checking UUID tree");
- ret = btrfs_check_uuid_tree(fs_info);
+ if (!btrfs_fs_is_rdonly(fs_info)) {
+ ret = btrfs_start_pre_rw_mount(fs_info);
if (ret) {
- btrfs_warn(fs_info,
- "failed to check the UUID tree: %d", ret);
close_ctree(fs_info);
return ret;
}
+ btrfs_discard_resume(fs_info);
+
+ if (fs_info->uuid_root &&
+ (btrfs_test_opt(fs_info, RESCAN_UUID_TREE) ||
+ fs_info->generation !=
+ btrfs_super_uuid_tree_generation(disk_super))) {
+ btrfs_info(fs_info, "checking UUID tree");
+ ret = btrfs_check_uuid_tree(fs_info);
+ if (ret) {
+ btrfs_warn(fs_info,
+ "failed to check the UUID tree: %d", ret);
+ close_ctree(fs_info);
+ return ret;
+ }
+ }
}
+ /* set open-ed flag for both rdonly and rw mounts */
set_bit(BTRFS_FS_OPEN, &fs_info->flags);
/* Kick the cleaner thread so it'll start deleting snapshots. */
- if (test_bit(BTRFS_FS_UNFINISHED_DROPS, &fs_info->flags))
+ if (test_bit(BTRFS_FS_UNFINISHED_DROPS, &fs_info->flags) &&
+ !btrfs_fs_is_rdonly(fs_info))
wake_up_process(fs_info->cleaner_kthread);
-clear_oneshot:
btrfs_clear_oneshot_options(fs_info);
return 0;
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 0df155f88c14..ad38303a7803 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -2111,8 +2111,6 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
goto restore;
btrfs_clear_sb_rdonly(sb);
-
- set_bit(BTRFS_FS_OPEN, &fs_info->flags);
}
out:
/*
--
2.33.1
^ permalink raw reply related [flat|nested] 4+ messages in thread