2 * Copyright (C) 2010 Oracle. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
21 #include <sys/ioctl.h>
22 #include <sys/mount.h>
27 #include <sys/types.h>
33 #include "kerncompat.h"
35 #include "transaction.h"
38 /* we store all the roots we find in an rbtree so that we can
39 * search for them later.
46 * one of these for each root we find.
49 struct rb_node rb_node;
54 /* the id of the root that references this one */
57 /* the dir id we're in from ref_tree */
60 /* generation when the root is created or last updated */
63 /* path from the subvol we live in to this root, including the
64 * root's name. This is null until we do the extra lookup ioctl.
68 /* the name of this root in the directory it lives in */
72 static void root_lookup_init(struct root_lookup *tree)
74 tree->root.rb_node = NULL;
77 static int comp_entry(struct root_info *entry, u64 root_id, u64 ref_tree)
79 if (entry->root_id > root_id)
81 if (entry->root_id < root_id)
83 if (entry->ref_tree > ref_tree)
85 if (entry->ref_tree < ref_tree)
90 static int comp_entry_with_gen(struct root_info *entry, u64 root_id,
91 u64 ref_tree, u64 gen)
97 return comp_entry(entry, root_id, ref_tree);
101 * insert a new root into the tree. returns the existing root entry
102 * if one is already there. Both root_id and ref_tree are used
105 static struct rb_node *tree_insert(struct rb_root *root, u64 root_id,
106 u64 ref_tree, u64 *gen, struct rb_node *node)
108 struct rb_node ** p = &root->rb_node;
109 struct rb_node * parent = NULL;
110 struct root_info *entry;
115 entry = rb_entry(parent, struct root_info, rb_node);
118 comp = comp_entry(entry, root_id, ref_tree);
120 comp = comp_entry_with_gen(entry, root_id, ref_tree,
131 entry = rb_entry(parent, struct root_info, rb_node);
132 rb_link_node(node, parent, p);
133 rb_insert_color(node, root);
138 * find a given root id in the tree. We return the smallest one,
139 * rb_next can be used to move forward looking for more if required
141 static struct root_info *tree_search(struct rb_root *root, u64 root_id)
143 struct rb_node * n = root->rb_node;
144 struct root_info *entry;
147 entry = rb_entry(n, struct root_info, rb_node);
149 if (entry->root_id < root_id)
151 else if (entry->root_id > root_id)
154 struct root_info *prev;
155 struct rb_node *prev_n;
160 prev = rb_entry(prev_n, struct root_info,
162 if (prev->root_id != root_id)
174 * this allocates a new root in the lookup tree.
176 * root_id should be the object id of the root
178 * ref_tree is the objectid of the referring root.
180 * dir_id is the directory in ref_tree where this root_id can be found.
182 * name is the name of root_id in that directory
184 * name_len is the length of name
186 static int add_root(struct root_lookup *root_lookup,
187 u64 root_id, u64 ref_tree, u64 dir_id, char *name,
188 int name_len, u64 *gen)
190 struct root_info *ri;
192 ri = malloc(sizeof(*ri) + name_len + 1);
194 printf("memory allocation failed\n");
197 memset(ri, 0, sizeof(*ri) + name_len + 1);
200 ri->root_id = root_id;
201 ri->ref_tree = ref_tree;
203 strncpy(ri->name, name, name_len);
205 ri->name[name_len] = 0;
209 ret = tree_insert(&root_lookup->root, root_id, ref_tree, gen,
212 printf("failed to insert tree %llu\n", (unsigned long long)root_id);
218 static int update_root(struct root_lookup *root_lookup, u64 root_id, u64 gen)
220 struct root_info *ri;
222 ri = tree_search(&root_lookup->root, root_id);
223 if (!ri || ri->root_id != root_id) {
224 fprintf(stderr, "could not find subvol %llu\n", root_id);
232 * for a given root_info, search through the root_lookup tree to construct
233 * the full path name to it.
235 * This can't be called until all the root_info->path fields are filled
236 * in by lookup_ino_path
238 static int resolve_root(struct root_lookup *rl, struct root_info *ri,
239 u64 *parent_id, u64 *top_id, char **path)
241 char *full_path = NULL;
243 struct root_info *found;
246 * we go backwards from the root_info object and add pathnames
247 * from parent directories as we go.
254 int add_len = strlen(found->path);
256 /* room for / and for null */
257 tmp = malloc(add_len + 2 + len);
259 memcpy(tmp + add_len + 1, full_path, len);
261 memcpy(tmp, found->path, add_len);
262 tmp [add_len + len + 1] = '\0';
267 full_path = strdup(found->path);
271 next = found->ref_tree;
272 /* record the first parent */
276 /* if the ref_tree refers to ourselves, we're at the top */
277 if (next == found->root_id) {
283 * if the ref_tree wasn't in our tree of roots, we're
286 found = tree_search(&rl->root, next);
299 * for a single root_info, ask the kernel to give us a path name
300 * inside it's ref_root for the dir_id where it lives.
302 * This fills in root_info->path with the path to the directory and and
303 * appends this root's name.
305 static int lookup_ino_path(int fd, struct root_info *ri)
307 struct btrfs_ioctl_ino_lookup_args args;
313 memset(&args, 0, sizeof(args));
314 args.treeid = ri->ref_tree;
315 args.objectid = ri->dir_id;
317 ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args);
320 fprintf(stderr, "ERROR: Failed to lookup path for root %llu - %s\n",
321 (unsigned long long)ri->ref_tree,
328 * we're in a subdirectory of ref_tree, the kernel ioctl
329 * puts a / in there for us
331 ri->path = malloc(strlen(ri->name) + strlen(args.name) + 1);
333 perror("malloc failed");
336 strcpy(ri->path, args.name);
337 strcat(ri->path, ri->name);
339 /* we're at the root of ref_tree */
340 ri->path = strdup(ri->name);
342 perror("strdup failed");
349 /* finding the generation for a given path is a two step process.
350 * First we use the inode loookup routine to find out the root id
352 * Then we use the tree search ioctl to scan all the root items for a
353 * given root id and spit out the latest generation we can find
355 static u64 find_root_gen(int fd)
357 struct btrfs_ioctl_ino_lookup_args ino_args;
359 struct btrfs_ioctl_search_args args;
360 struct btrfs_ioctl_search_key *sk = &args.key;
361 struct btrfs_ioctl_search_header *sh;
362 unsigned long off = 0;
367 memset(&ino_args, 0, sizeof(ino_args));
368 ino_args.objectid = BTRFS_FIRST_FREE_OBJECTID;
370 /* this ioctl fills in ino_args->treeid */
371 ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &ino_args);
374 fprintf(stderr, "ERROR: Failed to lookup path for dirid %llu - %s\n",
375 (unsigned long long)BTRFS_FIRST_FREE_OBJECTID,
380 memset(&args, 0, sizeof(args));
385 * there may be more than one ROOT_ITEM key if there are
386 * snapshots pending deletion, we have to loop through
389 sk->min_objectid = ino_args.treeid;
390 sk->max_objectid = ino_args.treeid;
391 sk->max_type = BTRFS_ROOT_ITEM_KEY;
392 sk->min_type = BTRFS_ROOT_ITEM_KEY;
393 sk->max_offset = (u64)-1;
394 sk->max_transid = (u64)-1;
398 ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
401 fprintf(stderr, "ERROR: can't perform the search - %s\n",
405 /* the ioctl returns the number of item it found in nr_items */
406 if (sk->nr_items == 0)
410 for (i = 0; i < sk->nr_items; i++) {
411 struct btrfs_root_item *item;
412 sh = (struct btrfs_ioctl_search_header *)(args.buf +
416 item = (struct btrfs_root_item *)(args.buf + off);
419 sk->min_objectid = sh->objectid;
420 sk->min_type = sh->type;
421 sk->min_offset = sh->offset;
423 if (sh->objectid > ino_args.treeid)
426 if (sh->objectid == ino_args.treeid &&
427 sh->type == BTRFS_ROOT_ITEM_KEY) {
428 max_found = max(max_found,
429 btrfs_root_generation(item));
432 if (sk->min_offset < (u64)-1)
437 if (sk->min_type != BTRFS_ROOT_ITEM_KEY)
439 if (sk->min_objectid != BTRFS_ROOT_ITEM_KEY)
445 /* pass in a directory id and this will return
446 * the full path of the parent directory inside its
449 * It may return NULL if it is in the root, or an ERR_PTR if things
452 static char *__ino_resolve(int fd, u64 dirid)
454 struct btrfs_ioctl_ino_lookup_args args;
459 memset(&args, 0, sizeof(args));
460 args.objectid = dirid;
462 ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args);
465 fprintf(stderr, "ERROR: Failed to lookup path for dirid %llu - %s\n",
466 (unsigned long long)dirid, strerror(e) );
472 * we're in a subdirectory of ref_tree, the kernel ioctl
473 * puts a / in there for us
475 full = strdup(args.name);
477 perror("malloc failed");
478 return ERR_PTR(-ENOMEM);
481 /* we're at the root of ref_tree */
488 * simple string builder, returning a new string with both
491 char *build_name(char *dirid, char *name)
497 full = malloc(strlen(dirid) + strlen(name) + 1);
506 * given an inode number, this returns the full path name inside the subvolume
507 * to that file/directory. cache_dirid and cache_name are used to
508 * cache the results so we can avoid tree searches if a later call goes
509 * to the same directory or file name
511 static char *ino_resolve(int fd, u64 ino, u64 *cache_dirid, char **cache_name)
519 struct btrfs_ioctl_search_args args;
520 struct btrfs_ioctl_search_key *sk = &args.key;
521 struct btrfs_ioctl_search_header *sh;
522 unsigned long off = 0;
526 memset(&args, 0, sizeof(args));
531 * step one, we search for the inode back ref. We just use the first
534 sk->min_objectid = ino;
535 sk->max_objectid = ino;
536 sk->max_type = BTRFS_INODE_REF_KEY;
537 sk->max_offset = (u64)-1;
538 sk->min_type = BTRFS_INODE_REF_KEY;
539 sk->max_transid = (u64)-1;
542 ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
545 fprintf(stderr, "ERROR: can't perform the search - %s\n",
549 /* the ioctl returns the number of item it found in nr_items */
550 if (sk->nr_items == 0)
554 sh = (struct btrfs_ioctl_search_header *)(args.buf + off);
556 if (sh->type == BTRFS_INODE_REF_KEY) {
557 struct btrfs_inode_ref *ref;
560 ref = (struct btrfs_inode_ref *)(sh + 1);
561 namelen = btrfs_stack_inode_ref_name_len(ref);
563 name = (char *)(ref + 1);
564 name = strndup(name, namelen);
566 /* use our cached value */
567 if (dirid == *cache_dirid && *cache_name) {
568 dirname = *cache_name;
575 * the inode backref gives us the file name and the parent directory id.
576 * From here we use __ino_resolve to get the path to the parent
578 dirname = __ino_resolve(fd, dirid);
580 full = build_name(dirname, name);
581 if (*cache_name && dirname != *cache_name)
584 *cache_name = dirname;
585 *cache_dirid = dirid;
591 static int get_default_subvolid(int fd, u64 *default_id)
593 struct btrfs_ioctl_search_args args;
594 struct btrfs_ioctl_search_key *sk = &args.key;
595 struct btrfs_ioctl_search_header *sh;
599 memset(&args, 0, sizeof(args));
602 * search for a dir item with a name 'default' in the tree of
603 * tree roots, it should point us to a default root
607 /* don't worry about ancient format and request only one item */
610 sk->max_objectid = BTRFS_ROOT_TREE_DIR_OBJECTID;
611 sk->min_objectid = BTRFS_ROOT_TREE_DIR_OBJECTID;
612 sk->max_type = BTRFS_DIR_ITEM_KEY;
613 sk->min_type = BTRFS_DIR_ITEM_KEY;
614 sk->max_offset = (u64)-1;
615 sk->max_transid = (u64)-1;
617 ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
621 /* the ioctl returns the number of items it found in nr_items */
622 if (sk->nr_items == 0)
625 sh = (struct btrfs_ioctl_search_header *)args.buf;
627 if (sh->type == BTRFS_DIR_ITEM_KEY) {
628 struct btrfs_dir_item *di;
632 di = (struct btrfs_dir_item *)(sh + 1);
633 name_len = btrfs_stack_dir_name_len(di);
634 name = (char *)(di + 1);
636 if (!strncmp("default", name, name_len))
637 found = btrfs_disk_key_objectid(&di->location);
645 static int __list_subvol_search(int fd, struct root_lookup *root_lookup)
648 struct btrfs_ioctl_search_args args;
649 struct btrfs_ioctl_search_key *sk = &args.key;
650 struct btrfs_ioctl_search_header *sh;
651 struct btrfs_root_ref *ref;
652 struct btrfs_root_item *ri;
653 unsigned long off = 0;
662 root_lookup_init(root_lookup);
663 memset(&args, 0, sizeof(args));
665 /* search in the tree of tree roots */
669 * set the min and max to backref keys. The search will
670 * only send back this type of key now.
672 sk->max_type = BTRFS_ROOT_BACKREF_KEY;
673 sk->min_type = BTRFS_ROOT_BACKREF_KEY;
675 sk->min_objectid = BTRFS_FIRST_FREE_OBJECTID;
678 * set all the other params to the max, we'll take any objectid
681 sk->max_objectid = BTRFS_LAST_FREE_OBJECTID;
682 sk->max_offset = (u64)-1;
683 sk->max_transid = (u64)-1;
686 /* just a big number, doesn't matter much */
690 ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
693 /* the ioctl returns the number of item it found in nr_items */
694 if (sk->nr_items == 0)
700 * for each item, pull the key out of the header and then
701 * read the root_ref item it contains
703 for (i = 0; i < sk->nr_items; i++) {
704 sh = (struct btrfs_ioctl_search_header *)(args.buf +
707 if (!get_gen && sh->type == BTRFS_ROOT_BACKREF_KEY) {
708 ref = (struct btrfs_root_ref *)(args.buf + off);
709 name_len = btrfs_stack_root_ref_name_len(ref);
710 name = (char *)(ref + 1);
711 dir_id = btrfs_stack_root_ref_dirid(ref);
713 add_root(root_lookup, sh->objectid, sh->offset,
714 dir_id, name, name_len, NULL);
715 } else if (get_gen && sh->type == BTRFS_ROOT_ITEM_KEY) {
716 ri = (struct btrfs_root_item *)(args.buf + off);
717 gen = btrfs_root_generation(ri);
719 update_root(root_lookup, sh->objectid, gen);
725 * record the mins in sk so we can make sure the
726 * next search doesn't repeat this root
728 sk->min_objectid = sh->objectid;
729 sk->min_type = sh->type;
730 sk->min_offset = sh->offset;
733 /* this iteration is done, step forward one root for the next
737 type = BTRFS_ROOT_ITEM_KEY;
739 type = BTRFS_ROOT_BACKREF_KEY;
741 if (sk->min_type < type) {
744 } else if (sk->min_objectid < BTRFS_LAST_FREE_OBJECTID) {
753 memset(&args, 0, sizeof(args));
756 sk->max_type = BTRFS_ROOT_ITEM_KEY;
757 sk->min_type = BTRFS_ROOT_ITEM_KEY;
759 sk->min_objectid = BTRFS_FIRST_FREE_OBJECTID;
761 sk->max_objectid = BTRFS_LAST_FREE_OBJECTID;
762 sk->max_offset = (u64)-1;
763 sk->max_transid = (u64)-1;
771 static int __list_snapshot_search(int fd, struct root_lookup *root_lookup)
774 struct btrfs_ioctl_search_args args;
775 struct btrfs_ioctl_search_key *sk = &args.key;
776 struct btrfs_ioctl_search_header *sh;
777 unsigned long off = 0;
781 root_lookup_init(root_lookup);
782 memset(&args, 0, sizeof(args));
785 sk->max_type = BTRFS_ROOT_ITEM_KEY;
786 sk->min_type = BTRFS_ROOT_ITEM_KEY;
787 sk->min_objectid = BTRFS_FIRST_FREE_OBJECTID;
788 sk->max_objectid = BTRFS_LAST_FREE_OBJECTID;
789 sk->max_offset = (u64)-1;
790 sk->max_transid = (u64)-1;
794 ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
797 /* the ioctl returns the number of item it found in nr_items */
798 if (sk->nr_items == 0)
804 * for each item, pull the key out of the header and then
805 * read the root_ref item it contains
807 for (i = 0; i < sk->nr_items; i++) {
808 sh = (struct btrfs_ioctl_search_header *)(args.buf +
811 if (sh->type == BTRFS_ROOT_ITEM_KEY && sh->offset) {
814 add_root(root_lookup, sh->objectid, 0,
820 * record the mins in sk so we can make sure the
821 * next search doesn't repeat this root
823 sk->min_objectid = sh->objectid;
824 sk->min_type = sh->type;
825 sk->min_offset = sh->offset;
828 /* this iteration is done, step forward one root for the next
831 if (sk->min_type < BTRFS_ROOT_ITEM_KEY) {
832 sk->min_type = BTRFS_ROOT_ITEM_KEY;
834 } else if (sk->min_objectid < BTRFS_LAST_FREE_OBJECTID) {
836 sk->min_type = BTRFS_ROOT_ITEM_KEY;
844 static int __list_subvol_fill_paths(int fd, struct root_lookup *root_lookup)
848 n = rb_first(&root_lookup->root);
850 struct root_info *entry;
852 entry = rb_entry(n, struct root_info, rb_node);
853 ret = lookup_ino_path(fd, entry);
862 int list_subvols(int fd, int print_parent, int get_default)
864 struct root_lookup root_lookup;
870 ret = get_default_subvolid(fd, &default_id);
872 fprintf(stderr, "ERROR: can't perform the search - %s\n",
876 if (default_id == 0) {
877 fprintf(stderr, "ERROR: 'default' dir item not found\n");
881 /* no need to resolve roots if FS_TREE is default */
882 if (default_id == BTRFS_FS_TREE_OBJECTID) {
883 printf("ID 5 (FS_TREE)\n");
888 ret = __list_subvol_search(fd, &root_lookup);
890 fprintf(stderr, "ERROR: can't perform the search - %s\n",
896 * now we have an rbtree full of root_info objects, but we need to fill
897 * in their path names within the subvol that is referencing each one.
899 ret = __list_subvol_fill_paths(fd, &root_lookup);
903 /* now that we have all the subvol-relative paths filled in,
904 * we have to string the subvols together so that we can get
905 * a path all the way back to the FS root
907 n = rb_last(&root_lookup.root);
909 struct root_info *entry;
914 entry = rb_entry(n, struct root_info, rb_node);
915 if (get_default && entry->root_id != default_id) {
920 resolve_root(&root_lookup, entry, &parent_id, &level, &path);
922 printf("ID %llu gen %llu parent %llu top level %llu path %s\n",
923 (unsigned long long)entry->root_id,
924 (unsigned long long)entry->gen,
925 (unsigned long long)parent_id,
926 (unsigned long long)level, path);
928 printf("ID %llu gen %llu top level %llu path %s\n",
929 (unsigned long long)entry->root_id,
930 (unsigned long long)entry->gen,
931 (unsigned long long)level, path);
941 int list_snapshots(int fd, int print_parent, int order)
943 struct root_lookup root_lookup;
944 struct root_lookup root_lookup_snap;
948 ret = __list_snapshot_search(fd, &root_lookup_snap);
950 fprintf(stderr, "ERROR: can't perform the search - %s\n",
955 ret = __list_subvol_search(fd, &root_lookup);
957 fprintf(stderr, "ERROR: can't perform the search - %s\n",
963 * now we have an rbtree full of root_info objects, but we need to fill
964 * in their path names within the subvol that is referencing each one.
966 ret = __list_subvol_fill_paths(fd, &root_lookup);
970 /* now that we have all the subvol-relative paths filled in,
971 * we have to string the subvols together so that we can get
972 * a path all the way back to the FS root
975 n = rb_last(&root_lookup_snap.root);
977 n = rb_first(&root_lookup_snap.root);
979 struct root_info *entry_snap;
980 struct root_info *entry;
985 entry_snap = rb_entry(n, struct root_info, rb_node);
986 entry = tree_search(&root_lookup.root, entry_snap->root_id);
988 resolve_root(&root_lookup, entry, &parent_id, &level, &path);
990 printf("ID %llu gen %llu cgen %llu parent %llu top level %llu path %s\n",
991 (unsigned long long)entry->root_id,
992 (unsigned long long)entry->gen,
993 (unsigned long long)entry_snap->gen,
994 (unsigned long long)parent_id,
995 (unsigned long long)level, path);
997 printf("ID %llu gen %llu cgen %llu top level %llu path %s\n",
998 (unsigned long long)entry->root_id,
999 (unsigned long long)entry->gen,
1000 (unsigned long long)entry_snap->gen,
1001 (unsigned long long)level, path);
1014 static int print_one_extent(int fd, struct btrfs_ioctl_search_header *sh,
1015 struct btrfs_file_extent_item *item,
1016 u64 found_gen, u64 *cache_dirid,
1017 char **cache_dir_name, u64 *cache_ino,
1018 char **cache_full_name)
1022 u64 disk_offset = 0;
1028 if (sh->objectid == *cache_ino) {
1029 name = *cache_full_name;
1030 } else if (*cache_full_name) {
1031 free(*cache_full_name);
1032 *cache_full_name = NULL;
1035 name = ino_resolve(fd, sh->objectid, cache_dirid,
1037 *cache_full_name = name;
1038 *cache_ino = sh->objectid;
1043 type = btrfs_stack_file_extent_type(item);
1044 compressed = btrfs_stack_file_extent_compression(item);
1046 if (type == BTRFS_FILE_EXTENT_REG ||
1047 type == BTRFS_FILE_EXTENT_PREALLOC) {
1048 disk_start = btrfs_stack_file_extent_disk_bytenr(item);
1049 disk_offset = btrfs_stack_file_extent_offset(item);
1050 len = btrfs_stack_file_extent_num_bytes(item);
1051 } else if (type == BTRFS_FILE_EXTENT_INLINE) {
1054 len = btrfs_stack_file_extent_ram_bytes(item);
1056 printf("unhandled extent type %d for inode %llu "
1057 "file offset %llu gen %llu\n",
1059 (unsigned long long)sh->objectid,
1060 (unsigned long long)sh->offset,
1061 (unsigned long long)found_gen);
1065 printf("inode %llu file offset %llu len %llu disk start %llu "
1066 "offset %llu gen %llu flags ",
1067 (unsigned long long)sh->objectid,
1068 (unsigned long long)sh->offset,
1069 (unsigned long long)len,
1070 (unsigned long long)disk_start,
1071 (unsigned long long)disk_offset,
1072 (unsigned long long)found_gen);
1078 if (type == BTRFS_FILE_EXTENT_PREALLOC) {
1079 printf("%sPREALLOC", flags ? "|" : "");
1082 if (type == BTRFS_FILE_EXTENT_INLINE) {
1083 printf("%sINLINE", flags ? "|" : "");
1089 printf(" %s\n", name);
1093 int find_updated_files(int fd, u64 root_id, u64 oldest_gen)
1096 struct btrfs_ioctl_search_args args;
1097 struct btrfs_ioctl_search_key *sk = &args.key;
1098 struct btrfs_ioctl_search_header *sh;
1099 struct btrfs_file_extent_item *item;
1100 unsigned long off = 0;
1105 u64 cache_dirid = 0;
1107 char *cache_dir_name = NULL;
1108 char *cache_full_name = NULL;
1109 struct btrfs_file_extent_item backup;
1111 memset(&backup, 0, sizeof(backup));
1112 memset(&args, 0, sizeof(args));
1114 sk->tree_id = root_id;
1117 * set all the other params to the max, we'll take any objectid
1120 sk->max_objectid = (u64)-1;
1121 sk->max_offset = (u64)-1;
1122 sk->max_transid = (u64)-1;
1123 sk->max_type = BTRFS_EXTENT_DATA_KEY;
1124 sk->min_transid = oldest_gen;
1125 /* just a big number, doesn't matter much */
1126 sk->nr_items = 4096;
1128 max_found = find_root_gen(fd);
1130 ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
1133 fprintf(stderr, "ERROR: can't perform the search- %s\n",
1137 /* the ioctl returns the number of item it found in nr_items */
1138 if (sk->nr_items == 0)
1144 * for each item, pull the key out of the header and then
1145 * read the root_ref item it contains
1147 for (i = 0; i < sk->nr_items; i++) {
1148 sh = (struct btrfs_ioctl_search_header *)(args.buf +
1153 * just in case the item was too big, pass something other
1159 item = (struct btrfs_file_extent_item *)(args.buf +
1161 found_gen = btrfs_stack_file_extent_generation(item);
1162 if (sh->type == BTRFS_EXTENT_DATA_KEY &&
1163 found_gen >= oldest_gen) {
1164 print_one_extent(fd, sh, item, found_gen,
1165 &cache_dirid, &cache_dir_name,
1166 &cache_ino, &cache_full_name);
1171 * record the mins in sk so we can make sure the
1172 * next search doesn't repeat this root
1174 sk->min_objectid = sh->objectid;
1175 sk->min_offset = sh->offset;
1176 sk->min_type = sh->type;
1178 sk->nr_items = 4096;
1179 if (sk->min_offset < (u64)-1)
1181 else if (sk->min_objectid < (u64)-1) {
1188 free(cache_dir_name);
1189 free(cache_full_name);
1190 printf("transid marker was %llu\n", (unsigned long long)max_found);
1194 char *path_for_root(int fd, u64 root)
1196 struct root_lookup root_lookup;
1198 char *ret_path = NULL;
1201 ret = __list_subvol_search(fd, &root_lookup);
1203 return ERR_PTR(ret);
1205 ret = __list_subvol_fill_paths(fd, &root_lookup);
1207 return ERR_PTR(ret);
1209 n = rb_last(&root_lookup.root);
1211 struct root_info *entry;
1216 entry = rb_entry(n, struct root_info, rb_node);
1217 resolve_root(&root_lookup, entry, &parent_id, &level, &path);
1218 if (entry->root_id == root)