1 /* 2 * Copyright (c) 2016 Jeff Mahoney <jeffm (at) suse.com> 3 * Copyright (c) 2016-2018 The strace developers. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "defs.h" 30 31 #ifdef HAVE_LINUX_BTRFS_H 32 33 #include DEF_MPERS_TYPE(struct_btrfs_ioctl_dev_replace_args) 34 #include DEF_MPERS_TYPE(struct_btrfs_ioctl_send_args) 35 #include DEF_MPERS_TYPE(struct_btrfs_ioctl_received_subvol_args) 36 #include DEF_MPERS_TYPE(struct_btrfs_ioctl_vol_args_v2) 37 38 # include <linux/btrfs.h> 39 40 typedef struct btrfs_ioctl_dev_replace_args 41 struct_btrfs_ioctl_dev_replace_args; 42 typedef struct btrfs_ioctl_send_args 43 struct_btrfs_ioctl_send_args; 44 typedef struct btrfs_ioctl_received_subvol_args 45 struct_btrfs_ioctl_received_subvol_args; 46 typedef struct btrfs_ioctl_vol_args_v2 47 struct_btrfs_ioctl_vol_args_v2; 48 49 #endif /* HAVE_LINUX_BTRFS_H */ 50 51 #include MPERS_DEFS 52 53 #ifdef HAVE_LINUX_BTRFS_H 54 55 #include "print_fields.h" 56 #include <linux/fs.h> 57 58 /* 59 * Prior to Linux 3.12, the BTRFS_IOC_DEFAULT_SUBVOL used u64 in 60 * its definition, which isn't exported by the kernel. 61 */ 62 typedef __u64 u64; 63 64 #ifndef HAVE_STRUCT_BTRFS_IOCTL_FEATURE_FLAGS_COMPAT_FLAGS 65 struct btrfs_ioctl_feature_flags { 66 uint64_t compat_flags; 67 uint64_t compat_ro_flags; 68 uint64_t incompat_flags; 69 }; 70 #endif 71 72 #ifndef HAVE_STRUCT_BTRFS_IOCTL_DEFRAG_RANGE_ARGS_START 73 struct btrfs_ioctl_defrag_range_args { 74 uint64_t start; 75 uint64_t len; 76 uint64_t flags; 77 uint32_t extent_thresh; 78 uint32_t compress_type; 79 uint32_t unused[4]; 80 }; 81 #endif 82 83 #ifndef BTRFS_LABEL_SIZE 84 # define BTRFS_LABEL_SIZE 256 85 #endif 86 87 #ifndef BTRFS_FIRST_FREE_OBJECTID 88 # define BTRFS_FIRST_FREE_OBJECTID 256ULL 89 #endif 90 91 #ifndef BTRFS_IOC_QUOTA_RESCAN 92 struct btrfs_ioctl_quota_rescan_args { 93 uint64_t flags, progress, reserved[6]; 94 }; 95 # define BTRFS_IOC_QUOTA_RESCAN _IOW(BTRFS_IOCTL_MAGIC, 44, \ 96 struct btrfs_ioctl_quota_rescan_args) 97 # define BTRFS_IOC_QUOTA_RESCAN_STATUS _IOR(BTRFS_IOCTL_MAGIC, 45, \ 98 struct btrfs_ioctl_quota_rescan_args) 99 #endif 100 101 #ifndef BTRFS_IOC_QUOTA_RESCAN_WAIT 102 # define BTRFS_IOC_QUOTA_RESCAN_WAIT _IO(BTRFS_IOCTL_MAGIC, 46) 103 #endif 104 105 #ifndef BTRFS_IOC_GET_FEATURES 106 # define BTRFS_IOC_GET_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ 107 struct btrfs_ioctl_feature_flags) 108 # define BTRFS_IOC_SET_FEATURES _IOW(BTRFS_IOCTL_MAGIC, 57, \ 109 struct btrfs_ioctl_feature_flags[2]) 110 # define BTRFS_IOC_GET_SUPPORTED_FEATURES _IOR(BTRFS_IOCTL_MAGIC, 57, \ 111 struct btrfs_ioctl_feature_flags[3]) 112 #endif 113 114 #ifndef BTRFS_IOC_TREE_SEARCH_V2 115 # define BTRFS_IOC_TREE_SEARCH_V2 _IOWR(BTRFS_IOCTL_MAGIC, 17, \ 116 struct btrfs_ioctl_search_args_v2) 117 struct btrfs_ioctl_search_args_v2 { 118 struct btrfs_ioctl_search_key key; /* in/out - search parameters */ 119 uint64_t buf_size; /* in - size of buffer 120 * out - on EOVERFLOW: needed size 121 * to store item */ 122 uint64_t buf[0]; /* out - found items */ 123 }; 124 #endif 125 126 #include "xlat/btrfs_balance_args.h" 127 #include "xlat/btrfs_balance_ctl_cmds.h" 128 #include "xlat/btrfs_balance_flags.h" 129 #include "xlat/btrfs_balance_state.h" 130 #include "xlat/btrfs_compress_types.h" 131 #include "xlat/btrfs_defrag_flags.h" 132 #include "xlat/btrfs_dev_replace_cmds.h" 133 #include "xlat/btrfs_dev_replace_results.h" 134 #include "xlat/btrfs_dev_replace_state.h" 135 #include "xlat/btrfs_dev_stats_flags.h" 136 #include "xlat/btrfs_dev_stats_values.h" 137 #include "xlat/btrfs_features_compat.h" 138 #include "xlat/btrfs_features_compat_ro.h" 139 #include "xlat/btrfs_features_incompat.h" 140 #include "xlat/btrfs_key_types.h" 141 #include "xlat/btrfs_qgroup_ctl_cmds.h" 142 #include "xlat/btrfs_qgroup_inherit_flags.h" 143 #include "xlat/btrfs_qgroup_limit_flags.h" 144 #include "xlat/btrfs_qgroup_status_flags.h" 145 #include "xlat/btrfs_scrub_flags.h" 146 #include "xlat/btrfs_send_flags.h" 147 #include "xlat/btrfs_snap_flags_v2.h" 148 #include "xlat/btrfs_space_info_flags.h" 149 #include "xlat/btrfs_tree_objectids.h" 150 151 static inline char 152 prnibble(char v) 153 { 154 if (v >= 10) 155 return 'a' + (v - 10); 156 return '0' + v; 157 } 158 159 /* 8-4-4-4-12 = 36 characters */ 160 #define UUID_STRING_SIZE 36 161 162 /* Formats uuid, returns 0 if it's all zeroes */ 163 static int 164 btrfs_unparse_uuid(unsigned char *uuid, char *out) 165 { 166 int i; 167 int ret = 0; 168 for (i = 0; i < BTRFS_UUID_SIZE; i++) { 169 if (i == 4 || i == 6 || i == 8 || i == 10) 170 *out++ = '-'; 171 *out++ = prnibble(uuid[i] >> 4); 172 *out++ = prnibble(uuid[i] & 0xf); 173 if (uuid[i]) 174 ret = 1; 175 } 176 *out = '\0'; 177 return ret; 178 } 179 180 static void 181 print_u64(const char *name, uint64_t value) 182 { 183 tprintf(", %s=%" PRIu64, name, value); 184 if (value == UINT64_MAX) 185 tprints_comment("UINT64_MAX"); 186 } 187 188 #define print_member_u64(obj, name) print_u64(#name, obj->name) 189 190 static void 191 btrfs_print_balance_args(const char *name, const struct btrfs_balance_args *bba) 192 { 193 tprintf(", %s={profiles=", name); 194 printflags64(btrfs_space_info_flags, bba->profiles, 195 "BTRFS_BLOCK_GROUP_???"); 196 print_member_u64(bba, usage); 197 print_member_u64(bba, devid); 198 print_member_u64(bba, pstart); 199 print_member_u64(bba, pend); 200 print_member_u64(bba, vstart); 201 print_member_u64(bba, vend); 202 print_member_u64(bba, target); 203 tprints(", flags="); 204 printflags64(btrfs_balance_args, bba->flags, "BTRFS_BALANCE_ARGS_???"); 205 tprints("}"); 206 } 207 208 static void 209 btrfs_print_balance(struct tcb *const tcp, const kernel_ulong_t arg, bool out) 210 { 211 struct btrfs_ioctl_balance_args balance_args; 212 213 if (umove_or_printaddr(tcp, arg, &balance_args)) 214 return; 215 216 tprints("{flags="); 217 printflags64(btrfs_balance_flags, balance_args.flags, 218 "BTRFS_BALANCE_???"); 219 if (out) { 220 tprints(", state="); 221 printflags64(btrfs_balance_state, balance_args.state, 222 "BTRFS_BALANCE_STATE_???"); 223 } 224 225 if (balance_args.flags & BTRFS_BALANCE_DATA) 226 btrfs_print_balance_args("data", &balance_args.data); 227 if (balance_args.flags & BTRFS_BALANCE_METADATA) 228 btrfs_print_balance_args("meta", &balance_args.meta); 229 if (balance_args.flags & BTRFS_BALANCE_SYSTEM) 230 btrfs_print_balance_args("sys", &balance_args.sys); 231 tprints("}"); 232 } 233 234 static void 235 btrfs_print_features(const struct btrfs_ioctl_feature_flags *flags) 236 { 237 tprints("{compat_flags="); 238 printflags64(btrfs_features_compat, flags->compat_flags, 239 "BTRFS_FEATURE_COMPAT_???"); 240 241 tprints(", compat_ro_flags="); 242 printflags64(btrfs_features_compat_ro, flags->compat_ro_flags, 243 "BTRFS_FEATURE_COMPAT_RO_???"); 244 245 tprints(", incompat_flags="); 246 printflags64(btrfs_features_incompat, flags->incompat_flags, 247 "BTRFS_FEATURE_INCOMPAT_???"); 248 tprints("}"); 249 } 250 251 static void 252 btrfs_print_qgroup_limit(const struct btrfs_qgroup_limit *lim) 253 { 254 tprints("{flags="); 255 printflags64(btrfs_qgroup_limit_flags, lim->flags, 256 "BTRFS_QGROUP_LIMIT_???"); 257 tprintf(", max_rfer=%" PRI__u64 ", max_excl=%" PRI__u64 258 ", rsv_rfer=%" PRI__u64 ", rsv_excl=%" PRI__u64 "}", 259 lim->max_rfer, lim->max_excl, 260 lim->rsv_rfer, lim->rsv_excl); 261 } 262 263 static void 264 btrfs_print_key_type(uint32_t type) 265 { 266 tprintf("%u", type); 267 tprints_comment(xlookup(btrfs_key_types, type)); 268 } 269 270 static void 271 btrfs_print_objectid(uint64_t objectid) 272 { 273 tprintf("%" PRIu64, objectid); 274 tprints_comment(xlookup(btrfs_tree_objectids, objectid)); 275 } 276 277 static void 278 btrfs_print_data_container_header(const struct btrfs_data_container *container) 279 { 280 tprintf("{bytes_left=%u, bytes_missing=%u" 281 ", elem_cnt=%u, elem_missed=%u, val=", 282 container->bytes_left, container->bytes_missing, 283 container->elem_cnt, container->elem_missed); 284 } 285 286 static void 287 btrfs_print_data_container_footer(void) 288 { 289 tprints("}"); 290 } 291 292 static bool 293 print_btrfs_data_container_logical_ino(struct tcb *tcp, void *elem_buf, 294 size_t elem_size, void *data) 295 { 296 const uint64_t *const record = elem_buf; 297 298 tprintf("{inum=%" PRIu64 ", offset=%" PRIu64 ", root=%" PRIu64 "}", 299 record[0], record[1], record[2]); 300 301 return true; 302 } 303 304 static void 305 btrfs_print_logical_ino_container(struct tcb *tcp, 306 const uint64_t inodes_addr) 307 { 308 struct btrfs_data_container container; 309 310 if (umove_or_printaddr(tcp, inodes_addr, &container)) 311 return; 312 313 btrfs_print_data_container_header(&container); 314 315 if (abbrev(tcp)) { 316 tprints("..."); 317 } else { 318 const uint64_t val_addr = 319 inodes_addr + offsetof(typeof(container), val); 320 uint64_t record[3]; 321 print_array(tcp, val_addr, container.elem_cnt / 3, 322 record, sizeof(record), 323 umoven_or_printaddr, 324 print_btrfs_data_container_logical_ino, 0); 325 } 326 327 btrfs_print_data_container_footer(); 328 } 329 330 static bool 331 print_btrfs_data_container_ino_path(struct tcb *tcp, void *elem_buf, 332 size_t elem_size, void *data) 333 { 334 const uint64_t *const offset = elem_buf; 335 const uint64_t *const val_addr = data; 336 337 printpath(tcp, *val_addr + *offset); 338 339 return true; 340 } 341 342 static void 343 btrfs_print_ino_path_container(struct tcb *tcp, 344 const uint64_t fspath_addr) 345 { 346 struct btrfs_data_container container; 347 348 if (umove_or_printaddr(tcp, fspath_addr, &container)) 349 return; 350 351 btrfs_print_data_container_header(&container); 352 353 if (abbrev(tcp)) { 354 tprints("..."); 355 } else { 356 uint64_t val_addr = 357 fspath_addr + offsetof(typeof(container), val); 358 uint64_t offset; 359 print_array(tcp, val_addr, container.elem_cnt, 360 &offset, sizeof(offset), 361 umoven_or_printaddr, 362 print_btrfs_data_container_ino_path, &val_addr); 363 } 364 365 btrfs_print_data_container_footer(); 366 } 367 368 static bool 369 print_uint64(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data) 370 { 371 tprintf("%" PRIu64, *(uint64_t *) elem_buf); 372 373 return true; 374 } 375 376 static void 377 btrfs_print_qgroup_inherit(struct tcb *const tcp, const kernel_ulong_t qgi_addr) 378 { 379 struct btrfs_qgroup_inherit inherit; 380 381 if (umove_or_printaddr(tcp, qgi_addr, &inherit)) 382 return; 383 384 tprints("{flags="); 385 printflags64(btrfs_qgroup_inherit_flags, inherit.flags, 386 "BTRFS_QGROUP_INHERIT_???"); 387 tprintf(", num_qgroups=%" PRI__u64 ", num_ref_copies=%" PRI__u64 388 ", num_excl_copies=%" PRI__u64 ", lim=", 389 inherit.num_qgroups, inherit.num_ref_copies, 390 inherit.num_excl_copies); 391 392 btrfs_print_qgroup_limit(&inherit.lim); 393 394 tprints(", qgroups="); 395 396 if (abbrev(tcp)) { 397 tprints("..."); 398 } else { 399 uint64_t record; 400 print_array(tcp, qgi_addr + offsetof(typeof(inherit), qgroups), 401 inherit.num_qgroups, &record, sizeof(record), 402 umoven_or_printaddr, print_uint64, 0); 403 } 404 tprints("}"); 405 } 406 407 static void 408 print_key_value_internal(struct tcb *tcp, const char *name, uint64_t value) 409 { 410 if (value) { 411 tprintf(", %s=%" PRIu64, name, value); 412 if (value == UINT64_MAX) 413 tprints_comment("UINT64_MAX"); 414 } 415 } 416 #define print_key_value(tcp, key, name) \ 417 print_key_value_internal((tcp), #name, (key)->name) 418 419 static void 420 btrfs_print_tree_search(struct tcb *tcp, struct btrfs_ioctl_search_key *key, 421 uint64_t buf_addr, uint64_t buf_size, bool print_size) 422 { 423 if (entering(tcp)) { 424 tprints("{key={tree_id="); 425 btrfs_print_objectid(key->tree_id); 426 427 if (key->min_objectid != BTRFS_FIRST_FREE_OBJECTID || 428 !abbrev(tcp)) { 429 tprints(", min_objectid="); 430 btrfs_print_objectid(key->min_objectid); 431 } 432 433 if (key->max_objectid != BTRFS_LAST_FREE_OBJECTID || 434 !abbrev(tcp)) { 435 tprints(", max_objectid="); 436 btrfs_print_objectid(key->max_objectid); 437 } 438 439 print_key_value(tcp, key, min_offset); 440 print_key_value(tcp, key, max_offset); 441 print_key_value(tcp, key, min_transid); 442 print_key_value(tcp, key, max_transid); 443 444 tprints(", min_type="); 445 btrfs_print_key_type(key->min_type); 446 tprints(", max_type="); 447 btrfs_print_key_type(key->max_type); 448 tprintf(", nr_items=%u}", key->nr_items); 449 if (print_size) 450 tprintf(", buf_size=%" PRIu64, buf_size); 451 tprints("}"); 452 } else { 453 tprintf("{key={nr_items=%u}", key->nr_items); 454 if (print_size) 455 tprintf(", buf_size=%" PRIu64, buf_size); 456 tprints(", buf="); 457 if (abbrev(tcp)) 458 tprints("..."); 459 else { 460 uint64_t i; 461 uint64_t off = 0; 462 tprints("["); 463 for (i = 0; i < key->nr_items; i++) { 464 struct btrfs_ioctl_search_header sh; 465 uint64_t addr = buf_addr + off; 466 if (i) 467 tprints(", "); 468 if (i > max_strlen || 469 umove(tcp, addr, &sh)) { 470 tprints("..."); 471 break; 472 } 473 tprintf("{transid=%" PRI__u64 ", objectid=", 474 sh.transid); 475 btrfs_print_objectid(sh.objectid); 476 tprintf(", offset=%" PRI__u64 ", type=", sh.offset); 477 btrfs_print_key_type(sh.type); 478 tprintf(", len=%u}", sh.len); 479 off += sizeof(sh) + sh.len; 480 481 } 482 tprints("]"); 483 } 484 tprints("}"); 485 } 486 } 487 488 static bool 489 print_objectid_callback(struct tcb *tcp, void *elem_buf, 490 size_t elem_size, void *data) 491 { 492 btrfs_print_objectid(*(uint64_t *) elem_buf); 493 494 return true; 495 } 496 497 static bool 498 print_btrfs_ioctl_space_info(struct tcb *tcp, void *elem_buf, 499 size_t elem_size, void *data) 500 { 501 const struct btrfs_ioctl_space_info *info = elem_buf; 502 503 tprints("{flags="); 504 printflags64(btrfs_space_info_flags, info->flags, 505 "BTRFS_SPACE_INFO_???"); 506 tprintf(", total_bytes=%" PRI__u64 ", used_bytes=%" PRI__u64 "}", 507 info->total_bytes, info->used_bytes); 508 509 return true; 510 } 511 512 MPERS_PRINTER_DECL(int, btrfs_ioctl, 513 struct tcb *const tcp, const unsigned int code, 514 const kernel_ulong_t arg) 515 { 516 switch (code) { 517 /* Take no arguments; command only. */ 518 case BTRFS_IOC_TRANS_START: 519 case BTRFS_IOC_TRANS_END: 520 case BTRFS_IOC_SYNC: 521 case BTRFS_IOC_SCRUB_CANCEL: 522 case BTRFS_IOC_QUOTA_RESCAN_WAIT: 523 /* 524 * The codes for these ioctls are based on each accepting a 525 * vol_args but none of them actually consume an argument. 526 */ 527 case BTRFS_IOC_DEFRAG: 528 case BTRFS_IOC_BALANCE: 529 break; 530 531 /* takes a signed int */ 532 case BTRFS_IOC_BALANCE_CTL: 533 tprints(", "); 534 printxval(btrfs_balance_ctl_cmds, arg, "BTRFS_BALANCE_CTL_???"); 535 break; 536 537 /* returns a 64 */ 538 case BTRFS_IOC_START_SYNC: /* R */ 539 if (entering(tcp)) 540 return 0; 541 /* fall through */ 542 /* takes a u64 */ 543 case BTRFS_IOC_DEFAULT_SUBVOL: /* W */ 544 case BTRFS_IOC_WAIT_SYNC: /* W */ 545 tprints(", "); 546 printnum_int64(tcp, arg, "%" PRIu64); 547 break; 548 549 /* u64 but describe a flags bitfield; we can make that symbolic */ 550 case BTRFS_IOC_SUBVOL_GETFLAGS: { /* R */ 551 uint64_t flags; 552 553 if (entering(tcp)) 554 return 0; 555 556 tprints(", "); 557 558 if (umove_or_printaddr(tcp, arg, &flags)) 559 break; 560 561 printflags64(btrfs_snap_flags_v2, flags, "BTRFS_SUBVOL_???"); 562 break; 563 } 564 565 case BTRFS_IOC_SUBVOL_SETFLAGS: { /* W */ 566 uint64_t flags; 567 568 tprints(", "); 569 570 if (umove_or_printaddr(tcp, arg, &flags)) 571 break; 572 573 printflags64(btrfs_snap_flags_v2, flags, "BTRFS_SUBVOL_???"); 574 break; 575 } 576 577 /* More complex types */ 578 case BTRFS_IOC_BALANCE_V2: /* RW */ 579 if (entering(tcp)) { 580 tprints(", "); 581 btrfs_print_balance(tcp, arg, false); 582 return 0; 583 } 584 585 if (syserror(tcp)) 586 break; 587 588 tprints(" => "); 589 btrfs_print_balance(tcp, arg, true); 590 break; 591 case BTRFS_IOC_BALANCE_PROGRESS: /* R */ 592 if (entering(tcp)) 593 return 0; 594 595 tprints(", "); 596 btrfs_print_balance(tcp, arg, true); 597 break; 598 599 case BTRFS_IOC_DEFRAG_RANGE: { /* W */ 600 struct btrfs_ioctl_defrag_range_args args; 601 602 tprints(", "); 603 604 if (umove_or_printaddr(tcp, arg, &args)) 605 break; 606 607 tprintf("{start=%" PRIu64 ", len=", (uint64_t)args.start); 608 609 tprintf("%" PRIu64, (uint64_t) args.len); 610 if (args.len == UINT64_MAX) 611 tprints_comment("UINT64_MAX"); 612 613 tprints(", flags="); 614 printflags64(btrfs_defrag_flags, args.flags, 615 "BTRFS_DEFRAG_RANGE_???"); 616 tprintf(", extent_thresh=%u, compress_type=", 617 args.extent_thresh); 618 printxval(btrfs_compress_types, args.compress_type, 619 "BTRFS_COMPRESS_???"); 620 tprints("}"); 621 break; 622 } 623 624 case BTRFS_IOC_DEV_INFO: { /* RW */ 625 struct btrfs_ioctl_dev_info_args args; 626 char uuid[UUID_STRING_SIZE+1]; 627 int valid; 628 629 if (entering(tcp)) 630 tprints(", "); 631 else if (syserror(tcp)) 632 break; 633 else 634 tprints(" => "); 635 if (umove_or_printaddr(tcp, arg, &args)) 636 break; 637 tprints("{"); 638 639 valid = btrfs_unparse_uuid(args.uuid, uuid); 640 if (entering(tcp)) { 641 tprintf("devid=%" PRI__u64, args.devid); 642 if (valid) 643 tprintf(", uuid=%s", uuid); 644 tprints("}"); 645 return 0; 646 } 647 if (valid) 648 tprintf("uuid=%s, ", uuid); 649 tprintf("bytes_used=%" PRI__u64 650 ", total_bytes=%" PRI__u64, 651 args.bytes_used, args.total_bytes); 652 PRINT_FIELD_CSTRING(", ", args, path); 653 tprints("}"); 654 break; 655 } 656 657 case BTRFS_IOC_DEV_REPLACE: { /* RW */ 658 struct_btrfs_ioctl_dev_replace_args args; 659 660 if (entering(tcp)) 661 tprints(", "); 662 else if (syserror(tcp)) 663 break; 664 else 665 tprints(" => "); 666 667 if (umove_or_printaddr(tcp, arg, &args)) 668 break; 669 670 if (entering(tcp)) { 671 tprints("{cmd="); 672 printxval64(btrfs_dev_replace_cmds, args.cmd, 673 "BTRFS_IOCTL_DEV_REPLACE_CMD_???"); 674 if (args.cmd == BTRFS_IOCTL_DEV_REPLACE_CMD_START) { 675 const char *str; 676 tprintf(", start={srcdevid=%" PRIu64 677 ", cont_reading_from_srcdev_mode=%" PRIu64 678 ", srcdev_name=", 679 (uint64_t) args.start.srcdevid, 680 (uint64_t) args.start.cont_reading_from_srcdev_mode); 681 682 str = (const char *) args.start.srcdev_name; 683 print_quoted_cstring(str, 684 sizeof(args.start.srcdev_name)); 685 tprints(", tgtdev_name="); 686 str = (const char *) args.start.tgtdev_name; 687 print_quoted_cstring(str, 688 sizeof(args.start.tgtdev_name)); 689 tprints("}"); 690 691 } 692 tprints("}"); 693 return 0; 694 } 695 696 tprints("{result="); 697 printxval64(btrfs_dev_replace_results, args.result, 698 "BTRFS_IOCTL_DEV_REPLACE_RESULT_???"); 699 if (args.cmd == BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS) { 700 tprints(", "); 701 printxval64(btrfs_dev_replace_state, 702 args.status.replace_state, 703 "BTRFS_IOCTL_DEV_REPLACE_STATE_???"); 704 tprintf(", progress_1000=%" PRIu64, 705 (uint64_t) args.status.progress_1000); 706 707 if (args.status.progress_1000 <= 1000) 708 tprintf_comment("%u.%u%%", 709 (unsigned) args.status.progress_1000 / 10, 710 (unsigned) args.status.progress_1000 % 10); 711 712 tprintf(", time_started=%" PRIu64, 713 (uint64_t) args.status.time_started); 714 tprints_comment(sprinttime(args.status.time_started)); 715 716 tprintf(", time_stopped=%" PRIu64, 717 (uint64_t) args.status.time_stopped); 718 tprints_comment(sprinttime(args.status.time_stopped)); 719 720 tprintf(", num_write_errors=%" PRIu64 721 ", num_uncorrectable_read_errors=%" PRIu64, 722 (uint64_t) args.status.num_write_errors, 723 (uint64_t) args.status.num_uncorrectable_read_errors); 724 } 725 tprints("}"); 726 break; 727 } 728 729 case BTRFS_IOC_GET_FEATURES: { /* R */ 730 struct btrfs_ioctl_feature_flags flags; 731 732 if (entering(tcp)) 733 return 0; 734 735 tprints(", "); 736 if (umove_or_printaddr(tcp, arg, &flags)) 737 break; 738 739 btrfs_print_features(&flags); 740 break; 741 } 742 743 case BTRFS_IOC_SET_FEATURES: { /* W */ 744 struct btrfs_ioctl_feature_flags flarg[2]; 745 746 tprints(", "); 747 748 if (umove_or_printaddr(tcp, arg, &flarg)) 749 break; 750 751 tprints("["); 752 btrfs_print_features(&flarg[0]); 753 tprints(", "); 754 btrfs_print_features(&flarg[1]); 755 tprints("]"); 756 break; 757 } 758 759 case BTRFS_IOC_GET_SUPPORTED_FEATURES: { /* R */ 760 struct btrfs_ioctl_feature_flags flarg[3]; 761 762 if (entering(tcp)) 763 return 0; 764 765 tprints(", "); 766 if (umove_or_printaddr(tcp, arg, &flarg)) 767 break; 768 769 tprints("["); 770 btrfs_print_features(&flarg[0]); 771 tprints_comment("supported"); 772 773 tprints(", "); 774 btrfs_print_features(&flarg[1]); 775 tprints_comment("safe to set"); 776 777 tprints(", "); 778 btrfs_print_features(&flarg[2]); 779 tprints_comment("safe to clear"); 780 tprints("]"); 781 782 break; 783 } 784 785 case BTRFS_IOC_FS_INFO: { /* R */ 786 struct btrfs_ioctl_fs_info_args args; 787 char uuid[UUID_STRING_SIZE+1]; 788 uint32_t nodesize, sectorsize, clone_alignment; 789 #ifndef HAVE_STRUCT_BTRFS_IOCTL_FS_INFO_ARGS_NODESIZE 790 uint32_t *reserved32; 791 #endif 792 793 if (entering(tcp)) 794 return 0; 795 796 tprints(", "); 797 if (umove_or_printaddr(tcp, arg, &args)) 798 break; 799 800 #ifdef HAVE_STRUCT_BTRFS_IOCTL_FS_INFO_ARGS_NODESIZE 801 nodesize = args.nodesize, 802 sectorsize = args.sectorsize, 803 clone_alignment = args.clone_alignment; 804 #else 805 reserved32 = (void *) args.reserved; 806 nodesize = reserved32[0]; 807 sectorsize = reserved32[1]; 808 clone_alignment = reserved32[2]; 809 #endif 810 btrfs_unparse_uuid(args.fsid, uuid); 811 812 tprints("{"); 813 tprintf("max_id=%" PRI__u64 ", num_devices=%" PRI__u64 814 ", fsid=%s, nodesize=%u, sectorsize=%u" 815 ", clone_alignment=%u", 816 args.max_id, args.num_devices, uuid, 817 nodesize, sectorsize, clone_alignment); 818 tprints("}"); 819 break; 820 } 821 822 case BTRFS_IOC_GET_DEV_STATS: { /* RW */ 823 struct btrfs_ioctl_get_dev_stats args; 824 uint64_t i; 825 826 if (entering(tcp)) 827 tprints(", "); 828 else if (syserror(tcp)) 829 break; 830 else 831 tprints(" => "); 832 if (umove_or_printaddr(tcp, arg, &args)) 833 break; 834 835 tprints("{"); 836 837 if (entering(tcp)) 838 tprintf("devid=%" PRI__u64 ", ", args.devid); 839 840 tprintf("nr_items=%" PRI__u64 ", flags=", args.nr_items); 841 printflags64(btrfs_dev_stats_flags, args.flags, 842 "BTRFS_DEV_STATS_???"); 843 844 if (entering(tcp)) { 845 tprints("}"); 846 return 0; 847 } 848 849 /* 850 * The structure has a 1k limit; Let's make sure we don't 851 * go off into the middle of nowhere with a bad nr_items 852 * value. 853 */ 854 tprints(", ["); 855 for (i = 0; i < args.nr_items; i++) { 856 if (i) 857 tprints(", "); 858 if (i >= ARRAY_SIZE(args.values)) { 859 tprints("..."); 860 break; 861 } 862 tprintf("%" PRI__u64, args.values[i]); 863 tprints_comment(xlookup(btrfs_dev_stats_values, i)); 864 } 865 tprints("]}"); 866 break; 867 } 868 869 case BTRFS_IOC_INO_LOOKUP: { /* RW */ 870 struct btrfs_ioctl_ino_lookup_args args; 871 872 if (entering(tcp)) 873 tprints(", "); 874 else if (syserror(tcp)) 875 break; 876 else 877 tprints(" => "); 878 879 if (umove_or_printaddr(tcp, arg, &args)) 880 break; 881 882 if (entering(tcp)) { 883 /* Use subvolume id of the containing root */ 884 if (args.treeid == 0) 885 set_tcb_priv_ulong(tcp, 1); 886 887 tprints("{treeid="); 888 btrfs_print_objectid(args.treeid); 889 tprints(", objectid="); 890 btrfs_print_objectid(args.objectid); 891 tprints("}"); 892 return 0; 893 } 894 895 tprints("{"); 896 if (get_tcb_priv_ulong(tcp)) { 897 tprints("treeid="); 898 btrfs_print_objectid(args.treeid); 899 tprints(", "); 900 } 901 902 PRINT_FIELD_CSTRING("", args, name); 903 tprints("}"); 904 break; 905 } 906 907 case BTRFS_IOC_INO_PATHS: { /* RW */ 908 struct btrfs_ioctl_ino_path_args args; 909 910 if (entering(tcp)) 911 tprints(", "); 912 else if (syserror(tcp)) 913 break; 914 else 915 tprints(" => "); 916 917 if (umove_or_printaddr(tcp, arg, &args)) 918 break; 919 920 tprints("{"); 921 922 if (entering(tcp)) { 923 tprintf("inum=%" PRI__u64 ", size=%" PRI__u64, 924 args.inum, args.size); 925 tprintf(", fspath=0x%" PRI__x64 "}", args.fspath); 926 return 0; 927 } 928 929 tprints("fspath="); 930 btrfs_print_ino_path_container(tcp, args.fspath); 931 932 tprints("}"); 933 break; 934 } 935 936 case BTRFS_IOC_LOGICAL_INO: { /* RW */ 937 struct btrfs_ioctl_logical_ino_args args; 938 939 if (entering(tcp)) 940 tprints(", "); 941 else if (syserror(tcp)) 942 break; 943 else 944 tprints(" => "); 945 946 if (umove_or_printaddr(tcp, arg, &args)) 947 break; 948 949 tprints("{"); 950 951 if (entering(tcp)) { 952 tprintf("logical=%" PRI__u64 ", size=%" PRI__u64, 953 args.logical, args.size); 954 tprintf(", inodes=0x%" PRI__x64 "}", args.inodes); 955 return 0; 956 } 957 958 tprints("inodes="); 959 btrfs_print_logical_ino_container(tcp, args.inodes); 960 961 tprints("}"); 962 break; 963 } 964 965 case BTRFS_IOC_QGROUP_ASSIGN: { /* W */ 966 struct btrfs_ioctl_qgroup_assign_args args; 967 968 tprints(", "); 969 if (umove_or_printaddr(tcp, arg, &args)) 970 break; 971 972 tprintf("{assign=%" PRI__u64 ", src=%" PRI__u64 973 ", dst=%" PRI__u64 "}", 974 args.assign, args.src, args.dst); 975 break; 976 } 977 978 case BTRFS_IOC_QGROUP_CREATE: { /* W */ 979 struct btrfs_ioctl_qgroup_create_args args; 980 981 tprints(", "); 982 if (umove_or_printaddr(tcp, arg, &args)) 983 break; 984 985 tprintf("{create=%" PRI__u64 ", qgroupid=%" PRI__u64 "}", 986 args.create, args.qgroupid); 987 break; 988 } 989 990 case BTRFS_IOC_QGROUP_LIMIT: { /* R */ 991 struct btrfs_ioctl_qgroup_limit_args args; 992 993 if (entering(tcp)) 994 return 0; 995 996 tprints(", "); 997 if (umove_or_printaddr(tcp, arg, &args)) 998 break; 999 1000 tprintf("{qgroupid=%" PRI__u64 ", lim=", args.qgroupid); 1001 btrfs_print_qgroup_limit(&args.lim); 1002 tprints("}"); 1003 break; 1004 } 1005 1006 case BTRFS_IOC_QUOTA_CTL: { /* W */ 1007 struct btrfs_ioctl_quota_ctl_args args; 1008 1009 tprints(", "); 1010 if (umove_or_printaddr(tcp, arg, &args)) 1011 break; 1012 1013 printxval64(btrfs_qgroup_ctl_cmds, args.cmd, 1014 "BTRFS_QUOTA_CTL_???"); 1015 tprints("}"); 1016 1017 break; 1018 } 1019 1020 case BTRFS_IOC_QUOTA_RESCAN: { /* W */ 1021 struct btrfs_ioctl_quota_rescan_args args; 1022 1023 tprints(", "); 1024 if (umove_or_printaddr(tcp, arg, &args)) 1025 break; 1026 1027 tprintf("{flags=%" PRIu64 "}", (uint64_t) args.flags); 1028 break; 1029 } 1030 1031 case BTRFS_IOC_QUOTA_RESCAN_STATUS: { /* R */ 1032 struct btrfs_ioctl_quota_rescan_args args; 1033 1034 if (entering(tcp)) 1035 return 0; 1036 1037 tprints(", "); 1038 if (umove_or_printaddr(tcp, arg, &args)) 1039 break; 1040 1041 tprintf("{flags=%" PRIu64 ", progress=", (uint64_t) args.flags); 1042 btrfs_print_objectid(args.progress); 1043 tprints("}"); 1044 break; 1045 } 1046 1047 case BTRFS_IOC_SET_RECEIVED_SUBVOL: { /* RW */ 1048 struct_btrfs_ioctl_received_subvol_args args; 1049 char uuid[UUID_STRING_SIZE+1]; 1050 1051 if (entering(tcp)) 1052 tprints(", "); 1053 else if (syserror(tcp)) 1054 break; 1055 else 1056 tprints(" => "); 1057 1058 if (umove_or_printaddr(tcp, arg, &args)) 1059 break; 1060 1061 if (entering(tcp)) { 1062 btrfs_unparse_uuid((unsigned char *)args.uuid, uuid); 1063 tprintf("{uuid=%s, stransid=%" PRIu64 1064 ", stime=%" PRIu64 ".%u, flags=%" PRIu64 1065 "}", uuid, (uint64_t) args.stransid, 1066 (uint64_t) args.stime.sec, args.stime.nsec, 1067 (uint64_t) args.flags); 1068 return 0; 1069 } 1070 tprintf("{rtransid=%" PRIu64 ", rtime=%" PRIu64 ".%u}", 1071 (uint64_t) args.rtransid, (uint64_t) args.rtime.sec, 1072 args.rtime.nsec); 1073 break; 1074 } 1075 1076 case BTRFS_IOC_SCRUB: /* RW */ 1077 case BTRFS_IOC_SCRUB_PROGRESS: { /* RW */ 1078 struct btrfs_ioctl_scrub_args args; 1079 1080 if (entering(tcp)) 1081 tprints(", "); 1082 else if (syserror(tcp)) 1083 break; 1084 else 1085 tprints(" => "); 1086 1087 if (umove_or_printaddr(tcp, arg, &args)) 1088 break; 1089 1090 if (entering(tcp)) { 1091 tprintf("{devid=%" PRI__u64, args.devid); 1092 if (code == BTRFS_IOC_SCRUB) { 1093 tprintf(", start=%" PRI__u64 ", end=", 1094 args.start); 1095 tprintf("%" PRI__u64, args.end); 1096 if (args.end == UINT64_MAX) 1097 tprints_comment("UINT64_MAX"); 1098 tprints(", flags="); 1099 printflags64(btrfs_scrub_flags, args.flags, 1100 "BTRFS_SCRUB_???"); 1101 } 1102 tprints("}"); 1103 return 0; 1104 } 1105 tprintf("{data_extents_scrubbed=%" PRI__u64 1106 ", tree_extents_scrubbed=%" PRI__u64 1107 ", data_bytes_scrubbed=%" PRI__u64 1108 ", tree_bytes_scrubbed=%" PRI__u64 1109 ", read_errors=%" PRI__u64 1110 ", csum_errors=%" PRI__u64 1111 ", verify_errors=%" PRI__u64 1112 ", no_csum=%" PRI__u64 1113 ", csum_discards=%" PRI__u64 1114 ", super_errors=%" PRI__u64 1115 ", malloc_errors=%" PRI__u64 1116 ", uncorrectable_errors=%" PRI__u64 1117 ", corrected_errors=%" PRI__u64 1118 ", last_physical=%" PRI__u64 1119 ", unverified_errors=%" PRI__u64 "}", 1120 args.progress.data_extents_scrubbed, 1121 args.progress.tree_extents_scrubbed, 1122 args.progress.data_bytes_scrubbed, 1123 args.progress.tree_bytes_scrubbed, 1124 args.progress.read_errors, 1125 args.progress.csum_errors, 1126 args.progress.verify_errors, 1127 args.progress.no_csum, 1128 args.progress.csum_discards, 1129 args.progress.super_errors, 1130 args.progress.malloc_errors, 1131 args.progress.uncorrectable_errors, 1132 args.progress.corrected_errors, 1133 args.progress.last_physical, 1134 args.progress.unverified_errors); 1135 break; 1136 } 1137 1138 case BTRFS_IOC_TREE_SEARCH: { /* RW */ 1139 struct btrfs_ioctl_search_args args; 1140 uint64_t buf_offset; 1141 1142 if (entering(tcp)) 1143 tprints(", "); 1144 else if (syserror(tcp)) 1145 break; 1146 else 1147 tprints(" => "); 1148 1149 if (umove_or_printaddr(tcp, arg, &args)) 1150 break; 1151 1152 buf_offset = offsetof(struct btrfs_ioctl_search_args, buf); 1153 btrfs_print_tree_search(tcp, &args.key, arg + buf_offset, 1154 sizeof(args.buf), false); 1155 if (entering(tcp)) 1156 return 0; 1157 break; 1158 } 1159 1160 case BTRFS_IOC_TREE_SEARCH_V2: { /* RW */ 1161 struct btrfs_ioctl_search_args_v2 args; 1162 uint64_t buf_offset; 1163 1164 if (entering(tcp)) 1165 tprints(", "); 1166 else if (syserror(tcp)) { 1167 if (tcp->u_error == EOVERFLOW) { 1168 tprints(" => "); 1169 tcp->u_error = 0; 1170 if (!umove_or_printaddr(tcp, arg, &args)) 1171 tprintf("{buf_size=%" PRIu64 "}", 1172 (uint64_t)args.buf_size); 1173 tcp->u_error = EOVERFLOW; 1174 } 1175 break; 1176 } else 1177 tprints(" => "); 1178 1179 if (umove_or_printaddr(tcp, arg, &args)) 1180 break; 1181 1182 buf_offset = offsetof(struct btrfs_ioctl_search_args_v2, buf); 1183 btrfs_print_tree_search(tcp, &args.key, arg + buf_offset, 1184 args.buf_size, true); 1185 if (entering(tcp)) 1186 return 0; 1187 break; 1188 } 1189 1190 case BTRFS_IOC_SEND: { /* W */ 1191 struct_btrfs_ioctl_send_args args; 1192 1193 tprints(", "); 1194 if (umove_or_printaddr(tcp, arg, &args)) 1195 break; 1196 1197 tprints("{send_fd="); 1198 printfd(tcp, args.send_fd); 1199 tprintf(", clone_sources_count=%" PRIu64 ", clone_sources=", 1200 (uint64_t) args.clone_sources_count); 1201 1202 if (abbrev(tcp)) 1203 tprints("..."); 1204 else { 1205 uint64_t record; 1206 print_array(tcp, ptr_to_kulong(args.clone_sources), 1207 args.clone_sources_count, 1208 &record, sizeof(record), 1209 umoven_or_printaddr, 1210 print_objectid_callback, 0); 1211 } 1212 tprints(", parent_root="); 1213 btrfs_print_objectid(args.parent_root); 1214 tprints(", flags="); 1215 printflags64(btrfs_send_flags, args.flags, 1216 "BTRFS_SEND_FLAGS_???"); 1217 tprints("}"); 1218 break; 1219 } 1220 1221 case BTRFS_IOC_SPACE_INFO: { /* RW */ 1222 struct btrfs_ioctl_space_args args; 1223 1224 if (entering(tcp)) 1225 tprints(", "); 1226 else if (syserror(tcp)) 1227 break; 1228 else 1229 tprints(" => "); 1230 1231 if (umove_or_printaddr(tcp, arg, &args)) 1232 break; 1233 1234 tprints("{"); 1235 if (entering(tcp)) { 1236 tprintf("space_slots=%" PRI__u64 "}", args.space_slots); 1237 return 0; 1238 } 1239 1240 tprintf("total_spaces=%" PRI__u64, args.total_spaces); 1241 1242 if (args.space_slots == 0 && args.total_spaces) { 1243 tprints("}"); 1244 break; 1245 } 1246 1247 tprints(", spaces="); 1248 1249 if (abbrev(tcp)) 1250 tprints("..."); 1251 else { 1252 struct btrfs_ioctl_space_info info; 1253 print_array(tcp, arg + offsetof(typeof(args), spaces), 1254 args.total_spaces, 1255 &info, sizeof(info), umoven_or_printaddr, 1256 print_btrfs_ioctl_space_info, 0); 1257 } 1258 tprints("}"); 1259 break; 1260 } 1261 1262 case BTRFS_IOC_SNAP_CREATE: 1263 case BTRFS_IOC_RESIZE: 1264 case BTRFS_IOC_SCAN_DEV: 1265 case BTRFS_IOC_ADD_DEV: 1266 case BTRFS_IOC_RM_DEV: 1267 case BTRFS_IOC_SUBVOL_CREATE: 1268 case BTRFS_IOC_SNAP_DESTROY: 1269 case BTRFS_IOC_DEVICES_READY: { /* W */ 1270 struct btrfs_ioctl_vol_args args; 1271 1272 tprints(", "); 1273 if (umove_or_printaddr(tcp, arg, &args)) 1274 break; 1275 1276 tprints("{fd="); 1277 printfd(tcp, args.fd); 1278 PRINT_FIELD_CSTRING(", ", args, name); 1279 tprints("}"); 1280 break; 1281 } 1282 1283 case BTRFS_IOC_SNAP_CREATE_V2: 1284 case BTRFS_IOC_SUBVOL_CREATE_V2: { /* code is W, but is actually RW */ 1285 struct_btrfs_ioctl_vol_args_v2 args; 1286 1287 if (entering(tcp)) 1288 tprints(", "); 1289 else if (syserror(tcp)) 1290 break; 1291 else 1292 tprints(" => "); 1293 1294 if (umove_or_printaddr(tcp, arg, &args)) 1295 break; 1296 1297 if (entering(tcp)) { 1298 tprints("{fd="); 1299 printfd(tcp, args.fd); 1300 tprints(", flags="); 1301 printflags64(btrfs_snap_flags_v2, args.flags, 1302 "BTRFS_SUBVOL_???"); 1303 if (args.flags & BTRFS_SUBVOL_QGROUP_INHERIT) { 1304 tprintf(", size=%" PRIu64 ", qgroup_inherit=", 1305 (uint64_t) args.size); 1306 1307 btrfs_print_qgroup_inherit(tcp, 1308 ptr_to_kulong(args.qgroup_inherit)); 1309 } 1310 PRINT_FIELD_CSTRING(", ", args, name); 1311 tprints("}"); 1312 return 0; 1313 } 1314 tprintf("{transid=%" PRIu64 "}", (uint64_t) args.transid); 1315 break; 1316 } 1317 1318 case BTRFS_IOC_GET_FSLABEL: /* R */ 1319 if (entering(tcp)) 1320 return 0; 1321 /* fall through */ 1322 case BTRFS_IOC_SET_FSLABEL: { /* W */ 1323 char label[BTRFS_LABEL_SIZE]; 1324 1325 tprints(", "); 1326 if (umove_or_printaddr(tcp, arg, &label)) 1327 break; 1328 print_quoted_cstring(label, sizeof(label)); 1329 break; 1330 } 1331 1332 case BTRFS_IOC_CLONE: /* FICLONE */ 1333 case BTRFS_IOC_CLONE_RANGE: /* FICLONERANGE */ 1334 #ifdef BTRFS_IOC_FILE_EXTENT_SAME 1335 case BTRFS_IOC_FILE_EXTENT_SAME: /* FIDEDUPERANGE */ 1336 #endif 1337 /* 1338 * FICLONE, FICLONERANGE, and FIDEDUPERANGE started out as 1339 * btrfs ioctls and the code was kept for the generic 1340 * implementations. We use the BTRFS_* names here because 1341 * they will be available on older systems. 1342 */ 1343 return file_ioctl(tcp, code, arg); 1344 1345 default: 1346 return RVAL_DECODED; 1347 }; 1348 return RVAL_IOCTL_DECODED; 1349 } 1350 #endif /* HAVE_LINUX_BTRFS_H */ 1351