[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