#include <linux/sched.h>
#include <linux/sched/mm.h>
#include <linux/slab.h>
#include <linux/ratelimit.h>
#include <linux/kthread.h>
#include <linux/semaphore.h>
#include <linux/uuid.h>
#include <linux/list_sort.h>
#include <linux/namei.h>
#include "misc.h"
#include "ctree.h"
#include "disk-io.h"
#include "transaction.h"
#include "volumes.h"
#include "raid56.h"
#include "rcu-string.h"
#include "dev-replace.h"
#include "sysfs.h"
#include "tree-checker.h"
#include "space-info.h"
#include "block-group.h"
#include "discard.h"
#include "zoned.h"
#include "fs.h"
#include "accessors.h"
#include "uuid-tree.h"
#include "ioctl.h"
#include "relocation.h"
#include "scrub.h"
#include "super.h"
#include "raid-stripe-tree.h"
#define BTRFS_BLOCK_GROUP_STRIPE_MASK …
struct btrfs_io_geometry { … };
const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = …;
enum btrfs_raid_types __attribute_const__ btrfs_bg_flags_to_raid_index(u64 flags)
{ … }
const char *btrfs_bg_type_to_raid_name(u64 flags)
{ … }
int btrfs_nr_parity_stripes(u64 type)
{ … }
void btrfs_describe_block_groups(u64 bg_flags, char *buf, u32 size_buf)
{ … }
static int init_first_rw_device(struct btrfs_trans_handle *trans);
static int btrfs_relocate_sys_chunks(struct btrfs_fs_info *fs_info);
static void btrfs_dev_stat_print_on_load(struct btrfs_device *device);
DEFINE_MUTEX(…) …;
static LIST_HEAD(fs_uuids);
struct list_head * __attribute_const__ btrfs_get_fs_uuids(void)
{ … }
static struct btrfs_fs_devices *alloc_fs_devices(const u8 *fsid)
{ … }
static void btrfs_free_device(struct btrfs_device *device)
{ … }
static void free_fs_devices(struct btrfs_fs_devices *fs_devices)
{ … }
void __exit btrfs_cleanup_fs_uuids(void)
{ … }
static bool match_fsid_fs_devices(const struct btrfs_fs_devices *fs_devices,
const u8 *fsid, const u8 *metadata_fsid)
{ … }
static noinline struct btrfs_fs_devices *find_fsid(
const u8 *fsid, const u8 *metadata_fsid)
{ … }
static int
btrfs_get_bdev_and_sb(const char *device_path, blk_mode_t flags, void *holder,
int flush, struct file **bdev_file,
struct btrfs_super_block **disk_super)
{ … }
static int btrfs_free_stale_devices(dev_t devt, struct btrfs_device *skip_device)
{ … }
static struct btrfs_fs_devices *find_fsid_by_device(
struct btrfs_super_block *disk_super,
dev_t devt, bool *same_fsid_diff_dev)
{ … }
static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices,
struct btrfs_device *device, blk_mode_t flags,
void *holder)
{ … }
const u8 *btrfs_sb_fsid_ptr(const struct btrfs_super_block *sb)
{ … }
static noinline struct btrfs_device *device_list_add(const char *path,
struct btrfs_super_block *disk_super,
bool *new_device_added)
{ … }
static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig)
{ … }
static void __btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices,
struct btrfs_device **latest_dev)
{ … }
void btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices)
{ … }
static void btrfs_close_bdev(struct btrfs_device *device)
{ … }
static void btrfs_close_one_device(struct btrfs_device *device)
{ … }
static void close_fs_devices(struct btrfs_fs_devices *fs_devices)
{ … }
void btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
{ … }
static int open_fs_devices(struct btrfs_fs_devices *fs_devices,
blk_mode_t flags, void *holder)
{ … }
static int devid_cmp(void *priv, const struct list_head *a,
const struct list_head *b)
{ … }
int btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
blk_mode_t flags, void *holder)
{ … }
void btrfs_release_disk_super(struct btrfs_super_block *super)
{ … }
static struct btrfs_super_block *btrfs_read_disk_super(struct block_device *bdev,
u64 bytenr, u64 bytenr_orig)
{ … }
int btrfs_forget_devices(dev_t devt)
{ … }
static bool btrfs_skip_registration(struct btrfs_super_block *disk_super,
const char *path, dev_t devt,
bool mount_arg_dev)
{ … }
struct btrfs_device *btrfs_scan_one_device(const char *path, blk_mode_t flags,
bool mount_arg_dev)
{ … }
static bool contains_pending_extent(struct btrfs_device *device, u64 *start,
u64 len)
{ … }
static u64 dev_extent_search_start(struct btrfs_device *device)
{ … }
static bool dev_extent_hole_check_zoned(struct btrfs_device *device,
u64 *hole_start, u64 *hole_size,
u64 num_bytes)
{ … }
static bool dev_extent_hole_check(struct btrfs_device *device, u64 *hole_start,
u64 *hole_size, u64 num_bytes)
{ … }
static int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes,
u64 *start, u64 *len)
{ … }
static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans,
struct btrfs_device *device,
u64 start, u64 *dev_extent_len)
{ … }
static u64 find_next_chunk(struct btrfs_fs_info *fs_info)
{ … }
static noinline int find_next_devid(struct btrfs_fs_info *fs_info,
u64 *devid_ret)
{ … }
static int btrfs_add_dev_item(struct btrfs_trans_handle *trans,
struct btrfs_device *device)
{ … }
static void update_dev_time(const char *device_path)
{ … }
static int btrfs_rm_dev_item(struct btrfs_trans_handle *trans,
struct btrfs_device *device)
{ … }
static int btrfs_check_raid_min_devices(struct btrfs_fs_info *fs_info,
u64 num_devices)
{ … }
static struct btrfs_device * btrfs_find_next_active_device(
struct btrfs_fs_devices *fs_devs, struct btrfs_device *device)
{ … }
void __cold btrfs_assign_next_active_device(struct btrfs_device *device,
struct btrfs_device *next_device)
{ … }
static u64 btrfs_num_devices(struct btrfs_fs_info *fs_info)
{ … }
static void btrfs_scratch_superblock(struct btrfs_fs_info *fs_info,
struct block_device *bdev, int copy_num)
{ … }
void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info, struct btrfs_device *device)
{ … }
int btrfs_rm_device(struct btrfs_fs_info *fs_info,
struct btrfs_dev_lookup_args *args,
struct file **bdev_file)
{ … }
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)
{ … }
int btrfs_get_dev_args_from_path(struct btrfs_fs_info *fs_info,
struct btrfs_dev_lookup_args *args,
const char *path)
{ … }
void btrfs_put_dev_args_from_path(struct btrfs_dev_lookup_args *args)
{ … }
struct btrfs_device *btrfs_find_device_by_devspec(
struct btrfs_fs_info *fs_info, u64 devid,
const char *device_path)
{ … }
static struct btrfs_fs_devices *btrfs_init_sprout(struct btrfs_fs_info *fs_info)
{ … }
static void btrfs_setup_sprout(struct btrfs_fs_info *fs_info,
struct btrfs_fs_devices *seed_devices)
{ … }
static int btrfs_finish_sprout(struct btrfs_trans_handle *trans)
{ … }
int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path)
{ … }
static noinline int btrfs_update_device(struct btrfs_trans_handle *trans,
struct btrfs_device *device)
{ … }
int btrfs_grow_device(struct btrfs_trans_handle *trans,
struct btrfs_device *device, u64 new_size)
{ … }
static int btrfs_free_chunk(struct btrfs_trans_handle *trans, u64 chunk_offset)
{ … }
static int btrfs_del_sys_chunk(struct btrfs_fs_info *fs_info, u64 chunk_offset)
{ … }
struct btrfs_chunk_map *btrfs_find_chunk_map_nolock(struct btrfs_fs_info *fs_info,
u64 logical, u64 length)
{ … }
struct btrfs_chunk_map *btrfs_find_chunk_map(struct btrfs_fs_info *fs_info,
u64 logical, u64 length)
{ … }
struct btrfs_chunk_map *btrfs_get_chunk_map(struct btrfs_fs_info *fs_info,
u64 logical, u64 length)
{ … }
static int remove_chunk_item(struct btrfs_trans_handle *trans,
struct btrfs_chunk_map *map, u64 chunk_offset)
{ … }
int btrfs_remove_chunk(struct btrfs_trans_handle *trans, u64 chunk_offset)
{ … }
int btrfs_relocate_chunk(struct btrfs_fs_info *fs_info, u64 chunk_offset)
{ … }
static int btrfs_relocate_sys_chunks(struct btrfs_fs_info *fs_info)
{ … }
static int btrfs_may_alloc_data_chunk(struct btrfs_fs_info *fs_info,
u64 chunk_offset)
{ … }
static void btrfs_disk_balance_args_to_cpu(struct btrfs_balance_args *cpu,
const struct btrfs_disk_balance_args *disk)
{ … }
static void btrfs_cpu_balance_args_to_disk(struct btrfs_disk_balance_args *disk,
const struct btrfs_balance_args *cpu)
{ … }
static int insert_balance_item(struct btrfs_fs_info *fs_info,
struct btrfs_balance_control *bctl)
{ … }
static int del_balance_item(struct btrfs_fs_info *fs_info)
{ … }
static void update_balance_args(struct btrfs_balance_control *bctl)
{ … }
static void reset_balance_state(struct btrfs_fs_info *fs_info)
{ … }
static int chunk_profiles_filter(u64 chunk_type,
struct btrfs_balance_args *bargs)
{ … }
static int chunk_usage_range_filter(struct btrfs_fs_info *fs_info, u64 chunk_offset,
struct btrfs_balance_args *bargs)
{ … }
static int chunk_usage_filter(struct btrfs_fs_info *fs_info,
u64 chunk_offset, struct btrfs_balance_args *bargs)
{ … }
static int chunk_devid_filter(struct extent_buffer *leaf,
struct btrfs_chunk *chunk,
struct btrfs_balance_args *bargs)
{ … }
static u64 calc_data_stripes(u64 type, int num_stripes)
{ … }
static int chunk_drange_filter(struct extent_buffer *leaf,
struct btrfs_chunk *chunk,
struct btrfs_balance_args *bargs)
{ … }
static int chunk_vrange_filter(struct extent_buffer *leaf,
struct btrfs_chunk *chunk,
u64 chunk_offset,
struct btrfs_balance_args *bargs)
{ … }
static int chunk_stripes_range_filter(struct extent_buffer *leaf,
struct btrfs_chunk *chunk,
struct btrfs_balance_args *bargs)
{ … }
static int chunk_soft_convert_filter(u64 chunk_type,
struct btrfs_balance_args *bargs)
{ … }
static int should_balance_chunk(struct extent_buffer *leaf,
struct btrfs_chunk *chunk, u64 chunk_offset)
{ … }
static int __btrfs_balance(struct btrfs_fs_info *fs_info)
{ … }
static int alloc_profile_is_valid(u64 flags, int extended)
{ … }
static inline int validate_convert_profile(struct btrfs_fs_info *fs_info,
const struct btrfs_balance_args *bargs,
u64 allowed, const char *type)
{ … }
static void describe_balance_args(struct btrfs_balance_args *bargs, char *buf,
u32 size_buf)
{ … }
static void describe_balance_start_or_resume(struct btrfs_fs_info *fs_info)
{ … }
int btrfs_balance(struct btrfs_fs_info *fs_info,
struct btrfs_balance_control *bctl,
struct btrfs_ioctl_balance_args *bargs)
{ … }
static int balance_kthread(void *data)
{ … }
int btrfs_resume_balance_async(struct btrfs_fs_info *fs_info)
{ … }
int btrfs_recover_balance(struct btrfs_fs_info *fs_info)
{ … }
int btrfs_pause_balance(struct btrfs_fs_info *fs_info)
{ … }
int btrfs_cancel_balance(struct btrfs_fs_info *fs_info)
{ … }
int btrfs_uuid_scan_kthread(void *data)
{ … }
int btrfs_create_uuid_tree(struct btrfs_fs_info *fs_info)
{ … }
int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
{ … }
static int btrfs_add_system_chunk(struct btrfs_fs_info *fs_info,
struct btrfs_key *key,
struct btrfs_chunk *chunk, int item_size)
{ … }
static int btrfs_cmp_device_info(const void *a, const void *b)
{ … }
static void check_raid56_incompat_flag(struct btrfs_fs_info *info, u64 type)
{ … }
static void check_raid1c34_incompat_flag(struct btrfs_fs_info *info, u64 type)
{ … }
struct alloc_chunk_ctl { … };
static void init_alloc_chunk_ctl_policy_regular(
struct btrfs_fs_devices *fs_devices,
struct alloc_chunk_ctl *ctl)
{ … }
static void init_alloc_chunk_ctl_policy_zoned(
struct btrfs_fs_devices *fs_devices,
struct alloc_chunk_ctl *ctl)
{ … }
static void init_alloc_chunk_ctl(struct btrfs_fs_devices *fs_devices,
struct alloc_chunk_ctl *ctl)
{ … }
static int gather_device_info(struct btrfs_fs_devices *fs_devices,
struct alloc_chunk_ctl *ctl,
struct btrfs_device_info *devices_info)
{ … }
static int decide_stripe_size_regular(struct alloc_chunk_ctl *ctl,
struct btrfs_device_info *devices_info)
{ … }
static int decide_stripe_size_zoned(struct alloc_chunk_ctl *ctl,
struct btrfs_device_info *devices_info)
{ … }
static int decide_stripe_size(struct btrfs_fs_devices *fs_devices,
struct alloc_chunk_ctl *ctl,
struct btrfs_device_info *devices_info)
{ … }
static void chunk_map_device_set_bits(struct btrfs_chunk_map *map, unsigned int bits)
{ … }
static void chunk_map_device_clear_bits(struct btrfs_chunk_map *map, unsigned int bits)
{ … }
void btrfs_remove_chunk_map(struct btrfs_fs_info *fs_info, struct btrfs_chunk_map *map)
{ … }
EXPORT_FOR_TESTS
int btrfs_add_chunk_map(struct btrfs_fs_info *fs_info, struct btrfs_chunk_map *map)
{ … }
EXPORT_FOR_TESTS
struct btrfs_chunk_map *btrfs_alloc_chunk_map(int num_stripes, gfp_t gfp)
{ … }
static struct btrfs_block_group *create_chunk(struct btrfs_trans_handle *trans,
struct alloc_chunk_ctl *ctl,
struct btrfs_device_info *devices_info)
{ … }
struct btrfs_block_group *btrfs_create_chunk(struct btrfs_trans_handle *trans,
u64 type)
{ … }
int btrfs_chunk_alloc_add_chunk_item(struct btrfs_trans_handle *trans,
struct btrfs_block_group *bg)
{ … }
static noinline int init_first_rw_device(struct btrfs_trans_handle *trans)
{ … }
static inline int btrfs_chunk_max_errors(struct btrfs_chunk_map *map)
{ … }
bool btrfs_chunk_writeable(struct btrfs_fs_info *fs_info, u64 chunk_offset)
{ … }
void btrfs_mapping_tree_free(struct btrfs_fs_info *fs_info)
{ … }
int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len)
{ … }
unsigned long btrfs_full_stripe_len(struct btrfs_fs_info *fs_info,
u64 logical)
{ … }
int btrfs_is_parity_mirror(struct btrfs_fs_info *fs_info, u64 logical, u64 len)
{ … }
static int find_live_mirror(struct btrfs_fs_info *fs_info,
struct btrfs_chunk_map *map, int first,
int dev_replace_is_ongoing)
{ … }
static struct btrfs_io_context *alloc_btrfs_io_context(struct btrfs_fs_info *fs_info,
u64 logical,
u16 total_stripes)
{ … }
void btrfs_get_bioc(struct btrfs_io_context *bioc)
{ … }
void btrfs_put_bioc(struct btrfs_io_context *bioc)
{ … }
struct btrfs_discard_stripe *btrfs_map_discard(struct btrfs_fs_info *fs_info,
u64 logical, u64 *length_ret,
u32 *num_stripes)
{ … }
static bool is_block_group_to_copy(struct btrfs_fs_info *fs_info, u64 logical)
{ … }
static void handle_ops_on_dev_replace(struct btrfs_io_context *bioc,
struct btrfs_dev_replace *dev_replace,
u64 logical,
struct btrfs_io_geometry *io_geom)
{ … }
static u64 btrfs_max_io_len(struct btrfs_chunk_map *map, u64 offset,
struct btrfs_io_geometry *io_geom)
{ … }
static int set_io_stripe(struct btrfs_fs_info *fs_info, u64 logical,
u64 *length, struct btrfs_io_stripe *dst,
struct btrfs_chunk_map *map,
struct btrfs_io_geometry *io_geom)
{ … }
static bool is_single_device_io(struct btrfs_fs_info *fs_info,
const struct btrfs_io_stripe *smap,
const struct btrfs_chunk_map *map,
int num_alloc_stripes,
enum btrfs_map_op op, int mirror_num)
{ … }
static void map_blocks_raid0(const struct btrfs_chunk_map *map,
struct btrfs_io_geometry *io_geom)
{ … }
static void map_blocks_raid1(struct btrfs_fs_info *fs_info,
struct btrfs_chunk_map *map,
struct btrfs_io_geometry *io_geom,
bool dev_replace_is_ongoing)
{ … }
static void map_blocks_dup(const struct btrfs_chunk_map *map,
struct btrfs_io_geometry *io_geom)
{ … }
static void map_blocks_raid10(struct btrfs_fs_info *fs_info,
struct btrfs_chunk_map *map,
struct btrfs_io_geometry *io_geom,
bool dev_replace_is_ongoing)
{ … }
static void map_blocks_raid56_write(struct btrfs_chunk_map *map,
struct btrfs_io_geometry *io_geom,
u64 logical, u64 *length)
{ … }
static void map_blocks_raid56_read(struct btrfs_chunk_map *map,
struct btrfs_io_geometry *io_geom)
{ … }
static void map_blocks_single(const struct btrfs_chunk_map *map,
struct btrfs_io_geometry *io_geom)
{ … }
int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
u64 logical, u64 *length,
struct btrfs_io_context **bioc_ret,
struct btrfs_io_stripe *smap, int *mirror_num_ret)
{ … }
static bool dev_args_match_fs_devices(const struct btrfs_dev_lookup_args *args,
const struct btrfs_fs_devices *fs_devices)
{ … }
static bool dev_args_match_device(const struct btrfs_dev_lookup_args *args,
const struct btrfs_device *device)
{ … }
struct btrfs_device *btrfs_find_device(const struct btrfs_fs_devices *fs_devices,
const struct btrfs_dev_lookup_args *args)
{ … }
static struct btrfs_device *add_missing_dev(struct btrfs_fs_devices *fs_devices,
u64 devid, u8 *dev_uuid)
{ … }
struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info,
const u64 *devid, const u8 *uuid,
const char *path)
{ … }
static void btrfs_report_missing_device(struct btrfs_fs_info *fs_info,
u64 devid, u8 *uuid, bool error)
{ … }
u64 btrfs_calc_stripe_length(const struct btrfs_chunk_map *map)
{ … }
#if BITS_PER_LONG == 32
static int check_32bit_meta_chunk(struct btrfs_fs_info *fs_info,
u64 logical, u64 length, u64 type)
{
if (!(type & BTRFS_BLOCK_GROUP_METADATA))
return 0;
if (logical + length < MAX_LFS_FILESIZE)
return 0;
btrfs_err_32bit_limit(fs_info);
return -EOVERFLOW;
}
static void warn_32bit_meta_chunk(struct btrfs_fs_info *fs_info,
u64 logical, u64 length, u64 type)
{
if (!(type & BTRFS_BLOCK_GROUP_METADATA))
return;
if (logical + length < BTRFS_32BIT_EARLY_WARN_THRESHOLD)
return;
btrfs_warn_32bit_limit(fs_info);
}
#endif
static struct btrfs_device *handle_missing_device(struct btrfs_fs_info *fs_info,
u64 devid, u8 *uuid)
{ … }
static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
struct btrfs_chunk *chunk)
{ … }
static void fill_device_from_item(struct extent_buffer *leaf,
struct btrfs_dev_item *dev_item,
struct btrfs_device *device)
{ … }
static struct btrfs_fs_devices *open_seed_devices(struct btrfs_fs_info *fs_info,
u8 *fsid)
{ … }
static int read_one_dev(struct extent_buffer *leaf,
struct btrfs_dev_item *dev_item)
{ … }
int btrfs_read_sys_array(struct btrfs_fs_info *fs_info)
{ … }
bool btrfs_check_rw_degradable(struct btrfs_fs_info *fs_info,
struct btrfs_device *failing_dev)
{ … }
static void readahead_tree_node_children(struct extent_buffer *node)
{ … }
int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
{ … }
int btrfs_init_devices_late(struct btrfs_fs_info *fs_info)
{ … }
static u64 btrfs_dev_stats_value(const struct extent_buffer *eb,
const struct btrfs_dev_stats_item *ptr,
int index)
{ … }
static void btrfs_set_dev_stats_value(struct extent_buffer *eb,
struct btrfs_dev_stats_item *ptr,
int index, u64 val)
{ … }
static int btrfs_device_init_dev_stats(struct btrfs_device *device,
struct btrfs_path *path)
{ … }
int btrfs_init_dev_stats(struct btrfs_fs_info *fs_info)
{ … }
static int update_dev_stat_item(struct btrfs_trans_handle *trans,
struct btrfs_device *device)
{ … }
int btrfs_run_dev_stats(struct btrfs_trans_handle *trans)
{ … }
void btrfs_dev_stat_inc_and_print(struct btrfs_device *dev, int index)
{ … }
static void btrfs_dev_stat_print_on_load(struct btrfs_device *dev)
{ … }
int btrfs_get_dev_stats(struct btrfs_fs_info *fs_info,
struct btrfs_ioctl_get_dev_stats *stats)
{ … }
void btrfs_commit_device_sizes(struct btrfs_transaction *trans)
{ … }
int btrfs_bg_type_to_factor(u64 flags)
{ … }
static int verify_one_dev_extent(struct btrfs_fs_info *fs_info,
u64 chunk_offset, u64 devid,
u64 physical_offset, u64 physical_len)
{ … }
static int verify_chunk_dev_extent_mapping(struct btrfs_fs_info *fs_info)
{ … }
int btrfs_verify_dev_extents(struct btrfs_fs_info *fs_info)
{ … }
bool btrfs_pinned_by_swapfile(struct btrfs_fs_info *fs_info, void *ptr)
{ … }
static int relocating_repair_kthread(void *data)
{ … }
bool btrfs_repair_one_zone(struct btrfs_fs_info *fs_info, u64 logical)
{ … }
static void map_raid56_repair_block(struct btrfs_io_context *bioc,
struct btrfs_io_stripe *smap,
u64 logical)
{ … }
int btrfs_map_repair_block(struct btrfs_fs_info *fs_info,
struct btrfs_io_stripe *smap, u64 logical,
u32 length, int mirror_num)
{ … }