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