diff --git a/btrfs-progs-build-fixes.patch b/btrfs-progs-build-fixes.patch index d189c5a..a78b451 100644 --- a/btrfs-progs-build-fixes.patch +++ b/btrfs-progs-build-fixes.patch @@ -1,18 +1,22 @@ ---- btrfs-progs-0.19/btrfsck.c -+++ btrfs-progs-0.19/btrfsck.c -@@ -21,6 +21,9 @@ - #include +diff --git a/btrfsck.c b/btrfsck.c +index 63e44d1..1e040c4 100644 +--- a/btrfsck.c ++++ b/btrfsck.c +@@ -22,7 +22,9 @@ #include + #include #include +#include -+#include + #include +#include #include "kerncompat.h" #include "ctree.h" #include "disk-io.h" ---- btrfs-progs-0.19/mkfs.c -+++ btrfs-progs-0.19/mkfs.c -@@ -341,7 +341,7 @@ int main(int ac, char **av) +diff --git a/mkfs.c b/mkfs.c +index 2e99b95..638f4c2 100644 +--- a/mkfs.c ++++ b/mkfs.c +@@ -348,7 +348,7 @@ int main(int ac, char **av) u64 alloc_start = 0; u64 metadata_profile = BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_DUP; u64 data_profile = BTRFS_BLOCK_GROUP_RAID0; @@ -21,7 +25,7 @@ u32 sectorsize = 4096; u32 nodesize = leafsize; u32 stripesize = 4096; -@@ -398,7 +398,7 @@ int main(int ac, char **av) +@@ -405,7 +405,7 @@ int main(int ac, char **av) print_usage(); } } diff --git a/btrfs-progs-upstream.patch b/btrfs-progs-upstream.patch index 2f41e3d..e81558f 100644 --- a/btrfs-progs-upstream.patch +++ b/btrfs-progs-upstream.patch @@ -1,5 +1,5 @@ diff --git a/Makefile b/Makefile -index 8097b5a..525676e 100644 +index 8097b5a..6e6f6c6 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CFLAGS = -g -Werror -Os @@ -33,7 +33,13 @@ index 8097b5a..525676e 100644 btrfsctl: $(objects) btrfsctl.o gcc $(CFLAGS) -o btrfsctl btrfsctl.o $(objects) $(LDFLAGS) $(LIBS) -@@ -56,6 +62,9 @@ btrfs-debug-tree: $(objects) debug-tree.o +@@ -53,9 +59,15 @@ mkfs.btrfs: $(objects) mkfs.o + btrfs-debug-tree: $(objects) debug-tree.o + gcc $(CFLAGS) -o btrfs-debug-tree $(objects) debug-tree.o $(LDFLAGS) $(LIBS) + ++btrfs-zero-log: $(objects) btrfs-zero-log.o ++ gcc $(CFLAGS) -o btrfs-zero-log $(objects) btrfs-zero-log.o $(LDFLAGS) $(LIBS) ++ btrfstune: $(objects) btrfstune.o gcc $(CFLAGS) -o btrfstune $(objects) btrfstune.o $(LDFLAGS) $(LIBS) @@ -43,16 +49,18 @@ index 8097b5a..525676e 100644 btrfs-image: $(objects) btrfs-image.o gcc $(CFLAGS) -o btrfs-image $(objects) btrfs-image.o -lpthread -lz $(LDFLAGS) $(LIBS) -@@ -68,6 +77,9 @@ quick-test: $(objects) quick-test.o - convert: $(objects) convert.o - gcc $(CFLAGS) -o btrfs-convert $(objects) convert.o -lext2fs $(LDFLAGS) $(LIBS) +@@ -66,7 +78,10 @@ quick-test: $(objects) quick-test.o + gcc $(CFLAGS) -o quick-test $(objects) quick-test.o $(LDFLAGS) $(LIBS) + convert: $(objects) convert.o +- gcc $(CFLAGS) -o btrfs-convert $(objects) convert.o -lext2fs $(LDFLAGS) $(LIBS) ++ gcc $(CFLAGS) -o btrfs-convert $(objects) convert.o -lext2fs -lcom_err $(LDFLAGS) $(LIBS) ++ +ioctl-test: $(objects) ioctl-test.o + gcc $(CFLAGS) -o ioctl-test $(objects) ioctl-test.o $(LDFLAGS) $(LIBS) -+ + manpages: cd man; make - diff --git a/btrfs-defrag.c b/btrfs-defrag.c new file mode 100644 index 0000000..8f1525a @@ -100,10 +108,10 @@ index 0000000..8f1525a + diff --git a/btrfs-list.c b/btrfs-list.c new file mode 100644 -index 0000000..7741705 +index 0000000..93766a8 --- /dev/null +++ b/btrfs-list.c -@@ -0,0 +1,825 @@ +@@ -0,0 +1,835 @@ +/* + * Copyright (C) 2010 Oracle. All rights reserved. + * @@ -122,6 +130,7 @@ index 0000000..7741705 + * Boston, MA 021110-1307, USA. + */ + ++#define _GNU_SOURCE +#ifndef __CHECKER__ +#include +#include @@ -768,9 +777,9 @@ index 0000000..7741705 + char **cache_dir_name, u64 *cache_ino, + char **cache_full_name) +{ -+ u64 len; -+ u64 disk_start; -+ u64 disk_offset; ++ u64 len = 0; ++ u64 disk_start = 0; ++ u64 disk_offset = 0; + u8 type; + int compressed = 0; + int flags = 0; @@ -803,6 +812,15 @@ index 0000000..7741705 + disk_start = 0; + disk_offset = 0; + len = btrfs_stack_file_extent_ram_bytes(item); ++ } else { ++ printf("unhandled extent type %d for inode %llu " ++ "file offset %llu gen %llu\n", ++ type, ++ (unsigned long long)sh->objectid, ++ (unsigned long long)sh->offset, ++ (unsigned long long)found_gen); ++ ++ return -EIO; + } + printf("inode %llu file offset %llu len %llu disk start %llu " + "offset %llu gen %llu flags ", @@ -1156,9 +1174,115 @@ index 0000000..a109c6a + close_ctree(root); + return ret; +} +diff --git a/btrfs-vol.c b/btrfs-vol.c +index 8069778..4ed799d 100644 +--- a/btrfs-vol.c ++++ b/btrfs-vol.c +@@ -108,10 +108,24 @@ int main(int ac, char **av) + if (device && strcmp(device, "missing") == 0 && + cmd == BTRFS_IOC_RM_DEV) { + fprintf(stderr, "removing missing devices from %s\n", mnt); +- } else if (device) { ++ } else if (cmd != BTRFS_IOC_BALANCE) { ++ if (cmd == BTRFS_IOC_ADD_DEV) { ++ ret = check_mounted(device); ++ if (ret < 0) { ++ fprintf(stderr, ++ "error checking %s mount status\n", ++ device); ++ exit(1); ++ } ++ if (ret == 1) { ++ fprintf(stderr, "%s is mounted\n", device); ++ exit(1); ++ } ++ } + devfd = open(device, O_RDWR); +- if (!devfd) { ++ if (devfd < 0) { + fprintf(stderr, "Unable to open device %s\n", device); ++ exit(1); + } + ret = fstat(devfd, &st); + if (ret) { +diff --git a/btrfs-zero-log.c b/btrfs-zero-log.c +new file mode 100644 +index 0000000..f10438b +--- /dev/null ++++ b/btrfs-zero-log.c +@@ -0,0 +1,69 @@ ++/* ++ * Copyright (C) 2007 Oracle. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public ++ * License v2 as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public ++ * License along with this program; if not, write to the ++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ * Boston, MA 021110-1307, USA. ++ */ ++ ++#define _XOPEN_SOURCE 500 ++#define _GNU_SOURCE 1 ++#include ++#include ++#include ++#include ++#include ++#include "kerncompat.h" ++#include "ctree.h" ++#include "disk-io.h" ++#include "print-tree.h" ++#include "transaction.h" ++#include "list.h" ++#include "version.h" ++#include "utils.h" ++ ++static void print_usage(void) ++{ ++ fprintf(stderr, "usage: btrfs-zero-log dev\n"); ++ fprintf(stderr, "%s\n", BTRFS_BUILD_VERSION); ++ exit(1); ++} ++ ++int main(int ac, char **av) ++{ ++ struct btrfs_root *root; ++ int ret; ++ ++ if (ac != 2) ++ print_usage(); ++ ++ radix_tree_init(); ++ ++ if((ret = check_mounted(av[1])) < 0) { ++ fprintf(stderr, "Could not check mount status: %s\n", strerror(ret)); ++ return ret; ++ } else if(ret) { ++ fprintf(stderr, "%s is currently mounted. Aborting.\n", av[1]); ++ return -EBUSY; ++ } ++ ++ root = open_ctree(av[1], 0, 1); ++ ++ if (root == NULL) ++ return 1; ++ ++ btrfs_set_super_log_root(&root->fs_info->super_copy, 0); ++ btrfs_set_super_log_root_level(&root->fs_info->super_copy, 0); ++ close_ctree(root); ++ return ret; ++} diff --git a/btrfs.c b/btrfs.c new file mode 100644 -index 0000000..ab5e57f +index 0000000..46314cf --- /dev/null +++ b/btrfs.c @@ -0,0 +1,387 @@ @@ -1178,7 +1302,7 @@ index 0000000..ab5e57f + * Boston, MA 021110-1307, USA. + */ + -+ ++#define _GNU_SOURCE +#include +#include +#include @@ -2520,10 +2644,28 @@ index 0000000..7bde191 +int find_updated_files(int fd, u64 root_id, u64 oldest_gen); +int do_find_newer(int argc, char **argv); diff --git a/btrfsck.c b/btrfsck.c -index 40c90f8..73f1836 100644 +index 40c90f8..63e44d1 100644 --- a/btrfsck.c +++ b/btrfsck.c -@@ -36,7 +36,7 @@ static u64 total_fs_tree_bytes = 0; +@@ -20,7 +20,9 @@ + #define _GNU_SOURCE 1 + #include + #include ++#include + #include ++#include + #include "kerncompat.h" + #include "ctree.h" + #include "disk-io.h" +@@ -28,6 +30,7 @@ + #include "transaction.h" + #include "list.h" + #include "version.h" ++#include "utils.h" + + static u64 bytes_used = 0; + static u64 total_csum_bytes = 0; +@@ -36,7 +39,7 @@ static u64 total_fs_tree_bytes = 0; static u64 btree_space_waste = 0; static u64 data_bytes_allocated = 0; static u64 data_bytes_referenced = 0; @@ -2532,7 +2674,7 @@ index 40c90f8..73f1836 100644 struct extent_backref { struct list_head list; -@@ -100,7 +100,11 @@ struct inode_backref { +@@ -100,7 +103,11 @@ struct inode_backref { #define REF_ERR_DUP_INODE_REF (1 << 5) #define REF_ERR_INDEX_UNMATCH (1 << 6) #define REF_ERR_FILETYPE_UNMATCH (1 << 7) @@ -2545,7 +2687,7 @@ index 40c90f8..73f1836 100644 struct inode_record { struct list_head backrefs; -@@ -144,6 +148,29 @@ struct inode_record { +@@ -144,6 +151,29 @@ struct inode_record { #define I_ERR_SOME_CSUM_MISSING (1 << 12) #define I_ERR_LINK_COUNT_WRONG (1 << 13) @@ -2575,7 +2717,7 @@ index 40c90f8..73f1836 100644 struct ptr_node { struct cache_extent cache; void *data; -@@ -151,6 +178,7 @@ struct ptr_node { +@@ -151,6 +181,7 @@ struct ptr_node { struct shared_node { struct cache_extent cache; @@ -2583,7 +2725,7 @@ index 40c90f8..73f1836 100644 struct cache_tree inode_cache; struct inode_record *current; u32 refs; -@@ -258,6 +286,14 @@ static void free_inode_rec(struct inode_record *rec) +@@ -258,6 +289,14 @@ static void free_inode_rec(struct inode_record *rec) free(rec); } @@ -2598,7 +2740,7 @@ index 40c90f8..73f1836 100644 static void maybe_free_inode_rec(struct cache_tree *inode_cache, struct inode_record *rec) { -@@ -309,8 +345,7 @@ static void maybe_free_inode_rec(struct cache_tree *inode_cache, +@@ -309,8 +348,7 @@ static void maybe_free_inode_rec(struct cache_tree *inode_cache, } BUG_ON(rec->refs != 1); @@ -2608,7 +2750,7 @@ index 40c90f8..73f1836 100644 cache = find_cache_extent(inode_cache, rec->ino, 1); node = container_of(cache, struct ptr_node, cache); BUG_ON(node->data != rec); -@@ -338,14 +373,12 @@ static int check_orphan_item(struct btrfs_root *root, u64 ino) +@@ -338,14 +376,12 @@ static int check_orphan_item(struct btrfs_root *root, u64 ino) return ret; } @@ -2624,7 +2766,7 @@ index 40c90f8..73f1836 100644 rec = active_node->current; BUG_ON(rec->ino != key->objectid || rec->refs > 1); -@@ -361,11 +394,8 @@ static int process_inode_item(struct btrfs_root *root, +@@ -361,11 +397,8 @@ static int process_inode_item(struct btrfs_root *root, if (btrfs_inode_flags(eb, item) & BTRFS_INODE_NODATASUM) rec->nodatasum = 1; rec->found_inode_item = 1; @@ -2638,7 +2780,23 @@ index 40c90f8..73f1836 100644 maybe_free_inode_rec(&active_node->inode_cache, rec); return 0; } -@@ -443,10 +473,9 @@ static int add_inode_backref(struct cache_tree *inode_cache, +@@ -391,7 +424,6 @@ static struct inode_backref *get_inode_backref(struct inode_record *rec, + memcpy(backref->name, name, namelen); + backref->name[namelen] = '\0'; + list_add_tail(&backref->list, &rec->backrefs); +- rec->found_link++; + return backref; + } + +@@ -419,6 +451,7 @@ static int add_inode_backref(struct cache_tree *inode_cache, + backref->filetype = filetype; + backref->found_dir_index = 1; + } else if (itemtype == BTRFS_DIR_ITEM_KEY) { ++ rec->found_link++; + if (backref->found_dir_item) + backref->errors |= REF_ERR_DUP_DIR_ITEM; + if (backref->found_dir_index && backref->filetype != filetype) +@@ -443,10 +476,10 @@ static int add_inode_backref(struct cache_tree *inode_cache, } static int merge_inode_recs(struct inode_record *src, struct inode_record *dst, @@ -2647,10 +2805,28 @@ index 40c90f8..73f1836 100644 { struct inode_backref *backref; - struct cache_tree *dst_cache = &dst_node->inode_cache; ++ u32 dir_count = 0; dst->merging = 1; list_for_each_entry(backref, &src->backrefs, list) { -@@ -510,14 +539,8 @@ static int merge_inode_recs(struct inode_record *src, struct inode_record *dst, +@@ -457,6 +490,7 @@ static int merge_inode_recs(struct inode_record *src, struct inode_record *dst, + BTRFS_DIR_INDEX_KEY, backref->errors); + } + if (backref->found_dir_item) { ++ dir_count++; + add_inode_backref(dst_cache, dst->ino, + backref->dir, 0, backref->name, + backref->namelen, backref->filetype, +@@ -481,6 +515,8 @@ static int merge_inode_recs(struct inode_record *src, struct inode_record *dst, + if (dst->first_extent_gap > src->first_extent_gap) + dst->first_extent_gap = src->first_extent_gap; + ++ BUG_ON(src->found_link < dir_count); ++ dst->found_link += src->found_link - dir_count; + dst->found_size += src->found_size; + if (src->extent_start != (u64)-1) { + if (dst->extent_start == (u64)-1) { +@@ -510,14 +546,8 @@ static int merge_inode_recs(struct inode_record *src, struct inode_record *dst, dst->errors |= I_ERR_DUP_INODE_ITEM; } } @@ -2666,7 +2842,7 @@ index 40c90f8..73f1836 100644 return 0; } -@@ -537,8 +560,9 @@ static int splice_shared_node(struct shared_node *src_node, +@@ -537,8 +567,9 @@ static int splice_shared_node(struct shared_node *src_node, if (src_node->current) current_ino = src_node->current->ino; @@ -2678,11 +2854,9 @@ index 40c90f8..73f1836 100644 cache = find_first_cache_extent(src, 0); while (cache) { node = container_of(cache, struct ptr_node, cache); -@@ -557,14 +581,28 @@ static int splice_shared_node(struct shared_node *src_node, - } +@@ -558,13 +589,26 @@ static int splice_shared_node(struct shared_node *src_node, ret = insert_existing_cache_extent(dst, &ins->cache); if (ret == -EEXIST) { -+ WARN_ON(src == &src_node->root_cache); conflict = get_inode_rec(dst, rec->ino, 1); - merge_inode_recs(rec, conflict, dst_node); + merge_inode_recs(rec, conflict, dst); @@ -2708,7 +2882,7 @@ index 40c90f8..73f1836 100644 if (current_ino > 0 && (!dst_node->current || current_ino > dst_node->current->ino)) { if (dst_node->current) { -@@ -616,6 +654,7 @@ static int add_shared_node(struct cache_tree *shared, u64 bytenr, u32 refs) +@@ -616,6 +660,7 @@ static int add_shared_node(struct cache_tree *shared, u64 bytenr, u32 refs) node = calloc(1, sizeof(*node)); node->cache.start = bytenr; node->cache.size = 1; @@ -2716,7 +2890,7 @@ index 40c90f8..73f1836 100644 cache_tree_init(&node->inode_cache); node->refs = refs; -@@ -646,6 +685,7 @@ static int enter_shared_node(struct btrfs_root *root, u64 bytenr, u32 refs, +@@ -646,6 +691,7 @@ static int enter_shared_node(struct btrfs_root *root, u64 bytenr, u32 refs, if (wc->root_level == wc->active_node && btrfs_root_refs(&root->root_item) == 0) { if (--node->refs == 0) { @@ -2724,7 +2898,7 @@ index 40c90f8..73f1836 100644 free_inode_recs(&node->inode_cache); remove_cache_extent(&wc->shared, &node->cache); free(node); -@@ -708,10 +748,12 @@ static int process_dir_item(struct extent_buffer *eb, +@@ -708,10 +754,12 @@ static int process_dir_item(struct extent_buffer *eb, int filetype; struct btrfs_dir_item *di; struct inode_record *rec; @@ -2737,7 +2911,7 @@ index 40c90f8..73f1836 100644 inode_cache = &active_node->inode_cache; rec = active_node->current; rec->found_dir_item = 1; -@@ -740,7 +782,9 @@ static int process_dir_item(struct extent_buffer *eb, +@@ -740,7 +788,9 @@ static int process_dir_item(struct extent_buffer *eb, key->objectid, key->offset, namebuf, len, filetype, key->type, error); } else if (location.type == BTRFS_ROOT_ITEM_KEY) { @@ -2748,7 +2922,7 @@ index 40c90f8..73f1836 100644 } else { fprintf(stderr, "warning line %d\n", __LINE__); } -@@ -977,8 +1021,7 @@ static int process_one_leaf(struct btrfs_root *root, struct extent_buffer *eb, +@@ -977,8 +1027,7 @@ static int process_one_leaf(struct btrfs_root *root, struct extent_buffer *eb, ret = process_inode_ref(eb, i, &key, active_node); break; case BTRFS_INODE_ITEM_KEY: @@ -2758,7 +2932,16 @@ index 40c90f8..73f1836 100644 break; case BTRFS_EXTENT_DATA_KEY: ret = process_file_extent(root, eb, i, &key, -@@ -1176,13 +1219,23 @@ static int check_inode_recs(struct btrfs_root *root, +@@ -1120,7 +1169,7 @@ static int check_root_dir(struct inode_record *rec) + + if (!rec->found_inode_item || rec->errors) + goto out; +- if (rec->nlink != 1 || rec->found_link != 1) ++ if (rec->nlink != 1 || rec->found_link != 0) + goto out; + if (list_empty(&rec->backrefs)) + goto out; +@@ -1176,13 +1225,23 @@ static int check_inode_recs(struct btrfs_root *root, node = container_of(cache, struct ptr_node, cache); rec = node->data; remove_cache_extent(inode_cache, &node->cache); @@ -2783,7 +2966,7 @@ index 40c90f8..73f1836 100644 error++; if (!rec->found_inode_item) rec->errors |= I_ERR_NO_INODE_ITEM; -@@ -1205,13 +1258,314 @@ static int check_inode_recs(struct btrfs_root *root, +@@ -1205,13 +1264,314 @@ static int check_inode_recs(struct btrfs_root *root, backref->namelen, backref->name, backref->filetype, backref->errors); } @@ -3099,7 +3282,7 @@ index 40c90f8..73f1836 100644 struct walk_control *wc) { int ret = 0; -@@ -1219,10 +1573,18 @@ static int check_fs_root(struct btrfs_root *root, +@@ -1219,10 +1579,18 @@ static int check_fs_root(struct btrfs_root *root, int level; struct btrfs_path path; struct shared_node root_node; @@ -3118,7 +3301,7 @@ index 40c90f8..73f1836 100644 cache_tree_init(&root_node.inode_cache); level = btrfs_header_level(root->node); -@@ -1266,6 +1628,8 @@ static int check_fs_root(struct btrfs_root *root, +@@ -1266,6 +1634,8 @@ static int check_fs_root(struct btrfs_root *root, } btrfs_release_path(root, &path); @@ -3127,7 +3310,7 @@ index 40c90f8..73f1836 100644 if (root_node.current) { root_node.current->checked = 1; maybe_free_inode_rec(&root_node.inode_cache, -@@ -1280,13 +1644,15 @@ static int fs_root_objectid(u64 objectid) +@@ -1280,13 +1650,15 @@ static int fs_root_objectid(u64 objectid) { if (objectid == BTRFS_FS_TREE_OBJECTID || objectid == BTRFS_TREE_RELOC_OBJECTID || @@ -3145,7 +3328,7 @@ index 40c90f8..73f1836 100644 { struct btrfs_path path; struct btrfs_key key; -@@ -1319,10 +1685,14 @@ static int check_fs_roots(struct btrfs_root *root) +@@ -1319,10 +1691,14 @@ static int check_fs_roots(struct btrfs_root *root) fs_root_objectid(key.objectid)) { tmp_root = btrfs_read_fs_root_no_cache(root->fs_info, &key); @@ -3161,7 +3344,7 @@ index 40c90f8..73f1836 100644 } path.slots[0]++; } -@@ -1895,7 +2265,6 @@ static int add_data_backref(struct cache_tree *extent_cache, u64 bytenr, +@@ -1895,7 +2271,6 @@ static int add_data_backref(struct cache_tree *extent_cache, u64 bytenr, return 0; } @@ -3169,23 +3352,55 @@ index 40c90f8..73f1836 100644 static int add_pending(struct cache_tree *pending, struct cache_tree *seen, u64 bytenr, u32 size) { -@@ -2443,6 +2812,7 @@ static void print_usage(void) +@@ -2443,14 +2818,45 @@ static void print_usage(void) int main(int ac, char **av) { + struct cache_tree root_cache; struct btrfs_root *root; ++ u64 bytenr = 0; int ret; ++ int num; -@@ -2450,6 +2820,7 @@ int main(int ac, char **av) +- if (ac < 2) ++ while(1) { ++ int c; ++ c = getopt(ac, av, "s:"); ++ if (c < 0) ++ break; ++ switch(c) { ++ case 's': ++ num = atol(optarg); ++ bytenr = btrfs_sb_offset(num); ++ printf("using SB copy %d, bytenr %llu\n", num, ++ (unsigned long long)bytenr); ++ break; ++ default: ++ print_usage(); ++ } ++ } ++ ac = ac - optind; ++ ++ if (ac != 1) print_usage(); radix_tree_init(); +- root = open_ctree(av[1], 0, 0); + cache_tree_init(&root_cache); - root = open_ctree(av[1], 0, 0); ++ ++ if((ret = check_mounted(av[optind])) < 0) { ++ fprintf(stderr, "Could not check mount status: %s\n", strerror(ret)); ++ return ret; ++ } else if(ret) { ++ fprintf(stderr, "%s is currently mounted. Aborting.\n", av[optind]); ++ return -EBUSY; ++ } ++ ++ root = open_ctree(av[optind], bytenr, 0); if (root == NULL) -@@ -2458,10 +2829,15 @@ int main(int ac, char **av) + return 1; +@@ -2458,10 +2864,15 @@ int main(int ac, char **av) ret = check_extents(root); if (ret) goto out; @@ -3203,7 +3418,7 @@ index 40c90f8..73f1836 100644 /* * there was a disk format change when mixed diff --git a/btrfsctl.c b/btrfsctl.c -index b323818..be6bf25 100644 +index b323818..92bdf39 100644 --- a/btrfsctl.c +++ b/btrfsctl.c @@ -29,6 +29,7 @@ @@ -3233,15 +3448,17 @@ index b323818..be6bf25 100644 printf("%s\n", BTRFS_BUILD_VERSION); exit(1); } -@@ -100,6 +104,7 @@ int main(int ac, char **av) +@@ -99,7 +103,9 @@ int main(int ac, char **av) + int i; unsigned long command = 0; int len; ++ char *pos; char *fullpath; + u64 objectid = 0; if (ac == 2 && strcmp(av[1], "-a") == 0) { fprintf(stderr, "Scanning for Btrfs filesystems\n"); -@@ -158,6 +163,18 @@ int main(int ac, char **av) +@@ -158,6 +164,28 @@ int main(int ac, char **av) print_usage(); } command = BTRFS_IOC_DEFRAG; @@ -3253,6 +3470,16 @@ index b323818..be6bf25 100644 + command = BTRFS_IOC_SNAP_DESTROY; + name = av[i + 1]; + len = strlen(name); ++ pos = strchr(name, '/'); ++ if (pos) { ++ if (*(pos + 1) == '\0') ++ *(pos) = '\0'; ++ else { ++ fprintf(stderr, ++ "error: / not allowed in names\n"); ++ exit(1); ++ } ++ } + if (len == 0 || len >= BTRFS_VOL_NAME_MAX) { + fprintf(stderr, "-D size too long\n"); + exit(1); @@ -3260,7 +3487,7 @@ index b323818..be6bf25 100644 } else if (strcmp(av[i], "-A") == 0) { if (i >= ac - 1) { fprintf(stderr, "-A requires an arg\n"); -@@ -178,6 +195,16 @@ int main(int ac, char **av) +@@ -178,6 +206,16 @@ int main(int ac, char **av) command = BTRFS_IOC_RESIZE; } else if (strcmp(av[i], "-c") == 0) { command = BTRFS_IOC_SYNC; @@ -3277,7 +3504,7 @@ index b323818..be6bf25 100644 } } if (command == 0) { -@@ -206,6 +233,9 @@ int main(int ac, char **av) +@@ -206,6 +244,9 @@ int main(int ac, char **av) if (command == BTRFS_IOC_SNAP_CREATE) { args.fd = fd; ret = ioctl(snap_fd, command, &args); @@ -3287,6 +3514,17 @@ index b323818..be6bf25 100644 } else ret = ioctl(fd, command, &args); if (ret < 0) { +@@ -219,8 +260,8 @@ int main(int ac, char **av) + } + printf("%s\n", BTRFS_BUILD_VERSION); + if (ret) +- exit(0); +- else + exit(1); ++ ++ return 0; + } + diff --git a/convert.c b/convert.c index d2c9efa..d037c98 100644 --- a/convert.c @@ -3320,10 +3558,25 @@ index d2c9efa..d037c98 100644 num_bytes, 1, 0); if (ret) diff --git a/ctree.h b/ctree.h -index a9062ea..64ecf12 100644 +index a9062ea..b79e238 100644 --- a/ctree.h +++ b/ctree.h -@@ -1047,6 +1047,7 @@ BTRFS_SETGET_STACK_FUNCS(block_group_flags, +@@ -350,11 +350,13 @@ struct btrfs_super_block { + * ones specified below then we will fail to mount + */ + #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) ++#define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (2ULL << 0) + + #define BTRFS_FEATURE_COMPAT_SUPP 0ULL + #define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL + #define BTRFS_FEATURE_INCOMPAT_SUPP \ +- BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF ++ (BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | \ ++ BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL) + + /* + * A leaf is full of items. offset and size tell us where to find +@@ -1047,6 +1049,7 @@ BTRFS_SETGET_STACK_FUNCS(block_group_flags, /* struct btrfs_inode_ref */ BTRFS_SETGET_FUNCS(inode_ref_name_len, struct btrfs_inode_ref, name_len, 16); @@ -3331,7 +3584,7 @@ index a9062ea..64ecf12 100644 BTRFS_SETGET_FUNCS(inode_ref_index, struct btrfs_inode_ref, index, 64); /* struct btrfs_inode_item */ -@@ -1325,6 +1326,10 @@ BTRFS_SETGET_FUNCS(root_ref_dirid, struct btrfs_root_ref, dirid, 64); +@@ -1325,6 +1328,10 @@ BTRFS_SETGET_FUNCS(root_ref_dirid, struct btrfs_root_ref, dirid, 64); BTRFS_SETGET_FUNCS(root_ref_sequence, struct btrfs_root_ref, sequence, 64); BTRFS_SETGET_FUNCS(root_ref_name_len, struct btrfs_root_ref, name_len, 16); @@ -3342,7 +3595,7 @@ index a9062ea..64ecf12 100644 /* struct btrfs_dir_item */ BTRFS_SETGET_FUNCS(dir_data_len, struct btrfs_dir_item, data_len, 16); BTRFS_SETGET_FUNCS(dir_type, struct btrfs_dir_item, type, 8); -@@ -1572,6 +1577,7 @@ static inline unsigned long btrfs_leaf_data(struct extent_buffer *l) +@@ -1572,6 +1579,7 @@ static inline unsigned long btrfs_leaf_data(struct extent_buffer *l) /* struct btrfs_file_extent_item */ BTRFS_SETGET_FUNCS(file_extent_type, struct btrfs_file_extent_item, type, 8); @@ -3350,7 +3603,7 @@ index a9062ea..64ecf12 100644 static inline unsigned long btrfs_file_extent_inline_start(struct btrfs_file_extent_item *e) -@@ -1588,18 +1594,30 @@ static inline u32 btrfs_file_extent_calc_inline_size(u32 datasize) +@@ -1588,18 +1596,30 @@ static inline u32 btrfs_file_extent_calc_inline_size(u32 datasize) BTRFS_SETGET_FUNCS(file_extent_disk_bytenr, struct btrfs_file_extent_item, disk_bytenr, 64); @@ -3381,6 +3634,196 @@ index a9062ea..64ecf12 100644 BTRFS_SETGET_FUNCS(file_extent_encryption, struct btrfs_file_extent_item, encryption, 8); BTRFS_SETGET_FUNCS(file_extent_other_encoding, struct btrfs_file_extent_item, +diff --git a/debug-tree.c b/debug-tree.c +index 1d47519..0525354 100644 +--- a/debug-tree.c ++++ b/debug-tree.c +@@ -116,19 +116,27 @@ int main(int ac, char **av) + int ret; + int slot; + int extent_only = 0; ++ int device_only = 0; ++ u64 block_only = 0; + struct btrfs_root *tree_root_scan; + + radix_tree_init(); + + while(1) { + int c; +- c = getopt(ac, av, "e"); ++ c = getopt(ac, av, "deb:"); + if (c < 0) + break; + switch(c) { + case 'e': + extent_only = 1; + break; ++ case 'd': ++ device_only = 1; ++ break; ++ case 'b': ++ block_only = atoll(optarg); ++ break; + default: + print_usage(); + } +@@ -142,14 +150,37 @@ int main(int ac, char **av) + fprintf(stderr, "unable to open %s\n", av[optind]); + exit(1); + } ++ if (block_only) { ++ leaf = read_tree_block(root, ++ block_only, ++ root->leafsize, 0); ++ ++ if (leaf && btrfs_header_level(leaf) != 0) { ++ free_extent_buffer(leaf); ++ leaf = NULL; ++ } ++ ++ if (!leaf) { ++ leaf = read_tree_block(root, ++ block_only, ++ root->nodesize, 0); ++ } ++ if (!leaf) { ++ fprintf(stderr, "failed to read %llu\n", block_only); ++ return 0; ++ } ++ btrfs_print_tree(root, leaf, 0); ++ return 0; ++ } ++ + if (!extent_only) { + printf("root tree\n"); + btrfs_print_tree(root->fs_info->tree_root, +- root->fs_info->tree_root->node); ++ root->fs_info->tree_root->node, 1); + + printf("chunk tree\n"); + btrfs_print_tree(root->fs_info->chunk_root, +- root->fs_info->chunk_root->node); ++ root->fs_info->chunk_root->node, 1); + } + tree_root_scan = root->fs_info->tree_root; + +@@ -175,7 +206,7 @@ again: + if (btrfs_key_type(&found_key) == BTRFS_ROOT_ITEM_KEY) { + unsigned long offset; + struct extent_buffer *buf; +- int skip = extent_only; ++ int skip = extent_only | device_only; + + offset = btrfs_item_ptr_offset(leaf, slot); + read_extent_buffer(leaf, &ri, offset, sizeof(ri)); +@@ -188,8 +219,9 @@ again: + printf("root"); + break; + case BTRFS_EXTENT_TREE_OBJECTID: +- skip = 0; +- if (!extent_only) ++ if (!device_only) ++ skip = 0; ++ if (!extent_only && !device_only) + printf("extent"); + break; + case BTRFS_CHUNK_TREE_OBJECTID: +@@ -198,9 +230,8 @@ again: + } + break; + case BTRFS_DEV_TREE_OBJECTID: +- if (!skip) { +- printf("device"); +- } ++ skip = 0; ++ printf("device"); + break; + case BTRFS_FS_TREE_OBJECTID: + if (!skip) { +@@ -208,9 +239,8 @@ again: + } + break; + case BTRFS_ROOT_TREE_DIR_OBJECTID: +- if (!skip) { +- printf("directory"); +- } ++ skip = 0; ++ printf("directory"); + break; + case BTRFS_CSUM_TREE_OBJECTID: + if (!skip) { +@@ -256,13 +286,13 @@ again: + printf("file"); + } + } +- if (!skip && !extent_only) { ++ if (extent_only && !skip) { ++ print_extents(tree_root_scan, buf); ++ } else if (!skip) { + printf(" tree "); + btrfs_print_key(&disk_key); + printf(" \n"); +- btrfs_print_tree(tree_root_scan, buf); +- } else if (extent_only && !skip) { +- print_extents(tree_root_scan, buf); ++ btrfs_print_tree(tree_root_scan, buf, 1); + } + } + path.slots[0]++; +@@ -275,7 +305,7 @@ again: + goto again; + } + +- if (extent_only) ++ if (extent_only || device_only) + return 0; + + printf("total bytes %llu\n", +diff --git a/dir-test.c b/dir-test.c +index 44f2758..3ae9c68 100644 +--- a/dir-test.c ++++ b/dir-test.c +@@ -485,7 +485,7 @@ int main(int ac, char **av) + if (ret) { + fprintf(stderr, "op %d failed %d:%d\n", + op, i, iterations); +- btrfs_print_tree(root, root->node); ++ btrfs_print_tree(root, root->node, 1); + fprintf(stderr, "op %d failed %d:%d\n", + op, i, iterations); + err = ret; +diff --git a/disk-io.c b/disk-io.c +index addebe1..a6e1000 100644 +--- a/disk-io.c ++++ b/disk-io.c +@@ -86,7 +86,7 @@ int csum_tree_block_size(struct extent_buffer *buf, u16 csum_size, + if (memcmp_extent_buffer(buf, result, 0, csum_size)) { + printk("checksum verify failed on %llu wanted %X " + "found %X\n", (unsigned long long)buf->start, +- *((int *)result), *((int *)buf)); ++ *((int *)result), *((char *)buf->data)); + free(result); + return 1; + } +@@ -970,13 +970,13 @@ int close_ctree(struct btrfs_root *root) + if (fs_info->csum_root->node) + free_extent_buffer(fs_info->csum_root->node); + +- if (root->fs_info->log_root_tree) { +- if (root->fs_info->log_root_tree->node) +- free_extent_buffer(root->fs_info->log_root_tree->node); +- free(root->fs_info->log_root_tree); ++ if (fs_info->log_root_tree) { ++ if (fs_info->log_root_tree->node) ++ free_extent_buffer(fs_info->log_root_tree->node); ++ free(fs_info->log_root_tree); + } + +- close_all_devices(root->fs_info); ++ close_all_devices(fs_info); + extent_io_tree_cleanup(&fs_info->extent_cache); + extent_io_tree_cleanup(&fs_info->free_space_cache); + extent_io_tree_cleanup(&fs_info->block_group_cache); diff --git a/ioctl-test.c b/ioctl-test.c new file mode 100644 index 0000000..7cf3bc2 @@ -3552,6 +3995,22 @@ index a084f33..776d7a9 100644 +#define BTRFS_IOC_SPACE_INFO _IOWR(BTRFS_IOCTL_MAGIC, 20, \ + struct btrfs_ioctl_space_args) #endif +diff --git a/kerncompat.h b/kerncompat.h +index e4c8ce0..46236cd 100644 +--- a/kerncompat.h ++++ b/kerncompat.h +@@ -42,7 +42,11 @@ + #define GFP_NOFS 0 + #define __read_mostly + #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) ++ ++#ifndef ULONG_MAX + #define ULONG_MAX (~0UL) ++#endif ++ + #define BUG() abort() + #ifdef __CHECKER__ + #define __force __attribute__((force)) diff --git a/man/Makefile b/man/Makefile index 4e8893b..4a90b75 100644 --- a/man/Makefile @@ -3750,3 +4209,391 @@ index 0000000..26ef982 +further details. +.SH SEE ALSO +.BR mkfs.btrfs (8) +diff --git a/print-tree.c b/print-tree.c +index 59f4358..ac575d5 100644 +--- a/print-tree.c ++++ b/print-tree.c +@@ -413,8 +413,11 @@ static void print_objectid(unsigned long long objectid, u8 type) + printf("MULTIPLE"); + break; + case BTRFS_FIRST_CHUNK_TREE_OBJECTID: +- printf("FIRST_CHUNK_TREE"); +- break; ++ if (type == BTRFS_CHUNK_ITEM_KEY) { ++ printf("FIRST_CHUNK_TREE"); ++ break; ++ } ++ /* fall-thru */ + default: + printf("%llu", objectid); + } +@@ -607,7 +610,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) + } + } + +-void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *eb) ++void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *eb, int follow) + { + int i; + u32 nr; +@@ -643,6 +646,9 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *eb) + (unsigned long long)btrfs_node_ptr_generation(eb, i)); + fflush(stdout); + } ++ if (!follow) ++ return; ++ + for (i = 0; i < nr; i++) { + struct extent_buffer *next = read_tree_block(root, + btrfs_node_blockptr(eb, i), +@@ -660,8 +666,7 @@ void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *eb) + if (btrfs_header_level(next) != + btrfs_header_level(eb) - 1) + BUG(); +- btrfs_print_tree(root, next); ++ btrfs_print_tree(root, next, 1); + free_extent_buffer(next); + } + } +- +diff --git a/print-tree.h b/print-tree.h +index 4d1a01a..495b81a 100644 +--- a/print-tree.h ++++ b/print-tree.h +@@ -19,6 +19,6 @@ + #ifndef __PRINT_TREE_ + #define __PRINT_TREE_ + void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l); +-void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *t); ++void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *t, int follow); + void btrfs_print_key(struct btrfs_disk_key *disk_key); + #endif +diff --git a/quick-test.c b/quick-test.c +index 351c706..fa6fd83 100644 +--- a/quick-test.c ++++ b/quick-test.c +@@ -85,7 +85,7 @@ int main(int ac, char **av) { + fprintf(stderr, "search %d:%d\n", num, i); + ret = btrfs_search_slot(NULL, root, &ins, &path, 0, 0); + if (ret) { +- btrfs_print_tree(root, root->node); ++ btrfs_print_tree(root, root->node, 1); + printf("unable to find %d\n", num); + exit(1); + } +@@ -148,7 +148,7 @@ int main(int ac, char **av) { + fprintf(stderr, "search %d:%d\n", num, i); + ret = btrfs_search_slot(NULL, root, &ins, &path, 0, 0); + if (ret) { +- btrfs_print_tree(root, root->node); ++ btrfs_print_tree(root, root->node, 1); + printf("unable to find %d\n", num); + exit(1); + } +@@ -196,7 +196,7 @@ int main(int ac, char **av) { + btrfs_commit_transaction(trans, root); + printf("tree size is now %d\n", tree_size); + printf("root %p commit root %p\n", root->node, root->commit_root); +- btrfs_print_tree(root, root->node); ++ btrfs_print_tree(root, root->node, 1); + close_ctree(root); + return 0; + } +diff --git a/random-test.c b/random-test.c +index 571735d..0003236 100644 +--- a/random-test.c ++++ b/random-test.c +@@ -404,7 +404,7 @@ int main(int ac, char **av) + if (ret) { + fprintf(stderr, "op %d failed %d:%d\n", + op, i, iterations); +- btrfs_print_tree(root, root->node); ++ btrfs_print_tree(root, root->node, 1); + fprintf(stderr, "op %d failed %d:%d\n", + op, i, iterations); + err = ret; +diff --git a/utils.c b/utils.c +index 2f4c6e1..fd894f3 100644 +--- a/utils.c ++++ b/utils.c +@@ -31,6 +31,10 @@ + #include + #include + #include ++#include ++#include ++#include ++#include + #include "kerncompat.h" + #include "radix-tree.h" + #include "ctree.h" +@@ -586,55 +590,224 @@ error: + return ret; + } + ++/* checks if a device is a loop device */ ++int is_loop_device (const char* device) { ++ struct stat statbuf; ++ ++ if(stat(device, &statbuf) < 0) ++ return -errno; ++ ++ return (S_ISBLK(statbuf.st_mode) && ++ MAJOR(statbuf.st_rdev) == LOOP_MAJOR); ++} ++ ++ ++/* Takes a loop device path (e.g. /dev/loop0) and returns ++ * the associated file (e.g. /images/my_btrfs.img) */ ++int resolve_loop_device(const char* loop_dev, char* loop_file, int max_len) ++{ ++ int loop_fd; ++ int ret_ioctl; ++ struct loop_info loopinfo; ++ ++ if ((loop_fd = open(loop_dev, O_RDONLY)) < 0) ++ return -errno; ++ ++ ret_ioctl = ioctl(loop_fd, LOOP_GET_STATUS, &loopinfo); ++ close(loop_fd); ++ ++ if (ret_ioctl == 0) ++ strncpy(loop_file, loopinfo.lo_name, max_len); ++ else ++ return -errno; ++ ++ return 0; ++} ++ ++/* Checks whether a and b are identical or device ++ * files associated with the same block device ++ */ ++int is_same_blk_file(const char* a, const char* b) ++{ ++ struct stat st_buf_a, st_buf_b; ++ char real_a[PATH_MAX]; ++ char real_b[PATH_MAX]; ++ ++ if(!realpath(a, real_a) || ++ !realpath(b, real_b)) ++ { ++ return -errno; ++ } ++ ++ /* Identical path? */ ++ if(strcmp(real_a, real_b) == 0) ++ return 1; ++ ++ if(stat(a, &st_buf_a) < 0 || ++ stat(b, &st_buf_b) < 0) ++ { ++ return -errno; ++ } ++ ++ /* Same blockdevice? */ ++ if(S_ISBLK(st_buf_a.st_mode) && ++ S_ISBLK(st_buf_b.st_mode) && ++ st_buf_a.st_rdev == st_buf_b.st_rdev) ++ { ++ return 1; ++ } ++ ++ /* Hardlink? */ ++ if (st_buf_a.st_dev == st_buf_b.st_dev && ++ st_buf_a.st_ino == st_buf_b.st_ino) ++ { ++ return 1; ++ } ++ ++ return 0; ++} ++ ++/* checks if a and b are identical or device ++ * files associated with the same block device or ++ * if one file is a loop device that uses the other ++ * file. ++ */ ++int is_same_loop_file(const char* a, const char* b) ++{ ++ char res_a[PATH_MAX]; ++ char res_b[PATH_MAX]; ++ const char* final_a; ++ const char* final_b; ++ int ret; ++ ++ /* Resolve a if it is a loop device */ ++ if((ret = is_loop_device(a)) < 0) { ++ return ret; ++ } else if(ret) { ++ if((ret = resolve_loop_device(a, res_a, sizeof(res_a))) < 0) ++ return ret; ++ ++ final_a = res_a; ++ } else { ++ final_a = a; ++ } ++ ++ /* Resolve b if it is a loop device */ ++ if((ret = is_loop_device(b)) < 0) { ++ return ret; ++ } else if(ret) { ++ if((ret = resolve_loop_device(b, res_b, sizeof(res_b))) < 0) ++ return ret; ++ ++ final_b = res_b; ++ } else { ++ final_b = b; ++ } ++ ++ return is_same_blk_file(final_a, final_b); ++} ++ ++/* Checks if a file exists and is a block or regular file*/ ++int is_existing_blk_or_reg_file(const char* filename) ++{ ++ struct stat st_buf; ++ ++ if(stat(filename, &st_buf) < 0) { ++ if(errno == ENOENT) ++ return 0; ++ else ++ return -errno; ++ } ++ ++ return (S_ISBLK(st_buf.st_mode) || S_ISREG(st_buf.st_mode)); ++} ++ ++/* Checks if a file is used (directly or indirectly via a loop device) ++ * by a device in fs_devices ++ */ ++int blk_file_in_dev_list(struct btrfs_fs_devices* fs_devices, const char* file) ++{ ++ int ret; ++ struct list_head *head; ++ struct list_head *cur; ++ struct btrfs_device *device; ++ ++ head = &fs_devices->devices; ++ list_for_each(cur, head) { ++ device = list_entry(cur, struct btrfs_device, dev_list); ++ ++ if((ret = is_same_loop_file(device->name, file))) ++ return ret; ++ } ++ ++ return 0; ++} ++ + /* + * returns 1 if the device was mounted, < 0 on error or 0 if everything +- * is safe to continue. TODO, this should also scan multi-device filesystems ++ * is safe to continue. + */ +-int check_mounted(char *file) ++int check_mounted(const char* file) + { +- struct mntent *mnt; +- struct stat st_buf; +- dev_t file_dev = 0; +- dev_t file_rdev = 0; +- ino_t file_ino = 0; ++ int ret; ++ int fd; ++ u64 total_devs = 1; ++ int is_btrfs; ++ struct btrfs_fs_devices* fs_devices_mnt = NULL; + FILE *f; +- int ret = 0; ++ struct mntent *mnt; + +- if ((f = setmntent ("/proc/mounts", "r")) == NULL) ++ fd = open(file, O_RDONLY); ++ if (fd < 0) { ++ fprintf (stderr, "check_mounted(): Could not open %s\n", file); + return -errno; ++ } + +- if (stat(file, &st_buf) < 0) { +- return -errno; +- } else { +- if (S_ISBLK(st_buf.st_mode)) { +- file_rdev = st_buf.st_rdev; +- } else { +- file_dev = st_buf.st_dev; +- file_ino = st_buf.st_ino; +- } ++ /* scan the initial device */ ++ ret = btrfs_scan_one_device(fd, file, &fs_devices_mnt, ++ &total_devs, BTRFS_SUPER_INFO_OFFSET); ++ is_btrfs = (ret >= 0); ++ close(fd); ++ ++ /* scan other devices */ ++ if (is_btrfs && total_devs > 1) { ++ if((ret = btrfs_scan_for_fsid(fs_devices_mnt, total_devs, 1))) ++ return ret; + } + ++ /* iterate over the list of currently mountes filesystems */ ++ if ((f = setmntent ("/proc/mounts", "r")) == NULL) ++ return -errno; ++ + while ((mnt = getmntent (f)) != NULL) { +- if (strcmp(file, mnt->mnt_fsname) == 0) +- break; ++ if(is_btrfs) { ++ if(strcmp(mnt->mnt_type, "btrfs") != 0) ++ continue; + +- if (stat(mnt->mnt_fsname, &st_buf) == 0) { +- if (S_ISBLK(st_buf.st_mode)) { +- if (file_rdev && (file_rdev == st_buf.st_rdev)) +- break; +- } else if (file_dev && ((file_dev == st_buf.st_dev) && +- (file_ino == st_buf.st_ino))) { +- break; +- } ++ ret = blk_file_in_dev_list(fs_devices_mnt, mnt->mnt_fsname); ++ } else { ++ /* ignore entries in the mount table that are not ++ associated with a file*/ ++ if((ret = is_existing_blk_or_reg_file(mnt->mnt_fsname)) < 0) ++ goto out_mntloop_err; ++ else if(!ret) ++ continue; ++ ++ ret = is_same_loop_file(file, mnt->mnt_fsname); + } +- } + +- if (mnt) { +- /* found an entry in mnt table */ +- ret = 1; ++ if(ret < 0) ++ goto out_mntloop_err; ++ else if(ret) ++ break; + } + ++ /* Did we find an entry in mnt table? */ ++ ret = (mnt != NULL); ++ ++out_mntloop_err: + endmntent (f); ++ + return ret; + } + +diff --git a/utils.h b/utils.h +index 7ff542b..9dce5b0 100644 +--- a/utils.h ++++ b/utils.h +@@ -36,7 +36,7 @@ int btrfs_scan_for_fsid(struct btrfs_fs_devices *fs_devices, u64 total_devs, + int run_ioctls); + void btrfs_register_one_device(char *fname); + int btrfs_scan_one_dir(char *dirname, int run_ioctl); +-int check_mounted(char *devicename); ++int check_mounted(const char *devicename); + int btrfs_device_already_in_root(struct btrfs_root *root, int fd, + int super_offset); + char *pretty_sizes(u64 size); diff --git a/btrfs-progs-valgrind.patch b/btrfs-progs-valgrind.patch index 3adbe57..decc197 100644 --- a/btrfs-progs-valgrind.patch +++ b/btrfs-progs-valgrind.patch @@ -1,31 +1,8 @@ -Hello, - -Started running valgrind against btrfsck since e2fsck seemed to have a myriad of -problems. btrfsck was actually not in too bad shape, only like 5 or 6 normal -errors and maybe 5 leaks. The big leak is the "seen" extent cache that we don't -seem to do anything with. Since I'm not sure what Yan is up to I just made it -so we free that cache before we return in case he wants it for something. With -these changes btrfsck doesn't spit out any errors while running valgrind and has -no leaks. This should also help any of the other utilities that use the generic -stuff. Thanks, - -Signed-off-by: Josef Bacik ---- - btrfsck.c | 2 ++ - disk-io.c | 29 ++++++++++++++++++----------- - extent-cache.c | 11 +++++++++++ - extent-cache.h | 1 + - extent-tree.c | 10 ++++++++++ - extent_io.c | 1 + - volumes.c | 16 +++++++++++++++- - volumes.h | 1 + - 8 files changed, 59 insertions(+), 12 deletions(-) - diff --git a/btrfsck.c b/btrfsck.c -index 40c90f8..9dd777f 100644 +index 63e44d1..1ae7487 100644 --- a/btrfsck.c +++ b/btrfsck.c -@@ -2431,6 +2431,8 @@ static int check_extents(struct btrfs_root *root) +@@ -2806,6 +2806,8 @@ static int check_extents(struct btrfs_root *root) break; } ret = check_extent_refs(root, &extent_cache); @@ -35,7 +12,7 @@ index 40c90f8..9dd777f 100644 } diff --git a/disk-io.c b/disk-io.c -index addebe1..4d4e902 100644 +index a6e1000..b903163 100644 --- a/disk-io.c +++ b/disk-io.c @@ -425,8 +425,10 @@ static int find_and_setup_log_root(struct btrfs_root *tree_root, @@ -91,24 +68,7 @@ index addebe1..4d4e902 100644 return 0; } -@@ -970,25 +976,26 @@ int close_ctree(struct btrfs_root *root) - if (fs_info->csum_root->node) - free_extent_buffer(fs_info->csum_root->node); - -- if (root->fs_info->log_root_tree) { -- if (root->fs_info->log_root_tree->node) -- free_extent_buffer(root->fs_info->log_root_tree->node); -- free(root->fs_info->log_root_tree); -+ if (fs_info->log_root_tree) { -+ if (fs_info->log_root_tree->node) -+ free_extent_buffer(fs_info->log_root_tree->node); - } - -- close_all_devices(root->fs_info); -+ close_all_devices(fs_info); - extent_io_tree_cleanup(&fs_info->extent_cache); - extent_io_tree_cleanup(&fs_info->free_space_cache); - extent_io_tree_cleanup(&fs_info->block_group_cache); +@@ -983,12 +989,14 @@ int close_ctree(struct btrfs_root *root) extent_io_tree_cleanup(&fs_info->pinned_extents); extent_io_tree_cleanup(&fs_info->pending_del); extent_io_tree_cleanup(&fs_info->extent_ins); @@ -238,10 +198,3 @@ index bb78751..e466b31 100644 int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset); +void btrfs_mapping_tree_free(struct btrfs_mapping_tree *tree); #endif --- -1.5.4.3 - --- -To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in -the body of a message to majordomo@vger.kernel.org -More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/btrfs-progs.spec b/btrfs-progs.spec index 36f9a18..0050761 100644 --- a/btrfs-progs.spec +++ b/btrfs-progs.spec @@ -1,18 +1,17 @@ Name: btrfs-progs Version: 0.19 -Release: 13%{?dist} +Release: 14%{?dist} Summary: Userspace programs for btrfs Group: System Environment/Base License: GPLv2 URL: http://btrfs.wiki.kernel.org/index.php/Main_Page Source0: http://www.kernel.org/pub/linux/kernel/people/mason/btrfs/%{name}-%{version}.tar.bz2 -Patch0: btrfs-progs-fix-labels.patch -Patch1: btrfs-progs-build-everything.patch -Patch2: btrfs-progs-valgrind.patch -Patch3: btrfs-progs-fix-return-value.patch +Patch0: btrfs-progs-upstream.patch +Patch1: btrfs-progs-fix-labels.patch +Patch2: btrfs-progs-build-everything.patch +Patch3: btrfs-progs-valgrind.patch Patch4: btrfs-progs-build-fixes.patch -Patch5: btrfs-progs-upstream.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: e2fsprogs-devel, libuuid-devel, zlib-devel, libacl-devel @@ -26,11 +25,10 @@ check, modify and correct any inconsistencies in the btrfs filesystem. %prep %setup -q %patch0 -p1 +%patch1 -p1 %patch2 -p1 %patch3 -p1 %patch4 -p1 -%patch5 -p1 -%patch1 -p1 %build make CFLAGS="$RPM_OPT_FLAGS" %{?_smp_mflags} @@ -65,6 +63,9 @@ rm -rf $RPM_BUILD_ROOT %{_mandir}/man8/btrfs.8.gz %changelog +* Thu Aug 04 2011 Josef Bacik 0.19-14 +- bring btrfs-progs uptodate with upstream + * Mon Feb 07 2011 Fedora Release Engineering - 0.19-13 - Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild