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"
39 /* we store all the roots we find in an rbtree so that we can
40 * search for them later.
47 * one of these for each root we find.
50 struct rb_node rb_node;
55 /* the id of the root that references this one */
58 /* the dir id we're in from ref_tree */
61 /* path from the subvol we live in to this root, including the
62 * root's name. This is null until we do the extra lookup ioctl.
66 /* the name of this root in the directory it lives in */
70 static void root_lookup_init(struct root_lookup *tree)
72 tree->root.rb_node = NULL;
75 static int comp_entry(struct root_info *entry, u64 root_id, u64 ref_tree)
77 if (entry->root_id > root_id)
79 if (entry->root_id < root_id)
81 if (entry->ref_tree > ref_tree)
83 if (entry->ref_tree < ref_tree)
89 * insert a new root into the tree. returns the existing root entry
90 * if one is already there. Both root_id and ref_tree are used
93 static struct rb_node *tree_insert(struct rb_root *root, u64 root_id,
94 u64 ref_tree, struct rb_node *node)
96 struct rb_node ** p = &root->rb_node;
97 struct rb_node * parent = NULL;
98 struct root_info *entry;
103 entry = rb_entry(parent, struct root_info, rb_node);
105 comp = comp_entry(entry, root_id, ref_tree);
115 entry = rb_entry(parent, struct root_info, rb_node);
116 rb_link_node(node, parent, p);
117 rb_insert_color(node, root);
122 * find a given root id in the tree. We return the smallest one,
123 * rb_next can be used to move forward looking for more if required
125 static struct root_info *tree_search(struct rb_root *root, u64 root_id)
127 struct rb_node * n = root->rb_node;
128 struct root_info *entry;
131 entry = rb_entry(n, struct root_info, rb_node);
133 if (entry->root_id < root_id)
135 else if (entry->root_id > root_id)
138 struct root_info *prev;
139 struct rb_node *prev_n;
144 prev = rb_entry(prev_n, struct root_info,
146 if (prev->root_id != root_id)
158 * this allocates a new root in the lookup tree.
160 * root_id should be the object id of the root
162 * ref_tree is the objectid of the referring root.
164 * dir_id is the directory in ref_tree where this root_id can be found.
166 * name is the name of root_id in that directory
168 * name_len is the length of name
170 static int add_root(struct root_lookup *root_lookup,
171 u64 root_id, u64 ref_tree, u64 dir_id, char *name,
174 struct root_info *ri;
176 ri = malloc(sizeof(*ri) + name_len + 1);
178 printf("memory allocation failed\n");
181 memset(ri, 0, sizeof(*ri) + name_len + 1);
184 ri->root_id = root_id;
185 ri->ref_tree = ref_tree;
186 strncpy(ri->name, name, name_len);
188 ret = tree_insert(&root_lookup->root, root_id, ref_tree, &ri->rb_node);
190 printf("failed to insert tree %llu\n", (unsigned long long)root_id);
197 * for a given root_info, search through the root_lookup tree to construct
198 * the full path name to it.
200 * This can't be called until all the root_info->path fields are filled
201 * in by lookup_ino_path
203 static int resolve_root(struct root_lookup *rl, struct root_info *ri, int print_parent)
207 char *full_path = NULL;
209 struct root_info *found;
212 * we go backwards from the root_info object and add pathnames
213 * from parent directories as we go.
219 int add_len = strlen(found->path);
221 /* room for / and for null */
222 tmp = malloc(add_len + 2 + len);
224 memcpy(tmp + add_len + 1, full_path, len);
226 memcpy(tmp, found->path, add_len);
227 tmp [add_len + len + 1] = '\0';
232 full_path = strdup(found->path);
236 next = found->ref_tree;
237 /* record the first parent */
238 if ( parent_id == 0 ) {
242 /* if the ref_tree refers to ourselves, we're at the top */
243 if (next == found->root_id) {
249 * if the ref_tree wasn't in our tree of roots, we're
252 found = tree_search(&rl->root, next);
259 printf("ID %llu parent %llu top level %llu path %s\n",
260 (unsigned long long)ri->root_id, (unsigned long long)parent_id, (unsigned long long)top_id,
263 printf("ID %llu top level %llu path %s\n",
264 (unsigned long long)ri->root_id, (unsigned long long)top_id,
272 * for a single root_info, ask the kernel to give us a path name
273 * inside it's ref_root for the dir_id where it lives.
275 * This fills in root_info->path with the path to the directory and and
276 * appends this root's name.
278 static int lookup_ino_path(int fd, struct root_info *ri)
280 struct btrfs_ioctl_ino_lookup_args args;
286 memset(&args, 0, sizeof(args));
287 args.treeid = ri->ref_tree;
288 args.objectid = ri->dir_id;
290 ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args);
293 fprintf(stderr, "ERROR: Failed to lookup path for root %llu - %s\n",
294 (unsigned long long)ri->ref_tree,
301 * we're in a subdirectory of ref_tree, the kernel ioctl
302 * puts a / in there for us
304 ri->path = malloc(strlen(ri->name) + strlen(args.name) + 1);
306 perror("malloc failed");
309 strcpy(ri->path, args.name);
310 strcat(ri->path, ri->name);
312 /* we're at the root of ref_tree */
313 ri->path = strdup(ri->name);
315 perror("strdup failed");
322 /* finding the generation for a given path is a two step process.
323 * First we use the inode loookup routine to find out the root id
325 * Then we use the tree search ioctl to scan all the root items for a
326 * given root id and spit out the latest generation we can find
328 static u64 find_root_gen(int fd)
330 struct btrfs_ioctl_ino_lookup_args ino_args;
332 struct btrfs_ioctl_search_args args;
333 struct btrfs_ioctl_search_key *sk = &args.key;
334 struct btrfs_ioctl_search_header *sh;
335 unsigned long off = 0;
340 memset(&ino_args, 0, sizeof(ino_args));
341 ino_args.objectid = BTRFS_FIRST_FREE_OBJECTID;
343 /* this ioctl fills in ino_args->treeid */
344 ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &ino_args);
347 fprintf(stderr, "ERROR: Failed to lookup path for dirid %llu - %s\n",
348 (unsigned long long)BTRFS_FIRST_FREE_OBJECTID,
353 memset(&args, 0, sizeof(args));
358 * there may be more than one ROOT_ITEM key if there are
359 * snapshots pending deletion, we have to loop through
362 sk->min_objectid = ino_args.treeid;
363 sk->max_objectid = ino_args.treeid;
364 sk->max_type = BTRFS_ROOT_ITEM_KEY;
365 sk->min_type = BTRFS_ROOT_ITEM_KEY;
366 sk->max_offset = (u64)-1;
367 sk->max_transid = (u64)-1;
371 ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
374 fprintf(stderr, "ERROR: can't perform the search - %s\n",
378 /* the ioctl returns the number of item it found in nr_items */
379 if (sk->nr_items == 0)
383 for (i = 0; i < sk->nr_items; i++) {
384 struct btrfs_root_item *item;
385 sh = (struct btrfs_ioctl_search_header *)(args.buf +
389 item = (struct btrfs_root_item *)(args.buf + off);
392 sk->min_objectid = sh->objectid;
393 sk->min_type = sh->type;
394 sk->min_offset = sh->offset;
396 if (sh->objectid > ino_args.treeid)
399 if (sh->objectid == ino_args.treeid &&
400 sh->type == BTRFS_ROOT_ITEM_KEY) {
401 max_found = max(max_found,
402 btrfs_root_generation(item));
405 if (sk->min_offset < (u64)-1)
410 if (sk->min_type != BTRFS_ROOT_ITEM_KEY)
412 if (sk->min_objectid != BTRFS_ROOT_ITEM_KEY)
418 /* pass in a directory id and this will return
419 * the full path of the parent directory inside its
422 * It may return NULL if it is in the root, or an ERR_PTR if things
425 static char *__ino_resolve(int fd, u64 dirid)
427 struct btrfs_ioctl_ino_lookup_args args;
432 memset(&args, 0, sizeof(args));
433 args.objectid = dirid;
435 ret = ioctl(fd, BTRFS_IOC_INO_LOOKUP, &args);
438 fprintf(stderr, "ERROR: Failed to lookup path for dirid %llu - %s\n",
439 (unsigned long long)dirid, strerror(e) );
445 * we're in a subdirectory of ref_tree, the kernel ioctl
446 * puts a / in there for us
448 full = strdup(args.name);
450 perror("malloc failed");
451 return ERR_PTR(-ENOMEM);
454 /* we're at the root of ref_tree */
461 * simple string builder, returning a new string with both
464 char *build_name(char *dirid, char *name)
470 full = malloc(strlen(dirid) + strlen(name) + 1);
479 * given an inode number, this returns the full path name inside the subvolume
480 * to that file/directory. cache_dirid and cache_name are used to
481 * cache the results so we can avoid tree searches if a later call goes
482 * to the same directory or file name
484 static char *ino_resolve(int fd, u64 ino, u64 *cache_dirid, char **cache_name)
492 struct btrfs_ioctl_search_args args;
493 struct btrfs_ioctl_search_key *sk = &args.key;
494 struct btrfs_ioctl_search_header *sh;
495 unsigned long off = 0;
499 memset(&args, 0, sizeof(args));
504 * step one, we search for the inode back ref. We just use the first
507 sk->min_objectid = ino;
508 sk->max_objectid = ino;
509 sk->max_type = BTRFS_INODE_REF_KEY;
510 sk->max_offset = (u64)-1;
511 sk->min_type = BTRFS_INODE_REF_KEY;
512 sk->max_transid = (u64)-1;
515 ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
518 fprintf(stderr, "ERROR: can't perform the search - %s\n",
522 /* the ioctl returns the number of item it found in nr_items */
523 if (sk->nr_items == 0)
527 sh = (struct btrfs_ioctl_search_header *)(args.buf + off);
529 if (sh->type == BTRFS_INODE_REF_KEY) {
530 struct btrfs_inode_ref *ref;
533 ref = (struct btrfs_inode_ref *)(sh + 1);
534 namelen = btrfs_stack_inode_ref_name_len(ref);
536 name = (char *)(ref + 1);
537 name = strndup(name, namelen);
539 /* use our cached value */
540 if (dirid == *cache_dirid && *cache_name) {
541 dirname = *cache_name;
548 * the inode backref gives us the file name and the parent directory id.
549 * From here we use __ino_resolve to get the path to the parent
551 dirname = __ino_resolve(fd, dirid);
553 full = build_name(dirname, name);
554 if (*cache_name && dirname != *cache_name)
557 *cache_name = dirname;
558 *cache_dirid = dirid;
564 int list_subvols(int fd, int print_parent)
566 struct root_lookup root_lookup;
569 struct btrfs_ioctl_search_args args;
570 struct btrfs_ioctl_search_key *sk = &args.key;
571 struct btrfs_ioctl_search_header *sh;
572 struct btrfs_root_ref *ref;
573 unsigned long off = 0;
580 root_lookup_init(&root_lookup);
582 memset(&args, 0, sizeof(args));
584 /* search in the tree of tree roots */
588 * set the min and max to backref keys. The search will
589 * only send back this type of key now.
591 sk->max_type = BTRFS_ROOT_BACKREF_KEY;
592 sk->min_type = BTRFS_ROOT_BACKREF_KEY;
595 * set all the other params to the max, we'll take any objectid
598 sk->max_objectid = (u64)-1;
599 sk->max_offset = (u64)-1;
600 sk->max_transid = (u64)-1;
602 /* just a big number, doesn't matter much */
606 ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
609 fprintf(stderr, "ERROR: can't perform the search - %s\n",
613 /* the ioctl returns the number of item it found in nr_items */
614 if (sk->nr_items == 0)
620 * for each item, pull the key out of the header and then
621 * read the root_ref item it contains
623 for (i = 0; i < sk->nr_items; i++) {
624 sh = (struct btrfs_ioctl_search_header *)(args.buf +
627 if (sh->type == BTRFS_ROOT_BACKREF_KEY) {
628 ref = (struct btrfs_root_ref *)(args.buf + off);
629 name_len = btrfs_stack_root_ref_name_len(ref);
630 name = (char *)(ref + 1);
631 dir_id = btrfs_stack_root_ref_dirid(ref);
633 add_root(&root_lookup, sh->objectid, sh->offset,
634 dir_id, name, name_len);
640 * record the mins in sk so we can make sure the
641 * next search doesn't repeat this root
643 sk->min_objectid = sh->objectid;
644 sk->min_type = sh->type;
645 sk->min_offset = sh->offset;
648 /* this iteration is done, step forward one root for the next
651 if (sk->min_objectid < (u64)-1) {
653 sk->min_type = BTRFS_ROOT_BACKREF_KEY;
659 * now we have an rbtree full of root_info objects, but we need to fill
660 * in their path names within the subvol that is referencing each one.
662 n = rb_first(&root_lookup.root);
664 struct root_info *entry;
666 entry = rb_entry(n, struct root_info, rb_node);
667 ret = lookup_ino_path(fd, entry);
673 /* now that we have all the subvol-relative paths filled in,
674 * we have to string the subvols together so that we can get
675 * a path all the way back to the FS root
677 n = rb_last(&root_lookup.root);
679 struct root_info *entry;
680 entry = rb_entry(n, struct root_info, rb_node);
681 resolve_root(&root_lookup, entry, print_parent);
688 static int print_one_extent(int fd, struct btrfs_ioctl_search_header *sh,
689 struct btrfs_file_extent_item *item,
690 u64 found_gen, u64 *cache_dirid,
691 char **cache_dir_name, u64 *cache_ino,
692 char **cache_full_name)
702 if (sh->objectid == *cache_ino) {
703 name = *cache_full_name;
704 } else if (*cache_full_name) {
705 free(*cache_full_name);
706 *cache_full_name = NULL;
709 name = ino_resolve(fd, sh->objectid, cache_dirid,
711 *cache_full_name = name;
712 *cache_ino = sh->objectid;
717 type = btrfs_stack_file_extent_type(item);
718 compressed = btrfs_stack_file_extent_compression(item);
720 if (type == BTRFS_FILE_EXTENT_REG ||
721 type == BTRFS_FILE_EXTENT_PREALLOC) {
722 disk_start = btrfs_stack_file_extent_disk_bytenr(item);
723 disk_offset = btrfs_stack_file_extent_offset(item);
724 len = btrfs_stack_file_extent_num_bytes(item);
725 } else if (type == BTRFS_FILE_EXTENT_INLINE) {
728 len = btrfs_stack_file_extent_ram_bytes(item);
730 printf("unhandled extent type %d for inode %llu "
731 "file offset %llu gen %llu\n",
733 (unsigned long long)sh->objectid,
734 (unsigned long long)sh->offset,
735 (unsigned long long)found_gen);
739 printf("inode %llu file offset %llu len %llu disk start %llu "
740 "offset %llu gen %llu flags ",
741 (unsigned long long)sh->objectid,
742 (unsigned long long)sh->offset,
743 (unsigned long long)len,
744 (unsigned long long)disk_start,
745 (unsigned long long)disk_offset,
746 (unsigned long long)found_gen);
752 if (type == BTRFS_FILE_EXTENT_PREALLOC) {
753 printf("%sPREALLOC", flags ? "|" : "");
756 if (type == BTRFS_FILE_EXTENT_INLINE) {
757 printf("%sINLINE", flags ? "|" : "");
763 printf(" %s\n", name);
767 int find_updated_files(int fd, u64 root_id, u64 oldest_gen)
770 struct btrfs_ioctl_search_args args;
771 struct btrfs_ioctl_search_key *sk = &args.key;
772 struct btrfs_ioctl_search_header *sh;
773 struct btrfs_file_extent_item *item;
774 unsigned long off = 0;
781 char *cache_dir_name = NULL;
782 char *cache_full_name = NULL;
783 struct btrfs_file_extent_item backup;
785 memset(&backup, 0, sizeof(backup));
786 memset(&args, 0, sizeof(args));
788 sk->tree_id = root_id;
791 * set all the other params to the max, we'll take any objectid
794 sk->max_objectid = (u64)-1;
795 sk->max_offset = (u64)-1;
796 sk->max_transid = (u64)-1;
797 sk->max_type = BTRFS_EXTENT_DATA_KEY;
798 sk->min_transid = oldest_gen;
799 /* just a big number, doesn't matter much */
802 max_found = find_root_gen(fd);
804 ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
807 fprintf(stderr, "ERROR: can't perform the search- %s\n",
811 /* the ioctl returns the number of item it found in nr_items */
812 if (sk->nr_items == 0)
818 * for each item, pull the key out of the header and then
819 * read the root_ref item it contains
821 for (i = 0; i < sk->nr_items; i++) {
822 sh = (struct btrfs_ioctl_search_header *)(args.buf +
827 * just in case the item was too big, pass something other
833 item = (struct btrfs_file_extent_item *)(args.buf +
835 found_gen = btrfs_stack_file_extent_generation(item);
836 if (sh->type == BTRFS_EXTENT_DATA_KEY &&
837 found_gen >= oldest_gen) {
838 print_one_extent(fd, sh, item, found_gen,
839 &cache_dirid, &cache_dir_name,
840 &cache_ino, &cache_full_name);
845 * record the mins in sk so we can make sure the
846 * next search doesn't repeat this root
848 sk->min_objectid = sh->objectid;
849 sk->min_offset = sh->offset;
850 sk->min_type = sh->type;
853 if (sk->min_offset < (u64)-1)
855 else if (sk->min_objectid < (u64)-1) {
862 free(cache_dir_name);
863 free(cache_full_name);
864 printf("transid marker was %llu\n", (unsigned long long)max_found);