Blame view
fs/btrfs/subvolume.c
2.7 KB
21a14facb fs: btrfs: Add si... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
/* * BTRFS filesystem implementation for U-Boot * * 2017 Marek Behun, CZ.NIC, marek.behun@nic.cz * * SPDX-License-Identifier: GPL-2.0+ */ #include "btrfs.h" #include <malloc.h> static int get_subvol_name(u64 subvolid, char *name, int max_len) { struct btrfs_root_ref rref; struct btrfs_inode_ref iref; struct btrfs_root root; u64 dir; char tmp[max(BTRFS_VOL_NAME_MAX, BTRFS_NAME_MAX)]; char *ptr; ptr = name + max_len - 1; *ptr = '\0'; while (subvolid != BTRFS_FS_TREE_OBJECTID) { subvolid = btrfs_lookup_root_ref(subvolid, &rref, tmp); if (subvolid == -1ULL) return -1; ptr -= rref.name_len + 1; if (ptr < name) goto too_long; memcpy(ptr + 1, tmp, rref.name_len); *ptr = '/'; if (btrfs_find_root(subvolid, &root, NULL)) return -1; dir = rref.dirid; while (dir != BTRFS_FIRST_FREE_OBJECTID) { dir = btrfs_lookup_inode_ref(&root, dir, &iref, tmp); if (dir == -1ULL) return -1; ptr -= iref.name_len + 1; if (ptr < name) goto too_long; memcpy(ptr + 1, tmp, iref.name_len); *ptr = '/'; } } if (ptr == name + max_len - 1) { name[0] = '/'; name[1] = '\0'; } else { memmove(name, ptr, name + max_len - ptr); } return 0; too_long: printf("%s: subvolume name too long ", __func__); return -1; } u64 btrfs_get_default_subvol_objectid(void) { struct btrfs_dir_item item; if (btrfs_lookup_dir_item(&btrfs_info.tree_root, btrfs_info.sb.root_dir_objectid, "default", 7, &item)) return BTRFS_FS_TREE_OBJECTID; return item.location.objectid; } static void list_subvols(u64 tree, char *nameptr, int max_name_len, int level) { struct btrfs_key key, *found_key; struct btrfs_path path; struct btrfs_root_ref *ref; int res; key.objectid = tree; key.type = BTRFS_ROOT_REF_KEY; key.offset = 0; if (btrfs_search_tree(&btrfs_info.tree_root, &key, &path)) return; do { found_key = btrfs_path_leaf_key(&path); if (btrfs_comp_keys_type(&key, found_key)) break; ref = btrfs_path_item_ptr(&path, struct btrfs_root_ref); btrfs_root_ref_to_cpu(ref); printf("ID %llu parent %llu name ", found_key->offset, tree); if (nameptr && !get_subvol_name(found_key->offset, nameptr, max_name_len)) printf("%s ", nameptr); else printf("%.*s ", (int) ref->name_len, (const char *) (ref + 1)); if (level > 0) list_subvols(found_key->offset, nameptr, max_name_len, level - 1); else printf("%s: Too much recursion, maybe skipping some " "subvolumes ", __func__); } while (!(res = btrfs_next_slot(&path))); btrfs_free_path(&path); } void btrfs_list_subvols(void) { char *nameptr = malloc(4096); list_subvols(BTRFS_FS_TREE_OBJECTID, nameptr, nameptr ? 4096 : 0, 40); if (nameptr) free(nameptr); } |