github.com/dennwc/btrfs@v0.0.0-20221026161108-3097362dc072/ioctl_h.go (about) 1 package btrfs 2 3 import ( 4 "encoding/binary" 5 "encoding/hex" 6 "github.com/dennwc/ioctl" 7 "os" 8 "strconv" 9 "strings" 10 "unsafe" 11 ) 12 13 var order = binary.LittleEndian 14 15 const ioctlMagic = 0x94 16 17 const devicePathNameMax = 1024 18 19 const ( 20 FSIDSize = 16 21 UUIDSize = 16 22 ) 23 24 var zeroUUID UUID 25 26 type UUID [UUIDSize]byte 27 28 func (id UUID) IsZero() bool { return id == zeroUUID } 29 func (id UUID) String() string { 30 if id.IsZero() { 31 return "<zero>" 32 } 33 buf := make([]byte, UUIDSize*2+4) 34 i := 0 35 i += hex.Encode(buf[i:], id[:4]) 36 buf[i] = '-' 37 i++ 38 i += hex.Encode(buf[i:], id[4:6]) 39 buf[i] = '-' 40 i++ 41 i += hex.Encode(buf[i:], id[6:8]) 42 buf[i] = '-' 43 i++ 44 i += hex.Encode(buf[i:], id[8:10]) 45 buf[i] = '-' 46 i++ 47 i += hex.Encode(buf[i:], id[10:]) 48 return string(buf) 49 } 50 51 type FSID [FSIDSize]byte 52 53 func (id FSID) String() string { return hex.EncodeToString(id[:]) } 54 55 const volNameMax = 4087 56 57 // this should be 4k 58 type btrfs_ioctl_vol_args struct { 59 fd int64 60 name [volNameMax + 1]byte 61 } 62 63 func (arg *btrfs_ioctl_vol_args) SetName(name string) { 64 n := copy(arg.name[:], name) 65 arg.name[n] = 0 66 } 67 68 type btrfs_qgroup_limit struct { 69 flags uint64 70 max_referenced uint64 71 max_exclusive uint64 72 rsv_referenced uint64 73 rsv_exclusive uint64 74 } 75 76 type btrfs_qgroup_inherit struct { 77 flags uint64 78 num_qgroups uint64 79 num_ref_copies uint64 80 num_excl_copies uint64 81 lim btrfs_qgroup_limit 82 //qgroups [0]uint64 83 } 84 85 type btrfs_ioctl_qgroup_limit_args struct { 86 qgroupid uint64 87 lim btrfs_qgroup_limit 88 } 89 90 type btrfs_ioctl_vol_args_v2_u1 struct { 91 size uint64 92 qgroup_inherit *btrfs_qgroup_inherit 93 } 94 95 const subvolNameMax = 4039 96 97 type SubvolFlags uint64 98 99 func (f SubvolFlags) ReadOnly() bool { 100 return f&SubvolReadOnly != 0 101 } 102 func (f SubvolFlags) String() string { 103 if f == 0 { 104 return "<nil>" 105 } 106 var out []string 107 if f&SubvolReadOnly != 0 { 108 out = append(out, "RO") 109 f = f & (^SubvolReadOnly) 110 } 111 if f != 0 { 112 out = append(out, "0x"+strconv.FormatInt(int64(f), 16)) 113 } 114 return strings.Join(out, "|") 115 } 116 117 // flags for subvolumes 118 // 119 // Used by: 120 // struct btrfs_ioctl_vol_args_v2.flags 121 // 122 // BTRFS_SUBVOL_RDONLY is also provided/consumed by the following ioctls: 123 // - BTRFS_IOC_SUBVOL_GETFLAGS 124 // - BTRFS_IOC_SUBVOL_SETFLAGS 125 const ( 126 subvolCreateAsync = SubvolFlags(1 << 0) 127 SubvolReadOnly = SubvolFlags(1 << 1) 128 subvolQGroupInherit = SubvolFlags(1 << 2) 129 ) 130 131 type btrfs_ioctl_vol_args_v2 struct { 132 fd int64 133 transid uint64 134 flags SubvolFlags 135 btrfs_ioctl_vol_args_v2_u1 136 unused [2]uint64 137 name [subvolNameMax + 1]byte 138 } 139 140 // structure to report errors and progress to userspace, either as a 141 // result of a finished scrub, a canceled scrub or a progress inquiry 142 type btrfs_scrub_progress struct { 143 data_extents_scrubbed uint64 // # of data extents scrubbed 144 tree_extents_scrubbed uint64 // # of tree extents scrubbed 145 data_bytes_scrubbed uint64 // # of data bytes scrubbed 146 tree_bytes_scrubbed uint64 // # of tree bytes scrubbed 147 read_errors uint64 // # of read errors encountered (EIO) 148 csum_errors uint64 // # of failed csum checks 149 // # of occurences, where the metadata of a tree block did not match the expected values, like generation or logical 150 verify_errors uint64 151 // # of 4k data block for which no csum is present, probably the result of data written with nodatasum 152 no_csum uint64 153 csum_discards uint64 // # of csum for which no data was found in the extent tree. 154 super_errors uint64 // # of bad super blocks encountered 155 malloc_errors uint64 // # of internal kmalloc errors. These will likely cause an incomplete scrub 156 uncorrectable_errors uint64 // # of errors where either no intact copy was found or the writeback failed 157 corrected_errors uint64 // # of errors corrected 158 // last physical address scrubbed. In case a scrub was aborted, this can be used to restart the scrub 159 last_physical uint64 160 // # of occurences where a read for a full (64k) bio failed, but the re- 161 // check succeeded for each 4k piece. Intermittent error. 162 unverified_errors uint64 163 } 164 165 type btrfs_ioctl_scrub_args struct { 166 devid uint64 // in 167 start uint64 // in 168 end uint64 // in 169 flags uint64 // in 170 progress btrfs_scrub_progress // out 171 // pad to 1k 172 _ [1024 - 4*8 - unsafe.Sizeof(btrfs_scrub_progress{})]byte 173 } 174 175 type contReadingFromSrcdevMode uint64 176 177 const ( 178 _BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_ALWAYS contReadingFromSrcdevMode = 0 179 _BTRFS_IOCTL_DEV_REPLACE_CONT_READING_FROM_SRCDEV_MODE_AVOID contReadingFromSrcdevMode = 1 180 ) 181 182 type btrfs_ioctl_dev_replace_start_params struct { 183 srcdevid uint64 // in, if 0, use srcdev_name instead 184 cont_reading_from_srcdev_mode contReadingFromSrcdevMode // in 185 srcdev_name [devicePathNameMax + 1]byte // in 186 tgtdev_name [devicePathNameMax + 1]byte // in 187 } 188 189 type devReplaceState uint64 190 191 const ( 192 _BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED devReplaceState = 0 193 _BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED devReplaceState = 1 194 _BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED devReplaceState = 2 195 _BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED devReplaceState = 3 196 _BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED devReplaceState = 4 197 ) 198 199 type btrfs_ioctl_dev_replace_status_params struct { 200 replace_state devReplaceState // out 201 progress_1000 uint64 // out, 0 <= x <= 1000 202 time_started uint64 // out, seconds since 1-Jan-1970 203 time_stopped uint64 // out, seconds since 1-Jan-1970 204 num_write_errors uint64 // out 205 num_uncorrectable_read_errors uint64 // out 206 } 207 208 type btrfs_ioctl_dev_replace_args_u1 struct { 209 cmd uint64 // in 210 result uint64 // out 211 start btrfs_ioctl_dev_replace_start_params // in 212 spare [64]uint64 213 } 214 215 type btrfs_ioctl_dev_replace_args_u2 struct { 216 cmd uint64 // in 217 result uint64 // out 218 status btrfs_ioctl_dev_replace_status_params // out 219 _ [unsafe.Sizeof(btrfs_ioctl_dev_replace_start_params{}) - unsafe.Sizeof(btrfs_ioctl_dev_replace_status_params{})]byte 220 spare [64]uint64 221 } 222 223 type btrfs_ioctl_dev_info_args struct { 224 devid uint64 // in/out 225 uuid UUID // in/out 226 bytes_used uint64 // out 227 total_bytes uint64 // out 228 _ [379]uint64 // pad to 4k 229 path [devicePathNameMax]byte // out 230 } 231 232 type btrfs_ioctl_fs_info_args struct { 233 max_id uint64 // out 234 num_devices uint64 // out 235 fsid FSID // out 236 nodesize uint32 // out 237 sectorsize uint32 // out 238 clone_alignment uint32 // out 239 _ [122*8 + 4]byte // pad to 1k 240 } 241 242 type btrfs_ioctl_feature_flags struct { 243 compat_flags FeatureFlags 244 compat_ro_flags FeatureFlags 245 incompat_flags IncompatFeatures 246 } 247 248 type argRange [8]byte 249 250 func (u argRange) asN() uint64 { 251 return order.Uint64(u[:]) 252 } 253 func (u argRange) asMinMax() (min, max uint32) { 254 return order.Uint32(u[:4]), order.Uint32(u[4:]) 255 } 256 257 // balance control ioctl modes 258 //#define BTRFS_BALANCE_CTL_PAUSE 1 259 //#define BTRFS_BALANCE_CTL_CANCEL 2 260 //#define BTRFS_BALANCE_CTL_RESUME 3 261 262 // this is packed, because it should be exactly the same as its disk 263 // byte order counterpart (struct btrfs_disk_balance_args) 264 type btrfs_balance_args struct { 265 profiles uint64 266 // usage filter 267 // BTRFS_BALANCE_ARGS_USAGE with a single value means '0..N' 268 // BTRFS_BALANCE_ARGS_USAGE_RANGE - range syntax, min..max 269 usage argRange 270 devid uint64 271 pstart uint64 272 pend uint64 273 vstart uint64 274 vend uint64 275 target uint64 276 flags uint64 277 // BTRFS_BALANCE_ARGS_LIMIT with value 'limit' (limit number of processed chunks) 278 // BTRFS_BALANCE_ARGS_LIMIT_RANGE - the extend version can use minimum and maximum 279 limit argRange 280 stripes_min uint32 281 stripes_max uint32 282 _ [48]byte 283 } 284 285 // Report balance progress to userspace. 286 // 287 // btrfs_balance_progress 288 type BalanceProgress struct { 289 Expected uint64 // estimated # of chunks that will be relocated to fulfill the request 290 Considered uint64 // # of chunks we have considered so far 291 Completed uint64 // # of chunks relocated so far 292 } 293 294 type BalanceState uint64 295 296 const ( 297 BalanceStateRunning BalanceState = (1 << 0) 298 BalanceStatePauseReq BalanceState = (1 << 1) 299 BalanceStateCancelReq BalanceState = (1 << 2) 300 ) 301 302 type btrfs_ioctl_balance_args struct { 303 flags BalanceFlags // in/out 304 state BalanceState // out 305 data btrfs_balance_args // in/out 306 meta btrfs_balance_args // in/out 307 sys btrfs_balance_args // in/out 308 stat BalanceProgress // out 309 _ [72 * 8]byte // pad to 1k 310 } 311 312 const _BTRFS_INO_LOOKUP_PATH_MAX = 4080 313 314 type btrfs_ioctl_ino_lookup_args struct { 315 treeid objectID 316 objectid objectID 317 name [_BTRFS_INO_LOOKUP_PATH_MAX]byte 318 } 319 320 func (arg *btrfs_ioctl_ino_lookup_args) Name() string { 321 n := 0 322 for i, b := range arg.name { 323 if b == '\x00' { 324 n = i 325 break 326 } 327 } 328 return string(arg.name[:n]) 329 } 330 331 type btrfs_ioctl_search_key struct { 332 tree_id objectID // which root are we searching. 0 is the tree of tree roots 333 // keys returned will be >= min and <= max 334 min_objectid objectID 335 max_objectid objectID 336 // keys returned will be >= min and <= max 337 min_offset uint64 338 max_offset uint64 339 // max and min transids to search for 340 min_transid uint64 341 max_transid uint64 342 // keys returned will be >= min and <= max 343 min_type treeKeyType 344 max_type treeKeyType 345 // how many items did userland ask for, and how many are we returning 346 nr_items uint32 347 _ [36]byte 348 } 349 350 type btrfs_ioctl_search_header struct { 351 transid uint64 352 objectid objectID 353 offset uint64 354 typ treeKeyType 355 len uint32 356 } 357 358 const _BTRFS_SEARCH_ARGS_BUFSIZE = (4096 - unsafe.Sizeof(btrfs_ioctl_search_key{})) 359 360 // the buf is an array of search headers where 361 // each header is followed by the actual item 362 // the type field is expanded to 32 bits for alignment 363 type btrfs_ioctl_search_args struct { 364 key btrfs_ioctl_search_key 365 buf [_BTRFS_SEARCH_ARGS_BUFSIZE]byte 366 } 367 368 // Extended version of TREE_SEARCH ioctl that can return more than 4k of bytes. 369 // The allocated size of the buffer is set in buf_size. 370 type btrfs_ioctl_search_args_v2 struct { 371 key btrfs_ioctl_search_key // in/out - search parameters 372 buf_size uint64 // in - size of buffer; out - on EOVERFLOW: needed size to store item 373 //buf [0]uint64 // out - found items 374 } 375 376 // With a @src_length of zero, the range from @src_offset->EOF is cloned! 377 type btrfs_ioctl_clone_range_args struct { 378 src_fd int64 379 src_offset uint64 380 src_length uint64 381 dest_offset uint64 382 } 383 384 // flags for the defrag range ioctl 385 type defragRange uint64 386 387 const ( 388 _BTRFS_DEFRAG_RANGE_COMPRESS defragRange = 1 389 _BTRFS_DEFRAG_RANGE_START_IO defragRange = 2 390 ) 391 392 const _BTRFS_SAME_DATA_DIFFERS = 1 393 394 // For extent-same ioctl 395 type btrfs_ioctl_same_extent_info struct { 396 fd int64 // in - destination file 397 logical_offset uint64 // in - start of extent in destination 398 bytes_deduped uint64 // out - total # of bytes we were able to dedupe from this file 399 // out; status of this dedupe operation: 400 // 0 if dedup succeeds 401 // < 0 for error 402 // == BTRFS_SAME_DATA_DIFFERS if data differs 403 status int32 404 reserved uint32 405 } 406 407 type btrfs_ioctl_same_args struct { 408 logical_offset uint64 // in - start of extent in source 409 length uint64 // in - length of extent 410 dest_count uint16 // in - total elements in info array 411 _ [6]byte 412 //info [0]btrfs_ioctl_same_extent_info 413 } 414 415 type btrfs_ioctl_defrag_range_args struct { 416 start uint64 // start of the defrag operation 417 len uint64 // number of bytes to defrag, use (u64)-1 to say all 418 // flags for the operation, which can include turning 419 // on compression for this one defrag 420 flags uint64 421 // any extent bigger than this will be considered 422 // already defragged. Use 0 to take the kernel default 423 // Use 1 to say every single extent must be rewritten 424 extent_thresh uint32 425 // which compression method to use if turning on compression 426 // for this defrag operation. If unspecified, zlib will be used 427 compress_type uint32 428 _ [16]byte // spare for later 429 } 430 431 type btrfs_ioctl_space_info struct { 432 flags uint64 433 total_bytes uint64 434 used_bytes uint64 435 } 436 437 type btrfs_ioctl_space_args struct { 438 space_slots uint64 439 total_spaces uint64 440 //spaces [0]btrfs_ioctl_space_info 441 } 442 443 type btrfs_data_container struct { 444 bytes_left uint32 // out -- bytes not needed to deliver output 445 bytes_missing uint32 // out -- additional bytes needed for result 446 elem_cnt uint32 // out 447 elem_missed uint32 // out 448 //val [0]uint64 449 } 450 451 type btrfs_ioctl_ino_path_args struct { 452 inum uint64 // in 453 size uint64 // in 454 _ [32]byte 455 // struct btrfs_data_container *fspath; out 456 fspath uint64 // out 457 } 458 459 type btrfs_ioctl_logical_ino_args struct { 460 logical uint64 // in 461 size uint64 // in 462 _ [32]byte 463 // struct btrfs_data_container *inodes; out 464 inodes uint64 465 } 466 467 // disk I/O failure stats 468 const ( 469 _BTRFS_DEV_STAT_WRITE_ERRS = iota // EIO or EREMOTEIO from lower layers 470 _BTRFS_DEV_STAT_READ_ERRS // EIO or EREMOTEIO from lower layers 471 _BTRFS_DEV_STAT_FLUSH_ERRS // EIO or EREMOTEIO from lower layers 472 473 // stats for indirect indications for I/O failures 474 475 // checksum error, bytenr error or contents is illegal: this is an 476 // indication that the block was damaged during read or write, or written to 477 // wrong location or read from wrong location 478 _BTRFS_DEV_STAT_CORRUPTION_ERRS 479 _BTRFS_DEV_STAT_GENERATION_ERRS // an indication that blocks have not been written 480 481 _BTRFS_DEV_STAT_VALUES_MAX 482 ) 483 484 // Reset statistics after reading; needs SYS_ADMIN capability 485 const _BTRFS_DEV_STATS_RESET = (1 << 0) 486 487 type btrfs_ioctl_get_dev_stats struct { 488 devid uint64 // in 489 nr_items uint64 // in/out 490 flags uint64 // in/out 491 values [_BTRFS_DEV_STAT_VALUES_MAX]uint64 // out values 492 _ [128 - 2 - _BTRFS_DEV_STAT_VALUES_MAX]uint64 // pad to 1k 493 } 494 495 const ( 496 _BTRFS_QUOTA_CTL_ENABLE = 1 497 _BTRFS_QUOTA_CTL_DISABLE = 2 498 // 3 has formerly been reserved for BTRFS_QUOTA_CTL_RESCAN 499 ) 500 501 type btrfs_ioctl_quota_ctl_args struct { 502 cmd uint64 503 status uint64 504 } 505 506 type btrfs_ioctl_quota_rescan_args struct { 507 flags uint64 508 progress uint64 509 _ [6]uint64 510 } 511 512 type btrfs_ioctl_qgroup_assign_args struct { 513 assign uint64 514 src uint64 515 dst uint64 516 } 517 518 type btrfs_ioctl_qgroup_create_args struct { 519 create uint64 520 qgroupid uint64 521 } 522 523 type btrfs_ioctl_timespec struct { 524 sec uint64 525 nsec uint32 526 } 527 528 type btrfs_ioctl_received_subvol_args struct { 529 uuid UUID // in 530 stransid uint64 // in 531 rtransid uint64 // out 532 stime btrfs_ioctl_timespec // in 533 rtime btrfs_ioctl_timespec // out 534 flags uint64 // in 535 _ [16]uint64 // in 536 } 537 538 const ( 539 // Caller doesn't want file data in the send stream, even if the 540 // search of clone sources doesn't find an extent. UPDATE_EXTENT 541 // commands will be sent instead of WRITE commands. 542 _BTRFS_SEND_FLAG_NO_FILE_DATA = 0x1 543 // Do not add the leading stream header. Used when multiple snapshots 544 // are sent back to back. 545 _BTRFS_SEND_FLAG_OMIT_STREAM_HEADER = 0x2 546 // Omit the command at the end of the stream that indicated the end 547 // of the stream. This option is used when multiple snapshots are 548 // sent back to back. 549 _BTRFS_SEND_FLAG_OMIT_END_CMD = 0x4 550 551 _BTRFS_SEND_FLAG_MASK = _BTRFS_SEND_FLAG_NO_FILE_DATA | 552 _BTRFS_SEND_FLAG_OMIT_STREAM_HEADER | 553 _BTRFS_SEND_FLAG_OMIT_END_CMD 554 ) 555 556 type btrfs_ioctl_send_args struct { 557 send_fd int64 // in 558 clone_sources_count uint64 // in 559 clone_sources *objectID // in 560 parent_root objectID // in 561 flags uint64 // in 562 _ [4]uint64 // in 563 } 564 565 var ( 566 _BTRFS_IOC_SNAP_CREATE = ioctl.IOW(ioctlMagic, 1, unsafe.Sizeof(btrfs_ioctl_vol_args{})) 567 _BTRFS_IOC_DEFRAG = ioctl.IOW(ioctlMagic, 2, unsafe.Sizeof(btrfs_ioctl_vol_args{})) 568 _BTRFS_IOC_RESIZE = ioctl.IOW(ioctlMagic, 3, unsafe.Sizeof(btrfs_ioctl_vol_args{})) 569 _BTRFS_IOC_SCAN_DEV = ioctl.IOW(ioctlMagic, 4, unsafe.Sizeof(btrfs_ioctl_vol_args{})) 570 _BTRFS_IOC_TRANS_START = ioctl.IO(ioctlMagic, 6) 571 _BTRFS_IOC_TRANS_END = ioctl.IO(ioctlMagic, 7) 572 _BTRFS_IOC_SYNC = ioctl.IO(ioctlMagic, 8) 573 _BTRFS_IOC_CLONE = ioctl.IOW(ioctlMagic, 9, 4) // int32 574 _BTRFS_IOC_ADD_DEV = ioctl.IOW(ioctlMagic, 10, unsafe.Sizeof(btrfs_ioctl_vol_args{})) 575 _BTRFS_IOC_RM_DEV = ioctl.IOW(ioctlMagic, 11, unsafe.Sizeof(btrfs_ioctl_vol_args{})) 576 _BTRFS_IOC_BALANCE = ioctl.IOW(ioctlMagic, 12, unsafe.Sizeof(btrfs_ioctl_vol_args{})) 577 _BTRFS_IOC_CLONE_RANGE = ioctl.IOW(ioctlMagic, 13, unsafe.Sizeof(btrfs_ioctl_clone_range_args{})) 578 _BTRFS_IOC_SUBVOL_CREATE = ioctl.IOW(ioctlMagic, 14, unsafe.Sizeof(btrfs_ioctl_vol_args{})) 579 _BTRFS_IOC_SNAP_DESTROY = ioctl.IOW(ioctlMagic, 15, unsafe.Sizeof(btrfs_ioctl_vol_args{})) 580 _BTRFS_IOC_DEFRAG_RANGE = ioctl.IOW(ioctlMagic, 16, unsafe.Sizeof(btrfs_ioctl_defrag_range_args{})) 581 _BTRFS_IOC_TREE_SEARCH = ioctl.IOWR(ioctlMagic, 17, unsafe.Sizeof(btrfs_ioctl_search_args{})) 582 _BTRFS_IOC_INO_LOOKUP = ioctl.IOWR(ioctlMagic, 18, unsafe.Sizeof(btrfs_ioctl_ino_lookup_args{})) 583 _BTRFS_IOC_DEFAULT_SUBVOL = ioctl.IOW(ioctlMagic, 19, 8) // uint64 584 _BTRFS_IOC_SPACE_INFO = ioctl.IOWR(ioctlMagic, 20, unsafe.Sizeof(btrfs_ioctl_space_args{})) 585 _BTRFS_IOC_START_SYNC = ioctl.IOR(ioctlMagic, 24, 8) // uint64 586 _BTRFS_IOC_WAIT_SYNC = ioctl.IOW(ioctlMagic, 22, 8) // uint64 587 _BTRFS_IOC_SNAP_CREATE_V2 = ioctl.IOW(ioctlMagic, 23, unsafe.Sizeof(btrfs_ioctl_vol_args_v2{})) 588 _BTRFS_IOC_SUBVOL_CREATE_V2 = ioctl.IOW(ioctlMagic, 24, unsafe.Sizeof(btrfs_ioctl_vol_args_v2{})) 589 _BTRFS_IOC_SUBVOL_GETFLAGS = ioctl.IOR(ioctlMagic, 25, 8) // uint64 590 _BTRFS_IOC_SUBVOL_SETFLAGS = ioctl.IOW(ioctlMagic, 26, 8) // uint64 591 _BTRFS_IOC_SCRUB = ioctl.IOWR(ioctlMagic, 27, unsafe.Sizeof(btrfs_ioctl_scrub_args{})) 592 _BTRFS_IOC_SCRUB_CANCEL = ioctl.IO(ioctlMagic, 28) 593 _BTRFS_IOC_SCRUB_PROGRESS = ioctl.IOWR(ioctlMagic, 29, unsafe.Sizeof(btrfs_ioctl_scrub_args{})) 594 _BTRFS_IOC_DEV_INFO = ioctl.IOWR(ioctlMagic, 30, unsafe.Sizeof(btrfs_ioctl_dev_info_args{})) 595 _BTRFS_IOC_FS_INFO = ioctl.IOR(ioctlMagic, 31, unsafe.Sizeof(btrfs_ioctl_fs_info_args{})) 596 _BTRFS_IOC_BALANCE_V2 = ioctl.IOWR(ioctlMagic, 32, unsafe.Sizeof(btrfs_ioctl_balance_args{})) 597 _BTRFS_IOC_BALANCE_CTL = ioctl.IOW(ioctlMagic, 33, 4) // int32 598 _BTRFS_IOC_BALANCE_PROGRESS = ioctl.IOR(ioctlMagic, 34, unsafe.Sizeof(btrfs_ioctl_balance_args{})) 599 _BTRFS_IOC_INO_PATHS = ioctl.IOWR(ioctlMagic, 35, unsafe.Sizeof(btrfs_ioctl_ino_path_args{})) 600 _BTRFS_IOC_LOGICAL_INO = ioctl.IOWR(ioctlMagic, 36, unsafe.Sizeof(btrfs_ioctl_ino_path_args{})) 601 _BTRFS_IOC_SET_RECEIVED_SUBVOL = ioctl.IOWR(ioctlMagic, 37, unsafe.Sizeof(btrfs_ioctl_received_subvol_args{})) 602 _BTRFS_IOC_SEND = ioctl.IOW(ioctlMagic, 38, unsafe.Sizeof(btrfs_ioctl_send_args{})) 603 _BTRFS_IOC_DEVICES_READY = ioctl.IOR(ioctlMagic, 39, unsafe.Sizeof(btrfs_ioctl_vol_args{})) 604 _BTRFS_IOC_QUOTA_CTL = ioctl.IOWR(ioctlMagic, 40, unsafe.Sizeof(btrfs_ioctl_quota_ctl_args{})) 605 _BTRFS_IOC_QGROUP_ASSIGN = ioctl.IOW(ioctlMagic, 41, unsafe.Sizeof(btrfs_ioctl_qgroup_assign_args{})) 606 _BTRFS_IOC_QGROUP_CREATE = ioctl.IOW(ioctlMagic, 42, unsafe.Sizeof(btrfs_ioctl_qgroup_create_args{})) 607 _BTRFS_IOC_QGROUP_LIMIT = ioctl.IOR(ioctlMagic, 43, unsafe.Sizeof(btrfs_ioctl_qgroup_limit_args{})) 608 _BTRFS_IOC_QUOTA_RESCAN = ioctl.IOW(ioctlMagic, 44, unsafe.Sizeof(btrfs_ioctl_quota_rescan_args{})) 609 _BTRFS_IOC_QUOTA_RESCAN_STATUS = ioctl.IOR(ioctlMagic, 45, unsafe.Sizeof(btrfs_ioctl_quota_rescan_args{})) 610 _BTRFS_IOC_QUOTA_RESCAN_WAIT = ioctl.IO(ioctlMagic, 46) 611 _BTRFS_IOC_GET_FSLABEL = ioctl.IOR(ioctlMagic, 49, labelSize) 612 _BTRFS_IOC_SET_FSLABEL = ioctl.IOW(ioctlMagic, 50, labelSize) 613 _BTRFS_IOC_GET_DEV_STATS = ioctl.IOWR(ioctlMagic, 52, unsafe.Sizeof(btrfs_ioctl_get_dev_stats{})) 614 _BTRFS_IOC_DEV_REPLACE = ioctl.IOWR(ioctlMagic, 53, unsafe.Sizeof(btrfs_ioctl_dev_replace_args_u1{})) 615 _BTRFS_IOC_FILE_EXTENT_SAME = ioctl.IOWR(ioctlMagic, 54, unsafe.Sizeof(btrfs_ioctl_same_args{})) 616 _BTRFS_IOC_GET_FEATURES = ioctl.IOR(ioctlMagic, 57, unsafe.Sizeof(btrfs_ioctl_feature_flags{})) 617 _BTRFS_IOC_SET_FEATURES = ioctl.IOW(ioctlMagic, 57, unsafe.Sizeof([2]btrfs_ioctl_feature_flags{})) 618 _BTRFS_IOC_GET_SUPPORTED_FEATURES = ioctl.IOR(ioctlMagic, 57, unsafe.Sizeof([3]btrfs_ioctl_feature_flags{})) 619 ) 620 621 func iocSnapCreate(f *os.File, in *btrfs_ioctl_vol_args) error { 622 return ioctl.Do(f, _BTRFS_IOC_SNAP_CREATE, in) 623 } 624 625 func iocSnapCreateV2(f *os.File, in *btrfs_ioctl_vol_args_v2) error { 626 return ioctl.Do(f, _BTRFS_IOC_SNAP_CREATE_V2, in) 627 } 628 629 func iocDefrag(f *os.File, out *btrfs_ioctl_vol_args) error { 630 return ioctl.Do(f, _BTRFS_IOC_DEFRAG, out) 631 } 632 633 func iocResize(f *os.File, in *btrfs_ioctl_vol_args) error { 634 return ioctl.Do(f, _BTRFS_IOC_RESIZE, in) 635 } 636 637 func iocScanDev(f *os.File, out *btrfs_ioctl_vol_args) error { 638 return ioctl.Do(f, _BTRFS_IOC_SCAN_DEV, out) 639 } 640 641 func iocTransStart(f *os.File) error { 642 return ioctl.Do(f, _BTRFS_IOC_TRANS_START, nil) 643 } 644 645 func iocTransEnd(f *os.File) error { 646 return ioctl.Do(f, _BTRFS_IOC_TRANS_END, nil) 647 } 648 649 func iocSync(f *os.File) error { 650 return ioctl.Do(f, _BTRFS_IOC_SYNC, nil) 651 } 652 653 func iocClone(dst, src *os.File) error { 654 return ioctl.Ioctl(dst, _BTRFS_IOC_CLONE, src.Fd()) 655 } 656 657 func iocAddDev(f *os.File, out *btrfs_ioctl_vol_args) error { 658 return ioctl.Do(f, _BTRFS_IOC_ADD_DEV, out) 659 } 660 661 func iocRmDev(f *os.File, out *btrfs_ioctl_vol_args) error { 662 return ioctl.Do(f, _BTRFS_IOC_RM_DEV, out) 663 } 664 665 func iocBalance(f *os.File, out *btrfs_ioctl_vol_args) error { 666 return ioctl.Do(f, _BTRFS_IOC_BALANCE, out) 667 } 668 669 func iocCloneRange(f *os.File, out *btrfs_ioctl_clone_range_args) error { 670 return ioctl.Do(f, _BTRFS_IOC_CLONE_RANGE, out) 671 } 672 673 func iocSubvolCreate(f *os.File, in *btrfs_ioctl_vol_args) error { 674 return ioctl.Do(f, _BTRFS_IOC_SUBVOL_CREATE, in) 675 } 676 677 func iocSubvolCreateV2(f *os.File, in *btrfs_ioctl_vol_args_v2) error { 678 return ioctl.Do(f, _BTRFS_IOC_SUBVOL_CREATE, in) 679 } 680 681 func iocSnapDestroy(f *os.File, in *btrfs_ioctl_vol_args) error { 682 return ioctl.Do(f, _BTRFS_IOC_SNAP_DESTROY, in) 683 } 684 685 func iocDefragRange(f *os.File, out *btrfs_ioctl_defrag_range_args) error { 686 return ioctl.Do(f, _BTRFS_IOC_DEFRAG_RANGE, out) 687 } 688 689 func iocTreeSearch(f *os.File, out *btrfs_ioctl_search_args) error { 690 return ioctl.Do(f, _BTRFS_IOC_TREE_SEARCH, out) 691 } 692 693 func iocInoLookup(f *os.File, out *btrfs_ioctl_ino_lookup_args) error { 694 return ioctl.Do(f, _BTRFS_IOC_INO_LOOKUP, out) 695 } 696 697 func iocDefaultSubvol(f *os.File, out *uint64) error { 698 return ioctl.Do(f, _BTRFS_IOC_DEFAULT_SUBVOL, out) 699 } 700 701 type spaceFlags uint64 702 703 func (f spaceFlags) BlockGroup() blockGroup { 704 return blockGroup(f) & _BTRFS_BLOCK_GROUP_MASK 705 } 706 707 type spaceInfo struct { 708 Flags spaceFlags 709 TotalBytes uint64 710 UsedBytes uint64 711 } 712 713 func iocSpaceInfo(f *os.File) ([]spaceInfo, error) { 714 arg := &btrfs_ioctl_space_args{} 715 if err := ioctl.Do(f, _BTRFS_IOC_SPACE_INFO, arg); err != nil { 716 return nil, err 717 } 718 n := arg.total_spaces 719 if n == 0 { 720 return nil, nil 721 } 722 const ( 723 argSize = unsafe.Sizeof(btrfs_ioctl_space_args{}) 724 infoSize = unsafe.Sizeof(btrfs_ioctl_space_info{}) 725 ) 726 buf := make([]byte, argSize+uintptr(n)*infoSize) 727 basePtr := unsafe.Pointer(&buf[0]) 728 arg = (*btrfs_ioctl_space_args)(basePtr) 729 arg.space_slots = n 730 if err := ioctl.Do(f, _BTRFS_IOC_SPACE_INFO, arg); err != nil { 731 return nil, err 732 } else if arg.total_spaces == 0 { 733 return nil, nil 734 } 735 if n > arg.total_spaces { 736 n = arg.total_spaces 737 } 738 out := make([]spaceInfo, n) 739 ptr := uintptr(basePtr) + argSize 740 for i := 0; i < int(n); i++ { 741 info := (*btrfs_ioctl_space_info)(unsafe.Pointer(ptr)) 742 out[i] = spaceInfo{ 743 Flags: spaceFlags(info.flags), 744 TotalBytes: info.total_bytes, 745 UsedBytes: info.used_bytes, 746 } 747 ptr += infoSize 748 } 749 return out, nil 750 } 751 752 func iocStartSync(f *os.File, out *uint64) error { 753 return ioctl.Do(f, _BTRFS_IOC_START_SYNC, out) 754 } 755 756 func iocWaitSync(f *os.File, out *uint64) error { 757 return ioctl.Do(f, _BTRFS_IOC_WAIT_SYNC, out) 758 } 759 760 func iocSubvolGetflags(f *os.File) (out SubvolFlags, err error) { 761 err = ioctl.Do(f, _BTRFS_IOC_SUBVOL_GETFLAGS, &out) 762 return 763 } 764 765 func iocSubvolSetflags(f *os.File, flags SubvolFlags) error { 766 v := uint64(flags) 767 return ioctl.Do(f, _BTRFS_IOC_SUBVOL_SETFLAGS, &v) 768 } 769 770 func iocScrub(f *os.File, out *btrfs_ioctl_scrub_args) error { 771 return ioctl.Do(f, _BTRFS_IOC_SCRUB, out) 772 } 773 774 func iocScrubCancel(f *os.File) error { 775 return ioctl.Do(f, _BTRFS_IOC_SCRUB_CANCEL, nil) 776 } 777 778 func iocScrubProgress(f *os.File, out *btrfs_ioctl_scrub_args) error { 779 return ioctl.Do(f, _BTRFS_IOC_SCRUB_PROGRESS, out) 780 } 781 782 func iocFsInfo(f *os.File) (out btrfs_ioctl_fs_info_args, err error) { 783 err = ioctl.Do(f, _BTRFS_IOC_FS_INFO, &out) 784 return 785 } 786 787 func iocDevInfo(f *os.File, devid uint64, uuid UUID) (out btrfs_ioctl_dev_info_args, err error) { 788 out.devid = devid 789 out.uuid = uuid 790 err = ioctl.Do(f, _BTRFS_IOC_DEV_INFO, &out) 791 return 792 } 793 794 func iocBalanceV2(f *os.File, out *btrfs_ioctl_balance_args) error { 795 return ioctl.Do(f, _BTRFS_IOC_BALANCE_V2, out) 796 } 797 798 func iocBalanceCtl(f *os.File, out *int32) error { 799 return ioctl.Do(f, _BTRFS_IOC_BALANCE_CTL, out) 800 } 801 802 func iocBalanceProgress(f *os.File, out *btrfs_ioctl_balance_args) error { 803 return ioctl.Do(f, _BTRFS_IOC_BALANCE_PROGRESS, out) 804 } 805 806 func iocInoPaths(f *os.File, out *btrfs_ioctl_ino_path_args) error { 807 return ioctl.Do(f, _BTRFS_IOC_INO_PATHS, out) 808 } 809 810 func iocLogicalIno(f *os.File, out *btrfs_ioctl_ino_path_args) error { 811 return ioctl.Do(f, _BTRFS_IOC_LOGICAL_INO, out) 812 } 813 814 func iocSetReceivedSubvol(f *os.File, out *btrfs_ioctl_received_subvol_args) error { 815 return ioctl.Do(f, _BTRFS_IOC_SET_RECEIVED_SUBVOL, out) 816 } 817 818 func iocSend(f *os.File, in *btrfs_ioctl_send_args) error { 819 return ioctl.Do(f, _BTRFS_IOC_SEND, in) 820 } 821 822 func iocDevicesReady(f *os.File, out *btrfs_ioctl_vol_args) error { 823 return ioctl.Do(f, _BTRFS_IOC_DEVICES_READY, out) 824 } 825 826 func iocQuotaCtl(f *os.File, out *btrfs_ioctl_quota_ctl_args) error { 827 return ioctl.Do(f, _BTRFS_IOC_QUOTA_CTL, out) 828 } 829 830 func iocQgroupAssign(f *os.File, out *btrfs_ioctl_qgroup_assign_args) error { 831 return ioctl.Do(f, _BTRFS_IOC_QGROUP_ASSIGN, out) 832 } 833 834 func iocQgroupCreate(f *os.File, out *btrfs_ioctl_qgroup_create_args) error { 835 return ioctl.Do(f, _BTRFS_IOC_QGROUP_CREATE, out) 836 } 837 838 func iocQgroupLimit(f *os.File, out *btrfs_ioctl_qgroup_limit_args) error { 839 return ioctl.Do(f, _BTRFS_IOC_QGROUP_LIMIT, out) 840 } 841 842 func iocQuotaRescan(f *os.File, out *btrfs_ioctl_quota_rescan_args) error { 843 return ioctl.Do(f, _BTRFS_IOC_QUOTA_RESCAN, out) 844 } 845 846 func iocQuotaRescanStatus(f *os.File, out *btrfs_ioctl_quota_rescan_args) error { 847 return ioctl.Do(f, _BTRFS_IOC_QUOTA_RESCAN_STATUS, out) 848 } 849 850 func iocQuotaRescanWait(f *os.File) error { 851 return ioctl.Do(f, _BTRFS_IOC_QUOTA_RESCAN_WAIT, nil) 852 } 853 854 func iocGetFslabel(f *os.File, out *[labelSize]byte) error { 855 return ioctl.Do(f, _BTRFS_IOC_GET_FSLABEL, out) 856 } 857 858 func iocSetFslabel(f *os.File, out *[labelSize]byte) error { 859 return ioctl.Do(f, _BTRFS_IOC_SET_FSLABEL, out) 860 } 861 862 func iocGetDevStats(f *os.File, out *btrfs_ioctl_get_dev_stats) error { 863 return ioctl.Do(f, _BTRFS_IOC_GET_DEV_STATS, out) 864 } 865 866 //func iocDevReplace(f *os.File, out *btrfs_ioctl_dev_replace_args) error { 867 // return ioctl.Do(f, _BTRFS_IOC_DEV_REPLACE, out) 868 //} 869 870 func iocFileExtentSame(f *os.File, out *btrfs_ioctl_same_args) error { 871 return ioctl.Do(f, _BTRFS_IOC_FILE_EXTENT_SAME, out) 872 } 873 874 func iocSetFeatures(f *os.File, out *[2]btrfs_ioctl_feature_flags) error { 875 return ioctl.Do(f, _BTRFS_IOC_SET_FEATURES, out) 876 }