void btrfs_print_key(struct btrfs_disk_key *disk_key) { u64 objectid = btrfs_disk_key_objectid(disk_key); u8 type = btrfs_disk_key_type(disk_key); u64 offset = btrfs_disk_key_offset(disk_key); printf("key ("); print_objectid(objectid, type); printf(" "); print_key_type(objectid, type); switch (type) { case BTRFS_QGROUP_RELATION_KEY: case BTRFS_QGROUP_INFO_KEY: case BTRFS_QGROUP_LIMIT_KEY: printf(" %llu/%llu)", btrfs_qgroup_level(offset), btrfs_qgroup_subvid(offset)); break; case BTRFS_UUID_KEY_SUBVOL: case BTRFS_UUID_KEY_RECEIVED_SUBVOL: printf(" 0x%016llx)", (unsigned long long)offset); break; default: if (offset == (u64)-1) printf(" -1)"); else printf(" %llu)", (unsigned long long)offset); break; } }
static int qgroup_assign(int assign, int argc, char **argv) { int ret = 0; int fd; int e; char *path = argv[3]; struct btrfs_ioctl_qgroup_assign_args args; DIR *dirstream = NULL; if (check_argc_exact(argc, 4)) return -1; memset(&args, 0, sizeof(args)); args.assign = assign; args.src = parse_qgroupid(argv[1]); args.dst = parse_qgroupid(argv[2]); /* * FIXME src should accept subvol path */ if (btrfs_qgroup_level(args.src) >= btrfs_qgroup_level(args.dst)) { fprintf(stderr, "ERROR: bad relation requested '%s'\n", path); return 1; } fd = open_file_or_dir(path, &dirstream); if (fd < 0) { fprintf(stderr, "ERROR: can't access '%s'\n", path); return 1; } ret = ioctl(fd, BTRFS_IOC_QGROUP_ASSIGN, &args); e = errno; close_file_or_dir(fd, dirstream); if (ret < 0) { fprintf(stderr, "ERROR: unable to assign quota group: %s\n", strerror(e)); return 1; } return 0; }
static int _cmd_qgroup_assign(int assign, int argc, char **argv, const char * const *usage_str) { int ret = 0; int fd; int rescan = 0; char *path; struct btrfs_ioctl_qgroup_assign_args args; DIR *dirstream = NULL; if (assign) { while (1) { enum { GETOPT_VAL_RESCAN = 256, GETOPT_VAL_NO_RESCAN }; static const struct option long_options[] = { { "rescan", no_argument, NULL, GETOPT_VAL_RESCAN }, { "no-rescan", no_argument, NULL, GETOPT_VAL_NO_RESCAN }, { NULL, 0, NULL, 0 } }; int c = getopt_long(argc, argv, "", long_options, NULL); if (c < 0) break; switch (c) { case GETOPT_VAL_RESCAN: rescan = 1; break; case GETOPT_VAL_NO_RESCAN: rescan = 0; break; default: /* Usage printed by the caller */ return -1; } } } else { clean_args_no_options(argc, argv, usage_str); } if (check_argc_exact(argc - optind, 3)) usage(usage_str); memset(&args, 0, sizeof(args)); args.assign = assign; args.src = parse_qgroupid(argv[optind]); args.dst = parse_qgroupid(argv[optind + 1]); path = argv[optind + 2]; /* * FIXME src should accept subvol path */ if (btrfs_qgroup_level(args.src) >= btrfs_qgroup_level(args.dst)) { error("bad relation requested: %s", path); return 1; } fd = btrfs_open_dir(path, &dirstream, 1); if (fd < 0) return 1; ret = ioctl(fd, BTRFS_IOC_QGROUP_ASSIGN, &args); if (ret < 0) { error("unable to assign quota group: %s", strerror(errno)); close_file_or_dir(fd, dirstream); return 1; } /* * If ret > 0, it means assign caused qgroup data inconsistent state. * Schedule a quota rescan if requested. * * The return value change only happens in newer kernel. But will not * cause problem since old kernel has a bug that will never clear * INCONSISTENT bit. */ if (ret > 0) { if (rescan) { struct btrfs_ioctl_quota_rescan_args qargs; printf("Quota data changed, rescan scheduled\n"); memset(&qargs, 0, sizeof(qargs)); ret = ioctl(fd, BTRFS_IOC_QUOTA_RESCAN, &qargs); if (ret < 0) error("quota rescan failed: %s", strerror(errno)); } else { warning("quotas may be inconsistent, rescan needed"); } } close_file_or_dir(fd, dirstream); return ret; }
static void print_objectid(u64 objectid, u8 type) { switch (type) { case BTRFS_DEV_EXTENT_KEY: printf("%llu", (unsigned long long)objectid); /* device id */ return; case BTRFS_QGROUP_RELATION_KEY: printf("%llu/%llu", btrfs_qgroup_level(objectid), btrfs_qgroup_subvid(objectid)); return; case BTRFS_UUID_KEY_SUBVOL: case BTRFS_UUID_KEY_RECEIVED_SUBVOL: printf("0x%016llx", (unsigned long long)objectid); return; } switch (objectid) { case BTRFS_ROOT_TREE_OBJECTID: if (type == BTRFS_DEV_ITEM_KEY) printf("DEV_ITEMS"); else printf("ROOT_TREE"); break; case BTRFS_EXTENT_TREE_OBJECTID: printf("EXTENT_TREE"); break; case BTRFS_CHUNK_TREE_OBJECTID: printf("CHUNK_TREE"); break; case BTRFS_DEV_TREE_OBJECTID: printf("DEV_TREE"); break; case BTRFS_FS_TREE_OBJECTID: printf("FS_TREE"); break; case BTRFS_ROOT_TREE_DIR_OBJECTID: printf("ROOT_TREE_DIR"); break; case BTRFS_CSUM_TREE_OBJECTID: printf("CSUM_TREE"); break; case BTRFS_BALANCE_OBJECTID: printf("BALANCE"); break; case BTRFS_ORPHAN_OBJECTID: printf("ORPHAN"); break; case BTRFS_TREE_LOG_OBJECTID: printf("TREE_LOG"); break; case BTRFS_TREE_LOG_FIXUP_OBJECTID: printf("LOG_FIXUP"); break; case BTRFS_TREE_RELOC_OBJECTID: printf("TREE_RELOC"); break; case BTRFS_DATA_RELOC_TREE_OBJECTID: printf("DATA_RELOC_TREE"); break; case BTRFS_EXTENT_CSUM_OBJECTID: printf("EXTENT_CSUM"); break; case BTRFS_FREE_SPACE_OBJECTID: printf("FREE_SPACE"); break; case BTRFS_FREE_INO_OBJECTID: printf("FREE_INO"); break; case BTRFS_QUOTA_TREE_OBJECTID: printf("QUOTA_TREE"); break; case BTRFS_UUID_TREE_OBJECTID: printf("UUID_TREE"); break; case BTRFS_MULTIPLE_OBJECTIDS: printf("MULTIPLE"); break; case (u64)-1: printf("-1"); break; case BTRFS_FIRST_CHUNK_TREE_OBJECTID: if (type == BTRFS_CHUNK_ITEM_KEY) { printf("FIRST_CHUNK_TREE"); break; } /* fall-thru */ default: printf("%llu", (unsigned long long)objectid); } }