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