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