From 34511226b84e4e5314e632bb0eeb3864ff62d0df97c5d2aa540037b5148b2a5a Mon Sep 17 00:00:00 2001 From: Dirk Mueller Date: Fri, 7 May 2010 13:05:46 +0000 Subject: [PATCH 1/5] - revert last change (bnc#599224#c3) OBS-URL: https://build.opensuse.org/package/show/filesystems/btrfsprogs?expand=0&rev=94 --- btrfsprogs.changes | 5 +++++ btrfsprogs.spec | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/btrfsprogs.changes b/btrfsprogs.changes index 72442eb..e1cdcc1 100644 --- a/btrfsprogs.changes +++ b/btrfsprogs.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Fri May 7 15:05:11 CEST 2010 - dmueller@suse.de + +- revert last change (bnc#599224#c3) + ------------------------------------------------------------------- Thu Apr 29 11:11:13 CEST 2010 - dmueller@suse.de diff --git a/btrfsprogs.spec b/btrfsprogs.spec index 5fa18e4..299bd4d 100644 --- a/btrfsprogs.spec +++ b/btrfsprogs.spec @@ -53,7 +53,8 @@ make %{?jobs:-j%jobs} CFLAGS="%{optflags}" all convert %install make install DESTDIR=${RPM_BUILD_ROOT} prefix=%{_prefix} bindir=/sbin mandir=%{_mandir} -ln ${RPM_BUILD_ROOT}/sbin/btrfsck ${RPM_BUILD_ROOT}/sbin/fsck.btrfs +# command line options are not compatible (bnc#599224) +#ln ${RPM_BUILD_ROOT}/sbin/btrfsck ${RPM_BUILD_ROOT}/sbin/fsck.btrfs %files %defattr(-, root, root) @@ -64,7 +65,7 @@ ln ${RPM_BUILD_ROOT}/sbin/btrfsck ${RPM_BUILD_ROOT}/sbin/fsck.btrfs /sbin/btrfsck /sbin/btrfsctl /sbin/mkfs.btrfs -/sbin/fsck.btrfs +#/sbin/fsck.btrfs /sbin/btrfs-map-logical %_mandir/man8/btrfs-image.8.gz %_mandir/man8/btrfs-show.8.gz From 36ce606d0854c91aac02c4e61c4f5afed81298f5ca1b6f3e66585847b49efc9e Mon Sep 17 00:00:00 2001 From: Dirk Mueller Date: Wed, 26 May 2010 15:14:58 +0000 Subject: [PATCH 2/5] - fix crash on creating filesystems (bnc#603620) OBS-URL: https://build.opensuse.org/package/show/filesystems/btrfsprogs?expand=0&rev=95 --- 0005-fix-use-after-free.patch | 39 +++++++++++++++++++++++++++++++++++ btrfsprogs.changes | 5 +++++ btrfsprogs.spec | 2 ++ 3 files changed, 46 insertions(+) create mode 100644 0005-fix-use-after-free.patch diff --git a/0005-fix-use-after-free.patch b/0005-fix-use-after-free.patch new file mode 100644 index 0000000..c354c3a --- /dev/null +++ b/0005-fix-use-after-free.patch @@ -0,0 +1,39 @@ +From: Jeff Mahoney +Subject: btrfsprogs: Fix use after free in close_ctree +References: bnc#603620 + + After the roots are closed, root is freed. Yet close_ctree continues + to use it. It works generally because no new memory is allocated in + the interim, but with glibc malloc perturbing enabled, it crashes + every time. This is because root->fs_info points to garbage. + + This patch uses the already-cached fs_info variable for the rest of + the accesses and fixes the crash. + + +Signed-off-by: Jeff Mahoney +--- + disk-io.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/disk-io.c ++++ b/disk-io.c +@@ -971,13 +971,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/btrfsprogs.changes b/btrfsprogs.changes index e1cdcc1..91d2d5f 100644 --- a/btrfsprogs.changes +++ b/btrfsprogs.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Wed May 26 17:00:46 CEST 2010 - dmueller@suse.de + +- fix crash on creating filesystems (bnc#603620) + ------------------------------------------------------------------- Fri May 7 15:05:11 CEST 2010 - dmueller@suse.de diff --git a/btrfsprogs.spec b/btrfsprogs.spec index 299bd4d..733cd1f 100644 --- a/btrfsprogs.spec +++ b/btrfsprogs.spec @@ -32,6 +32,7 @@ Patch2: 0002-btrfsctl-add-snapshot-subvolume-destroy-ioctl.patch Patch3: 0003-btrfsck-check-root-back-forward-references.patch Patch4: 0004-Add-btrfs-map-logical-program-to-map-and-read-logica.patch Patch5: 0001-Plug-Memory-leak-in-find_and_setup_log_root.patch +Patch6: 0005-fix-use-after-free.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: libacl-devel libext2fs-devel libuuid-devel zlib-devel @@ -47,6 +48,7 @@ file systems. %patch3 -p1 %patch4 -p1 %patch5 -p1 +%patch6 -p1 %build make %{?jobs:-j%jobs} CFLAGS="%{optflags}" all convert From 6d78376d8559c4ba7110d76d8a6fae80a3a3373e4b603e1f85b2536348962c31 Mon Sep 17 00:00:00 2001 From: OBS User autobuild Date: Wed, 9 Jun 2010 14:56:50 +0000 Subject: [PATCH 3/5] Accepting request 41263 from filesystems checked in (request 41263) OBS-URL: https://build.opensuse.org/request/show/41263 OBS-URL: https://build.opensuse.org/package/show/filesystems/btrfsprogs?expand=0&rev=96 --- 0005-fix-use-after-free.patch | 39 ----------------------------------- btrfsprogs.changes | 10 --------- btrfsprogs.spec | 7 ++----- 3 files changed, 2 insertions(+), 54 deletions(-) delete mode 100644 0005-fix-use-after-free.patch diff --git a/0005-fix-use-after-free.patch b/0005-fix-use-after-free.patch deleted file mode 100644 index c354c3a..0000000 --- a/0005-fix-use-after-free.patch +++ /dev/null @@ -1,39 +0,0 @@ -From: Jeff Mahoney -Subject: btrfsprogs: Fix use after free in close_ctree -References: bnc#603620 - - After the roots are closed, root is freed. Yet close_ctree continues - to use it. It works generally because no new memory is allocated in - the interim, but with glibc malloc perturbing enabled, it crashes - every time. This is because root->fs_info points to garbage. - - This patch uses the already-cached fs_info variable for the rest of - the accesses and fixes the crash. - - -Signed-off-by: Jeff Mahoney ---- - disk-io.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - ---- a/disk-io.c -+++ b/disk-io.c -@@ -971,13 +971,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/btrfsprogs.changes b/btrfsprogs.changes index 91d2d5f..72442eb 100644 --- a/btrfsprogs.changes +++ b/btrfsprogs.changes @@ -1,13 +1,3 @@ -------------------------------------------------------------------- -Wed May 26 17:00:46 CEST 2010 - dmueller@suse.de - -- fix crash on creating filesystems (bnc#603620) - -------------------------------------------------------------------- -Fri May 7 15:05:11 CEST 2010 - dmueller@suse.de - -- revert last change (bnc#599224#c3) - ------------------------------------------------------------------- Thu Apr 29 11:11:13 CEST 2010 - dmueller@suse.de diff --git a/btrfsprogs.spec b/btrfsprogs.spec index 733cd1f..5fa18e4 100644 --- a/btrfsprogs.spec +++ b/btrfsprogs.spec @@ -32,7 +32,6 @@ Patch2: 0002-btrfsctl-add-snapshot-subvolume-destroy-ioctl.patch Patch3: 0003-btrfsck-check-root-back-forward-references.patch Patch4: 0004-Add-btrfs-map-logical-program-to-map-and-read-logica.patch Patch5: 0001-Plug-Memory-leak-in-find_and_setup_log_root.patch -Patch6: 0005-fix-use-after-free.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: libacl-devel libext2fs-devel libuuid-devel zlib-devel @@ -48,15 +47,13 @@ file systems. %patch3 -p1 %patch4 -p1 %patch5 -p1 -%patch6 -p1 %build make %{?jobs:-j%jobs} CFLAGS="%{optflags}" all convert %install make install DESTDIR=${RPM_BUILD_ROOT} prefix=%{_prefix} bindir=/sbin mandir=%{_mandir} -# command line options are not compatible (bnc#599224) -#ln ${RPM_BUILD_ROOT}/sbin/btrfsck ${RPM_BUILD_ROOT}/sbin/fsck.btrfs +ln ${RPM_BUILD_ROOT}/sbin/btrfsck ${RPM_BUILD_ROOT}/sbin/fsck.btrfs %files %defattr(-, root, root) @@ -67,7 +64,7 @@ make install DESTDIR=${RPM_BUILD_ROOT} prefix=%{_prefix} bindir=/sbin mandir=%{_ /sbin/btrfsck /sbin/btrfsctl /sbin/mkfs.btrfs -#/sbin/fsck.btrfs +/sbin/fsck.btrfs /sbin/btrfs-map-logical %_mandir/man8/btrfs-image.8.gz %_mandir/man8/btrfs-show.8.gz From 5e9a890439588c2c44ec9675689b389664f69fe28876ff0db6e207c203e5caf3 Mon Sep 17 00:00:00 2001 From: Dirk Mueller Date: Thu, 16 Dec 2010 19:56:57 +0000 Subject: [PATCH 4/5] - update to v0.19-35-g1b444cd: * used space accounting fix for the converter * Add btrfs-list for listing subvolumes * Add new util: 'btrfs' * multidevice support for check_mounted * check slash in deleting subvolumes * Add btrfsck option to select the super block copy * btrfs-debug-tree: add -d option to print only the device mapping OBS-URL: https://build.opensuse.org/package/show/filesystems/btrfsprogs?expand=0&rev=97 --- ...mory-leak-in-find_and_setup_log_root.patch | 27 +- ...ace-accounting-fix-for-the-converter.patch | 49 -- ...add-snapshot-subvolume-destroy-ioctl.patch | 69 -- ...k-check-root-back-forward-references.patch | 700 ------------------ ...gical-program-to-map-and-read-logica.patch | 271 ------- btrfs-progs-0.19.tar.bz2 | 3 - btrfs-progs-v0.19-35-g1b444cd.tar.bz2 | 3 + btrfsprogs.changes | 22 + btrfsprogs.spec | 31 +- 9 files changed, 49 insertions(+), 1126 deletions(-) delete mode 100644 0001-used-space-accounting-fix-for-the-converter.patch delete mode 100644 0002-btrfsctl-add-snapshot-subvolume-destroy-ioctl.patch delete mode 100644 0003-btrfsck-check-root-back-forward-references.patch delete mode 100644 0004-Add-btrfs-map-logical-program-to-map-and-read-logica.patch delete mode 100644 btrfs-progs-0.19.tar.bz2 create mode 100644 btrfs-progs-v0.19-35-g1b444cd.tar.bz2 diff --git a/0001-Plug-Memory-leak-in-find_and_setup_log_root.patch b/0001-Plug-Memory-leak-in-find_and_setup_log_root.patch index 448055d..2fcf171 100644 --- a/0001-Plug-Memory-leak-in-find_and_setup_log_root.patch +++ b/0001-Plug-Memory-leak-in-find_and_setup_log_root.patch @@ -1,33 +1,28 @@ -From 4145e527ba81c288aa081073e1ce68fa0ceb4107 Mon Sep 17 00:00:00 2001 -From: Dirk Mueller -Date: Fri, 26 Mar 2010 11:25:43 +0100 -Subject: [PATCH] Plug Memory leak in find_and_setup_log_root() +commit a2fe2e1b978f724f53d025461e65adb4e030d043 +Author: Dirk Mueller +Date: Thu Dec 16 20:40:34 2010 +0100 -The error path forgets to free a previously allocated -memory structure. ---- - disk-io.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) + [PATCH] Plug Memory leak in find_and_setup_log_root() + + The error path forgets to free a previously allocated + memory structure. diff --git a/disk-io.c b/disk-io.c -index addebe1..eab3f0b 100644 +index a6e1000..2b5e1d5 100644 --- a/disk-io.c +++ b/disk-io.c -@@ -422,12 +422,13 @@ static int find_and_setup_log_root(struct btrfs_root *tree_root, - struct btrfs_super_block *disk_super) +@@ -423,11 +423,13 @@ static int find_and_setup_log_root(struct btrfs_root *tree_root, { u32 blocksize; -+ struct btrfs_root *log_root; u64 blocknr = btrfs_super_log_root(disk_super); - struct btrfs_root *log_root = malloc(sizeof(struct btrfs_root)); ++ struct btrfs_root *log_root; if (blocknr == 0) return 0; + log_root = malloc(sizeof(struct btrfs_root)); ++ blocksize = btrfs_level_size(tree_root, btrfs_super_log_root_level(disk_super)); --- -1.7.0.2 - diff --git a/0001-used-space-accounting-fix-for-the-converter.patch b/0001-used-space-accounting-fix-for-the-converter.patch deleted file mode 100644 index 059cab9..0000000 --- a/0001-used-space-accounting-fix-for-the-converter.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 4f89b6eb0718ade63152791db32794da78fbba70 Mon Sep 17 00:00:00 2001 -From: Yan Zheng -Date: Fri, 12 Jun 2009 12:55:50 -0400 -Subject: [PATCH 1/4] used space accounting fix for the converter - -remove code that updates the total used space, since -btrfs_update_block_group does that work now. - -Signed-off-by: Yan Zheng -Signed-off-by: Chris Mason ---- - convert.c | 7 ------- - 1 files changed, 0 insertions(+), 7 deletions(-) - -diff --git a/convert.c b/convert.c -index d2c9efa..d037c98 100644 ---- a/convert.c -+++ b/convert.c -@@ -370,7 +370,6 @@ static int record_file_extent(struct btrfs_trans_handle *trans, - struct btrfs_extent_item *ei; - u32 blocksize = root->sectorsize; - u64 nbytes; -- u64 bytes_used; - - if (disk_bytenr == 0) { - ret = btrfs_insert_file_extent(trans, root, objectid, -@@ -432,9 +431,6 @@ static int record_file_extent(struct btrfs_trans_handle *trans, - nbytes = btrfs_stack_inode_nbytes(inode) + num_bytes; - btrfs_set_stack_inode_nbytes(inode, nbytes); - -- bytes_used = btrfs_root_used(&root->root_item); -- btrfs_set_root_used(&root->root_item, bytes_used + num_bytes); -- - btrfs_release_path(root, &path); - - ins_key.objectid = disk_bytenr; -@@ -454,9 +450,6 @@ static int record_file_extent(struct btrfs_trans_handle *trans, - - btrfs_mark_buffer_dirty(leaf); - -- bytes_used = btrfs_super_bytes_used(&info->super_copy); -- btrfs_set_super_bytes_used(&info->super_copy, bytes_used + -- num_bytes); - ret = btrfs_update_block_group(trans, root, disk_bytenr, - num_bytes, 1, 0); - if (ret) --- -1.6.6.1 - diff --git a/0002-btrfsctl-add-snapshot-subvolume-destroy-ioctl.patch b/0002-btrfsctl-add-snapshot-subvolume-destroy-ioctl.patch deleted file mode 100644 index 8dc234e..0000000 --- a/0002-btrfsctl-add-snapshot-subvolume-destroy-ioctl.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 45195b216d5da399aa71c11f111b2c0b45e54c82 Mon Sep 17 00:00:00 2001 -From: Yan, Zheng -Date: Mon, 21 Sep 2009 16:03:57 -0400 -Subject: [PATCH 2/4] btrfsctl: add snapshot/subvolume destroy ioctl - -resend Aaron Straus's patch - -Signed-off-by: Yan Zheng -Signed-off-by: Chris Mason ---- - btrfsctl.c | 15 ++++++++++++++- - ioctl.h | 3 +++ - 2 files changed, 17 insertions(+), 1 deletions(-) - -diff --git a/btrfsctl.c b/btrfsctl.c -index b323818..66c4e89 100644 ---- a/btrfsctl.c -+++ b/btrfsctl.c -@@ -46,7 +46,7 @@ static inline int ioctl(int fd, int define, void *arg) { return 0; } - static void print_usage(void) - { - printf("usage: btrfsctl [ -d file|dir] [ -s snap_name subvol|tree ]\n"); -- printf(" [-r size] [-A device] [-a] [-c]\n"); -+ printf(" [-r size] [-A device] [-a] [-c] [-D dir .]\n"); - printf("\t-d filename: defragments one file\n"); - printf("\t-d directory: defragments the entire Btree\n"); - printf("\t-s snap_name dir: creates a new snapshot of dir\n"); -@@ -55,6 +55,7 @@ static void print_usage(void) - printf("\t-A device: scans the device file for a Btrfs filesystem\n"); - printf("\t-a: scans all devices for Btrfs filesystems\n"); - printf("\t-c: forces a single FS sync\n"); -+ printf("\t-D: delete snapshot\n"); - printf("%s\n", BTRFS_BUILD_VERSION); - exit(1); - } -@@ -158,6 +159,18 @@ int main(int ac, char **av) - print_usage(); - } - command = BTRFS_IOC_DEFRAG; -+ } else if (strcmp(av[i], "-D") == 0) { -+ if (i >= ac - 1) { -+ fprintf(stderr, "-D requires an arg\n"); -+ print_usage(); -+ } -+ command = BTRFS_IOC_SNAP_DESTROY; -+ name = av[i + 1]; -+ len = strlen(name); -+ if (len == 0 || len >= BTRFS_VOL_NAME_MAX) { -+ fprintf(stderr, "-D size too long\n"); -+ exit(1); -+ } - } else if (strcmp(av[i], "-A") == 0) { - if (i >= ac - 1) { - fprintf(stderr, "-A requires an arg\n"); -diff --git a/ioctl.h b/ioctl.h -index a084f33..4410ac0 100644 ---- a/ioctl.h -+++ b/ioctl.h -@@ -56,4 +56,7 @@ struct btrfs_ioctl_vol_args { - /* 13 is for CLONE_RANGE */ - #define BTRFS_IOC_SUBVOL_CREATE _IOW(BTRFS_IOCTL_MAGIC, 14, \ - struct btrfs_ioctl_vol_args) -+ -+#define BTRFS_IOC_SNAP_DESTROY _IOW(BTRFS_IOCTL_MAGIC, 15, \ -+ struct btrfs_ioctl_vol_args) - #endif --- -1.6.6.1 - diff --git a/0003-btrfsck-check-root-back-forward-references.patch b/0003-btrfsck-check-root-back-forward-references.patch deleted file mode 100644 index bfe41fc..0000000 --- a/0003-btrfsck-check-root-back-forward-references.patch +++ /dev/null @@ -1,700 +0,0 @@ -From 6f3cf25a4e7932bc737ed06bc95f73f80772092d Mon Sep 17 00:00:00 2001 -From: Yan, Zheng -Date: Mon, 21 Sep 2009 16:03:57 -0400 -Subject: [PATCH 3/4] btrfsck: check root back/forward references - -This patch adds semantic checks for links to snapshot/subvolume and -root back/forward references. - -Signed-off-by: Yan Zheng -Signed-off-by: Chris Mason ---- - btrfsck.c | 444 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- - 1 files changed, 410 insertions(+), 34 deletions(-) - -diff --git a/btrfsck.c b/btrfsck.c -index 40c90f8..73f1836 100644 ---- a/btrfsck.c -+++ b/btrfsck.c -@@ -36,7 +36,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; --int found_old_backref = 0; -+static int found_old_backref = 0; - - struct extent_backref { - struct list_head list; -@@ -100,7 +100,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) --#define REF_ERR_NAME_TOO_LONG (1 << 8) -+#define REF_ERR_NAME_TOO_LONG (1 << 8) // 100 -+#define REF_ERR_NO_ROOT_REF (1 << 9) -+#define REF_ERR_NO_ROOT_BACKREF (1 << 10) -+#define REF_ERR_DUP_ROOT_REF (1 << 11) -+#define REF_ERR_DUP_ROOT_BACKREF (1 << 12) - - struct inode_record { - struct list_head backrefs; -@@ -144,6 +148,29 @@ struct inode_record { - #define I_ERR_SOME_CSUM_MISSING (1 << 12) - #define I_ERR_LINK_COUNT_WRONG (1 << 13) - -+struct root_backref { -+ struct list_head list; -+ unsigned int found_dir_item:1; -+ unsigned int found_dir_index:1; -+ unsigned int found_back_ref:1; -+ unsigned int found_forward_ref:1; -+ unsigned int reachable:1; -+ int errors; -+ u64 ref_root; -+ u64 dir; -+ u64 index; -+ u16 namelen; -+ char name[0]; -+}; -+ -+struct root_record { -+ struct list_head backrefs; -+ struct cache_extent cache; -+ unsigned int found_root_item:1; -+ u64 objectid; -+ u32 found_ref; -+}; -+ - struct ptr_node { - struct cache_extent cache; - void *data; -@@ -151,6 +178,7 @@ struct ptr_node { - - struct shared_node { - struct cache_extent cache; -+ struct cache_tree root_cache; - struct cache_tree inode_cache; - struct inode_record *current; - u32 refs; -@@ -258,6 +286,14 @@ static void free_inode_rec(struct inode_record *rec) - free(rec); - } - -+static int can_free_inode_rec(struct inode_record *rec) -+{ -+ if (!rec->errors && rec->checked && rec->found_inode_item && -+ rec->nlink == rec->found_link && list_empty(&rec->backrefs)) -+ return 1; -+ return 0; -+} -+ - 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, - } - - BUG_ON(rec->refs != 1); -- if (!rec->errors && rec->nlink == rec->found_link && -- list_empty(&rec->backrefs)) { -+ if (can_free_inode_rec(rec)) { - 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) - return ret; - } - --static int process_inode_item(struct btrfs_root *root, -- struct extent_buffer *eb, -+static int process_inode_item(struct extent_buffer *eb, - int slot, struct btrfs_key *key, - struct shared_node *active_node) - { - struct inode_record *rec; - struct btrfs_inode_item *item; -- int ret; - - 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, - if (btrfs_inode_flags(eb, item) & BTRFS_INODE_NODATASUM) - rec->nodatasum = 1; - rec->found_inode_item = 1; -- if (rec->nlink == 0) { -- ret = check_orphan_item(root, rec->ino); -- if (ret == -ENOENT) -- rec->errors |= I_ERR_NO_ORPHAN_ITEM; -- } -+ if (rec->nlink == 0) -+ rec->errors |= I_ERR_NO_ORPHAN_ITEM; - 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, - } - - static int merge_inode_recs(struct inode_record *src, struct inode_record *dst, -- struct shared_node *dst_node) -+ struct cache_tree *dst_cache) - { - struct inode_backref *backref; -- struct cache_tree *dst_cache = &dst_node->inode_cache; - - 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, - dst->errors |= I_ERR_DUP_INODE_ITEM; - } - } -- -- if (src->checked) { -- dst->checked = 1; -- if (dst_node->current == dst) -- dst_node->current = NULL; -- } - dst->merging = 0; -- maybe_free_inode_rec(dst_cache, dst); -+ - return 0; - } - -@@ -537,8 +560,9 @@ static int splice_shared_node(struct shared_node *src_node, - if (src_node->current) - current_ino = src_node->current->ino; - -- src = &src_node->inode_cache; -- dst = &dst_node->inode_cache; -+ src = &src_node->root_cache; -+ dst = &dst_node->root_cache; -+again: - 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, - } - 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); -+ if (rec->checked) { -+ conflict->checked = 1; -+ if (dst_node->current == conflict) -+ dst_node->current = NULL; -+ } -+ maybe_free_inode_rec(dst, conflict); - free_inode_rec(rec); - free(ins); - } else { - BUG_ON(ret); - } - } -+ -+ if (src == &src_node->root_cache) { -+ src = &src_node->inode_cache; -+ dst = &dst_node->inode_cache; -+ goto again; -+ } -+ - 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) - node = calloc(1, sizeof(*node)); - node->cache.start = bytenr; - node->cache.size = 1; -+ cache_tree_init(&node->root_cache); - 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, - if (wc->root_level == wc->active_node && - btrfs_root_refs(&root->root_item) == 0) { - if (--node->refs == 0) { -+ free_inode_recs(&node->root_cache); - 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, - int filetype; - struct btrfs_dir_item *di; - struct inode_record *rec; -+ struct cache_tree *root_cache; - struct cache_tree *inode_cache; - struct btrfs_key location; - char namebuf[BTRFS_NAME_LEN]; - -+ root_cache = &active_node->root_cache; - 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, - key->objectid, key->offset, namebuf, - len, filetype, key->type, error); - } else if (location.type == BTRFS_ROOT_ITEM_KEY) { -- /* fixme: check root back & forward references */ -+ add_inode_backref(root_cache, location.objectid, -+ key->objectid, key->offset, namebuf, -+ len, filetype, key->type, error); - } 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, - ret = process_inode_ref(eb, i, &key, active_node); - break; - case BTRFS_INODE_ITEM_KEY: -- ret = process_inode_item(root, eb, i, &key, -- active_node); -+ ret = process_inode_item(eb, i, &key, active_node); - 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, - node = container_of(cache, struct ptr_node, cache); - rec = node->data; - remove_cache_extent(inode_cache, &node->cache); -+ free(node); - if (rec->ino == root_dirid || - rec->ino == BTRFS_ORPHAN_OBJECTID) { -- free(node); - free_inode_rec(rec); - continue; - } - -+ if (rec->errors & I_ERR_NO_ORPHAN_ITEM) { -+ ret = check_orphan_item(root, rec->ino); -+ if (ret == 0) -+ rec->errors &= ~I_ERR_NO_ORPHAN_ITEM; -+ if (can_free_inode_rec(rec)) { -+ free_inode_rec(rec); -+ continue; -+ } -+ } -+ - 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, - backref->namelen, backref->name, - backref->filetype, backref->errors); - } -- free(node); - free_inode_rec(rec); - } - return (error > 0) ? -1 : 0; - } - -+static struct root_record *get_root_rec(struct cache_tree *root_cache, -+ u64 objectid) -+{ -+ struct cache_extent *cache; -+ struct root_record *rec = NULL; -+ int ret; -+ -+ cache = find_cache_extent(root_cache, objectid, 1); -+ if (cache) { -+ rec = container_of(cache, struct root_record, cache); -+ } else { -+ rec = calloc(1, sizeof(*rec)); -+ rec->objectid = objectid; -+ INIT_LIST_HEAD(&rec->backrefs); -+ rec->cache.start = objectid; -+ rec->cache.size = 1; -+ -+ ret = insert_existing_cache_extent(root_cache, &rec->cache); -+ BUG_ON(ret); -+ } -+ return rec; -+} -+ -+static struct root_backref *get_root_backref(struct root_record *rec, -+ u64 ref_root, u64 dir, u64 index, -+ const char *name, int namelen) -+{ -+ struct root_backref *backref; -+ -+ list_for_each_entry(backref, &rec->backrefs, list) { -+ if (backref->ref_root != ref_root || backref->dir != dir || -+ backref->namelen != namelen) -+ continue; -+ if (memcmp(name, backref->name, namelen)) -+ continue; -+ return backref; -+ } -+ -+ backref = malloc(sizeof(*backref) + namelen + 1); -+ memset(backref, 0, sizeof(*backref)); -+ backref->ref_root = ref_root; -+ backref->dir = dir; -+ backref->index = index; -+ backref->namelen = namelen; -+ memcpy(backref->name, name, namelen); -+ backref->name[namelen] = '\0'; -+ list_add_tail(&backref->list, &rec->backrefs); -+ return backref; -+} -+ -+static void free_root_recs(struct cache_tree *root_cache) -+{ -+ struct cache_extent *cache; -+ struct root_record *rec; -+ struct root_backref *backref; -+ -+ while (1) { -+ cache = find_first_cache_extent(root_cache, 0); -+ if (!cache) -+ break; -+ rec = container_of(cache, struct root_record, cache); -+ remove_cache_extent(root_cache, &rec->cache); -+ -+ while (!list_empty(&rec->backrefs)) { -+ backref = list_entry(rec->backrefs.next, -+ struct root_backref, list); -+ list_del(&backref->list); -+ free(backref); -+ } -+ kfree(rec); -+ } -+} -+ -+static int add_root_backref(struct cache_tree *root_cache, -+ u64 root_id, u64 ref_root, u64 dir, u64 index, -+ const char *name, int namelen, -+ int item_type, int errors) -+{ -+ struct root_record *rec; -+ struct root_backref *backref; -+ -+ rec = get_root_rec(root_cache, root_id); -+ backref = get_root_backref(rec, ref_root, dir, index, name, namelen); -+ -+ backref->errors |= errors; -+ -+ if (item_type != BTRFS_DIR_ITEM_KEY) { -+ if (backref->found_dir_index || backref->found_back_ref || -+ backref->found_forward_ref) { -+ if (backref->index != index) -+ backref->errors |= REF_ERR_INDEX_UNMATCH; -+ } else { -+ backref->index = index; -+ } -+ } -+ -+ if (item_type == BTRFS_DIR_ITEM_KEY) { -+ backref->found_dir_item = 1; -+ backref->reachable = 1; -+ rec->found_ref++; -+ } else if (item_type == BTRFS_DIR_INDEX_KEY) { -+ backref->found_dir_index = 1; -+ } else if (item_type == BTRFS_ROOT_REF_KEY) { -+ if (backref->found_forward_ref) -+ backref->errors |= REF_ERR_DUP_ROOT_REF; -+ backref->found_forward_ref = 1; -+ } else if (item_type == BTRFS_ROOT_BACKREF_KEY) { -+ if (backref->found_back_ref) -+ backref->errors |= REF_ERR_DUP_ROOT_BACKREF; -+ backref->found_back_ref = 1; -+ } else { -+ BUG_ON(1); -+ } -+ -+ return 0; -+} -+ -+static int merge_root_recs(struct btrfs_root *root, -+ struct cache_tree *src_cache, -+ struct cache_tree *dst_cache) -+{ -+ struct cache_extent *cache; -+ struct ptr_node *node; -+ struct inode_record *rec; -+ struct inode_backref *backref; -+ -+ if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) { -+ free_inode_recs(src_cache); -+ return 0; -+ } -+ -+ while (1) { -+ cache = find_first_cache_extent(src_cache, 0); -+ if (!cache) -+ break; -+ node = container_of(cache, struct ptr_node, cache); -+ rec = node->data; -+ remove_cache_extent(src_cache, &node->cache); -+ free(node); -+ -+ list_for_each_entry(backref, &rec->backrefs, list) { -+ BUG_ON(backref->found_inode_ref); -+ if (backref->found_dir_item) -+ add_root_backref(dst_cache, rec->ino, -+ root->root_key.objectid, backref->dir, -+ backref->index, backref->name, -+ backref->namelen, BTRFS_DIR_ITEM_KEY, -+ backref->errors); -+ if (backref->found_dir_index) -+ add_root_backref(dst_cache, rec->ino, -+ root->root_key.objectid, backref->dir, -+ backref->index, backref->name, -+ backref->namelen, BTRFS_DIR_INDEX_KEY, -+ backref->errors); -+ } -+ free_inode_rec(rec); -+ } -+ return 0; -+} -+ -+static int check_root_refs(struct btrfs_root *root, -+ struct cache_tree *root_cache) -+{ -+ struct root_record *rec; -+ struct root_record *ref_root; -+ struct root_backref *backref; -+ struct cache_extent *cache; -+ int loop = 1; -+ int ret; -+ int error; -+ int errors = 0; -+ -+ rec = get_root_rec(root_cache, BTRFS_FS_TREE_OBJECTID); -+ rec->found_ref = 1; -+ -+ /* fixme: this can not detect circular references */ -+ while (loop) { -+ loop = 0; -+ cache = find_first_cache_extent(root_cache, 0); -+ while (1) { -+ if (!cache) -+ break; -+ rec = container_of(cache, struct root_record, cache); -+ cache = next_cache_extent(cache); -+ -+ if (rec->found_ref == 0) -+ continue; -+ -+ list_for_each_entry(backref, &rec->backrefs, list) { -+ if (!backref->reachable) -+ continue; -+ -+ ref_root = get_root_rec(root_cache, -+ backref->ref_root); -+ if (ref_root->found_ref > 0) -+ continue; -+ -+ backref->reachable = 0; -+ rec->found_ref--; -+ if (rec->found_ref == 0) -+ loop = 1; -+ } -+ } -+ } -+ -+ cache = find_first_cache_extent(root_cache, 0); -+ while (1) { -+ if (!cache) -+ break; -+ rec = container_of(cache, struct root_record, cache); -+ cache = next_cache_extent(cache); -+ -+ if (rec->found_ref == 0 && -+ rec->objectid >= BTRFS_FIRST_FREE_OBJECTID && -+ rec->objectid <= BTRFS_LAST_FREE_OBJECTID) { -+ ret = check_orphan_item(root->fs_info->tree_root, -+ rec->objectid); -+ if (ret == 0) -+ continue; -+ errors++; -+ fprintf(stderr, "fs tree %llu not referenced\n", -+ (unsigned long long)rec->objectid); -+ } -+ -+ error = 0; -+ if (rec->found_ref > 0 && !rec->found_root_item) -+ error = 1; -+ list_for_each_entry(backref, &rec->backrefs, list) { -+ if (!backref->found_dir_item) -+ backref->errors |= REF_ERR_NO_DIR_ITEM; -+ if (!backref->found_dir_index) -+ backref->errors |= REF_ERR_NO_DIR_INDEX; -+ if (!backref->found_back_ref) -+ backref->errors |= REF_ERR_NO_ROOT_BACKREF; -+ if (!backref->found_forward_ref) -+ backref->errors |= REF_ERR_NO_ROOT_REF; -+ if (backref->reachable && backref->errors) -+ error = 1; -+ } -+ if (!error) -+ continue; -+ -+ errors++; -+ fprintf(stderr, "fs tree %llu refs %u %s\n", -+ (unsigned long long)rec->objectid, rec->found_ref, -+ rec->found_root_item ? "" : "not found"); -+ -+ list_for_each_entry(backref, &rec->backrefs, list) { -+ if (!backref->reachable) -+ continue; -+ if (!backref->errors && rec->found_root_item) -+ continue; -+ fprintf(stderr, "\tunresolved ref root %llu dir %llu" -+ " index %llu namelen %u name %s error %x\n", -+ (unsigned long long)backref->ref_root, -+ (unsigned long long)backref->dir, -+ (unsigned long long)backref->index, -+ backref->namelen, backref->name, -+ backref->errors); -+ } -+ } -+ return errors > 0 ? 1 : 0; -+} -+ -+static int process_root_ref(struct extent_buffer *eb, int slot, -+ struct btrfs_key *key, -+ struct cache_tree *root_cache) -+{ -+ u64 dirid; -+ u64 index; -+ u32 len; -+ u32 name_len; -+ struct btrfs_root_ref *ref; -+ char namebuf[BTRFS_NAME_LEN]; -+ int error; -+ -+ ref = btrfs_item_ptr(eb, slot, struct btrfs_root_ref); -+ -+ dirid = btrfs_root_ref_dirid(eb, ref); -+ index = btrfs_root_ref_sequence(eb, ref); -+ name_len = btrfs_root_ref_name_len(eb, ref); -+ -+ if (name_len <= BTRFS_NAME_LEN) { -+ len = name_len; -+ error = 0; -+ } else { -+ len = BTRFS_NAME_LEN; -+ error = REF_ERR_NAME_TOO_LONG; -+ } -+ read_extent_buffer(eb, namebuf, (unsigned long)(ref + 1), len); -+ -+ if (key->type == BTRFS_ROOT_REF_KEY) { -+ add_root_backref(root_cache, key->offset, key->objectid, dirid, -+ index, namebuf, len, key->type, error); -+ } else { -+ add_root_backref(root_cache, key->objectid, key->offset, dirid, -+ index, namebuf, len, key->type, error); -+ } -+ return 0; -+} -+ - static int check_fs_root(struct btrfs_root *root, -+ struct cache_tree *root_cache, - struct walk_control *wc) - { - int ret = 0; -@@ -1219,10 +1573,18 @@ static int check_fs_root(struct btrfs_root *root, - int level; - struct btrfs_path path; - struct shared_node root_node; -+ struct root_record *rec; - struct btrfs_root_item *root_item = &root->root_item; - -+ if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) { -+ rec = get_root_rec(root_cache, root->root_key.objectid); -+ if (btrfs_root_refs(root_item) > 0) -+ rec->found_root_item = 1; -+ } -+ - btrfs_init_path(&path); - memset(&root_node, 0, sizeof(root_node)); -+ cache_tree_init(&root_node.root_cache); - 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, - } - btrfs_release_path(root, &path); - -+ merge_root_recs(root, &root_node.root_cache, root_cache); -+ - 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) - { - if (objectid == BTRFS_FS_TREE_OBJECTID || - objectid == BTRFS_TREE_RELOC_OBJECTID || -+ objectid == BTRFS_DATA_RELOC_TREE_OBJECTID || - (objectid >= BTRFS_FIRST_FREE_OBJECTID && -- objectid < BTRFS_LAST_FREE_OBJECTID)) -+ objectid <= BTRFS_LAST_FREE_OBJECTID)) - return 1; - return 0; - } - --static int check_fs_roots(struct btrfs_root *root) -+static int check_fs_roots(struct btrfs_root *root, -+ struct cache_tree *root_cache) - { - struct btrfs_path path; - struct btrfs_key key; -@@ -1319,10 +1685,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); -- ret = check_fs_root(tmp_root, &wc); -+ ret = check_fs_root(tmp_root, root_cache, &wc); - if (ret) - err = 1; - btrfs_free_fs_root(root->fs_info, tmp_root); -+ } else if (key.type == BTRFS_ROOT_REF_KEY || -+ key.type == BTRFS_ROOT_BACKREF_KEY) { -+ process_root_ref(leaf, path.slots[0], &key, -+ root_cache); - } - path.slots[0]++; - } -@@ -1895,7 +2265,6 @@ static int add_data_backref(struct cache_tree *extent_cache, u64 bytenr, - return 0; - } - -- - 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) - - int main(int ac, char **av) - { -+ struct cache_tree root_cache; - struct btrfs_root *root; - int ret; - -@@ -2450,6 +2820,7 @@ int main(int ac, char **av) - print_usage(); - - radix_tree_init(); -+ cache_tree_init(&root_cache); - root = open_ctree(av[1], 0, 0); - - if (root == NULL) -@@ -2458,10 +2829,15 @@ int main(int ac, char **av) - ret = check_extents(root); - if (ret) - goto out; -- ret = check_fs_roots(root); -+ ret = check_fs_roots(root, &root_cache); -+ if (ret) -+ goto out; - -+ ret = check_root_refs(root, &root_cache); - out: -+ free_root_recs(&root_cache); - close_ctree(root); -+ - if (found_old_backref) { - /* - * there was a disk format change when mixed --- -1.6.6.1 - diff --git a/0004-Add-btrfs-map-logical-program-to-map-and-read-logica.patch b/0004-Add-btrfs-map-logical-program-to-map-and-read-logica.patch deleted file mode 100644 index 685acf7..0000000 --- a/0004-Add-btrfs-map-logical-program-to-map-and-read-logica.patch +++ /dev/null @@ -1,271 +0,0 @@ -From ab8fb4c99516c186641bda1dbc0e788f68b4dc77 Mon Sep 17 00:00:00 2001 -From: Chris Mason -Date: Thu, 12 Nov 2009 14:34:09 -0500 -Subject: [PATCH 4/4] Add btrfs-map-logical program to map and read logical block numbers - -This allows us to figure out which physical byte offset on which device -is the real location for a given logical block number. It can -optionally read the block in and save it to a file for debugging -analysis. - -Signed-off-by: Chris Mason ---- - Makefile | 6 +- - btrfs-map-logical.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 226 insertions(+), 1 deletions(-) - create mode 100644 btrfs-map-logical.c - -diff --git a/Makefile b/Makefile -index 8097b5a..02f881e 100644 ---- a/Makefile -+++ b/Makefile -@@ -16,7 +16,8 @@ prefix ?= /usr/local - bindir = $(prefix)/bin - LIBS=-luuid - --progs = btrfsctl mkfs.btrfs btrfs-debug-tree btrfs-show btrfs-vol btrfsck -+progs = btrfsctl mkfs.btrfs btrfs-debug-tree btrfs-show btrfs-vol btrfsck \ -+ btrfs-map-logical - - # make C=1 to enable sparse - ifdef C -@@ -56,6 +57,9 @@ btrfs-debug-tree: $(objects) debug-tree.o - btrfstune: $(objects) btrfstune.o - gcc $(CFLAGS) -o btrfstune $(objects) btrfstune.o $(LDFLAGS) $(LIBS) - -+btrfs-map-logical: $(objects) btrfs-map-logical.o -+ gcc $(CFLAGS) -o btrfs-map-logical $(objects) btrfs-map-logical.o $(LDFLAGS) $(LIBS) -+ - btrfs-image: $(objects) btrfs-image.o - gcc $(CFLAGS) -o btrfs-image $(objects) btrfs-image.o -lpthread -lz $(LDFLAGS) $(LIBS) - -diff --git a/btrfs-map-logical.c b/btrfs-map-logical.c -new file mode 100644 -index 0000000..a109c6a ---- /dev/null -+++ b/btrfs-map-logical.c -@@ -0,0 +1,221 @@ -+/* -+ * Copyright (C) 2009 Oracle. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public -+ * License v2 as published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public -+ * License along with this program; if not, write to the -+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, -+ * Boston, MA 021110-1307, USA. -+ */ -+ -+#define _XOPEN_SOURCE 500 -+#define _GNU_SOURCE 1 -+#include -+#include -+#include -+#include -+#include -+#include "kerncompat.h" -+#include "ctree.h" -+#include "volumes.h" -+#include "disk-io.h" -+#include "print-tree.h" -+#include "transaction.h" -+#include "list.h" -+#include "version.h" -+ -+/* we write the mirror info to stdout unless they are dumping the data -+ * to stdout -+ * */ -+static FILE *info_file; -+ -+struct extent_buffer *debug_read_block(struct btrfs_root *root, u64 bytenr, -+ u32 blocksize, int copy) -+{ -+ int ret; -+ int dev_nr; -+ struct extent_buffer *eb; -+ u64 length; -+ struct btrfs_multi_bio *multi = NULL; -+ struct btrfs_device *device; -+ int num_copies; -+ int mirror_num = 1; -+ -+ eb = btrfs_find_create_tree_block(root, bytenr, blocksize); -+ if (!eb) -+ return NULL; -+ -+ dev_nr = 0; -+ length = blocksize; -+ while (1) { -+ ret = btrfs_map_block(&root->fs_info->mapping_tree, READ, -+ eb->start, &length, &multi, mirror_num); -+ BUG_ON(ret); -+ device = multi->stripes[0].dev; -+ eb->fd = device->fd; -+ device->total_ios++; -+ eb->dev_bytenr = multi->stripes[0].physical; -+ -+ fprintf(info_file, "mirror %d logical %Lu physical %Lu " -+ "device %s\n", mirror_num, bytenr, eb->dev_bytenr, -+ device->name); -+ kfree(multi); -+ -+ if (!copy || mirror_num == copy) -+ ret = read_extent_from_disk(eb); -+ -+ num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, -+ eb->start, eb->len); -+ if (num_copies == 1) -+ break; -+ -+ mirror_num++; -+ if (mirror_num > num_copies) -+ break; -+ } -+ return eb; -+} -+ -+static void print_usage(void) -+{ -+ fprintf(stderr, "usage: btrfs-map-logical [options] mount_point\n"); -+ fprintf(stderr, "\t-l Logical extent to map\n"); -+ fprintf(stderr, "\t-c Copy of the extent to read (usually 1 or 2)\n"); -+ fprintf(stderr, "\t-o Output file to hold the extent\n"); -+ fprintf(stderr, "\t-s Number of bytes to read\n"); -+ exit(1); -+} -+ -+static struct option long_options[] = { -+ /* { "byte-count", 1, NULL, 'b' }, */ -+ { "logical", 1, NULL, 'l' }, -+ { "copy", 1, NULL, 'c' }, -+ { "output", 1, NULL, 'c' }, -+ { "bytes", 1, NULL, 'b' }, -+ { 0, 0, 0, 0} -+}; -+ -+int main(int ac, char **av) -+{ -+ struct cache_tree root_cache; -+ struct btrfs_root *root; -+ struct extent_buffer *eb; -+ char *dev; -+ char *output_file = NULL; -+ u64 logical = 0; -+ int ret = 0; -+ int option_index = 0; -+ int copy = 0; -+ u64 bytes = 0; -+ int out_fd = 0; -+ int err; -+ -+ while(1) { -+ int c; -+ c = getopt_long(ac, av, "l:c:o:b:", long_options, -+ &option_index); -+ if (c < 0) -+ break; -+ switch(c) { -+ case 'l': -+ logical = atoll(optarg); -+ if (logical == 0) { -+ fprintf(stderr, -+ "invalid extent number\n"); -+ print_usage(); -+ } -+ break; -+ case 'c': -+ copy = atoi(optarg); -+ if (copy == 0) { -+ fprintf(stderr, -+ "invalid copy number\n"); -+ print_usage(); -+ } -+ break; -+ case 'b': -+ bytes = atoll(optarg); -+ if (bytes == 0) { -+ fprintf(stderr, -+ "invalid byte count\n"); -+ print_usage(); -+ } -+ break; -+ case 'o': -+ output_file = strdup(optarg); -+ break; -+ default: -+ print_usage(); -+ } -+ } -+ ac = ac - optind; -+ if (ac == 0) -+ print_usage(); -+ if (logical == 0) -+ print_usage(); -+ if (copy < 0) -+ print_usage(); -+ -+ dev = av[optind]; -+ -+ radix_tree_init(); -+ cache_tree_init(&root_cache); -+ -+ root = open_ctree(dev, 0, 0); -+ if (!root) { -+ fprintf(stderr, "Open ctree failed\n"); -+ exit(1); -+ } -+ -+ if (output_file) { -+ if (strcmp(output_file, "-") == 0) { -+ out_fd = 1; -+ info_file = stderr; -+ } else { -+ out_fd = open(output_file, O_RDWR | O_CREAT, 0600); -+ if (out_fd < 0) -+ goto close; -+ err = ftruncate(out_fd, 0); -+ if (err) { -+ close(out_fd); -+ goto close; -+ } -+ info_file = stdout; -+ } -+ } -+ -+ if (bytes == 0) -+ bytes = root->sectorsize; -+ -+ bytes = (bytes + root->sectorsize - 1) / root->sectorsize; -+ bytes *= root->sectorsize; -+ -+ while (bytes > 0) { -+ eb = debug_read_block(root, logical, root->sectorsize, copy); -+ if (eb && output_file) { -+ err = write(out_fd, eb->data, eb->len); -+ if (err < 0 || err != eb->len) { -+ fprintf(stderr, "output file write failed\n"); -+ goto out_close_fd; -+ } -+ } -+ free_extent_buffer(eb); -+ logical += root->sectorsize; -+ bytes -= root->sectorsize; -+ } -+ -+out_close_fd: -+ if (output_file && out_fd != 1) -+ close(out_fd); -+close: -+ close_ctree(root); -+ return ret; -+} --- -1.6.6.1 - diff --git a/btrfs-progs-0.19.tar.bz2 b/btrfs-progs-0.19.tar.bz2 deleted file mode 100644 index 3096125..0000000 --- a/btrfs-progs-0.19.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f8a3dd03e87a33506d16ccc1e5a77c4c38ff1fa84b9502ed4b88c0b39fab70fc -size 118119 diff --git a/btrfs-progs-v0.19-35-g1b444cd.tar.bz2 b/btrfs-progs-v0.19-35-g1b444cd.tar.bz2 new file mode 100644 index 0000000..8aacf83 --- /dev/null +++ b/btrfs-progs-v0.19-35-g1b444cd.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe020924c698dd770d9ff46cb3f8a3c19b561b3c296d39e1e9c08f172e2c1728 +size 132541 diff --git a/btrfsprogs.changes b/btrfsprogs.changes index 72442eb..ac6e84a 100644 --- a/btrfsprogs.changes +++ b/btrfsprogs.changes @@ -1,3 +1,25 @@ +------------------------------------------------------------------- +Thu Dec 16 20:53:19 CET 2010 - dmueller@suse.de + +- update to v0.19-35-g1b444cd: + * used space accounting fix for the converter + * Add btrfs-list for listing subvolumes + * Add new util: 'btrfs' + * multidevice support for check_mounted + * check slash in deleting subvolumes + * Add btrfsck option to select the super block copy + * btrfs-debug-tree: add -d option to print only the device mapping + +------------------------------------------------------------------- +Wed May 26 17:00:46 CEST 2010 - dmueller@suse.de + +- fix crash on creating filesystems (bnc#603620) + +------------------------------------------------------------------- +Fri May 7 15:05:11 CEST 2010 - dmueller@suse.de + +- revert last change (bnc#599224#c3) + ------------------------------------------------------------------- Thu Apr 29 11:11:13 CEST 2010 - dmueller@suse.de diff --git a/btrfsprogs.spec b/btrfsprogs.spec index 5fa18e4..a49c964 100644 --- a/btrfsprogs.spec +++ b/btrfsprogs.spec @@ -15,48 +15,42 @@ # Please submit bugfixes or comments via http://bugs.opensuse.org/ # - - Name: btrfsprogs Url: http://oss.oracle.com/~mason/btrfs/ Version: 0.19 -Release: 8 +Release: 35.g1b444cd +%define tar_version v0.19-35-g1b444cd Summary: Btrfs File System Utilities License: GNU General Public License (GPL) Group: System/Filesystems Supplements: filesystem(btrfs) -Source: http://ftp.kernel.org/pub/linux/kernel/people/mason/btrfs/btrfs-progs-%{version}.tar.bz2 +Source: btrfs-progs-%{tar_version}.tar.bz2 Patch0: memleak-fix.diff -Patch1: 0001-used-space-accounting-fix-for-the-converter.patch -Patch2: 0002-btrfsctl-add-snapshot-subvolume-destroy-ioctl.patch -Patch3: 0003-btrfsck-check-root-back-forward-references.patch -Patch4: 0004-Add-btrfs-map-logical-program-to-map-and-read-logica.patch -Patch5: 0001-Plug-Memory-leak-in-find_and_setup_log_root.patch +Patch1: 0001-Plug-Memory-leak-in-find_and_setup_log_root.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: libacl-devel libext2fs-devel libuuid-devel zlib-devel %description -This package contains utilities for creating, checking, and debugging btrfs -file systems. +This package contains utilities for creating, checking, and +debugging btrfs file systems. %prep -%setup -q -n btrfs-progs-%{version} +%setup -q -n btrfs-progs-%{tar_version} %patch0 %patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 %build make %{?jobs:-j%jobs} CFLAGS="%{optflags}" all convert %install make install DESTDIR=${RPM_BUILD_ROOT} prefix=%{_prefix} bindir=/sbin mandir=%{_mandir} -ln ${RPM_BUILD_ROOT}/sbin/btrfsck ${RPM_BUILD_ROOT}/sbin/fsck.btrfs +# command line options are not compatible (bnc#599224) +#ln ${RPM_BUILD_ROOT}/sbin/btrfsck ${RPM_BUILD_ROOT}/sbin/fsck.btrfs + %files %defattr(-, root, root) +/sbin/btrfs /sbin/btrfs-debug-tree /sbin/btrfs-show /sbin/btrfs-vol @@ -64,13 +58,14 @@ ln ${RPM_BUILD_ROOT}/sbin/btrfsck ${RPM_BUILD_ROOT}/sbin/fsck.btrfs /sbin/btrfsck /sbin/btrfsctl /sbin/mkfs.btrfs -/sbin/fsck.btrfs +#/sbin/fsck.btrfs /sbin/btrfs-map-logical %_mandir/man8/btrfs-image.8.gz %_mandir/man8/btrfs-show.8.gz %_mandir/man8/btrfsck.8.gz %_mandir/man8/btrfsctl.8.gz %_mandir/man8/mkfs.btrfs.8.gz +%_mandir/man8/btrfs.8.gz %clean rm -rf $RPM_BUILD_ROOT From 078cfa8efc6f7e40fa8c0182cef8f8fad3b88901ed23907f255e037b733aa04e Mon Sep 17 00:00:00 2001 From: Dirk Mueller Date: Mon, 14 Mar 2011 18:24:28 +0000 Subject: [PATCH 5/5] - add link for fsck.btrfs (bnc#665899) OBS-URL: https://build.opensuse.org/package/show/filesystems/btrfsprogs?expand=0&rev=98 --- btrfsprogs.changes | 5 +++++ btrfsprogs.spec | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/btrfsprogs.changes b/btrfsprogs.changes index ac6e84a..7312ca0 100644 --- a/btrfsprogs.changes +++ b/btrfsprogs.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Mon Mar 14 19:19:34 CET 2011 - dmueller@suse.de + +- add link for fsck.btrfs (bnc#665899) + ------------------------------------------------------------------- Thu Dec 16 20:53:19 CET 2010 - dmueller@suse.de diff --git a/btrfsprogs.spec b/btrfsprogs.spec index a49c964..7966ef8 100644 --- a/btrfsprogs.spec +++ b/btrfsprogs.spec @@ -29,6 +29,8 @@ Patch0: memleak-fix.diff Patch1: 0001-Plug-Memory-leak-in-find_and_setup_log_root.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: libacl-devel libext2fs-devel libuuid-devel zlib-devel +# for /bin/true +Requires: coreutils %description This package contains utilities for creating, checking, and @@ -46,6 +48,7 @@ make %{?jobs:-j%jobs} CFLAGS="%{optflags}" all convert make install DESTDIR=${RPM_BUILD_ROOT} prefix=%{_prefix} bindir=/sbin mandir=%{_mandir} # command line options are not compatible (bnc#599224) #ln ${RPM_BUILD_ROOT}/sbin/btrfsck ${RPM_BUILD_ROOT}/sbin/fsck.btrfs +ln -s /bin/true ${RPM_BUILD_ROOT}/sbin/fsck.btrfs %files @@ -58,7 +61,7 @@ make install DESTDIR=${RPM_BUILD_ROOT} prefix=%{_prefix} bindir=/sbin mandir=%{_ /sbin/btrfsck /sbin/btrfsctl /sbin/mkfs.btrfs -#/sbin/fsck.btrfs +/sbin/fsck.btrfs /sbin/btrfs-map-logical %_mandir/man8/btrfs-image.8.gz %_mandir/man8/btrfs-show.8.gz