1 /*
2  * Copyright (C) 2007 Oracle.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public
6  * License v2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public
14  * License along with this program; if not, write to the
15  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16  * Boston, MA 021110-1307, USA.
17  */
18 
19 /// D translation of ioctl.h from btrfs-progs (v5.9)
20 module btrfs.c.ioctl;
21 
22 extern(C):
23 
24 import core.sys.posix.sys.ioctl;
25 
26 import btrfs.c.kerncompat;
27 
28 import btrfs.c.kernel_shared.ctree : BTRFS_LABEL_SIZE;
29 
30 enum BTRFS_IOCTL_MAGIC = 0x94;
31 enum BTRFS_VOL_NAME_MAX = 255;
32 
33 /* this should be 4k */
34 enum BTRFS_PATH_NAME_MAX = 4087;
35 struct btrfs_ioctl_vol_args {
36 	__s64 fd;
37 	ubyte[BTRFS_PATH_NAME_MAX + 1] name;
38 }
39 // static assert((btrfs_ioctl_vol_args).sizeof == 4096);
40 
41 enum BTRFS_DEVICE_PATH_NAME_MAX = 1024;
42 
43 enum BTRFS_SUBVOL_CREATE_ASYNC	= (1UL << 0);
44 enum BTRFS_SUBVOL_RDONLY		= (1UL << 1);
45 enum BTRFS_SUBVOL_QGROUP_INHERIT	= (1UL << 2);
46 enum BTRFS_DEVICE_SPEC_BY_ID		= (1UL << 3);
47 enum BTRFS_SUBVOL_SPEC_BY_ID		= (1UL << 4);
48 
49 enum BTRFS_VOL_ARG_V2_FLAGS_SUPPORTED		=
50 			(BTRFS_SUBVOL_CREATE_ASYNC |
51 			BTRFS_SUBVOL_RDONLY |
52 			BTRFS_SUBVOL_QGROUP_INHERIT |
53 			BTRFS_DEVICE_SPEC_BY_ID |
54 			BTRFS_SUBVOL_SPEC_BY_ID);
55 
56 enum BTRFS_FSID_SIZE = 16;
57 public import btrfs.c.kernel_shared.ctree : BTRFS_UUID_SIZE;
58 
59 enum BTRFS_QGROUP_INHERIT_SET_LIMITS	= (1UL << 0);
60 
61 struct btrfs_qgroup_limit {
62 	__u64	flags;
63 	__u64	max_referenced;
64 	__u64	max_exclusive;
65 	__u64	rsv_referenced;
66 	__u64	rsv_exclusive;
67 }
68 // static assert((btrfs_qgroup_limit).sizeof == 40);
69 
70 struct btrfs_qgroup_inherit {
71 	__u64	flags;
72 	__u64	num_qgroups;
73 	__u64	num_ref_copies;
74 	__u64	num_excl_copies;
75 	btrfs_qgroup_limit lim;
76 	__u64[0]	qgroups;
77 }
78 // static assert((btrfs_qgroup_inherit).sizeof == 72);
79 
80 struct btrfs_ioctl_qgroup_limit_args {
81 	__u64	qgroupid;
82 	btrfs_qgroup_limit lim;
83 }
84 // static assert((btrfs_ioctl_qgroup_limit_args).sizeof == 48);
85 
86 enum BTRFS_SUBVOL_NAME_MAX = 4039;
87 struct btrfs_ioctl_vol_args_v2 {
88 	__s64 fd;
89 	__u64 transid;
90 	__u64 flags;
91 	union {
92 		struct {
93 			__u64 size;
94 			btrfs_qgroup_inherit /*__user*/ *qgroup_inherit;
95 		}
96 		__u64[4] unused;
97 	}
98 	union {
99 		char[BTRFS_SUBVOL_NAME_MAX + 1] name;
100 		__u64 devid;
101 		__u64 subvolid;
102 	}
103 }
104 // static assert((btrfs_ioctl_vol_args_v2).sizeof == 4096);
105 
106 /*
107  * structure to report errors and progress to userspace, either as a
108  * result of a finished scrub, a canceled scrub or a progress inquiry
109  */
110 struct btrfs_scrub_progress {
111 	__u64 data_extents_scrubbed;	/* # of data extents scrubbed */
112 	__u64 tree_extents_scrubbed;	/* # of tree extents scrubbed */
113 	__u64 data_bytes_scrubbed;	/* # of data bytes scrubbed */
114 	__u64 tree_bytes_scrubbed;	/* # of tree bytes scrubbed */
115 	__u64 read_errors;		/* # of read errors encountered (EIO) */
116 	__u64 csum_errors;		/* # of failed csum checks */
117 	__u64 verify_errors;		/* # of occurrences, where the metadata
118 					 * of a tree block did not match the
119 					 * expected values, like generation or
120 					 * logical */
121 	__u64 no_csum;			/* # of 4k data block for which no csum
122 					 * is present, probably the result of
123 					 * data written with nodatasum */
124 	__u64 csum_discards;		/* # of csum for which no data was found
125 					 * in the extent tree. */
126 	__u64 super_errors;		/* # of bad super blocks encountered */
127 	__u64 malloc_errors;		/* # of internal kmalloc errors. These
128 					 * will likely cause an incomplete
129 					 * scrub */
130 	__u64 uncorrectable_errors;	/* # of errors where either no intact
131 					 * copy was found or the writeback
132 					 * failed */
133 	__u64 corrected_errors;		/* # of errors corrected */
134 	__u64 last_physical;		/* last physical address scrubbed. In
135 					 * case a scrub was aborted, this can
136 					 * be used to restart the scrub */
137 	__u64 unverified_errors;	/* # of occurrences where a read for a
138 					 * full (64k) bio failed, but the re-
139 					 * check succeeded for each 4k piece.
140 					 * Intermittent error. */
141 }
142 
143 enum BTRFS_SCRUB_READONLY	= 1;
144 struct btrfs_ioctl_scrub_args {
145 	__u64 devid;				/* in */
146 	__u64 start;				/* in */
147 	__u64 end;				/* in */
148 	__u64 flags;				/* in */
149 	btrfs_scrub_progress progress;	/* out */
150 	/* pad to 1k */
151 	__u64[(1024-32-(btrfs_scrub_progress).sizeof)/8] unused;
152 }
153 // static assert((btrfs_ioctl_scrub_args).sizeof == 1024);
154 
155 enum BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS	= 0;
156 enum BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID	= 1;
157 struct btrfs_ioctl_dev_replace_start_params {
158 	__u64 srcdevid;	/* in, if 0, use srcdev_name instead */
159 	__u64 cont_reading_from_srcdev_mode;	/* in, see #define
160 						 * above */
161 	__u8[BTRFS_DEVICE_PATH_NAME_MAX + 1] srcdev_name;	/* in */
162 	__u8[BTRFS_DEVICE_PATH_NAME_MAX + 1] tgtdev_name;	/* in */
163 }
164 // static assert((btrfs_ioctl_dev_replace_start_params).sizeof == 2072);
165 
166 enum BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED	= 0;
167 enum BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED		= 1;
168 enum BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED		= 2;
169 enum BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED		= 3;
170 enum BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED		= 4;
171 struct btrfs_ioctl_dev_replace_status_params {
172 	__u64 replace_state;	/* out, see #define above */
173 	__u64 progress_1000;	/* out, 0 <= x <= 1000 */
174 	__u64 time_started;	/* out, seconds since 1-Jan-1970 */
175 	__u64 time_stopped;	/* out, seconds since 1-Jan-1970 */
176 	__u64 num_write_errors;	/* out */
177 	__u64 num_uncorrectable_read_errors;	/* out */
178 }
179 // static assert((btrfs_ioctl_dev_replace_status_params).sizeof == 48);
180 
181 enum BTRFS_IOCTL_DEV_REPLACE_CMD_START			= 0;
182 enum BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS			= 1;
183 enum BTRFS_IOCTL_DEV_REPLACE_CMD_CANCEL			= 2;
184 enum BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_RESULT		= -1;
185 enum BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR			= 0;
186 enum BTRFS_IOCTL_DEV_REPLACE_RESULT_NOT_STARTED		= 1;
187 enum BTRFS_IOCTL_DEV_REPLACE_RESULT_ALREADY_STARTED		= 2;
188 enum BTRFS_IOCTL_DEV_REPLACE_RESULT_SCRUB_INPROGRESS		= 3;
189 struct btrfs_ioctl_dev_replace_args {
190 	__u64 cmd;	/* in */
191 	__u64 result;	/* out */
192 
193 	union {
194 		btrfs_ioctl_dev_replace_start_params start;
195 		btrfs_ioctl_dev_replace_status_params status;
196 	}	/* in/out */
197 
198 	__u64[64] spare;
199 }
200 // static assert((btrfs_ioctl_dev_replace_args).sizeof == 2600);
201 
202 struct btrfs_ioctl_dev_info_args {
203 	__u64 devid;				/* in/out */
204 	__u8[BTRFS_UUID_SIZE] uuid;		/* in/out */
205 	__u64 bytes_used;			/* out */
206 	__u64 total_bytes;			/* out */
207 	__u64[379] unused;			/* pad to 4k */
208 	__u8[BTRFS_DEVICE_PATH_NAME_MAX] path;	/* out */
209 }
210 // static assert((btrfs_ioctl_dev_info_args).sizeof == 4096);
211 
212 struct btrfs_ioctl_fs_info_args {
213 	__u64 max_id;				/* out */
214 	__u64 num_devices;			/* out */
215 	__u8[BTRFS_FSID_SIZE] fsid;		/* out */
216 	__u32 nodesize;				/* out */
217 	__u32 sectorsize;			/* out */
218 	__u32 clone_alignment;			/* out */
219 	__u32 reserved32;
220 	__u64[122] reserved;			/* pad to 1k */
221 }
222 // static assert((btrfs_ioctl_fs_info_args).sizeof == 1024);
223 
224 struct btrfs_ioctl_feature_flags {
225 	__u64 compat_flags;
226 	__u64 compat_ro_flags;
227 	__u64 incompat_flags;
228 }
229 // static assert((btrfs_ioctl_feature_flags).sizeof == 24);
230 
231 /* balance control ioctl modes */
232 enum BTRFS_BALANCE_CTL_PAUSE		= 1;
233 enum BTRFS_BALANCE_CTL_CANCEL	= 2;
234 enum BTRFS_BALANCE_CTL_RESUME	= 3;
235 
236 /*
237  * this is packed, because it should be exactly the same as its disk
238  * byte order counterpart (btrfs_disk_balance_args)
239  */
240 struct btrfs_balance_args {
241 align(1):
242 	__u64 profiles;
243 
244 	/*
245 	 * usage filter
246 	 * BTRFS_BALANCE_ARGS_USAGE with a single value means '0..N'
247 	 * BTRFS_BALANCE_ARGS_USAGE_RANGE - range syntax, min..max
248 	 */
249 	union {
250 		__u64 usage;
251 		struct {
252 			__u32 usage_min;
253 			__u32 usage_max;
254 		}
255 	}
256 
257 	__u64 devid;
258 	__u64 pstart;
259 	__u64 pend;
260 	__u64 vstart;
261 	__u64 vend;
262 
263 	__u64 target;
264 
265 	__u64 flags;
266 
267 	/*
268 	 * BTRFS_BALANCE_ARGS_LIMIT with value 'limit'
269 	 * BTRFS_BALANCE_ARGS_LIMIT_RANGE - the extend version can use minimum
270 	 * and maximum
271 	 */
272 	union {
273 		__u64 limit;		/* limit number of processed chunks */
274 		struct {
275 			__u32 limit_min;
276 			__u32 limit_max;
277 		}
278 	}
279 	__u32 stripes_min;
280 	__u32 stripes_max;
281 	__u64[6] unused;
282 }
283 
284 /* report balance progress to userspace */
285 struct btrfs_balance_progress {
286 	__u64 expected;		/* estimated # of chunks that will be
287 				 * relocated to fulfil the request */
288 	__u64 considered;	/* # of chunks we have considered so far */
289 	__u64 completed;	/* # of chunks relocated so far */
290 }
291 
292 enum BTRFS_BALANCE_STATE_RUNNING	= (1UL << 0);
293 enum BTRFS_BALANCE_STATE_PAUSE_REQ	= (1UL << 1);
294 enum BTRFS_BALANCE_STATE_CANCEL_REQ	= (1UL << 2);
295 
296 struct btrfs_ioctl_balance_args {
297 	__u64 flags;				/* in/out */
298 	__u64 state;				/* out */
299 
300 	btrfs_balance_args data;		/* in/out */
301 	btrfs_balance_args meta;		/* in/out */
302 	btrfs_balance_args sys;		/* in/out */
303 
304 	btrfs_balance_progress stat;	/* out */
305 
306 	__u64[72] unused;			/* pad to 1k */
307 }
308 // static assert((btrfs_ioctl_balance_args).sizeof == 1024);
309 
310 enum BTRFS_INO_LOOKUP_PATH_MAX = 4080;
311 struct btrfs_ioctl_ino_lookup_args {
312 	__u64 treeid;
313 	__u64 objectid;
314 	char[BTRFS_INO_LOOKUP_PATH_MAX] name;
315 }
316 // static assert((btrfs_ioctl_ino_lookup_args).sizeof == 4096);
317 
318 enum BTRFS_INO_LOOKUP_USER_PATH_MAX	= (4080 - BTRFS_VOL_NAME_MAX - 1);
319 struct btrfs_ioctl_ino_lookup_user_args {
320 	/* in, inode number containing the subvolume of 'subvolid' */
321 	__u64 dirid;
322 	/* in */
323 	__u64 treeid;
324 	/* out, name of the subvolume of 'treeid' */
325 	char[BTRFS_VOL_NAME_MAX + 1] name;
326 	/*
327 	 * out, constructed path from the directory with which the ioctl is
328 	 * called to dirid
329 	 */
330 	char[BTRFS_INO_LOOKUP_USER_PATH_MAX] path;
331 }
332 // static assert((btrfs_ioctl_ino_lookup_user_args).sizeof == 4096);
333 
334 struct btrfs_ioctl_search_key {
335 	/* which root are we searching.  0 is the tree of tree roots */
336 	__u64 tree_id;
337 
338 	/* keys returned will be >= min and <= max */
339 	__u64 min_objectid;
340 	__u64 max_objectid;
341 
342 	/* keys returned will be >= min and <= max */
343 	__u64 min_offset;
344 	__u64 max_offset;
345 
346 	/* max and min transids to search for */
347 	__u64 min_transid;
348 	__u64 max_transid;
349 
350 	/* keys returned will be >= min and <= max */
351 	__u32 min_type;
352 	__u32 max_type;
353 
354 	/*
355 	 * how many items did userland ask for, and how many are we
356 	 * returning
357 	 */
358 	__u32 nr_items;
359 
360 	/* align to 64 bits */
361 	__u32 unused;
362 
363 	/* some extra for later */
364 	__u64 unused1;
365 	__u64 unused2;
366 	__u64 unused3;
367 	__u64 unused4;
368 }
369 
370 struct btrfs_ioctl_search_header {
371 	__u64 transid;
372 	__u64 objectid;
373 	__u64 offset;
374 	__u32 type;
375 	__u32 len;
376 } /*__attribute__((may_alias))*/
377 
378 enum BTRFS_SEARCH_ARGS_BUFSIZE = (4096 - (btrfs_ioctl_search_key).sizeof);
379 /*
380  * the buf is an array of search headers where
381  * each header is followed by the actual item
382  * the type field is expanded to 32 bits for alignment
383  */
384 struct btrfs_ioctl_search_args {
385 	btrfs_ioctl_search_key key;
386 	ubyte[BTRFS_SEARCH_ARGS_BUFSIZE] buf;
387 }
388 
389 /*
390  * Extended version of TREE_SEARCH ioctl that can return more than 4k of bytes.
391  * The allocated size of the buffer is set in buf_size.
392  */
393 struct btrfs_ioctl_search_args_v2 {
394 	btrfs_ioctl_search_key key;        /* in/out - search parameters */
395 	__u64 buf_size;			   /* in - size of buffer
396 					    * out - on EOVERFLOW: needed size
397 					    *       to store item */
398 	__u64[0] buf;                      /* out - found items */
399 }
400 // static assert((btrfs_ioctl_search_args_v2).sizeof == 112);
401 
402 /* With a @src_length of zero, the range from @src_offset->EOF is cloned! */
403 struct btrfs_ioctl_clone_range_args {
404 	__s64 src_fd;
405 	__u64 src_offset, src_length;
406 	__u64 dest_offset;
407 }
408 // static assert((btrfs_ioctl_clone_range_args).sizeof == 32);
409 
410 /* flags for the defrag range ioctl */
411 enum BTRFS_DEFRAG_RANGE_COMPRESS = 1;
412 enum BTRFS_DEFRAG_RANGE_START_IO = 2;
413 
414 enum BTRFS_SAME_DATA_DIFFERS	= 1;
415 /* For extent-same ioctl */
416 struct btrfs_ioctl_same_extent_info {
417 	__s64 fd;		/* in - destination file */
418 	__u64 logical_offset;	/* in - start of extent in destination */
419 	__u64 bytes_deduped;	/* out - total # of bytes we were able
420 				 * to dedupe from this file */
421 	/* status of this dedupe operation:
422 	 * 0 if dedup succeeds
423 	 * < 0 for error
424 	 * == BTRFS_SAME_DATA_DIFFERS if data differs
425 	 */
426 	__s32 status;		/* out - see above description */
427 	__u32 reserved;
428 }
429 
430 struct btrfs_ioctl_same_args {
431 	__u64 logical_offset;	/* in - start of extent in source */
432 	__u64 length;		/* in - length of extent */
433 	__u16 dest_count;	/* in - total elements in info array */
434 	__u16 reserved1;
435 	__u32 reserved2;
436 	btrfs_ioctl_same_extent_info[0] info;
437 }
438 // static assert((btrfs_ioctl_same_args).sizeof == 24);
439 
440 struct btrfs_ioctl_defrag_range_args {
441 	/* start of the defrag operation */
442 	__u64 start;
443 
444 	/* number of bytes to defrag, use (u64)-1 to say all */
445 	__u64 len;
446 
447 	/*
448 	 * flags for the operation, which can include turning
449 	 * on compression for this one defrag
450 	 */
451 	__u64 flags;
452 
453 	/*
454 	 * any extent bigger than this will be considered
455 	 * already defragged.  Use 0 to take the kernel default
456 	 * Use 1 to say every single extent must be rewritten
457 	 */
458 	__u32 extent_thresh;
459 
460 	/*
461 	 * which compression method to use if turning on compression
462 	 * for this defrag operation.  If unspecified, zlib will
463 	 * be used
464 	 */
465 	__u32 compress_type;
466 
467 	/* spare for later */
468 	__u32[4] unused;
469 }
470 // static assert((btrfs_ioctl_defrag_range_args).sizeof == 48);
471 
472 struct btrfs_ioctl_space_info {
473 	__u64 flags;
474 	__u64 total_bytes;
475 	__u64 used_bytes;
476 }
477 
478 struct btrfs_ioctl_space_args {
479 	__u64 space_slots;
480 	__u64 total_spaces;
481 	btrfs_ioctl_space_info[0] spaces;
482 }
483 // static assert((btrfs_ioctl_space_args).sizeof == 16);
484 
485 struct btrfs_data_container {
486 	__u32	bytes_left;	/* out -- bytes not needed to deliver output */
487 	__u32	bytes_missing;	/* out -- additional bytes needed for result */
488 	__u32	elem_cnt;	/* out */
489 	__u32	elem_missed;	/* out */
490 	__u64[0]	val;		/* out */
491 }
492 
493 struct btrfs_ioctl_ino_path_args {
494 	__u64				inum;		/* in */
495 	__u64				size;		/* in */
496 	__u64[4]				reserved;
497 	/* struct btrfs_data_container	*fspath;	   out */
498 	__u64				fspath;		/* out */
499 }
500 // static assert((btrfs_ioctl_ino_path_args).sizeof == 56);
501 
502 struct btrfs_ioctl_logical_ino_args {
503 	__u64				logical;	/* in */
504 	__u64				size;		/* in */
505 	__u64[3]				reserved;
506 	__u64				flags;		/* in */
507 	/* struct btrfs_data_container	*inodes;	out   */
508 	__u64				inodes;
509 }
510 
511 /*
512  * Return every ref to the extent, not just those containing logical block.
513  * Requires logical == extent bytenr.
514  */
515 enum BTRFS_LOGICAL_INO_ARGS_IGNORE_OFFSET    = (1UL << 0);
516 
517 enum btrfs_dev_stat_values {
518 	/* disk I/O failure stats */
519 	BTRFS_DEV_STAT_WRITE_ERRS, /* EIO or EREMOTEIO from lower layers */
520 	BTRFS_DEV_STAT_READ_ERRS, /* EIO or EREMOTEIO from lower layers */
521 	BTRFS_DEV_STAT_FLUSH_ERRS, /* EIO or EREMOTEIO from lower layers */
522 
523 	/* stats for indirect indications for I/O failures */
524 	BTRFS_DEV_STAT_CORRUPTION_ERRS, /* checksum error, bytenr error or
525 					 * contents is illegal: this is an
526 					 * indication that the block was damaged
527 					 * during read or write, or written to
528 					 * wrong location or read from wrong
529 					 * location */
530 	BTRFS_DEV_STAT_GENERATION_ERRS, /* an indication that blocks have not
531 					 * been written */
532 
533 	BTRFS_DEV_STAT_VALUES_MAX
534 }
535 
536 /* Reset statistics after reading; needs SYS_ADMIN capability */
537 enum	BTRFS_DEV_STATS_RESET		= (1UL << 0);
538 
539 struct btrfs_ioctl_get_dev_stats {
540 	__u64 devid;				/* in */
541 	__u64 nr_items;				/* in/out */
542 	__u64 flags;				/* in/out */
543 
544 	/* out values: */
545 	__u64[btrfs_dev_stat_values.BTRFS_DEV_STAT_VALUES_MAX] values;
546 
547 	__u64[128 - 2 - btrfs_dev_stat_values.BTRFS_DEV_STAT_VALUES_MAX] unused; /* pad to 1k + 8B */
548 }
549 // static assert((btrfs_ioctl_get_dev_stats).sizeof == 1032);
550 
551 /* BTRFS_IOC_SNAP_CREATE is no longer used by the btrfs command */
552 enum BTRFS_QUOTA_CTL_ENABLE	= 1;
553 enum BTRFS_QUOTA_CTL_DISABLE	= 2;
554 /* 3 has formerly been reserved for BTRFS_QUOTA_CTL_RESCAN */
555 struct btrfs_ioctl_quota_ctl_args {
556 	__u64 cmd;
557 	__u64 status;
558 }
559 // static assert((btrfs_ioctl_quota_ctl_args).sizeof == 16);
560 
561 struct btrfs_ioctl_quota_rescan_args {
562 	__u64	flags;
563 	__u64   progress;
564 	__u64[6]   reserved;
565 }
566 // static assert((btrfs_ioctl_quota_rescan_args).sizeof == 64);
567 
568 struct btrfs_ioctl_qgroup_assign_args {
569 	__u64 assign;
570 	__u64 src;
571 	__u64 dst;
572 }
573 
574 struct btrfs_ioctl_qgroup_create_args {
575 	__u64 create;
576 	__u64 qgroupid;
577 }
578 // static assert((btrfs_ioctl_qgroup_create_args).sizeof == 16);
579 
580 struct btrfs_ioctl_timespec {
581 	__u64 sec;
582 	__u32 nsec;
583 }
584 
585 struct btrfs_ioctl_received_subvol_args {
586 	char[BTRFS_UUID_SIZE]	uuid;	/* in */
587 	__u64	stransid;		/* in */
588 	__u64	rtransid;		/* out */
589 	btrfs_ioctl_timespec stime; /* in */
590 	btrfs_ioctl_timespec rtime; /* out */
591 	__u64	flags;			/* in */
592 	__u64[16]	reserved;		/* in */
593 }
594 // static assert((btrfs_ioctl_received_subvol_args).sizeof == 200);
595 
596 /*
597  * If we have a 32-bit userspace and 64-bit kernel, then the UAPI
598  * structures are incorrect, as the timespec structure from userspace
599  * is 4 bytes too small. We define these alternatives here for backward
600  * compatibility, the kernel understands both values.
601  */
602 
603 /*
604  * Structure size is different on 32bit and 64bit, has some padding if the
605  * structure is embedded. Packing makes sure the size is same on both, but will
606  * be misaligned on 64bit.
607  *
608  * NOTE: do not use in your code, this is for testing only
609  */
610 struct btrfs_ioctl_timespec_32 {
611 align(1):
612 	__u64 sec;
613 	__u32 nsec;
614 }
615 
616 struct btrfs_ioctl_received_subvol_args_32 {
617 align(1):
618 	char[BTRFS_UUID_SIZE]	uuid;	/* in */
619 	__u64	stransid;		/* in */
620 	__u64	rtransid;		/* out */
621 	btrfs_ioctl_timespec_32 stime; /* in */
622 	btrfs_ioctl_timespec_32 rtime; /* out */
623 	__u64	flags;			/* in */
624 	__u64[16]	reserved;		/* in */
625 }
626 // static assert((btrfs_ioctl_received_subvol_args_32).sizeof == 192);
627 
628 enum BTRFS_IOC_SET_RECEIVED_SUBVOL_32_COMPAT_DEFINED = 1;
629 
630 /*
631  * Caller doesn't want file data in the send stream, even if the
632  * search of clone sources doesn't find an extent. UPDATE_EXTENT
633  * commands will be sent instead of WRITE commands.
634  */
635 enum BTRFS_SEND_FLAG_NO_FILE_DATA		= 0x1;
636 
637 /*
638  * Do not add the leading stream header. Used when multiple snapshots
639  * are sent back to back.
640  */
641 enum BTRFS_SEND_FLAG_OMIT_STREAM_HEADER	= 0x2;
642 
643 /*
644  * Omit the command at the end of the stream that indicated the end
645  * of the stream. This option is used when multiple snapshots are
646  * sent back to back.
647  */
648 enum BTRFS_SEND_FLAG_OMIT_END_CMD		= 0x4;
649 
650 enum BTRFS_SEND_FLAG_MASK =
651 	(BTRFS_SEND_FLAG_NO_FILE_DATA |
652 	 BTRFS_SEND_FLAG_OMIT_STREAM_HEADER |
653 	 BTRFS_SEND_FLAG_OMIT_END_CMD);
654 
655 struct btrfs_ioctl_send_args {
656 	__s64 send_fd;			/* in */
657 	__u64 clone_sources_count;	/* in */
658 	__u64 /*__user*/ *clone_sources;	/* in */
659 	__u64 parent_root;		/* in */
660 	__u64 flags;			/* in */
661 	__u64[4] reserved;		/* in */
662 }
663 /*
664  * Size of structure depends on pointer width, was not caught in the early
665  * days.  Kernel handles pointer width differences transparently.
666  */
667 // static assert((__u64 *).sizeof == 8
668 // 	     ? (btrfs_ioctl_send_args).sizeof == 72
669 // 	     : ((void *).sizeof == 4
670 // 		? (btrfs_ioctl_send_args).sizeof == 68
671 // 		: 0));
672 
673 /*
674  * Different pointer width leads to structure size change. Kernel should accept
675  * both ioctl values (derived from the structures) for backward compatibility.
676  * Size of this structure is same on 32bit and 64bit though.
677  *
678  * NOTE: do not use in your code, this is for testing only
679  */
680 struct btrfs_ioctl_send_args_64 {
681 align(1):
682 	__s64 send_fd;			/* in */
683 	__u64 clone_sources_count;	/* in */
684 	union {
685 		__u64 /*__user*/ *clone_sources;	/* in */
686 		__u64 __clone_sources_alignment;
687 	}
688 	__u64 parent_root;		/* in */
689 	__u64 flags;			/* in */
690 	__u64[4] reserved;		/* in */
691 }
692 // static assert((btrfs_ioctl_send_args_64).sizeof == 72);
693 
694 enum BTRFS_IOC_SEND_64_COMPAT_DEFINED = 1;
695 
696 /*
697  * Information about a fs tree root.
698  *
699  * All items are filled by the ioctl
700  */
701 struct btrfs_ioctl_get_subvol_info_args {
702 	/* Id of this subvolume */
703 	__u64 treeid;
704 
705 	/* Name of this subvolume, used to get the real name at mount point */
706 	char[BTRFS_VOL_NAME_MAX + 1] name;
707 
708 	/*
709 	 * Id of the subvolume which contains this subvolume.
710 	 * Zero for top-level subvolume or a deleted subvolume.
711 	 */
712 	__u64 parent_id;
713 
714 	/*
715 	 * Inode number of the directory which contains this subvolume.
716 	 * Zero for top-level subvolume or a deleted subvolume
717 	 */
718 	__u64 dirid;
719 
720 	/* Latest transaction id of this subvolume */
721 	__u64 generation;
722 
723 	/* Flags of this subvolume */
724 	__u64 flags;
725 
726 	/* UUID of this subvolume */
727 	__u8[BTRFS_UUID_SIZE] uuid;
728 
729 	/*
730 	 * UUID of the subvolume of which this subvolume is a snapshot.
731 	 * All zero for a non-snapshot subvolume.
732 	 */
733 	__u8[BTRFS_UUID_SIZE] parent_uuid;
734 
735 	/*
736 	 * UUID of the subvolume from which this subvolume was received.
737 	 * All zero for non-received subvolume.
738 	 */
739 	__u8[BTRFS_UUID_SIZE] received_uuid;
740 
741 	/* Transaction id indicating when change/create/send/receive happened */
742 	__u64 ctransid;
743 	__u64 otransid;
744 	__u64 stransid;
745 	__u64 rtransid;
746 	/* Time corresponding to c/o/s/rtransid */
747 	btrfs_ioctl_timespec ctime;
748 	btrfs_ioctl_timespec otime;
749 	btrfs_ioctl_timespec stime;
750 	btrfs_ioctl_timespec rtime;
751 
752 	/* Must be zero */
753 	__u64[8] reserved;
754 }
755 
756 enum BTRFS_MAX_ROOTREF_BUFFER_NUM			= 255;
757 struct btrfs_ioctl_get_subvol_rootref_args {
758 	/* in/out, minimum id of rootref's treeid to be searched */
759 	__u64 min_treeid;
760 
761 	/* out */
762 	struct _rootref {
763 		__u64 treeid;
764 		__u64 dirid;
765 	} _rootref[BTRFS_MAX_ROOTREF_BUFFER_NUM] rootref;
766 
767 	/* out, number of found items */
768 	__u8 num_items;
769 	__u8[7] align_;
770 }
771 // static assert((btrfs_ioctl_get_subvol_rootref_args).sizeof == 4096);
772 
773 /* Error codes as returned by the kernel */
774 enum btrfs_err_code {
775 	notused,
776 	BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET,
777 	BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET,
778 	BTRFS_ERROR_DEV_RAID5_MIN_NOT_MET,
779 	BTRFS_ERROR_DEV_RAID6_MIN_NOT_MET,
780 	BTRFS_ERROR_DEV_TGT_REPLACE,
781 	BTRFS_ERROR_DEV_MISSING_NOT_FOUND,
782 	BTRFS_ERROR_DEV_ONLY_WRITABLE,
783 	BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS,
784 	BTRFS_ERROR_DEV_RAID1C3_MIN_NOT_MET,
785 	BTRFS_ERROR_DEV_RAID1C4_MIN_NOT_MET,
786 }
787 
788 /* An error code to error string mapping for the kernel
789 *  error codes
790 */
791 const(char)* btrfs_err_str()(btrfs_err_code err_code)
792 {
793 	switch (err_code) {
794 		case btrfs_err_code.BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET:
795 			return "unable to go below two devices on raid1";
796 		case btrfs_err_code.BTRFS_ERROR_DEV_RAID1C3_MIN_NOT_MET:
797 			return "unable to go below three devices on raid1c3";
798 		case btrfs_err_code.BTRFS_ERROR_DEV_RAID1C4_MIN_NOT_MET:
799 			return "unable to go below four devices on raid1c4";
800 		case btrfs_err_code.BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET:
801 			return "unable to go below four devices on raid10";
802 		case btrfs_err_code.BTRFS_ERROR_DEV_RAID5_MIN_NOT_MET:
803 			return "unable to go below two devices on raid5";
804 		case btrfs_err_code.BTRFS_ERROR_DEV_RAID6_MIN_NOT_MET:
805 			return "unable to go below three devices on raid6";
806 		case btrfs_err_code.BTRFS_ERROR_DEV_TGT_REPLACE:
807 			return "unable to remove the dev_replace target dev";
808 		case btrfs_err_code.BTRFS_ERROR_DEV_MISSING_NOT_FOUND:
809 			return "no missing devices found to remove";
810 		case btrfs_err_code.BTRFS_ERROR_DEV_ONLY_WRITABLE:
811 			return "unable to remove the only writeable device";
812 		case btrfs_err_code.BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS:
813 			return "add/delete/balance/replace/resize operation " ~
814 				"in progress";
815 		default:
816 			return null;
817 	}
818 }
819 
820 enum BTRFS_IOC_SNAP_CREATE = _IOW!(btrfs_ioctl_vol_args)(BTRFS_IOCTL_MAGIC, 1);
821 enum BTRFS_IOC_DEFRAG = _IOW!(btrfs_ioctl_vol_args)(BTRFS_IOCTL_MAGIC, 2);
822 enum BTRFS_IOC_RESIZE = _IOW!(btrfs_ioctl_vol_args)(BTRFS_IOCTL_MAGIC, 3);
823 enum BTRFS_IOC_SCAN_DEV = _IOW!(btrfs_ioctl_vol_args)(BTRFS_IOCTL_MAGIC, 4);
824 enum BTRFS_IOC_FORGET_DEV = _IOW!(btrfs_ioctl_vol_args)(BTRFS_IOCTL_MAGIC, 5);
825 /* trans start and trans end are dangerous, and only for
826  * use by applications that know how to avoid the
827  * resulting deadlocks
828  */
829 enum BTRFS_IOC_TRANS_START  = _IO(BTRFS_IOCTL_MAGIC, 6);
830 enum BTRFS_IOC_TRANS_END    = _IO(BTRFS_IOCTL_MAGIC, 7);
831 enum BTRFS_IOC_SYNC         = _IO(BTRFS_IOCTL_MAGIC, 8);
832 
833 enum BTRFS_IOC_CLONE        = _IOW!(int)(BTRFS_IOCTL_MAGIC, 9);
834 enum BTRFS_IOC_ADD_DEV = _IOW!(btrfs_ioctl_vol_args)(BTRFS_IOCTL_MAGIC, 10);
835 enum BTRFS_IOC_RM_DEV = _IOW!(btrfs_ioctl_vol_args)(BTRFS_IOCTL_MAGIC, 11);
836 enum BTRFS_IOC_BALANCE = _IOW!(btrfs_ioctl_vol_args)(BTRFS_IOCTL_MAGIC, 12);
837 
838 enum BTRFS_IOC_CLONE_RANGE = _IOW!(btrfs_ioctl_clone_range_args)(BTRFS_IOCTL_MAGIC, 13);
839 
840 enum BTRFS_IOC_SUBVOL_CREATE = _IOW!(btrfs_ioctl_vol_args)(BTRFS_IOCTL_MAGIC, 14);
841 enum BTRFS_IOC_SNAP_DESTROY = _IOW!(btrfs_ioctl_vol_args)(BTRFS_IOCTL_MAGIC, 15);
842 enum BTRFS_IOC_DEFRAG_RANGE = _IOW!(btrfs_ioctl_defrag_range_args)(BTRFS_IOCTL_MAGIC, 16);
843 enum BTRFS_IOC_TREE_SEARCH = _IOWR!(btrfs_ioctl_search_args)(BTRFS_IOCTL_MAGIC, 17);
844 enum BTRFS_IOC_TREE_SEARCH_V2 = _IOWR!(btrfs_ioctl_search_args_v2)(BTRFS_IOCTL_MAGIC, 17);
845 enum BTRFS_IOC_INO_LOOKUP = _IOWR!(btrfs_ioctl_ino_lookup_args)(BTRFS_IOCTL_MAGIC, 18);
846 enum BTRFS_IOC_DEFAULT_SUBVOL = _IOW!(__u64)(BTRFS_IOCTL_MAGIC, 19);
847 enum BTRFS_IOC_SPACE_INFO = _IOWR!(btrfs_ioctl_space_args)(BTRFS_IOCTL_MAGIC, 20);
848 enum BTRFS_IOC_START_SYNC = _IOR!(__u64)(BTRFS_IOCTL_MAGIC, 24);
849 enum BTRFS_IOC_WAIT_SYNC  = _IOW!(__u64)(BTRFS_IOCTL_MAGIC, 22);
850 enum BTRFS_IOC_SNAP_CREATE_V2 = _IOW!(btrfs_ioctl_vol_args_v2)(BTRFS_IOCTL_MAGIC, 23);
851 enum BTRFS_IOC_SUBVOL_CREATE_V2 = _IOW!(btrfs_ioctl_vol_args_v2)(BTRFS_IOCTL_MAGIC, 24);
852 enum BTRFS_IOC_SUBVOL_GETFLAGS = _IOR!(__u64)(BTRFS_IOCTL_MAGIC, 25);
853 enum BTRFS_IOC_SUBVOL_SETFLAGS = _IOW!(__u64)(BTRFS_IOCTL_MAGIC, 26);
854 enum BTRFS_IOC_SCRUB = _IOWR!(btrfs_ioctl_scrub_args)(BTRFS_IOCTL_MAGIC, 27);
855 enum BTRFS_IOC_SCRUB_CANCEL = _IO(BTRFS_IOCTL_MAGIC, 28);
856 enum BTRFS_IOC_SCRUB_PROGRESS = _IOWR!(btrfs_ioctl_scrub_args)(BTRFS_IOCTL_MAGIC, 29);
857 enum BTRFS_IOC_DEV_INFO = _IOWR!(btrfs_ioctl_dev_info_args)(BTRFS_IOCTL_MAGIC, 30);
858 enum BTRFS_IOC_FS_INFO = _IOR!(btrfs_ioctl_fs_info_args)(BTRFS_IOCTL_MAGIC, 31);
859 enum BTRFS_IOC_BALANCE_V2 = _IOWR!(btrfs_ioctl_balance_args)(BTRFS_IOCTL_MAGIC, 32);
860 enum BTRFS_IOC_BALANCE_CTL = _IOW!(int)(BTRFS_IOCTL_MAGIC, 33);
861 enum BTRFS_IOC_BALANCE_PROGRESS = _IOR!(btrfs_ioctl_balance_args)(BTRFS_IOCTL_MAGIC, 34);
862 enum BTRFS_IOC_INO_PATHS = _IOWR!(btrfs_ioctl_ino_path_args)(BTRFS_IOCTL_MAGIC, 35);
863 enum BTRFS_IOC_LOGICAL_INO = _IOWR!(btrfs_ioctl_logical_ino_args)(BTRFS_IOCTL_MAGIC, 36);
864 enum BTRFS_IOC_SET_RECEIVED_SUBVOL = _IOWR!(btrfs_ioctl_received_subvol_args)(BTRFS_IOCTL_MAGIC, 37);
865 
866 static if (BTRFS_IOC_SET_RECEIVED_SUBVOL_32_COMPAT_DEFINED)
867 enum BTRFS_IOC_SET_RECEIVED_SUBVOL_32 = _IOWR!(btrfs_ioctl_received_subvol_args_32)(BTRFS_IOCTL_MAGIC, 37);
868 
869 static if (BTRFS_IOC_SEND_64_COMPAT_DEFINED)
870 enum BTRFS_IOC_SEND_64 = _IOW!(btrfs_ioctl_send_args_64)(BTRFS_IOCTL_MAGIC, 38);
871 
872 enum BTRFS_IOC_SEND = _IOW!(btrfs_ioctl_send_args)(BTRFS_IOCTL_MAGIC, 38);
873 enum BTRFS_IOC_DEVICES_READY = _IOR!(btrfs_ioctl_vol_args)(BTRFS_IOCTL_MAGIC, 39);
874 enum BTRFS_IOC_QUOTA_CTL = _IOWR!(btrfs_ioctl_quota_ctl_args)(BTRFS_IOCTL_MAGIC, 40);
875 enum BTRFS_IOC_QGROUP_ASSIGN = _IOW!(btrfs_ioctl_qgroup_assign_args)(BTRFS_IOCTL_MAGIC, 41);
876 enum BTRFS_IOC_QGROUP_CREATE = _IOW!(btrfs_ioctl_qgroup_create_args)(BTRFS_IOCTL_MAGIC, 42);
877 enum BTRFS_IOC_QGROUP_LIMIT = _IOR!(btrfs_ioctl_qgroup_limit_args)(BTRFS_IOCTL_MAGIC, 43);
878 enum BTRFS_IOC_QUOTA_RESCAN = _IOW!(btrfs_ioctl_quota_rescan_args)(BTRFS_IOCTL_MAGIC, 44);
879 enum BTRFS_IOC_QUOTA_RESCAN_STATUS = _IOR!(btrfs_ioctl_quota_rescan_args)(BTRFS_IOCTL_MAGIC, 45);
880 enum BTRFS_IOC_QUOTA_RESCAN_WAIT = _IO(BTRFS_IOCTL_MAGIC, 46);
881 enum BTRFS_IOC_GET_FSLABEL = _IOR!(char[BTRFS_LABEL_SIZE])(BTRFS_IOCTL_MAGIC, 49);
882 enum BTRFS_IOC_SET_FSLABEL = _IOW!(char[BTRFS_LABEL_SIZE])(BTRFS_IOCTL_MAGIC, 50);
883 enum BTRFS_IOC_GET_DEV_STATS = _IOWR!(btrfs_ioctl_get_dev_stats)(BTRFS_IOCTL_MAGIC, 52);
884 enum BTRFS_IOC_DEV_REPLACE = _IOWR!(btrfs_ioctl_dev_replace_args)(BTRFS_IOCTL_MAGIC, 53);
885 enum BTRFS_IOC_FILE_EXTENT_SAME = _IOWR!(btrfs_ioctl_same_args)(BTRFS_IOCTL_MAGIC, 54);
886 enum BTRFS_IOC_GET_FEATURES = _IOR!(btrfs_ioctl_feature_flags)(BTRFS_IOCTL_MAGIC, 57);
887 enum BTRFS_IOC_SET_FEATURES = _IOW!(btrfs_ioctl_feature_flags[2])(BTRFS_IOCTL_MAGIC, 57);
888 enum BTRFS_IOC_GET_SUPPORTED_FEATURES = _IOR!(btrfs_ioctl_feature_flags[3])(BTRFS_IOCTL_MAGIC, 57);
889 enum BTRFS_IOC_RM_DEV_V2	= _IOW!(btrfs_ioctl_vol_args_v2)(BTRFS_IOCTL_MAGIC, 58);
890 enum BTRFS_IOC_LOGICAL_INO_V2 = _IOWR!(btrfs_ioctl_logical_ino_args)(BTRFS_IOCTL_MAGIC, 59);
891 enum BTRFS_IOC_GET_SUBVOL_INFO = _IOR!(btrfs_ioctl_get_subvol_info_args)(BTRFS_IOCTL_MAGIC, 60);
892 enum BTRFS_IOC_GET_SUBVOL_ROOTREF = _IOWR!(btrfs_ioctl_get_subvol_rootref_args)(BTRFS_IOCTL_MAGIC, 61);
893 enum BTRFS_IOC_INO_LOOKUP_USER = _IOWR!(btrfs_ioctl_ino_lookup_user_args)(BTRFS_IOCTL_MAGIC, 62);
894 enum BTRFS_IOC_SNAP_DESTROY_V2 = _IOW!(btrfs_ioctl_vol_args_v2)(BTRFS_IOCTL_MAGIC, 63);