本篇文章主要内容来自 btrfs 文件系统的 ioctl 的官方接口文档,并在原文档的基础上,结合 Btrfs 内核代码的实现,补充了很多原文档缺失的内容,我愿称之为 btrfs-ioctl (2) plus。
⚠️请注意, ioctl
的数量、含义和定义会随着时间改变,本文内容参考了 Linux v6.13.7 版本的代码,完稿时间为 2025 年 4 月 11 日,如果时间相差很远的话请自行验证文章内容的正确性。同时,由于笔者水平有限,如果有任何错误,恳请指正 Orz。
# 速览
# 数据结构与定义
# btrfs_ioctl_vol_args
/* this should be 4k */ | |
#define BTRFS_PATH_NAME_MAX 4087 | |
struct btrfs_ioctl_vol_args { | |
__s64 fd; | |
char name[BTRFS_PATH_NAME_MAX + 1]; | |
}; |
# btrfs_ioctl_vol_args_v2
#define BTRFS_SUBVOL_RDONLY (1ULL << 1) | |
#define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2) | |
#define BTRFS_DEVICE_SPEC_BY_ID (1ULL << 3) | |
#define BTRFS_SUBVOL_SPEC_BY_ID (1ULL << 4) | |
#define BTRFS_SUBVOL_NAME_MAX 4039 | |
struct btrfs_ioctl_vol_args_v2 { | |
__s64 fd; | |
__u64 transid; | |
__u64 flags; | |
union { | |
struct { | |
__u64 size; | |
struct btrfs_qgroup_inherit __user *qgroup_inherit; | |
}; | |
__u64 unused[4]; | |
}; | |
union { | |
char name[BTRFS_SUBVOL_NAME_MAX + 1]; | |
__u64 devid; | |
__u64 subvolid; | |
}; | |
}; |
#define BTRFS_QGROUP_INHERIT_SET_LIMITS (1ULL << 0) | |
struct btrfs_qgroup_inherit { | |
__u64 flags; | |
__u64 num_qgroups; | |
__u64 num_ref_copies; | |
__u64 num_excl_copies; | |
struct btrfs_qgroup_limit lim; | |
__u64 qgroups[]; | |
}; |
#define BTRFS_QGROUP_LIMIT_MAX_RFER (1ULL << 0) | |
#define BTRFS_QGROUP_LIMIT_MAX_EXCL (1ULL << 1) | |
#define BTRFS_QGROUP_LIMIT_RSV_RFER (1ULL << 2) | |
#define BTRFS_QGROUP_LIMIT_RSV_EXCL (1ULL << 3) | |
#define BTRFS_QGROUP_LIMIT_RFER_CMPR (1ULL << 4) | |
#define BTRFS_QGROUP_LIMIT_EXCL_CMPR (1ULL << 5) | |
struct btrfs_qgroup_limit { | |
__u64 flags; | |
__u64 max_rfer; | |
__u64 max_excl; | |
__u64 rsv_rfer; | |
__u64 rsv_excl; | |
}; |
# btrfs_ioctl_get_subvol_info_args
#define BTRFS_VOL_NAME_MAX 255 | |
#define BTRFS_UUID_SIZE 16 | |
struct btrfs_ioctl_get_subvol_info_args { | |
__u64 treeid; /* 此子卷的 ID */ | |
char name[BTRFS_VOL_NAME_MAX + 1]; /* 子卷名称,用于获取挂载点的真实名称 */ | |
__u64 parent_id; /* 包含此子卷的父卷 ID,顶层子卷或已删除子卷为 0 */ | |
__u64 dirid; /* 包含此子卷的目录的 inode 号,顶层子卷或已删除子卷为 0 */ | |
__u64 generation; /* 子卷的最新事务 ID */ | |
__u64 flags; /* 子卷标志 */ | |
__u8 uuid[BTRFS_UUID_SIZE]; /* 子卷 UUID */ | |
__u8 parent_uuid[BTRFS_UUID_SIZE]; /* 如果当前子卷是某个子卷的快照,就保存那个原始子卷的 UUID。否则为全 0。 */ | |
__u8 received_uuid[BTRFS_UUID_SIZE]; /* 如果这个子卷是通过 btrfs receive 创建的,这里记录 “发送方的源子卷 UUID”。否则全为 0 */ | |
/* 创建 / 修改 / 发送 / 接收操作的事务 ID */ | |
__u64 ctransid; | |
__u64 otransid; | |
__u64 stransid; | |
__u64 rtransid; | |
/* 对应 c/o/s/rtransid 的时间 */ | |
struct btrfs_ioctl_timespec ctime; | |
struct btrfs_ioctl_timespec otime; | |
struct btrfs_ioctl_timespec stime; | |
struct btrfs_ioctl_timespec rtime; | |
__u64 reserved[8]; /* 必须为 0 */ | |
}; |
struct btrfs_ioctl_timespec { | |
__u64 sec; | |
__u32 nsec; | |
}; |
# btrfs_ioctl_received_subvol_args
#define BTRFS_UUID_SIZE 16 | |
struct btrfs_ioctl_received_subvol_args { | |
char uuid[BTRFS_UUID_SIZE]; /* 输入 */ | |
__u64 stransid; /* 输入 */ | |
__u64 rtransid; /* 输出 */ | |
struct btrfs_ioctl_timespec stime; /* 输入 */ | |
struct btrfs_ioctl_timespec rtime; /* 输出 */ | |
__u64 flags; /* 输入 */ | |
__u64 reserved[16]; /* 输入 */ | |
}; |
参见 struct btrfs_ioctl_timespec
# btrfs_ioctl_fs_info_args
/* 请求校验和类型和大小信息 */ | |
#define BTRFS_FS_INFO_FLAG_CSUM_INFO (1U << 0) | |
/* 请求文件系统代际(generation)信息 */ | |
#define BTRFS_FS_INFO_FLAG_GENERATION (1U << 1) | |
/* 请求文件系统元数据 UUID */ | |
#define BTRFS_FS_INFO_FLAG_METADATA_UUID (1U << 2) | |
#define BTRFS_FSID_SIZE 16 | |
struct btrfs_ioctl_fs_info_args { | |
__u64 max_id; /* 输出 */ | |
__u64 num_devices; /* 输出 */ | |
__u8 fsid[BTRFS_FSID_SIZE]; /* 输出 */ | |
__u32 nodesize; /* 输出 */ | |
__u32 sectorsize; /* 输出 */ | |
__u32 clone_alignment; /* 输出 */ | |
__u16 csum_type; /* 输出 */ | |
__u16 csum_size; /* 输出 */ | |
__u64 flags; /* 输入 / 输出 */ | |
__u64 generation; /* 输出 */ | |
__u8 metadata_uuid[BTRFS_FSID_SIZE]; /* 输出 */ | |
__u8 reserved[944]; /* 填充至 1KB */ | |
}; |
# btrfs_ioctl_ino_lookup_args
#define BTRFS_INO_LOOKUP_PATH_MAX 4080 | |
struct btrfs_ioctl_ino_lookup_args { | |
__u64 treeid; | |
__u64 objectid; | |
char name[BTRFS_INO_LOOKUP_PATH_MAX]; | |
}; |
# btrfs_ioctl_subvol_wait
/* 等待指定的 subvolid 删除完成(清理结束) */ | |
#define BTRFS_SUBVOL_SYNC_WAIT_FOR_ONE (0) | |
/* 等待所有队列中的子卷清除完成 */ | |
#define BTRFS_SUBVOL_SYNC_WAIT_FOR_QUEUED (1) | |
/* 统计队列中的子卷数 */ | |
#define BTRFS_SUBVOL_SYNC_COUNT (2) | |
/* 读取清理队列中第一个子卷 ID(即 " 正在清理” 或 “马上要清理” 的那个)(若为空则为 0) */ | |
#define BTRFS_SUBVOL_SYNC_PEEK_FIRST (3) | |
/* 查看队列中的最后一个子卷 ID(若为空则为 0) */ | |
#define BTRFS_SUBVOL_SYNC_PEEK_LAST (4) | |
struct btrfs_ioctl_subvol_wait { | |
__u64 subvolid; /* 子卷(包括快照)的唯一 ID */ | |
__u32 mode; | |
__u32 count; | |
}; |
# btrfs_ioctl_clone_range_args
/* 如果把 src_length 设置为 0,那就表示 “从 src_offset 开始,一直到源文件结尾 (EOF) 的内容都会被克隆”。 */ | |
struct btrfs_ioctl_clone_range_args { | |
__s64 src_fd; | |
__u64 src_offset, src_length; | |
__u64 dest_offset; | |
}; |
# btrfs_ioctl_defrag_range_args
/* | |
* 用于碎片整理区间 ioctl 的标志定义 | |
* | |
* 使用于: | |
* struct btrfs_ioctl_defrag_range_args.flags | |
*/ | |
#define BTRFS_DEFRAG_RANGE_COMPRESS 1 // 开启压缩功能 | |
#define BTRFS_DEFRAG_RANGE_START_IO 2 // 启动 I/O 操作 | |
#define BTRFS_DEFRAG_RANGE_FLAGS_SUPP (BTRFS_DEFRAG_RANGE_COMPRESS | \ | |
BTRFS_DEFRAG_RANGE_START_IO) // 支持的标志位(压缩 + 启动 IO) | |
struct btrfs_ioctl_defrag_range_args { | |
/* 碎片整理操作的起始位置 */ | |
__u64 start; | |
/* 要整理的字节数,使用 (u64)-1 表示 “整理全部” */ | |
__u64 len; | |
/* 操作标志,可以用来开启本次整理中的压缩功能 */ | |
__u64 flags; | |
/* 任何大于该值的 extent(连续块)会被认为已经整理过。*/ | |
/* 使用 0 表示使用内核默认值;*/ | |
/* 使用 1 表示每一个 extent 都必须被重写。*/ | |
__u32 extent_thresh; | |
/* 如果开启压缩,本字段用于指定使用哪种压缩方法。*/ | |
/* 如果未指定,默认使用 zlib。*/ | |
__u32 compress_type; | |
/* 保留字段,供将来使用 */ | |
__u32 unused[4]; | |
}; |
# btrfs_ioctl_search_args
#define BTRFS_SEARCH_ARGS_BUFSIZE (4096 - sizeof(struct btrfs_ioctl_search_key)) | |
/* buf 是一个由多个搜索头(search header)组成的数组,*/ | |
/* 每个头部后面紧跟着实际的 item(项目)。*/ | |
/* 为了对齐(alignment),type 字段被扩展为 32 位。*/ | |
struct btrfs_ioctl_search_args { | |
struct btrfs_ioctl_search_key key; | |
char buf[BTRFS_SEARCH_ARGS_BUFSIZE]; | |
}; |
/* Btrfs SEARCH ioctl 系列命令的搜索条件 */ | |
struct btrfs_ioctl_search_key { | |
/* | |
* 要搜索的树 ID。1 表示 “树根树”,2 表示 “extent 树”,等等…… | |
* | |
* 如果 tree_id 设置为特殊值 0,则会在传递给 ioctl 的 inode 所在的子卷树中进行搜索。 | |
*/ | |
__u64 tree_id; /* 输入 */ | |
/* | |
* 执行树搜索时,实际上是从一个 136 位线性搜索空间中取出一个区间。 | |
* | |
* 一个完整的 136 位树键(tree key)格式如下: | |
* (objectid << 72) + (type << 64) + offset | |
* | |
* 对 objectid、type 和 offset 的最小值和最大值定义了搜索区间的 | |
* min_key 到 max_key 范围。所有落在该范围 [min_key, max_key] | |
* 内的元数据项(metadata item)将会被返回。 | |
* | |
* 另外,也可以通过指定事务 ID 范围(transid)来过滤返回的项,这些 ID | |
* 表示这些元数据块最后一次被写入时所属的事务(COW 操作后的写入)。 | |
* 需要注意的是,这个事务 ID 只是说明该元数据页最近一次被写入的事务, | |
* 并不代表某个具体 item 是在哪个事务中创建或修改的。 | |
*/ | |
__u64 min_objectid; /* 输入 */ | |
__u64 max_objectid; /* 输入 */ | |
__u64 min_offset; /* 输入 */ | |
__u64 max_offset; /* 输入 */ | |
__u64 min_transid; /* 输入 */ | |
__u64 max_transid; /* 输入 */ | |
__u32 min_type; /* 输入 */ | |
__u32 max_type; /* 输入 */ | |
/* | |
* 输入:期望返回的最大 item 数量; | |
* 输出:实际返回的 item 数量,受以下限制之一: | |
* - 达到搜索范围的上限; | |
* - 达到输入指定的 nr_items 数量; | |
* - 填满了提供的内存缓冲区。 | |
*/ | |
__u32 nr_items; /* 输入 / 输出 */ | |
/* 为对齐到 64 位而保留 */ | |
__u32 unused; | |
/* 保留字段,用于将来扩展 */ | |
__u64 unused1; | |
__u64 unused2; | |
__u64 unused3; | |
__u64 unused4; | |
}; |
# btrfs_ioctl_search_args_v2
/* | |
* TREE_SEARCH ioctl 的扩展版本,允许返回超过 4KB 的数据。 | |
* 通过 buf_size 指定缓冲区的分配大小。 | |
*/ | |
struct btrfs_ioctl_search_args_v2 { | |
struct btrfs_ioctl_search_key key; /* 输入 / 输出 - 搜索参数 */ | |
__u64 buf_size; /* 输入 - 缓冲区大小 | |
* 输出 - 若返回 EOVERFLOW: 表示存储所有 item 所需的大小 */ | |
__u64 buf[]; /* 输出 - 搜索到的条目 */ | |
}; |
# btrfs_ioctl_space_args
struct btrfs_ioctl_space_args { | |
__u64 space_slots; | |
__u64 total_spaces; | |
struct btrfs_ioctl_space_info spaces[]; | |
}; |
struct btrfs_ioctl_space_info { | |
__u64 flags; //flags 代表不同空间类型,参考下面的代码块 | |
__u64 total_bytes; | |
__u64 used_bytes; | |
}; |
/* different types of block groups (and chunks) */ | |
#define BTRFS_BLOCK_GROUP_DATA (1ULL << 0) | |
#define BTRFS_BLOCK_GROUP_SYSTEM (1ULL << 1) | |
#define BTRFS_BLOCK_GROUP_METADATA (1ULL << 2) | |
#define BTRFS_BLOCK_GROUP_RAID0 (1ULL << 3) | |
#define BTRFS_BLOCK_GROUP_RAID1 (1ULL << 4) | |
#define BTRFS_BLOCK_GROUP_DUP (1ULL << 5) | |
#define BTRFS_BLOCK_GROUP_RAID10 (1ULL << 6) | |
#define BTRFS_BLOCK_GROUP_RAID5 (1ULL << 7) | |
#define BTRFS_BLOCK_GROUP_RAID6 (1ULL << 8) | |
#define BTRFS_BLOCK_GROUP_RAID1C3 (1ULL << 9) | |
#define BTRFS_BLOCK_GROUP_RAID1C4 (1ULL << 10) | |
#define BTRFS_BLOCK_GROUP_RESERVED (BTRFS_AVAIL_ALLOC_BIT_SINGLE | \ | |
BTRFS_SPACE_INFO_GLOBAL_RSV) | |
#define BTRFS_BLOCK_GROUP_TYPE_MASK (BTRFS_BLOCK_GROUP_DATA | \ | |
BTRFS_BLOCK_GROUP_SYSTEM | \ | |
BTRFS_BLOCK_GROUP_METADATA) | |
#define BTRFS_BLOCK_GROUP_PROFILE_MASK (BTRFS_BLOCK_GROUP_RAID0 | \ | |
BTRFS_BLOCK_GROUP_RAID1 | \ | |
BTRFS_BLOCK_GROUP_RAID1C3 | \ | |
BTRFS_BLOCK_GROUP_RAID1C4 | \ | |
BTRFS_BLOCK_GROUP_RAID5 | \ | |
BTRFS_BLOCK_GROUP_RAID6 | \ | |
BTRFS_BLOCK_GROUP_DUP | \ | |
BTRFS_BLOCK_GROUP_RAID10) | |
#define BTRFS_BLOCK_GROUP_RAID56_MASK (BTRFS_BLOCK_GROUP_RAID5 | \ | |
BTRFS_BLOCK_GROUP_RAID6) | |
#define BTRFS_BLOCK_GROUP_RAID1_MASK (BTRFS_BLOCK_GROUP_RAID1 | \ | |
BTRFS_BLOCK_GROUP_RAID1C3 | \ | |
BTRFS_BLOCK_GROUP_RAID1C4) |
# btrfs_ioctl_scrub_args
#define BTRFS_SCRUB_READONLY 1 | |
#define BTRFS_SCRUB_SUPPORTED_FLAGS (BTRFS_SCRUB_READONLY) | |
struct btrfs_ioctl_scrub_args { | |
__u64 devid; /* 输入 */ | |
__u64 start; /* 输入 */ | |
__u64 end; /* 输入 */ | |
__u64 flags; /* 输入 */ | |
struct btrfs_scrub_progress progress; /* 输出 */ | |
/* 填充到 1K */ | |
__u64 unused[(1024-32-sizeof(struct btrfs_scrub_progress))/8]; | |
}; |
/* | |
* 向用户空间报告错误和进度的结构体,用于以下几种情况: | |
* - scrub(校验 / 清理)操作完成后 | |
* - scrub 操作被取消时 | |
* - 用户主动查询 scrub 进度时 | |
*/ | |
struct btrfs_scrub_progress { | |
__u64 data_extents_scrubbed; /* 已校验的数据 extent 数量 */ | |
__u64 tree_extents_scrubbed; /* 已校验的元数据(树) extent 数量 */ | |
__u64 data_bytes_scrubbed; /* 已校验的数据字节数 */ | |
__u64 tree_bytes_scrubbed; /* 已校验的元数据字节数 */ | |
__u64 read_errors; /* 读取错误次数(例如 EIO 错误) */ | |
__u64 csum_errors; /* 校验和(checksum)检查失败次数 */ | |
__u64 verify_errors; /* 元数据校验失败次数,例如树块中的 | |
* generation(版本号)或逻辑地址不一致 */ | |
__u64 no_csum; /* 缺失校验和的 4K 数据块数量,可能由于写入时 | |
* 使用了 nodatasum 挂载选项 */ | |
__u64 csum_discards; /* 检测到校验和项但未能在 extent 树中 | |
* 找到对应数据的次数 */ | |
__u64 super_errors; /* 检测到损坏的超级块数量 */ | |
__u64 malloc_errors; /* 内部 kmalloc 分配失败次数,这通常意味着 | |
* scrub 操作未能完整执行 */ | |
__u64 uncorrectable_errors; /* 无法修复的错误次数: | |
* 要么无法找到完好的副本,要么回写失败 */ | |
__u64 corrected_errors; /* 已成功修复的错误数量 */ | |
__u64 last_physical; /* 最后一次成功 scrub 的物理地址; | |
* 如果 scrub 中断,可以用此值重启 */ | |
__u64 unverified_errors; /* 未确认错误次数: | |
* 指整块(64KB bio)读取失败,但逐个 4K | |
* 分片重新校验后都通过,属于间歇性错误 */ | |
}; |
# btrfs_ioctl_dev_info_args
#define BTRFS_UUID_SIZE 16 | |
#define BTRFS_DEVICE_PATH_NAME_MAX 1024 | |
struct btrfs_ioctl_dev_info_args { | |
__u64 devid; /* 输入 / 输出 */ | |
__u8 uuid[BTRFS_UUID_SIZE]; /* 输入 / 输出 */ | |
__u64 bytes_used; /* 输出 */ | |
__u64 total_bytes; /* 输出 */ | |
/* | |
* 可选输出项(out)。 | |
* | |
* 用于显示该设备的 fsid,允许用户空间检查该设备是否是一个 seeding 设备。 | |
* | |
* 此字段在内核 v6.3 中引入,因此用户空间仍需检查内核是否修改了此值。 | |
* 较旧的内核版本不会修改这里的值。 | |
*/ | |
__u8 fsid[BTRFS_UUID_SIZE]; | |
__u64 unused[377]; /* 填充到 4K */ | |
__u8 path[BTRFS_DEVICE_PATH_NAME_MAX]; /* 输出 */ | |
}; |
seeding device:只读的「种子设备」,用于创建新文件系统的初始快照,不参与后续写操作。
# btrfs_ioctl_balance_args
/* | |
* balance 的 flags 定义 | |
* | |
* Restriper's general type filter | |
* | |
* 用于: | |
* btrfs_ioctl_balance_args.flags | |
* btrfs_balance_control.flags (internal) | |
*/ | |
#define BTRFS_BALANCE_DATA (1ULL << 0) | |
#define BTRFS_BALANCE_SYSTEM (1ULL << 1) | |
#define BTRFS_BALANCE_METADATA (1ULL << 2) | |
#define BTRFS_BALANCE_TYPE_MASK (BTRFS_BALANCE_DATA | \ | |
BTRFS_BALANCE_SYSTEM | \ | |
BTRFS_BALANCE_METADATA) | |
#define BTRFS_BALANCE_FORCE (1ULL << 3) | |
#define BTRFS_BALANCE_RESUME (1ULL << 4) | |
/* | |
* balance state 的 flags 定义 | |
* | |
* 用于: | |
* struct btrfs_ioctl_balance_args.state | |
*/ | |
#define BTRFS_BALANCE_STATE_RUNNING (1ULL << 0) | |
#define BTRFS_BALANCE_STATE_PAUSE_REQ (1ULL << 1) | |
#define BTRFS_BALANCE_STATE_CANCEL_REQ (1ULL << 2) | |
struct btrfs_ioctl_balance_args { | |
__u64 flags; /* 输入 / 输出 */ | |
__u64 state; /* 输出 */ | |
struct btrfs_balance_args data; /* 输入 / 输出 */ | |
struct btrfs_balance_args meta; /* 输入 / 输出 */ | |
struct btrfs_balance_args sys; /* 输入 / 输出 */ | |
struct btrfs_balance_progress stat; /* 输出 */ | |
__u64 unused[72]; /* 填充至 1k */ | |
}; |
/* | |
* per-type balance args 的 flags 定义 | |
* | |
* Balance filters | |
* | |
* 用于: | |
* struct btrfs_balance_args | |
*/ | |
#define BTRFS_BALANCE_ARGS_PROFILES (1ULL << 0) | |
#define BTRFS_BALANCE_ARGS_USAGE (1ULL << 1) | |
#define BTRFS_BALANCE_ARGS_DEVID (1ULL << 2) | |
#define BTRFS_BALANCE_ARGS_DRANGE (1ULL << 3) | |
#define BTRFS_BALANCE_ARGS_VRANGE (1ULL << 4) | |
#define BTRFS_BALANCE_ARGS_LIMIT (1ULL << 5) | |
#define BTRFS_BALANCE_ARGS_LIMIT_RANGE (1ULL << 6) | |
#define BTRFS_BALANCE_ARGS_STRIPES_RANGE (1ULL << 7) | |
#define BTRFS_BALANCE_ARGS_USAGE_RANGE (1ULL << 10) | |
#define BTRFS_BALANCE_ARGS_MASK \ | |
(BTRFS_BALANCE_ARGS_PROFILES | \ | |
BTRFS_BALANCE_ARGS_USAGE | \ | |
BTRFS_BALANCE_ARGS_DEVID | \ | |
BTRFS_BALANCE_ARGS_DRANGE | \ | |
BTRFS_BALANCE_ARGS_VRANGE | \ | |
BTRFS_BALANCE_ARGS_LIMIT | \ | |
BTRFS_BALANCE_ARGS_LIMIT_RANGE | \ | |
BTRFS_BALANCE_ARGS_STRIPES_RANGE | \ | |
BTRFS_BALANCE_ARGS_USAGE_RANGE) | |
/* | |
* 此结构体使用了 packed(紧凑)属性, | |
* 因为它必须与磁盘上的字节序对应结构体(struct btrfs_disk_balance_args)完全一致。 | |
*/ | |
struct btrfs_balance_args { | |
__u64 profiles; | |
/* | |
* 使用率过滤器 | |
* 使用 BTRFS_BALANCE_ARGS_USAGE 且赋单个值表示使用率在 0 到 N 之间 | |
* 使用 BTRFS_BALANCE_ARGS_USAGE_RANGE 表示范围语法,即 min 到 max | |
*/ | |
union { | |
__u64 usage; | |
struct { | |
__u32 usage_min; // 使用率下限(单位是百分比 * 100) | |
__u32 usage_max; | |
}; | |
}; | |
__u64 devid; | |
__u64 pstart; | |
__u64 pend; | |
__u64 vstart; | |
__u64 vend; | |
__u64 target; | |
__u64 flags; | |
/* | |
* 使用 BTRFS_BALANCE_ARGS_LIMIT 且赋值 'limit' | |
* 或使用 BTRFS_BALANCE_ARGS_LIMIT_RANGE,支持最小值与最大值 | |
*/ | |
union { | |
__u64 limit; // 限制处理的数据块(chunk)数量 | |
struct { | |
__u32 limit_min; | |
__u32 limit_max; | |
}; | |
}; | |
/* | |
* 处理跨越 stripes_min 到 stripes_max 个设备的数据块 | |
* 使用 BTRFS_BALANCE_ARGS_STRIPES_RANGE | |
*/ | |
__u32 stripes_min; | |
__u32 stripes_max; | |
__u64 unused[6]; | |
} __attribute__ ((__packed__)); |
/* 向用户空间报告 balance 进度 */ | |
struct btrfs_balance_progress { | |
__u64 expected; /* 预估为满足本次 balance 请求而需要迁移的数据块(chunk)数量 */ | |
__u64 considered; /* 到目前为止已经被考虑处理的数据块数量 */ | |
__u64 completed; /* 到目前为止已成功迁移的数据块数量 */ | |
}; |
# btrfs_ioctl_ino_path_args
struct btrfs_ioctl_ino_path_args { | |
__u64 inum; /* 输入 */ | |
__u64 size; /* 输入 */ | |
__u64 reserved[4]; | |
/* struct btrfs_data_container *fspath;*/ | |
__u64 fspath; /* 输出 */ | |
}; |
struct btrfs_data_container { | |
__u32 bytes_left; /* 输出:未使用的字节数 —— 指输出结果所需空间少于提供的空间时,剩余的字节数 */ | |
__u32 bytes_missing; /* 输出:结果还需要的额外字节数 —— 当提供的缓冲区不够用时,表示还缺多少字节 */ | |
__u32 elem_cnt; /* 输出:实际返回的元素数量 */ | |
__u32 elem_missed; /* 输出:因为空间不足而未返回的元素数量 */ | |
__u64 val[]; /* 输出:可变长度数组,用于存放返回的数据值(通常是 u64 类型的 ID 或其他值) */ | |
}; |
# btrfs_ioctl_logical_ino_args
/* | |
* Return every ref to the extent, not just those containing logical block. | |
* Requires logical == extent bytenr. | |
*/ | |
#define BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET (1ULL << 0) | |
struct btrfs_ioctl_logical_ino_args { | |
__u64 logical; /* 输入 */ | |
__u64 size; /* 输入 */ | |
__u64 reserved[3]; /* 目前必须为 0 */ | |
__u64 flags; /* 输入,v2 only */ | |
/* struct btrfs_data_container *inodes; 输出 */ | |
__u64 inodes; | |
}; |
参见 struct btrfs_data_container
# btrfs_ioctl_send_args
/* | |
* 调用者不希望在发送流(send stream)中包含文件数据,即使在克隆源查找时找不到相应的数据块。 | |
* 此时将发送 UPDATE_EXTENT 指令,而不是 WRITE 指令。 | |
*/ | |
#define BTRFS_SEND_FLAG_NO_FILE_DATA 0x1 | |
/* | |
* 不添加流头部(stream header)。该选项用于连续发送多个快照时。 | |
*/ | |
#define BTRFS_SEND_FLAG_OMIT_STREAM_HEADER 0x2 | |
/* | |
* 省略发送流末尾用于标识结束的指令。 | |
* 该选项用于连续发送多个快照的场景。 | |
*/ | |
#define BTRFS_SEND_FLAG_OMIT_END_CMD 0x4 | |
/* | |
* 从结构体中读取协议版本。 | |
*/ | |
#define BTRFS_SEND_FLAG_VERSION 0x8 | |
/* | |
* 使用 ENCODED_WRITE 指令发送压缩数据,而不是先解压再用 WRITE 指令发送。 | |
* 需要协议版本 >= 2。 | |
*/ | |
#define BTRFS_SEND_FLAG_COMPRESSED 0x10 | |
#define BTRFS_SEND_FLAG_MASK \ | |
(BTRFS_SEND_FLAG_NO_FILE_DATA | \ | |
BTRFS_SEND_FLAG_OMIT_STREAM_HEADER | \ | |
BTRFS_SEND_FLAG_OMIT_END_CMD | \ | |
BTRFS_SEND_FLAG_VERSION | \ | |
BTRFS_SEND_FLAG_COMPRESSED) | |
struct btrfs_ioctl_send_args { | |
__s64 send_fd; /* 输入 */ | |
__u64 clone_sources_count; /* 输入 */ | |
__u64 __user *clone_sources; /* 输入 */ | |
__u64 parent_root; /* 输入 */ | |
__u64 flags; /* 输入 */ | |
__u32 version; /* 输入 */ | |
__u8 reserved[28]; /* 输入 */ | |
}; |
# btrfs_ioctl_quota_ctl_args
#define BTRFS_QUOTA_CTL_ENABLE 1 | |
#define BTRFS_QUOTA_CTL_DISABLE 2 | |
#define BTRFS_QUOTA_CTL_RESCAN__NOTUSED 3 | |
#define BTRFS_QUOTA_CTL_ENABLE_SIMPLE_QUOTA 4 | |
struct btrfs_ioctl_quota_ctl_args { | |
__u64 cmd; | |
__u64 status; | |
}; |
# btrfs_ioctl_qgroup_assign_args
struct btrfs_ioctl_qgroup_assign_args { | |
__u64 assign; | |
__u64 src; | |
__u64 dst; | |
}; |
# btrfs_ioctl_qgroup_create_args
struct btrfs_ioctl_qgroup_create_args { | |
__u64 create; | |
__u64 qgroupid; | |
}; |
# btrfs_ioctl_qgroup_limit_args
struct btrfs_ioctl_qgroup_limit_args { | |
__u64 qgroupid; | |
struct btrfs_qgroup_limit lim; | |
}; |
# btrfs_ioctl_quota_rescan_args
struct btrfs_ioctl_quota_rescan_args { | |
__u64 flags; | |
__u64 progress; | |
__u64 reserved[6]; | |
}; |
# btrfs_ioctl_get_dev_stats
enum btrfs_dev_stat_values { | |
/* 磁盘 I/O 故障统计 */ | |
BTRFS_DEV_STAT_WRITE_ERRS, /* 来自底层的写入错误(EIO 或 EREMOTEIO) */ | |
BTRFS_DEV_STAT_READ_ERRS, /* 来自底层的读取错误(EIO 或 EREMOTEIO) */ | |
BTRFS_DEV_STAT_FLUSH_ERRS, /* 来自底层的刷新错误(EIO 或 EREMOTEIO) */ | |
/* 间接反映 I/O 错误的统计数据 */ | |
BTRFS_DEV_STAT_CORRUPTION_ERRS, /* 校验和错误、bytenr 错误或内容非法: | |
* 表明数据块在读写过程中遭到破坏, | |
* 或写入 / 读取了错误的位置 */ | |
BTRFS_DEV_STAT_GENERATION_ERRS, /* 表示某些块可能尚未被写入 */ | |
BTRFS_DEV_STAT_VALUES_MAX /* 统计值的最大数目(用于数组边界) */ | |
}; | |
/* 读取后重置统计数据;需要 SYS_ADMIN 权限 */ | |
#define BTRFS_DEV_STATS_RESET (1ULL << 0) | |
/* 获取设备统计信息的结构体 */ | |
struct btrfs_ioctl_get_dev_stats { | |
__u64 devid; /* 输入 - 要查询的设备 ID */ | |
__u64 nr_items; /* 输入 / 输出 - 请求的统计项数量,返回实际填充的数量 */ | |
__u64 flags; /* 输入 / 输出 - 控制标志,比如是否重置统计数据 */ | |
/* 输出值:各类错误计数 */ | |
__u64 values[BTRFS_DEV_STAT_VALUES_MAX]; | |
/* | |
* 此结构体被填充为 1032 字节。 | |
* 原本意图是填充到 1024 字节,但在添加 flags 字段时未调整填充计算。 | |
*/ | |
__u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; | |
}; |
# btrfs_ioctl_dev_replace_args
#define BTRFS_IOCTL_DEV_REPLACE_CMD_START 0 | |
#define BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS 1 | |
#define BTRFS_IOCTL_DEV_REPLACE_CMD_CANCEL 2 | |
#define BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR 0 | |
#define BTRFS_IOCTL_DEV_REPLACE_RESULT_NOT_STARTED 1 | |
#define BTRFS_IOCTL_DEV_REPLACE_RESULT_ALREADY_STARTED 2 | |
#define BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS 3 | |
struct btrfs_ioctl_dev_replace_args { | |
__u64 cmd; /* 输入 */ | |
__u64 result; /* 输出 */ | |
union { | |
struct btrfs_ioctl_dev_replace_start_params start; | |
struct btrfs_ioctl_dev_replace_status_params status; | |
}; /* 输入 / 输出 */ | |
__u64 spare[64]; | |
}; |
#define BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS 0 | |
#define BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID 1 | |
struct btrfs_ioctl_dev_replace_start_params { | |
__u64 srcdevid; /* 输入,如果是 0, 使用 srcdev_name 来代替 */ | |
__u64 cont_reading_from_srcdev_mode; /* 输入,使用上面定义的 #define */ | |
__u8 srcdev_name[BTRFS_DEVICE_PATH_NAME_MAX + 1]; /* 输入 */ | |
__u8 tgtdev_name[BTRFS_DEVICE_PATH_NAME_MAX + 1]; /* 输入 */ | |
}; |
#define BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED 0 | |
#define BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED 1 | |
#define BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED 2 | |
#define BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED 3 | |
#define BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED 4 | |
struct btrfs_ioctl_dev_replace_status_params { | |
__u64 replace_state; /* 输出,使用上面定义的 #define */ | |
__u64 progress_1000; /* 输出,0 <= x <= 1000 */ | |
__u64 time_started; /* 输出,是从 1-Jan-1970 开始的秒数 */ | |
__u64 time_stopped; /* 输出,是从 1-Jan-1970 开始的秒数 */ | |
__u64 num_write_errors; /* 输出 */ | |
__u64 num_uncorrectable_read_errors; /* 输出 */ | |
}; |
# btrfs_ioctl_same_args
struct btrfs_ioctl_same_args { | |
__u64 logical_offset; /* 输入 - 源文件中 extent 的起始偏移 */ | |
__u64 length; /* 输入 - extent 的长度 */ | |
__u16 dest_count; /* 输入 - info 数组中的目标文件数量 */ | |
__u16 reserved1; | |
__u32 reserved2; | |
struct btrfs_ioctl_same_extent_info info[]; /* 每个目标文件的去重信息 */ | |
}; |
#define BTRFS_SAME_DATA_DIFFERS 1 | |
/* 用于 extent-same ioctl */ | |
struct btrfs_ioctl_same_extent_info { | |
__s64 fd; /* 输入 - 目标文件的文件描述符 */ | |
__u64 logical_offset; /* 输入 - 目标文件中 extent 的起始偏移 */ | |
__u64 bytes_deduped; /* 输出 - 实际成功去重的字节数 */ | |
/* 本次去重操作的状态: | |
* 0 表示成功去重 | |
* 小于 0 表示发生错误 | |
* 等于 BTRFS_SAME_DATA_DIFFERS 表示数据不一致,不能去重 | |
*/ | |
__s32 status; /* 输出 - 状态值,含义如上 */ | |
__u32 reserved; | |
}; |
# btrfs_ioctl_feature_flags
/* | |
* feature flags | |
* | |
* 用于: | |
* struct btrfs_ioctl_feature_flags | |
*/ | |
#define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE (1ULL << 0) | |
/* | |
* 在大端系统上,旧版内核(< 4.9)会生成损坏的空闲空间树位图, | |
* 而 btrfs-progs 工具(版本 < 4.7.3)也可能破坏空闲空间树。 | |
* 如果该位被清除(为 0),则表示空闲空间树不可信。 | |
* btrfs-progs 也可以有意清除此位,以请求内核重建空闲空间树, | |
* 但对于不了解该位的旧内核,此操作可能无效。 | |
* 如果不确定,建议在首次挂载时手动清除缓存, | |
* 尤其是在启动旧版本内核时。 | |
*/ | |
#define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID (1ULL << 1) | |
#define BTRFS_FEATURE_COMPAT_RO_VERITY (1ULL << 2) | |
/* | |
* 将所有块组项放入专用的块组树中, | |
* 由于更好的局部性,这可以大大减少大文件系统的挂载时间。 | |
*/ | |
#define BTRFS_FEATURE_COMPAT_RO_BLOCK_GROUP_TREE (1ULL << 3) | |
#define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) | |
#define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1) | |
#define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS (1ULL << 2) | |
#define BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO (1ULL << 3) | |
#define BTRFS_FEATURE_INCOMPAT_COMPRESS_ZSTD (1ULL << 4) | |
/* | |
* 较早的内核曾尝试使用更大的元数据块, | |
* 但相关代码存在很多问题。我们不再允许它们继续尝试。 | |
*/ | |
#define BTRFS_FEATURE_INCOMPAT_BIG_METADATA (1ULL << 5) | |
#define BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF (1ULL << 6) | |
#define BTRFS_FEATURE_INCOMPAT_RAID56 (1ULL << 7) | |
#define BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA (1ULL << 8) | |
#define BTRFS_FEATURE_INCOMPAT_NO_HOLES (1ULL << 9) | |
#define BTRFS_FEATURE_INCOMPAT_METADATA_UUID (1ULL << 10) | |
#define BTRFS_FEATURE_INCOMPAT_RAID1C34 (1ULL << 11) | |
#define BTRFS_FEATURE_INCOMPAT_ZONED (1ULL << 12) | |
#define BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2 (1ULL << 13) | |
#define BTRFS_FEATURE_INCOMPAT_RAID_STRIPE_TREE (1ULL << 14) | |
#define BTRFS_FEATURE_INCOMPAT_SIMPLE_QUOTA (1ULL << 16) | |
struct btrfs_ioctl_feature_flags { | |
__u64 compat_flags; | |
__u64 compat_ro_flags; | |
__u64 incompat_flags; | |
}; |
# btrfs_ioctl_get_subvol_rootref_args
#define BTRFS_MAX_ROOTREF_BUFFER_NUM 255 | |
struct btrfs_ioctl_get_subvol_rootref_args { | |
/* 输入 / 输出,用于指定要搜索的 rootref 的最小 treeid */ | |
__u64 min_treeid; | |
/* 输出 */ | |
struct { | |
__u64 treeid; | |
__u64 dirid; | |
} rootref[BTRFS_MAX_ROOTREF_BUFFER_NUM]; | |
/* 输出,找到的项的数量 */ | |
__u8 num_items; | |
__u8 align[7]; | |
}; |
# btrfs_ioctl_ino_lookup_user_args
#define BTRFS_VOL_NAME_MAX 255 | |
#define BTRFS_INO_LOOKUP_USER_PATH_MAX (4080 - BTRFS_VOL_NAME_MAX - 1) | |
struct btrfs_ioctl_ino_lookup_user_args { | |
/* 输入,包含'subvolid' 所对应子卷的 inode 编号 */ | |
__u64 dirid; | |
/* 输入 */ | |
__u64 treeid; | |
/* 输出,指定 'treeid' 的子卷名称 */ | |
char name[BTRFS_VOL_NAME_MAX + 1]; | |
/* 输出,从调用该 ioctl 的目录到指定 dirid 所构建的路径 */ | |
char path[BTRFS_INO_LOOKUP_USER_PATH_MAX]; | |
}; |
# btrfs_ioctl_encoded_io_args
/* | |
* 用于编码读写的数据和元数据。 | |
* | |
* 编码 I/O (Encoded I/O) 会绕过文件系统自动执行的任何编码操作(例如压缩)。 | |
* 这可以用于读取文件的压缩内容,或直接将预压缩数据写入文件。 | |
* | |
* BTRFS_IOC_ENCODED_READ 和 BTRFS_IOC_ENCODED_WRITE 本质上类似于 | |
* preadv/pwritev,但额外携带了有关数据编码方式和未编码数据大小的元信息。 | |
* | |
* BTRFS_IOC_ENCODED_READ 会将编码数据填入提供的 iovec 中,填充元数据字段, | |
* 并返回编码数据的大小。每次调用读取一个 extent。它也可以读取未编码数据。 | |
* | |
* BTRFS_IOC_ENCODED_WRITE 使用元数据字段,从 iovec 中写入编码数据,并返回编码数据的大小。 | |
* 注意:写入时不会验证编码数据是否有效;如果数据无效(例如无法解压),则后续读取可能会返回错误。 | |
* | |
* 由于文件系统的页缓存中保存的是解码后的数据,因此编码 I/O 会绕过页缓存。 | |
* 编码 I/O 需要 CAP_SYS_ADMIN 权限。 | |
*/ | |
struct btrfs_ioctl_encoded_io_args { | |
/* 读写操作的输入参数 */ | |
/* | |
* 包含编码数据的 iovec 数组。 | |
* | |
* 对于读取操作,如果编码数据大小大于所有 iov [n].iov_len (0 <= n < iovcnt) 的总和, | |
* 则 ioctl 调用失败并返回 ENOBUFS。 | |
* | |
* 对于写入操作,编码数据的大小为所有 iov [n].iov_len 的总和(0 <= n < iovcnt)。 | |
* 必须小于 128 KiB(未来可能放宽限制),也必须小于等于 unencoded_len。 | |
*/ | |
const struct iovec __user *iov; | |
/* iovec 数组中的元素数量 */ | |
unsigned long iovcnt; | |
/* | |
* 文件偏移量 | |
* | |
* 对于写操作,必须对齐到文件系统的扇区大小。 | |
*/ | |
__s64 offset; | |
/* 当前必须为零 */ | |
__u64 flags; | |
/* | |
* 以下字段为读取操作的输出参数,包含返回的编码数据元信息; | |
* 对于写入操作,这些字段必须由用户设置为编码数据的元信息。 | |
*/ | |
/* | |
* 文件中数据的长度 | |
* | |
* 必须小于等于 unencoded_len - unencoded_offset。 | |
* 对于写操作,除非数据末尾位于或超出文件当前末尾,否则必须对齐到扇区大小。 | |
*/ | |
__u64 len; | |
/* | |
* 未编码(即解密解压后)的数据长度。 | |
* | |
* 对于写操作,不能超过 128 KiB(未来可能放宽限制)。 | |
* 如果实际未编码数据长于 unencoded_len,则会被截断; | |
* 若短于该值,则使用 0 填充。 | |
*/ | |
__u64 unencoded_len; | |
/* | |
* 从未编码数据首字节到文件中逻辑数据首字节的偏移。 | |
* | |
* 必须小于 unencoded_len。 | |
*/ | |
__u64 unencoded_offset; | |
/* | |
* BTRFS_ENCODED_IO_COMPRESSION_* 类型。 | |
* | |
* 对于写操作,不能为 BTRFS_ENCODED_IO_COMPRESSION_NONE。 | |
*/ | |
__u32 compression; | |
/* 当前总是 BTRFS_ENCODED_IO_ENCRYPTION_NONE */ | |
__u32 encryption; | |
/* | |
* 为将来扩展预留 | |
* | |
* 对于读取操作,总是返回为零。用户应检查是否有非零字节, | |
* 如果有,说明内核使用了结构体的新版本,包含用户定义中缺失的附加信息。 | |
* | |
* 对于写操作,必须将其清零。 | |
*/ | |
__u8 reserved[64]; | |
}; |
/* 数据未压缩 */ | |
#define BTRFS_ENCODED_IO_COMPRESSION_NONE 0 | |
/* 数据作为单个 zlib 流进行压缩。 */ | |
#define BTRFS_ENCODED_IO_COMPRESSION_ZLIB 1 | |
/* | |
* 数据作为单个 zstd 帧进行压缩,并且 windowLog 压缩参数设置为不超过 17。 | |
*/ | |
#define BTRFS_ENCODED_IO_COMPRESSION_ZSTD 2 | |
/* | |
* 数据按扇区逐个压缩(使用常量名称中指示的扇区大小), | |
* 使用 LZO1X 压缩,并以 fs/btrfs/lzo.c 中文档化的格式进行包装。 | |
* 对于写操作,压缩扇区大小必须与文件系统的扇区大小匹配。 | |
*/ | |
#define BTRFS_ENCODED_IO_COMPRESSION_LZO_4K 3 | |
#define BTRFS_ENCODED_IO_COMPRESSION_LZO_8K 4 | |
#define BTRFS_ENCODED_IO_COMPRESSION_LZO_16K 5 | |
#define BTRFS_ENCODED_IO_COMPRESSION_LZO_32K 6 | |
#define BTRFS_ENCODED_IO_COMPRESSION_LZO_64K 7 | |
#define BTRFS_ENCODED_IO_COMPRESSION_TYPES 8 | |
/* 数据未加密 */ | |
#define BTRFS_ENCODED_IO_ENCRYPTION_NONE 0 | |
#define BTRFS_ENCODED_IO_ENCRYPTION_TYPES 1 |
# 详细描述
# BTRFS_IOC_SNAP_CREATE_V2
为一个子卷创建一个快照。
Field | Description |
---|---|
ioctl fd | 创建新快照的目录的文件描述符 |
ioctl args | struct btrfs_ioctl_vol_args_v2 |
args.fd | 表示要快照的子卷中任意目录的文件描述符,必须位于同一个文件系统上 |
args.transid | 该字段会被忽略 |
args.flags | 可以设置为 BTRFS_SUBVOL_RDONLY 的任意子集来使新快照只读,或设置为 BTRFS_SUBVOL_QGROUP_INHERIT 来应用 qgroup_inherit 字段 |
args.name | 新子卷在 ioctl fd 指定的目录下的名称 |
# BTRFS_IOC_SCAN_DEV
扫描指定设备并将其注册到文件系统模块中,以便在挂载时自动关联设备和文件系统。此操作针对的是控制设备,而不是已挂载文件系统中的文件。可以安全地重复调用同一设备路径。
Field | Description |
---|---|
ioctl fd | 控制设备的文件描述符 /dev/btrfs-control |
ioctl args | struct btrfs_ioctl_vol_args |
args.fd | 该字段会被忽略 |
args.name | 设备的绝对路径 |
# BTRFS_IOC_SYNC
与 sync()
系统调用一样同步文件系统数据,另外会唤醒内部事务线程,从而触发子卷清理或队列碎片整理等操作。
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件或目录的文件描述符 |
ioctl args | NULL |
# BTRFS_IOC_ADD_DEV
将指定的块设备添加到文件系统。与命令 btrfs device add
不同的是,这个操作不会执行任何安全检查(例如:该设备上是否已有其他文件系统)、也不会进行设备预处理(比如 TRIM 操作或重置分区区域),因此请谨慎使用。
这是一个文件系统独占操作,如果当前文件系统已有其他实例正在运行,这个操作将会失败。但有一个例外:当系统处于 “平衡操作(balance)已暂停” 的状态时,仍然可以执行该操作。
所需权限: CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件或目录的文件描述符 |
ioctl args | struct btrfs_ioctl_vol_args |
args.fd | 该字段会被忽略 |
args.name | 要被添加的块设备的绝对路径 |
# BTRFS_IOC_RM_DEV
*(Linux v3.0 引入,v4.7 过时)* 从文件系统中移除指定路径的设备,或者通过特殊路径 "cancel"
取消正在进行的设备删除操作。
这是一个文件系统独占操作,如果已有其他操作在运行,则该操作会失败。
执行此操作需要权限:CAP_SYS_ADMIN。
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件或目录的文件描述符 |
ioctl args | struct btrfs_ioctl_vol_args |
args.fd | 该字段会被忽略 |
args.name | 要被删除的块设备的绝对路径 或 字符串 *“cancel”* |
# BTRFS_IOC_INO_LOOKUP
解析 inode 号为路径(需要 CAP_SYS_ADMIN
权限),或读取给定文件所属的子卷 ID(此为特殊情况,不受权限限制)。由于路径名缓冲区的大小小于 PATH_MAX(4096 字节),因此路径有可能会被截断。该功能也可以通过 btrfs inspect-internal rootid 实现。
一般情况下,此操作需要 CAP_SYS_ADMIN
权限,并且可以将任意文件解析为其路径。而用于读取所属子卷的特殊情况则不受权限限制:
struct btrfs_ioctl_ino_lookup_args args; | |
fd = open("file", ...); | |
args.treeid = 0; | |
args.objectid = BTRFS_FIRST_FREE_OBJECTID; | |
ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args); | |
/* args.treeid now contains the subvolume id */ |
Field | Description |
---|---|
ioctl fd | 待寻找子卷 id 的文件或目录的文件描述符 |
ioctl args | struct btrfs_ioctl_ino_lookup_args |
args.treeid | 用于路径解析的子卷 ID(需要 CAP_SYS_ADMIN 权限);如果设置为 0,则使用包含该 fd 的子卷。 |
args.objectid | 要查询的 inode 号,对应于 INODE_REF_KEY 的 key.objectid 。或者,作为特殊情况,设置为 BTRFS_FIRST_FREE_OBJECTID 以仅读取树 ID 并清空 args.name 缓冲区。 |
args.name | 相对于顶层子卷的路径,或留空字符串。 |
# BTRFS_IOC_DEFAULT_SUBVOL
将指定的子卷 ID 设置为默认子卷,当挂载该文件系统时如果未指定 subvol=路径
或 subvolid=ID
选项,则挂载此默认子卷。
Field | Description |
---|---|
ioctl fd | 用于在其内部创建新快照的目录的文件描述符 |
ioctl args | 要设置为默认子卷的子卷数字值 (uint64_t) |
# BTRFS_IOC_SUBVOL_CREATE_V2
(3.6 版本引入) 创建一个新的子卷, qgroup inheritance
和 limits
可以被指定。
Field | Description |
---|---|
ioctl fd | 新子卷的父目录的文件描述符 |
ioctl args | struct btrfs_ioctl_vol_args_v2 |
args.fd | 该字段会被忽略 |
args.transid | 该字段会被忽略 |
args.flags | 要在子卷上设置的 flags, BTRFS_SUBVOL_RDONLY 表示只读, BTRFS_SUBVOL_QGROUP_INHERIT 表示要处理 qgroup 相关的字段 |
args.size | args.qgroup_inherit 中的条目数 |
args.qgroup_inherit | 继承给定的配额组(qgroups (struct btrfs_qgroup_inherit) )和 limits (struct btrfs_qgroup_limit) |
name | 子卷的名字,尽管缓冲区已经几乎能到达 4KB,但是 Linux VFS 限制了文件名长度最大为 255 个字符且不能包含斜杠( / ) |
# BTRFS_IOC_SUBVOL_GETFLAGS
读取一个子卷的 flags。返回的 flags 要么是 0,要么是 BTRFS_SUBVOL_RDONLY
。
Field | Description |
---|---|
ioctl fd | 要检查的子卷的文件描述符 |
ioctl args | uint64_t |
# BTRFS_IOC_SUBVOL_SETFLAGS
设置一个子卷的 flags。
Field | Description |
---|---|
ioctl fd | 要改变的子卷的文件描述符 |
ioctl args | uint64_t,要么是 0,要么是 BTRFS_SUBVOL_RDONLY |
# BTRFS_IOC_GET_FSLABEL
将文件系统的标签读取到给定的缓冲区中,也可以从 /sys/fs/btrfs/FSID/label
中读取,但这需要知道该文件系统的 FSID
。
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件 / 目录的文件描述符 |
ioctl args | char buffer[BTRFS_LABEL_SIZE] |
# BTRFS_IOC_SET_FSLABEL
将文件系统的标签设置为给定的缓冲区内容。最大长度包括终止的 NUL 字符。或者,也可以通过写入 /sys/fs/btrfs/FSID/label
来设置标签,但这需要知道文件系统的 FSID(并且在更改永久生效之前需要显式提交)。
所需权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件 / 目录的文件描述符 |
ioctl args | char buffer[BTRFS_LABEL_SIZE] |
# BTRFS_IOC_FS_INFO
读取文件系统的内部信息。数据可以双向交换,部分结构可以选择性填充。保留的字节可用于获取新的信息,但始终取决于设置的标志。
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件 / 目录的文件描述符 |
ioctl args | struct btrfs_ioctl_fs_info_args |
# BTRFS_IOC_GET_SUBVOL_INFO
获取一个子卷的信息。
Field | Description |
---|---|
ioctl fd | 要检查的子卷的文件描述符 |
ioctl args | struct btrfs_ioctl_get_subvol_info_args |
# BTRFS_IOC_SNAP_DESTROY_V2
销毁一个子卷,该子卷可能是也可能不是快照。
Field | Description |
---|---|
ioctl fd | 如果 flags 不包括 BTRFS_SUBVOL_SPEC_BY_ID ,或者在非 root 用户命名空间中执行,参数 fd 为包含要删除的子卷的父目录的文件描述符;否则, fd 为要删除的子卷在同一文件系统中的任何目录的文件描述符,但不在同一子卷中 |
ioctl args | struct btrfs_ioctl_vol_args_v2 |
args.fd | 该字段会被忽略 |
args.transid | 该字段会被忽略 |
args.flags | 如果通过 name 字段用指定目录中的名称标识子卷,则为 0;如果用 subvolid 字段指定子卷的 ID,则为 BTRFS_SUBVOL_SPEC_BY_ID |
args.name | 仅当 flags 不包含 BTRFS_SUBVOL_SPEC_BY_ID 时有用,指定要删除的子卷的名称(在参数 fd 所标识的目录中) |
args.subvolid | 只有在 flags 包含 BTRFS_SUBVOL_SPEC_BY_ID 时有用,指定要删除的子卷的子卷 ID |
# BTRFS_IOC_SUBVOL_SYNC_WAIT
(自内核 6.13 起) 等待一个已删除的子卷被清理完成,或查询其当前状态。
该 ioctl 提供多种操作模式,其中最常见的是:等待特定子卷的清理完成,或等待所有当前排队待清理的子卷。例如,备份程序在删除子卷后会使用该功能,等待其真正被清理,以确认磁盘空间是否已释放。
其他模式则提供更高的灵活性,比如用于监控或在子卷删除队列中设置 “检查点”,而无需使用 SEARCH_TREE
操作。
注意事项:
- 等待操作是可中断的,超时时间为 1 秒,且该值不可配置。
- 多次调用该 ioctl 会看到不同的状态,因此在使用 “计数” 或 “查看下一个 / 最后一个” 等模式时存在竞争条件(racy)。
使用场景(常量定义详见此处):
- 某个子卷 A 被删除后,等待其清理完成(
WAIT_FOR_ONE
) - 一批子卷被删除后,等待所有清理完成(
WAIT_FOR_QUEUED
或PEEK_LAST
+WAIT_FOR_ONE
) - 统计当前待清理子卷的数量(非阻塞),用于监控目的
- 报告清理进度(使用
PEEK_NEXT
),若清理太快可能会遗漏部分子卷 - 在用户空间自行实现等待逻辑(持续使用
PEEK_LAST
,直到其返回 0)
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中的任意文件 / 目录的文件描述符 |
ioctl args | struct btrfs_ioctl_subvol_wait |
args.subvolid | 依赖于具体的模式,指定是要等待的子卷的数字 id,还是 PEEK 模式查询的子卷的数字 id |
args.mode | 上述描述的操作模式 |
args.count | 如果 mode 设置为 COUNT ,则为排队等待清理的子卷数量 |
# BTRFS_IOC_DEFRAG
对文件或目录执行碎片整理(defragmentation)。
对目录操作所需权限: CAP_SYS_ADMIN
对文件操作所需权限:对该 inode 具有 “写权限”。
BTRFS_IOC_DEFRAG
在include/uapi/linux/btrfs.h
中的参数定义为:
#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \
struct btrfs_ioctl_vol_args)
然而实际上在
fs/btrfs/ioctl.c
的具体实现为:
case BTRFS_IOC_DEFRAG: return btrfs_ioctl_defrag(file, NULL); case BTRFS_IOC_DEFRAG_RANGE: return btrfs_ioctl_defrag(file, argp);可见
BTRFS_IOC_DEFRAG
和BTRFS_IOC_DEFRAG_RANGE
最终都调用了 btrfs_ioctl_defrag,且btrfs_ioctl_defrag
实际的调用参数是NULL
,与声明不符,这是一个 “历史遗留” 问题,在早期BTRFS_IOC_DEFRAG
确实使用btrfs_ioctl_vol_args
参数,但是后来,这个 ioctl 的处理方式发生了变化,用户空间传参变得 “可选”,允许传一个更详细的结构体struct btrfs_ioctl_defrag_range_args
,这里不变只是为保持 ioctl 编号一致性的一个声明。
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件或目录的文件描述符 |
ioctl args | 该字段会被忽略 |
# BTRFS_IOC_DEFRAG_RANGE
对文件或目录执行碎片整理(新接口,可以提供更细颗粒度的管理)
对目录操作所需权限: CAP_SYS_ADMIN
对文件操作所需权限:对该 inode 具有 “写权限”。
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件或目录的文件描述符 |
ioctl args | struct btrfs_ioctl_defrag_range_args |
args.start | 碎片整理操作的起始位置 |
args.len | 要进行碎片整理的字节数,使用 (u64)-1 表示所有 |
args.flags | 操作的标记,包括开启压缩功能等 |
args.extent_thresh | 任何大于该值的 extent(连续块)会被认为已经整理过;0 表示使用内核默认值,1 表示必须重写所有范围 |
args.compress_type | 如果为该磁盘碎片操作开启压缩功能,应使用哪种压缩方法。如果未指定,将使用 zlib |
args.unused | 备用 |
# BTRFS_IOC_RESIZE
调整(resize)某个 Btrfs 设备的容量大小。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件或目录的文件描述符 |
ioctl args | struct btrfs_ioctl_vol_args |
args.fd | 该字段会被忽略 |
args.name | 见下表 |
args.name
的含义见下表
args.name | 含义 |
---|---|
"max" | 将设备扩容到其最大容量 |
"+10G" | 当前设备扩容 10 GB |
"1:+5G" | devid=1 的设备扩容 5 GB |
"2:-1T" | devid=2 的设备缩小 1 TB |
"cancel" | 取消当前 resize 操作 |
# BTRFS_IOC_CLONE
用于提供 CoW 文件系统的 clone
支持。
这里的 “clone”,指的是 文件数据块级的 “写时复制”(Copy-on-Write, COW)克隆操作,它让你在两个文件之间共享物理存储数据而不进行真正的数据复制。简单来说就是:“把一个文件的一段内容,映射到另一个文件中相同长度的位置 —— 如果没人改动,两个文件用的是同一块磁盘空间;只有修改时,才会触发真正的复制。”
早期用于兼容的通用接口,该接口等价于内核中的 FICLONE
命令。 FICLONE
命令是 Linux 4.5 之后内核中引入的用于支持所有 CoW(Copy-on-Write)文件系统的命令,所以在这之后,该接口就被 FICLONE
代替了。Btrfs 在 btrfs_ioctl()
里没有专门实现 BTRFS_IOC_CLONE
,而是统一走 VFS 层的 FICLONE
分发逻辑,VFS 会调用 Btrfs 的 btrfs_remap_file_range()
,最终执行 clone
逻辑。调用路径为: ioctl_file_clone
→ vfs_clone_file_range
→ btrfs_remap_file_range
。
# BTRFS_IOC_CLONE_RANGE
对 FICLONE
的扩展,用于将一个文件中的指定范围的数据 clone
到另一个文件的指定位置,提供了比 FICLONE
更灵活的 克隆部分范围的能力。
同 BTRFS_IOC_CLONE 一样, BTRFS_IOC_CLONE_RANGE
也是 btrfs 早期实现的,后被又被 VFS 统一的实现的 FICLONERANGE
所替代,现在在 Btrfs 代码中已经没有专门的实现了,而是走 VFS 层的 FICLONERANGE
分发逻辑,调用路径为: ioctl_file_clone_range
→ ioctl_file_clone
→ vfs_clone_file_range
→ btrfs_remap_file_range
# BTRFS_IOC_FILE_EXTENT_SAME
在支持 CoW 的文件系统上,可以使用此 ioctl
来让两个数据相同的文件使用同一份物理存储(相当于删除重复数据)。早期仅在 Btrfs 内实现,在 Linux 4.5 后由 VFS 统一实现并分发,调用路径为: ioctl_file_dedupe_range
→ vfs_dedupe_file_range
→ vfs_dedupe_file_range_one
→ btrfs_remap_file_range
。
# BTRFS_IOC_TREE_SEARCH
(Linux v3.0 引入,v3.16 过时)搜索 Btrfs 的元数据树。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件或目录的文件描述符 |
ioctl args | struct btrfs_ioctl_search_args |
args.key | 搜索配置,字段请参考 struct btrfs_ioctl_search_key |
args.buf | 搜索到的条目 |
# BTRFS_IOC_TREE_SEARCH_V2
(自内核 3.16 起)搜索 Btrfs 的元数据树。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件或目录的文件描述符 |
ioctl args | struct btrfs_ioctl_search_args_V2 |
args.key | 搜索配置,字段请参考 struct btrfs_ioctl_search_key |
args.buf_size | buffer 缓冲区大小;若返回 EOVERFLOW,表示 buffer 空间不足,则该项存储所有 item 所需的大小 |
args.buf | 搜索到的条目 |
# BTRFS_IOC_SPACE_INFO
查询磁盘空间使用情况(包括数据区、元数据区、系统区、RAID 分布情况等)。
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件或目录的文件描述符 |
ioctl args | struct btrfs_ioctl_space_args |
args.space_slots | 用户请求的条目数量(0 表示只想获取总数) |
args.total_spaces | 实际返回的空间条目数量 |
args.spaces | 空间条目的内存区,参考 struct btrfs_ioctl_space_info |
可返回的空间类型包括:
static const u64 types[] = { | |
BTRFS_BLOCK_GROUP_DATA, | |
BTRFS_BLOCK_GROUP_SYSTEM, | |
BTRFS_BLOCK_GROUP_METADATA, | |
BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA | |
}; |
# BTRFS_IOC_START_SYNC
强制触发一次子卷事务(transaction)提交,并返回该次提交(或最近一次提交)的 transaction ID 给用户。
Field | Description |
---|---|
ioctl fd | 待同步的子卷的文件 / 目录的文件描述符 |
ioctl args | uint64_t,事务 ID;如果当前没有进行中的事务,则返回的是上一次的 transaction ID |
# BTRFS_IOC_WAIT_SYNC
等待指定的事务 ID(transaction ID)提交完成,如果没有指定,则等待当前正在提交的事务完成。
Field | Description |
---|---|
ioctl fd | 等待的子卷的文件 / 目录的文件描述符 |
ioctl args | uint64_t,事务 ID;如果为 NULL,表示等待当前活跃的事务完成 |
# BTRFS_IOC_SCRUB
对一个 Btrfs 设备进行 scrub(校验和修复)操作,主要用于数据完整性检查。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件或目录的文件描述符 |
ioctl args | struct btrfs_ioctl_scrub_args |
args.device | 目标设备 ID,0 表示默认设备,也可用 BTRFS_IOC_DEV_INFO 获取设备列表 |
args.start | 开始偏移,0 表示从设备起始位置 |
args.end | 结束偏移 |
args.flags | 控制行为,目前只有两个:0 表示读写(校验 + 修复),1 表示只读(只校验不修复) |
args.progress | 记录 scrub 的错误或进度信息,具体请参考 struct btrfs_scrub_progress |
# BTRFS_IOC_SCRUB_CANCEL
取消正在运行的 scrub 操作。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件或目录的文件描述符 |
ioctl args | NULL |
# BTRFS_IOC_SCRUB_PROGRESS
获取 scrub 进度信息。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件或目录的文件描述符 |
ioctl args | struct btrfs_ioctl_scrub_args |
args.device | 目标设备 ID,0 表示默认设备,也可用 BTRFS_IOC_DEV_INFO 获取设备列表 |
args.start | 无需填充,由内核填写,表示 scrub 的开始偏移 |
args.end | 无需填充,由内核填写,表示 scrub 的结束偏移 |
args.flags | 无需填充,由内核填写,表示行为标志 |
args.progress | 无需填充,由内核填写,记录 scrub 的错误或进度信息,具体请参考 struct btrfs_scrub_progress |
# BTRFS_IOC_DEV_INFO
获取指定 Btrfs 设备的基本信息(设备 ID、使用空间、总空间、UUID、挂载路径等)。
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件或目录的文件描述符 |
ioctl args | struct btrfs_ioctl_dev_info_args |
args.devid | 指定设备 ID |
args.uuid | 指定设备的 UUID,若 uuid 不为全零,就使用 uuid 查找;否则就使用 devid 查找 |
args.bytes_used | 无需填充,由内核填写,表示设备已使用了多少字节 |
args.total_bytes | 无需填充,由内核填写,表示设备总可用字节数 |
args.fsid | 无需填充,由内核填写,表示文件系统的唯一标识符(此字段在内核 v6.3 中引入) |
args.path | 无需填充,由内核填写,表示设备的挂载路径(或设备名称) |
# BTRFS_IOC_ENCODED_READ
以用户指定的格式(可能包括压缩)从 Btrfs 文件系统中读取一个数据范围,并将其写入用户空间的 iovec 缓冲区中,这个读取是按块读取原始数据的。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | 要读取的文件的文件描述符 |
ioctl args | struct btrfs_ioctl_encoded_io_args |
args.iov | 用户空间 iovec 数组地址,用于接收数据 |
args.iovcnt | iovec 数组的数量 |
args.offset | 文件偏移 |
args.flags | 目前必须为 0 |
args.len | 要读取的长度 |
args.unencoded_len | 未编码(例如解密、解压后)的数据长度 |
args.unencoded_offset | 从未编码数据首字节到文件中逻辑数据首字节的偏移 |
args.compression | 返回压缩算法类型,类型参考 BTRFS_ENCODED_IO_COMPRESSION_* |
args.encryption | 目前必须是 BTRFS_ENCODED_IO_ENCRYPTION_NONE |
args.reserved | 保留项 |
# BTRFS_IOC_ENCODED_WRITE
向文件中写入已编码(通常压缩过)的原始数据块,常用于备份恢复、数据迁移等低层次的操作。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | 要写入的文件的文件描述符 |
ioctl args | struct btrfs_ioctl_encoded_io_args |
args.iov | 用户空间 iovec 数组地址,用于写入数据 |
args.iovcnt | iovec 数组的数量 |
args.offset | 文件偏移,指定从何处开始写,必须扇区对齐 |
args.flags | 目前必须为 0 |
args.len | 要写入的逻辑数据长度(解压后的大小),必须扇区对齐 |
args.unencoded_len | 未编码(例如解密、解压后)的数据长度,必须小于 128KB(未来可能扩展) |
args.unencoded_offset | 从未编码数据首字节到文件中逻辑数据首字节的偏移 |
args.compression | 目前必须为 BTRFS_ENCODED_IO_COMPRESSION_NONE |
args.encryption | 目前必须是 BTRFS_ENCODED_IO_ENCRYPTION_NONE |
args.reserved | 保留项,必须为 0 |
# BTRFS_IOC_GET_SUBVOL_ROOTREF
查询包含当前 inode 的子卷(subvolume)所对应的 ROOTREF
信息,但不返回子卷名称。
Btrfs 通过 “引用(root ref)” 来记录和管理子卷之间的关系,其定义为一组键值对(key-value):
key 的类型为 struct btrfs_key;
//btrfs_key 是 btrfs 的一个通用核心结构,当其作为 root ref 项的 key 时,其 type 取值只能为注释中的两种。
struct btrfs_key {__u64 objectid;
__u8 type; // BTRFS_ROOT_REF_KEY 或 BTRFS_ROOT_BACKREF_KEY__u64 offset;
} __attribute__ ((__packed__));value 的类型为 struct btrfs_root_ref;
/*
* this is used for both forward and backward root refs
*/
struct btrfs_root_ref { __le64 dirid; // 父目录 Inode __le64 sequence; // 在父目录中的目录索引 __le16 name_len; // 引用该子卷的目录项的名称长度/* 实际的名称字符串紧随其后(变长数据) */
} __attribute__ ((__packed__));当新创建一个子卷 / 快照时,会创建两个
ROOT REF
项,他们的作用是便于快速识别某个子卷或快照的父目录。每当创建一个子卷时,系统会创建两个ROOT REF
项(一个用于前向引用(parent → child),一个用于反向引用(child → parent))。前向引用可以让我们快速定位子卷在目录中的挂载位置(即该子卷是在哪个目录下创建的),这在执行递归快照等操作时非常有用。反向引用则用于帮助恢复丢失的快照。这两个
ROOT REF
项的key
的字段含义是不同的,当代表前向引用时,key 字段的含义如下:
- key.objectid = 父子卷的 id
- key.type = BTRFS_ROOT_REF_KEY
- key.offset = 新创建的子卷 / 快照的 id
当代表反向引用时,key 字段的含义如下:
- key.objectid = 新创建的子卷 / 快照的 id
- key.type = BTRFS_ROOT_REF_KEY
- key.offset = 父子卷的 id
Field | Description |
---|---|
ioctl fd | 指定子卷(或快照)内的任意文件或目录 的文件描述符 |
ioctl args | struct btrfs_ioctl_get_subvol_rootref_args |
args.min_treeid | 指定要搜索的 rootref 的最小 treeid,可用于分页搜索,执行后该项将替换为搜索的最后一个子树 ID, 这样就可以用该项执行继续搜索。 |
args.rootref.treeid | 无需填充,由内核填写,表示当前子卷引用的子卷 id |
args.rootref.dirid | 无需填充,由内核填写,表示当前子卷引用的子卷的父目录 Inode |
args.num_items | 无需填充,由内核填写,表示找到的项的数量 |
# BTRFS_IOC_INO_LOOKUP_USER
在用户态安全地获取某个 inode 的路径信息,专为 非特权用户(unprivileged user)设计,主要用于让用户程序安全地查询某个 inode 在文件系统中的路径。相比于 ino_lookup ioctl
的区别如下:
会调用
inode_permission()
检查路径构建过程中的执行权限(EXEC
)和读取权限(READ
),没有权限就返回-EACCES
。路径的起点必须是打开的 fd 所指的 inode,构造路径只能在此子树中进行。如果路径跳出了这个范围(不是此目录下的某项),也返回
-EACCES
。不仅查 inode 的路径,也会查到它所属的子卷的名字。
Field | Description |
---|---|
ioctl fd | 包含待搜索 inode 的目录的文件描述符 |
ioctl args | struct btrfs_ioctl_ino_lookup_user_args |
args.dirid | 要查询的 inode 编号 |
args.treeid | 待查询的 inode 所在子卷的 tree ID |
args.name | 无需填充,由内核填写,inode 所在的子卷名称 |
args.path | 无需填充,由内核填写,从调用该 ioctl 的目录到指定 dirid 所构建的路径 |
# BTRFS_IOC_BALANCE_V2
触发或恢复一次平衡(balance)操作,同一时间只能有一个 balance 操作正在执行。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中的任意文件 / 目录的文件描述符 |
ioctl args | struct btrfs_ioctl_balance_args |
args.flags | 控制标志,控制 balance 的具体行为,具体请参考 BTRFS_BALANCE_* |
args.state | 无需填充,由内核填写,有三种状态,具体请参考 BTRFS_BALANCE_STATE_* |
args.data | 控制针对用户数据块(data)的 balance 行为,具体请参考 struct btrfs_balance_args |
args.meta | 控制针对元数据块(metadata)的 balance 行为,具体请参考 struct btrfs_balance_args |
args.sys | 控制针对系统块(system)的 balance 行为,具体请参考 struct btrfs_balance_args |
args.stat | 无需填充,由内核填写,表示 balance 的进度信息 |
# BTRFS_IOC_BALANCE_CTL
暂停或取消当前正在运行的 balance 操作的状态
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中的任意文件 / 目录的文件描述符 |
ioctl args | int,只能是两种值 BTRFS_BALANCE_CTL_PAUSE 或 BTRFS_BALANCE_CTL_CANCEL |
/* balance control ioctl modes */ | |
#define BTRFS_BALANCE_CTL_PAUSE 1 | |
#define BTRFS_BALANCE_CTL_CANCEL 2 |
# BTRFS_IOC_BALANCE_PROGRESS
获取当前 balance 操作的进度
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中的任意文件 / 目录的文件描述符 |
ioctl args | struct btrfs_ioctl_balance_args |
args.flags | 无需填充,由内核填写,控制标志,具体请参考 BTRFS_BALANCE_* |
args.state | 无需填充,由内核填写,返回当前 balance 状态,具体请参考 BTRFS_BALANCE_STATE_* |
args.data | 无需填充,由内核填写,返回用户数据块(data)的 balance 状态,具体请参考 struct btrfs_balance_args |
args.meta | 无需填充,由内核填写,返回元数据块(metadata)的 balance 状态,具体请参考 struct btrfs_balance_args |
args.sys | 无需填充,由内核填写,返回系统块(system)的 balance 状态,具体请参考 struct btrfs_balance_args |
args.stat | 无需填充,由内核填写,表示 balance 的进度信息 |
# BTRFS_IOC_INO_PATHS
给定一个 inode 编号,查找它在文件系统中所有对应的路径(从根到该 inode 的路径名),由于多个目录项可能指向同一个 inode(如硬链接),所以该函数可能会返回多个路径。
需要权限:CAP_DAC_READ_SEARCH
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件 / 目录的文件描述符 |
ioctl args | struct btrfs_ioctl_ino_path_args |
args.inum | 要查找路径的 inode 编号 |
args.size | 用户分配的输出缓冲区大小 |
args.reserved | 保留 |
args.fspath | 传入一个 buffer 用于接收数据,其实是一个 struct btrfs_data_container 指针,存储了路径信息(一系列偏移值,可以在偏移值处找到对应路径字符串) |
# BTRFS_IOC_LOGICAL_INO
根据物理地址(logical block address)反查出使用这个地址的文件 inode。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件 / 目录的文件描述符 |
ioctl args | struct btrfs_ioctl_logical_ino_args |
args.logical | 要查询的逻辑地址 |
args.size | 传入 buffer 的大小 |
args.reserved | 保留,目前必须为 0 |
args.flags | 该字段会被忽略,仅 BTRFS_IOC_LOGICAL_INO_V2 支持该参数 |
args.inodes | 传入一个 buffer 用于接收数据,其实是一个 struct btrfs_data_container 指针,存储查询结果 |
# BTRFS_IOC_SET_RECEIVED_SUBVOL
设置子卷的 “接收元信息”,例如该子卷是哪个父子卷衍生的、什么时候发送 / 接收的等等信息。
Field | Description |
---|---|
ioctl fd | 指向接收子卷目录的文件描述符 |
ioctl args | struct btrfs_ioctl_received_subvol_args |
args.uuid | 发送方子卷的 uuid |
args.stransid | 发送方子卷创建时的 transid |
args.rtransid | 无需填充,由内核填写,表示接收方的 transid(本地记录) |
args.stime | 发送方的快照创建时间 |
args.rtime | 无需填充,由内核填写,表示接收方的接收时间 |
args.flags | 该字段目前会被忽略,建议置 0 |
args.reserved | 保留 |
# BTRFS_IOC_SEND
将一个子卷快照的数据(相对于父子卷快照的增量或全量数据)发送到用户空间,以便可以传输到远程或另一个 Btrfs 文件系统上进行 receive
操作。
Field | Description |
---|---|
ioctl fd | 待发送子卷根目录的文件描述符 |
ioctl args | struct btrfs_ioctl_send_args |
args.send_fd | 发送目标(用户空间进程会从这个 fd 读取快照内容) |
args.clone_sources_count | 克隆源快照的数量 |
args.clone_sources | 指向多个 clone 源 subvol 的 ID 列表(用于增量复制) |
args.parent_root | 父快照的 root id;0 表示是全量快照导出 |
args.flags | 控制选项,参考 BTRFS_SEND_FLAG_* |
args.version | 接口版本号 |
args.reserved | 保留 |
# BTRFS_IOC_DEVICES_READY
检查设备是否准备就绪。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | /dev/btrfs-control 的文件描述符 |
ioctl args | struct btrfs_ioctl_vol_args |
args.fd | 该字段会被忽略 |
args.name | 待检查的设备名称,例如: /dev/sdb |
# BTRFS_IOC_QUOTA_CTL
提供对配额(quota)系统的启用和禁用控制。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件 / 目录的文件描述符 |
ioctl args | struct btrfs_ioctl_quota_ctl_args |
args.cmd | 实际执行的指令,包括启用、禁止等,具体请参考 BTRFS_QUOTA_CTL_ENABLE* |
args.status | 该字段会被忽略 |
# BTRFS_IOC_QGROUP_ASSIGN
在两个 quota group(配额组)之间建立或删除父子关系,以便子 qgroup 的空间使用能正确累加到父 qgroup 中,实现 “层次配额” 的管理。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件 / 目录的文件描述符 |
ioctl args | struct btrfs_ioctl_qgroup_assign_args |
args.assign | 非零:添加关系,零:删除关系 |
args.src | 子配额组 ID |
args.dst | 父配额组 ID |
# BTRFS_IOC_QGROUP_CREATE
创建或删除一个配额组(quota group)。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件 / 目录的文件描述符 |
ioctl args | struct btrfs_ioctl_qgroup_create_args |
args.create | 非零:创建,零:删除 |
args.qgroupid | 配额组 ID |
# BTRFS_IOC_QGROUP_LIMIT
为某个 qgroup 设置配额限制,需要先开启配额功能。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | 要设置配额的子卷目录的文件描述符 |
ioctl args | struct btrfs_ioctl_qgroup_limit_args |
args.qgroupid | 0,表示 “当前子卷”,也就是用户打开的这个 file 所在的子卷;否则就使用用户提供的 qgroupid |
args.lim | 配额限制参数,具体请参考 struct btrfs_qgroup_limit |
# BTRFS_IOC_QUOTA_RESCAN
对整个文件系统重新扫描以更新 qgroup(配额组)信息,确保它们是最新和一致的,需要先开启配额功能。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件 / 目录的文件描述符 |
ioctl args | struct btrfs_ioctl_quota_rescan_args |
args.flags | 必须为 0 |
args.progress | 该字段会被忽略 |
# BTRFS_IOC_QUOTA_RESCAN_STATUS
获取当前的 qgroup rescan(重新扫描)状态。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件 / 目录的文件描述符 |
ioctl args | struct btrfs_ioctl_quota_rescan_args |
args.flags | 无需填充,由内核填写,1 表示 “正在扫描”,0 表示 “没有扫描正在进行” |
args.progress | 无需填充,由内核填写,表示当前扫描状态,对应 objectid |
# BTRFS_IOC_QUOTA_RESCAN_WAIT
等待 quota rescan (配额重新扫描)完成。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件 / 目录的文件描述符 |
ioctl args | NULL |
# BTRFS_IOC_GET_DEV_STATS
获取块设备(device)的统计信息,比如 I/O 错误次数,同时也可以重置这些统计数据。
重置操作需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件 / 目录的文件描述符 |
ioctl args | struct btrfs_ioctl_get_dev_stats |
args.devid | 要查询的设备 ID |
args.nr_items | 输入:请求的统计项数量,输出:返回实际填充的数量 |
args.flags | 控制标志,例如是否重置统计数据 |
args.values | 无需填充,由内核填写,输出各项信息,具体请参考 BTRFS_DEV_STAT_*_ERRS |
# BTRFS_IOC_DEV_REPLACE
在 Btrfs 文件系统中进行设备替换(device replace)操作,包括启动、查询状态、取消设备替换。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件 / 目录的文件描述符 |
ioctl args | struct btrfs_ioctl_dev_replace_args |
args.cmd | 要执行的设备替换操作:start、status、cancel 等 |
args.result | 无需填充,由内核填写,表示执行结果,具体请参考 BTRFS_IOCTL_DEV_REPLACE_RESULT_* |
args.start (union) | 若执行的是开始(start)操作,则需要填充替换设备的信息,结构为 btrfs_ioctl_dev_replace_start_params |
args.status (union) | 若执行的是查询(status)操作,则该项由内核填充为状态信息,结构为 btrfs_ioctl_dev_replace_status_params |
# BTRFS_IOC_GET_FEATURES
获取当前挂载文件系统支持的 feature 标志。
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件 / 目录的文件描述符 |
ioctl args | struct btrfs_ioctl_feature_flags |
args.compat_flags | 无需填写,由内核填充,表示兼容特性,不支持这些特性的内核可以安全忽略这些特性 |
args.compat_ro_flags | 无需填写,由内核填充,表示只读兼容特性,不支持这些特性的内核只能挂载为只读 |
args.incompat_flags | 无需填写,由内核填充,表示不兼容特性,不支持这些特性的内核无法挂载 |
上述三个 flag 的可选值请参考 struct btrfs_ioctl_feature_flags 。
# BTRFS_IOC_SET_FEATURES
开启或关闭某些文件系统特性标志(features flags)。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件 / 目录的文件描述符 |
ioctl args | struct btrfs_ioctl_feature_flags[2] |
args[0] | 要修改的标志位 |
args[1] | 掩码,表示用户想保留的位(其他位会被清空) |
其中每个参数都是 struct btrfs_ioctl_feature_flags 类型,flags 含义可以参考 BTRFS_IOC_GET_FEATURES。
# BTRFS_IOC_GET_SUPPORTED_FEATURES
获取内核支持的特性(features)。
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件 / 目录的文件描述符 |
ioctl args | struct btrfs_ioctl_feature_flags[2] |
args[0] | 无需填写,由内核填充,表示哪些特性是当前内核支持的 |
args[1] | 无需填写,由内核填充,表示哪些特性可以安全启用(set) |
args[1] | 无需填写,由内核填充,表示哪些特性可以安全关闭(clear) |
# BTRFS_IOC_RM_DEV_V2
(4.7 版本引入) 删除一个设备(比如一个 btrfs
多设备卷中的某个设备),或取消当前的设备删除操作。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件或目录的文件描述符 |
ioctl args | struct btrfs_ioctl_vol_args_V2 |
args.fd | 该字段目前会被忽略 |
args.transid | 该字段目前会被忽略 |
args.flags | 控制标志,只能是空或 BTRFS_DEVICE_SPEC_BY_ID |
args.size | 该字段目前会被忽略 |
args.qgroup_inherit | 该字段目前会被忽略 |
args.name (union) | "cancel" :取消当前设备删除操作;或是要删除设备的路径 |
args.devid (union) | 要删除的设备 id,使能该项需要 flag 为 BTRFS_DEVICE_SPEC_BY_ID |
args.subvolid (union) | 该项目前会被忽略 |
# BTRFS_IOC_LOGICAL_INO_V2
将某个逻辑地址(logical address)反查出它所属于的 inode(也就是哪个文件使用了这个物理块)。
需要权限:CAP_SYS_ADMIN
Field | Description |
---|---|
ioctl fd | Btrfs 文件系统中任意文件 / 目录的文件描述符 |
ioctl args | struct btrfs_ioctl_logical_ino_args |
args.logical | 要查询的逻辑地址 |
args.size | 传入 buffer 的大小 |
args.reserved | 保留,目前必须为 0 |
args.flags | 控制标志,目前只能是 BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET ,用于控制是否忽略 page offset。 |
args.inodes | 传入一个 buffer 用于接收数据,其实是一个 struct btrfs_data_container 指针,存储查询结果 |
V2 版本允许根据 logical address 查找整个 block(或 extents),而不仅仅是精确 offset 对应的那一块。这在某些情况很有用,比如你只知道大致逻辑地址,但不是 page-aligned 或不是精确的起始偏移。