[btrfs-progs] update to newest upstream

Josef Bacik josef at fedoraproject.org
Thu Aug 4 14:15:58 UTC 2011


commit a37e25db178df6dedccc55c1cd074fd0b185a9ca
Author: Josef Bacik <josef at redhat.com>
Date:   Thu Aug 4 10:15:35 2011 -0400

    update to newest upstream

 btrfs-progs-build-fixes.patch |   22 +-
 btrfs-progs-upstream.patch    |  957 ++++++++++++++++++++++++++++++++++++++---
 btrfs-progs-valgrind.patch    |   55 +---
 btrfs-progs.spec              |   17 +-
 4 files changed, 928 insertions(+), 123 deletions(-)
---
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 <stdio.h>
+diff --git a/btrfsck.c b/btrfsck.c
+index 63e44d1..1e040c4 100644
+--- a/btrfsck.c
++++ b/btrfsck.c
+@@ -22,7 +22,9 @@
  #include <stdlib.h>
+ #include <unistd.h>
  #include <fcntl.h>
 +#include <sys/types.h>
-+#include <sys/stat.h>
+ #include <sys/stat.h>
 +#include <unistd.h>
  #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 <sys/ioctl.h>
 +#include <sys/mount.h>
@@ -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 <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <fcntl.h>
++#include <sys/stat.h>
++#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 <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
@@ -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 <stdio.h>
+ #include <stdlib.h>
++#include <unistd.h>
+ #include <fcntl.h>
++#include <sys/stat.h>
+ #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 <fcntl.h>
+ #include <unistd.h>
+ #include <mntent.h>
++#include <linux/loop.h>
++#include <linux/major.h>
++#include <linux/kdev_t.h>
++#include <limits.h>
+ #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 <jbacik at redhat.com>
----
- 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 at 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 <josef at toxicpanda.com> 0.19-14
+- bring btrfs-progs uptodate with upstream
+
 * Mon Feb 07 2011 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 0.19-13
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
 


More information about the scm-commits mailing list