162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#include "messages.h"
462306a36Sopenharmony_ci#include "ctree.h"
562306a36Sopenharmony_ci#include "fs.h"
662306a36Sopenharmony_ci#include "accessors.h"
762306a36Sopenharmony_ci
862306a36Sopenharmony_civoid __btrfs_set_fs_incompat(struct btrfs_fs_info *fs_info, u64 flag,
962306a36Sopenharmony_ci			     const char *name)
1062306a36Sopenharmony_ci{
1162306a36Sopenharmony_ci	struct btrfs_super_block *disk_super;
1262306a36Sopenharmony_ci	u64 features;
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci	disk_super = fs_info->super_copy;
1562306a36Sopenharmony_ci	features = btrfs_super_incompat_flags(disk_super);
1662306a36Sopenharmony_ci	if (!(features & flag)) {
1762306a36Sopenharmony_ci		spin_lock(&fs_info->super_lock);
1862306a36Sopenharmony_ci		features = btrfs_super_incompat_flags(disk_super);
1962306a36Sopenharmony_ci		if (!(features & flag)) {
2062306a36Sopenharmony_ci			features |= flag;
2162306a36Sopenharmony_ci			btrfs_set_super_incompat_flags(disk_super, features);
2262306a36Sopenharmony_ci			btrfs_info(fs_info,
2362306a36Sopenharmony_ci				"setting incompat feature flag for %s (0x%llx)",
2462306a36Sopenharmony_ci				name, flag);
2562306a36Sopenharmony_ci		}
2662306a36Sopenharmony_ci		spin_unlock(&fs_info->super_lock);
2762306a36Sopenharmony_ci		set_bit(BTRFS_FS_FEATURE_CHANGED, &fs_info->flags);
2862306a36Sopenharmony_ci	}
2962306a36Sopenharmony_ci}
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_civoid __btrfs_clear_fs_incompat(struct btrfs_fs_info *fs_info, u64 flag,
3262306a36Sopenharmony_ci			       const char *name)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	struct btrfs_super_block *disk_super;
3562306a36Sopenharmony_ci	u64 features;
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	disk_super = fs_info->super_copy;
3862306a36Sopenharmony_ci	features = btrfs_super_incompat_flags(disk_super);
3962306a36Sopenharmony_ci	if (features & flag) {
4062306a36Sopenharmony_ci		spin_lock(&fs_info->super_lock);
4162306a36Sopenharmony_ci		features = btrfs_super_incompat_flags(disk_super);
4262306a36Sopenharmony_ci		if (features & flag) {
4362306a36Sopenharmony_ci			features &= ~flag;
4462306a36Sopenharmony_ci			btrfs_set_super_incompat_flags(disk_super, features);
4562306a36Sopenharmony_ci			btrfs_info(fs_info,
4662306a36Sopenharmony_ci				"clearing incompat feature flag for %s (0x%llx)",
4762306a36Sopenharmony_ci				name, flag);
4862306a36Sopenharmony_ci		}
4962306a36Sopenharmony_ci		spin_unlock(&fs_info->super_lock);
5062306a36Sopenharmony_ci		set_bit(BTRFS_FS_FEATURE_CHANGED, &fs_info->flags);
5162306a36Sopenharmony_ci	}
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_civoid __btrfs_set_fs_compat_ro(struct btrfs_fs_info *fs_info, u64 flag,
5562306a36Sopenharmony_ci			      const char *name)
5662306a36Sopenharmony_ci{
5762306a36Sopenharmony_ci	struct btrfs_super_block *disk_super;
5862306a36Sopenharmony_ci	u64 features;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	disk_super = fs_info->super_copy;
6162306a36Sopenharmony_ci	features = btrfs_super_compat_ro_flags(disk_super);
6262306a36Sopenharmony_ci	if (!(features & flag)) {
6362306a36Sopenharmony_ci		spin_lock(&fs_info->super_lock);
6462306a36Sopenharmony_ci		features = btrfs_super_compat_ro_flags(disk_super);
6562306a36Sopenharmony_ci		if (!(features & flag)) {
6662306a36Sopenharmony_ci			features |= flag;
6762306a36Sopenharmony_ci			btrfs_set_super_compat_ro_flags(disk_super, features);
6862306a36Sopenharmony_ci			btrfs_info(fs_info,
6962306a36Sopenharmony_ci				"setting compat-ro feature flag for %s (0x%llx)",
7062306a36Sopenharmony_ci				name, flag);
7162306a36Sopenharmony_ci		}
7262306a36Sopenharmony_ci		spin_unlock(&fs_info->super_lock);
7362306a36Sopenharmony_ci		set_bit(BTRFS_FS_FEATURE_CHANGED, &fs_info->flags);
7462306a36Sopenharmony_ci	}
7562306a36Sopenharmony_ci}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_civoid __btrfs_clear_fs_compat_ro(struct btrfs_fs_info *fs_info, u64 flag,
7862306a36Sopenharmony_ci				const char *name)
7962306a36Sopenharmony_ci{
8062306a36Sopenharmony_ci	struct btrfs_super_block *disk_super;
8162306a36Sopenharmony_ci	u64 features;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	disk_super = fs_info->super_copy;
8462306a36Sopenharmony_ci	features = btrfs_super_compat_ro_flags(disk_super);
8562306a36Sopenharmony_ci	if (features & flag) {
8662306a36Sopenharmony_ci		spin_lock(&fs_info->super_lock);
8762306a36Sopenharmony_ci		features = btrfs_super_compat_ro_flags(disk_super);
8862306a36Sopenharmony_ci		if (features & flag) {
8962306a36Sopenharmony_ci			features &= ~flag;
9062306a36Sopenharmony_ci			btrfs_set_super_compat_ro_flags(disk_super, features);
9162306a36Sopenharmony_ci			btrfs_info(fs_info,
9262306a36Sopenharmony_ci				"clearing compat-ro feature flag for %s (0x%llx)",
9362306a36Sopenharmony_ci				name, flag);
9462306a36Sopenharmony_ci		}
9562306a36Sopenharmony_ci		spin_unlock(&fs_info->super_lock);
9662306a36Sopenharmony_ci		set_bit(BTRFS_FS_FEATURE_CHANGED, &fs_info->flags);
9762306a36Sopenharmony_ci	}
9862306a36Sopenharmony_ci}
99