Accepting request 108879 from filesystems
- place binaries in /usr tree (UsrMerge project) - adjust mkinitrd script accordingly - add btrfsck repair options for: - rebuild extent records - fix block group accounting - reset csums for rescue nodatasum mount - prune corrupt extent allocation tree blocks - device scanning fixes for dm and multipath - initrd support: move btrfs device scan after block device setup - documentation updates - add csize for file commpressed size - updated restore utility OBS-URL: https://build.opensuse.org/request/show/108879 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/btrfsprogs?expand=0&rev=26
This commit is contained in:
parent
dc3edf7a66
commit
c3a893d519
File diff suppressed because it is too large
Load Diff
181
0114-btrfs-progs-Add-ioctl-to-read-compressed-size-of-a-f.patch
Normal file
181
0114-btrfs-progs-Add-ioctl-to-read-compressed-size-of-a-f.patch
Normal file
@ -0,0 +1,181 @@
|
||||
From 72218a2090e1cbafe9baa97aaa465a28438c3dbb Mon Sep 17 00:00:00 2001
|
||||
From: David Sterba <dsterba@suse.cz>
|
||||
Date: Mon, 19 Dec 2011 17:51:11 +0100
|
||||
Subject: [PATCH 16/43] btrfs-progs: Add ioctl to read compressed size of a
|
||||
file
|
||||
|
||||
Signed-off-by: David Sterba <dsterba@suse.cz>
|
||||
---
|
||||
btrfs.c | 9 ++++++-
|
||||
btrfs_cmds.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
btrfs_cmds.h | 1 +
|
||||
ioctl.h | 13 ++++++++++
|
||||
man/btrfs.8.in.old | 10 +++++++
|
||||
5 files changed, 100 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/btrfs.c b/btrfs.c
|
||||
index e78f194..f5b8fd4 100644
|
||||
--- a/btrfs.c
|
||||
+++ b/btrfs.c
|
||||
@@ -325,7 +325,14 @@ static struct Command commands[] = {
|
||||
"filesystem label", "<device> [<newlabel>]\n"
|
||||
"With one argument, get the label of filesystem on <device>.\n"
|
||||
"If <newlabel> is passed, set the filesystem label to <newlabel>.\n"
|
||||
- "The filesystem must be unmounted.\n"
|
||||
+ "The filesystem must be unmounted."
|
||||
+ },
|
||||
+ { do_compr_size, -1,
|
||||
+ "filesystem csize", "[-s start] [-e end] <file>\n"
|
||||
+ "Read ordinary and compressed size of extents in the range [start,end)\n"
|
||||
+ "-s start range start inclusive, accepts K/M/G modifiers\n"
|
||||
+ "-e end range end exclusive, accepts K/M/G modifiers\n",
|
||||
+ NULL
|
||||
},
|
||||
{ do_scrub_start, -1,
|
||||
"scrub start", "[-Bdqr] <path>|<device>\n"
|
||||
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
|
||||
index 12346e5..c8196d1 100644
|
||||
--- a/btrfs_cmds.c
|
||||
+++ b/btrfs_cmds.c
|
||||
@@ -2058,3 +2058,71 @@ out:
|
||||
free(inodes);
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
+int do_compr_size(int argc, char **argv)
|
||||
+{
|
||||
+ int ret;
|
||||
+ int fd;
|
||||
+ struct btrfs_ioctl_compr_size_args args;
|
||||
+
|
||||
+ args.start = 0;
|
||||
+ args.end = (u64)-1;
|
||||
+ optind = 1;
|
||||
+ while (1) {
|
||||
+ int c = getopt(argc, argv, "s:e:r");
|
||||
+ if (c < 0)
|
||||
+ break;
|
||||
+ switch (c) {
|
||||
+ case 's':
|
||||
+ args.start = parse_size(optarg);
|
||||
+ break;
|
||||
+ case 'e':
|
||||
+ args.end = parse_size(optarg);
|
||||
+ break;
|
||||
+ default:
|
||||
+ fprintf(stderr, "ERROR: Invalid arguments for csize\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (args.start > args.end) {
|
||||
+ fprintf(stderr, "ERROR: Invalid range for csize\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ if (argc - optind == 0) {
|
||||
+ fprintf(stderr, "ERROR: Invalid arguments for csize\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+ argc -= optind;
|
||||
+
|
||||
+ fd = open_file_or_dir(argv[optind]);
|
||||
+ if (fd < 0) {
|
||||
+ fprintf(stderr, "ERROR: can't access '%s'\n", argv[optind]);
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ ret = ioctl(fd, BTRFS_IOC_COMPR_SIZE, &args);
|
||||
+ if (ret < 0) {
|
||||
+ fprintf(stderr, "ERROR: ioctl returned %d, errno %d %s\n",
|
||||
+ ret, errno, strerror(errno));
|
||||
+ return errno;
|
||||
+ }
|
||||
+
|
||||
+ printf("File name: %s\n", argv[optind]);
|
||||
+ if (args.end == (u64)-1)
|
||||
+ printf("File range: %llu-EOF\n",
|
||||
+ (unsigned long long)args.start);
|
||||
+ else
|
||||
+ printf("File range: %llu-%llu\n",
|
||||
+ (unsigned long long)args.start,
|
||||
+ (unsigned long long)args.end);
|
||||
+
|
||||
+ printf("Compressed size: %llu\n",
|
||||
+ (unsigned long long)(args.compressed_size << 9));
|
||||
+ printf("Uncompressed size: %llu\n",
|
||||
+ (unsigned long long)(args.size << 9));
|
||||
+ printf("Ratio: %3.2f%%\n",
|
||||
+ 100.0 * args.compressed_size / args.size);
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/btrfs_cmds.h b/btrfs_cmds.h
|
||||
index 53d51d6..07dad7a 100644
|
||||
--- a/btrfs_cmds.h
|
||||
+++ b/btrfs_cmds.h
|
||||
@@ -46,3 +46,4 @@ int open_file_or_dir(const char *fname);
|
||||
int do_ino_to_path(int nargs, char **argv);
|
||||
int do_logical_to_ino(int nargs, char **argv);
|
||||
char *path_for_root(int fd, u64 root);
|
||||
+int do_compr_size(int argc, char **argv);
|
||||
diff --git a/ioctl.h b/ioctl.h
|
||||
index 78aebce..a820098 100644
|
||||
--- a/ioctl.h
|
||||
+++ b/ioctl.h
|
||||
@@ -272,6 +272,17 @@ struct btrfs_ioctl_logical_ino_args {
|
||||
__u64 inodes;
|
||||
};
|
||||
|
||||
+struct btrfs_ioctl_compr_size_args {
|
||||
+ /* Range start, inclusive */
|
||||
+ __u64 start; /* in */
|
||||
+ /* Range end, exclusive */
|
||||
+ __u64 end; /* in */
|
||||
+ __u64 size; /* out */
|
||||
+ __u64 compressed_size; /* out */
|
||||
+ __u64 reserved[2];
|
||||
+};
|
||||
+
|
||||
+
|
||||
/* BTRFS_IOC_SNAP_CREATE is no longer used by the btrfs command */
|
||||
#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
|
||||
struct btrfs_ioctl_vol_args)
|
||||
@@ -330,5 +341,7 @@ struct btrfs_ioctl_logical_ino_args {
|
||||
struct btrfs_ioctl_ino_path_args)
|
||||
#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
|
||||
struct btrfs_ioctl_ino_path_args)
|
||||
+#define BTRFS_IOC_COMPR_SIZE _IOR(BTRFS_IOCTL_MAGIC, 51, \
|
||||
+ struct btrfs_ioctl_compr_size_args)
|
||||
|
||||
#endif
|
||||
diff --git a/man/btrfs.8.in.old b/man/btrfs.8.in.old
|
||||
index be478e0..b7dacea 100644
|
||||
--- a/man/btrfs.8.in.old
|
||||
+++ b/man/btrfs.8.in.old
|
||||
@@ -31,6 +31,8 @@ btrfs \- control a btrfs filesystem
|
||||
.PP
|
||||
\fBbtrfs\fP \fBfilesystem defragment\fP\fI <file>|<dir> [<file>|<dir>...]\fP
|
||||
.PP
|
||||
+\fBbtrfs\fP \fBfilesystem csize \fP\fI [-s start] [-e end] <file> \fP
|
||||
+.PP
|
||||
\fBbtrfs\fP \fBdevice scan\fP\fI [--all-devices|<device> [<device>...]]\fP
|
||||
.PP
|
||||
\fBbtrfs\fP \fBdevice show\fP\fI [--all-devices|<uuid>|<label>]\fP
|
||||
@@ -209,6 +211,14 @@ If \fB--all-devices\fP is passed, all the devices under /dev are scanned;
|
||||
otherwise the devices list is extracted from the /proc/partitions file.
|
||||
.TP
|
||||
|
||||
+\fBfilesystem csize \fR \fI [-s start] [-e end] <file> \fR
|
||||
+Read ordinary and compressed size of extents in the range [start,end) of \fI<file>\fR
|
||||
+.IP
|
||||
+\fB-s start\fP range start inclusive, accepts K/M/G modifiers
|
||||
+.IP
|
||||
+\fB-e end\fP range end exclusive, accepts K/M/G modifiers
|
||||
+.TP
|
||||
+
|
||||
\fBdevice balance\fR \fI<path>\fR
|
||||
Balance the chunks of the filesystem identified by \fI<path>\fR
|
||||
across the devices.
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,34 @@
|
||||
From b36b23becb0d79faefd38da11b684a78b95243c9 Mon Sep 17 00:00:00 2001
|
||||
From: Josef Bacik <josef@redhat.com>
|
||||
Date: Wed, 4 Jan 2012 09:56:06 -0500
|
||||
Subject: [PATCH 36/43] Btrfs-progs: make find root spit out the size of the
|
||||
disk
|
||||
|
||||
In order to figure out what exactly is broken on a fs we need to spit out the
|
||||
current offset we are on and the size of the fs to know if the super is wrong
|
||||
and we just need to ignore it, or if the offset we got is bad and we should just
|
||||
keep searching. Thanks,
|
||||
|
||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
||||
---
|
||||
find-root.c | 4 +++-
|
||||
1 files changed, 3 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/find-root.c b/find-root.c
|
||||
index e0bc069..f9cb7ed 100644
|
||||
--- a/find-root.c
|
||||
+++ b/find-root.c
|
||||
@@ -258,7 +258,9 @@ static int find_root(struct btrfs_root *root)
|
||||
|
||||
if (offset >
|
||||
btrfs_super_total_bytes(&root->fs_info->super_copy)) {
|
||||
- printf("Went past the fs size, exiting");
|
||||
+ printf("Went past the fs size, exiting, offset=%Lu, "
|
||||
+ "total_bytes=%Lu\n", offset,
|
||||
+ btrfs_super_total_bytes(&root->fs_info->super_copy));
|
||||
break;
|
||||
}
|
||||
if (offset >= (metadata_offset + metadata_size)) {
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
50
0140-Btrfs-progs-add-some-verbose-output-to-find-root.patch
Normal file
50
0140-Btrfs-progs-add-some-verbose-output-to-find-root.patch
Normal file
@ -0,0 +1,50 @@
|
||||
From d4d88fe3c9b393e2b21754237104c68a37123aa6 Mon Sep 17 00:00:00 2001
|
||||
From: Josef Bacik <josef@redhat.com>
|
||||
Date: Wed, 4 Jan 2012 10:03:33 -0500
|
||||
Subject: [PATCH 37/43] Btrfs-progs: add some verbose output to find-root
|
||||
|
||||
Trying to track down why we can't find roots, add some verbose output so we know
|
||||
what chunks we're scanning and when we move to new chunks. Thanks,
|
||||
|
||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
||||
---
|
||||
find-root.c | 9 +++++++++
|
||||
1 files changed, 9 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/find-root.c b/find-root.c
|
||||
index f9cb7ed..484f85f 100644
|
||||
--- a/find-root.c
|
||||
+++ b/find-root.c
|
||||
@@ -250,6 +250,10 @@ static int find_root(struct btrfs_root *root)
|
||||
return ret;
|
||||
|
||||
offset = metadata_offset;
|
||||
+ if (verbose)
|
||||
+ printf("Checking metadata chunk %Lu, size %Lu\n",
|
||||
+ metadata_offset, metadata_size);
|
||||
+
|
||||
while (1) {
|
||||
u64 map_length = 4096;
|
||||
u64 type;
|
||||
@@ -264,6 +268,8 @@ static int find_root(struct btrfs_root *root)
|
||||
break;
|
||||
}
|
||||
if (offset >= (metadata_offset + metadata_size)) {
|
||||
+ if (verbose)
|
||||
+ printf("Moving to the next metadata chunk\n");
|
||||
err = btrfs_next_metadata(&root->fs_info->mapping_tree,
|
||||
&metadata_offset,
|
||||
&metadata_size);
|
||||
@@ -272,6 +278,9 @@ static int find_root(struct btrfs_root *root)
|
||||
break;
|
||||
}
|
||||
offset = metadata_offset;
|
||||
+ if (verbose)
|
||||
+ printf("Checking metadata chunk %Lu, size %Lu"
|
||||
+ "\n", metadata_offset, metadata_size);
|
||||
}
|
||||
mirror_num = 1;
|
||||
again:
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
@ -0,0 +1,46 @@
|
||||
From f0346659db85b826c14392f9a627d845ab47b7e2 Mon Sep 17 00:00:00 2001
|
||||
From: Josef Bacik <josef@redhat.com>
|
||||
Date: Wed, 4 Jan 2012 10:36:41 -0500
|
||||
Subject: [PATCH 38/43] Btrfs-progs: fix restore to actually use the root
|
||||
location if specified
|
||||
|
||||
We were using the wrong variable for the root location if we specified -f when
|
||||
doing restore. Fix this. Thanks,
|
||||
|
||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
||||
---
|
||||
restore.c | 6 +++---
|
||||
1 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/restore.c b/restore.c
|
||||
index 95daef2..0b75902 100644
|
||||
--- a/restore.c
|
||||
+++ b/restore.c
|
||||
@@ -871,13 +871,13 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_
|
||||
return NULL;
|
||||
}
|
||||
if (!root_location)
|
||||
- bytenr = btrfs_super_root(&root->fs_info->super_copy);
|
||||
+ root_location = btrfs_super_root(&root->fs_info->super_copy);
|
||||
|
||||
blocksize = btrfs_level_size(root,
|
||||
btrfs_super_root_level(&root->fs_info->super_copy));
|
||||
generation = btrfs_super_generation(&root->fs_info->super_copy);
|
||||
|
||||
- root->fs_info->tree_root->node = read_tree_block(root, bytenr,
|
||||
+ root->fs_info->tree_root->node = read_tree_block(root, root_location,
|
||||
blocksize,
|
||||
generation);
|
||||
if (!root->fs_info->tree_root->node) {
|
||||
@@ -895,7 +895,7 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_
|
||||
|
||||
root->fs_info->fs_root = btrfs_read_fs_root(root->fs_info, &key);
|
||||
if (IS_ERR(root->fs_info->fs_root)) {
|
||||
- fprintf(stderr, "Couldn't read fs_root: %ld\n", PTR_ERR(root));
|
||||
+ fprintf(stderr, "Couldn't read fs_root: %d\n", PTR_ERR(root));
|
||||
close_ctree(root);
|
||||
return NULL;
|
||||
}
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
@ -0,0 +1,35 @@
|
||||
From a3958e5a851f8d0efeafe5946b8a32ea0fd45436 Mon Sep 17 00:00:00 2001
|
||||
From: Josef Bacik <josef@redhat.com>
|
||||
Date: Wed, 4 Jan 2012 10:37:43 -0500
|
||||
Subject: [PATCH 39/43] Btrfs-progs: remove the physical disk size check from
|
||||
find-root
|
||||
|
||||
Our logical offsets may be beyond what we think the size of the disk is, so our
|
||||
check is bogus, remove it. Thanks,
|
||||
|
||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
||||
---
|
||||
find-root.c | 7 -------
|
||||
1 files changed, 0 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/find-root.c b/find-root.c
|
||||
index 484f85f..43cb778 100644
|
||||
--- a/find-root.c
|
||||
+++ b/find-root.c
|
||||
@@ -260,13 +260,6 @@ static int find_root(struct btrfs_root *root)
|
||||
int mirror_num;
|
||||
int num_copies;
|
||||
|
||||
- if (offset >
|
||||
- btrfs_super_total_bytes(&root->fs_info->super_copy)) {
|
||||
- printf("Went past the fs size, exiting, offset=%Lu, "
|
||||
- "total_bytes=%Lu\n", offset,
|
||||
- btrfs_super_total_bytes(&root->fs_info->super_copy));
|
||||
- break;
|
||||
- }
|
||||
if (offset >= (metadata_offset + metadata_size)) {
|
||||
if (verbose)
|
||||
printf("Moving to the next metadata chunk\n");
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
@ -0,0 +1,34 @@
|
||||
From 5ec6eeaff067c706e5bb9fc3144e9bab4e50da1e Mon Sep 17 00:00:00 2001
|
||||
From: Josef Bacik <josef@redhat.com>
|
||||
Date: Wed, 4 Jan 2012 10:48:32 -0500
|
||||
Subject: [PATCH 40/43] Btrfs-progs: fix error output and dont read from cache
|
||||
|
||||
If we have to build our fs_info by hand don't read from the cache when looking
|
||||
for the fs_root just in case we set something up last time. Also actually print
|
||||
the right error, not the root which is ok. Thanks,
|
||||
|
||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
||||
---
|
||||
restore.c | 5 +++--
|
||||
1 files changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/restore.c b/restore.c
|
||||
index 0b75902..abc66ca 100644
|
||||
--- a/restore.c
|
||||
+++ b/restore.c
|
||||
@@ -893,9 +893,10 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_
|
||||
key.type = BTRFS_ROOT_ITEM_KEY;
|
||||
key.offset = (u64)-1;
|
||||
|
||||
- root->fs_info->fs_root = btrfs_read_fs_root(root->fs_info, &key);
|
||||
+ root->fs_info->fs_root = btrfs_read_fs_root_no_cache(root->fs_info, &key);
|
||||
if (IS_ERR(root->fs_info->fs_root)) {
|
||||
- fprintf(stderr, "Couldn't read fs_root: %d\n", PTR_ERR(root));
|
||||
+ fprintf(stderr, "Couldn't read fs_root: %d\n",
|
||||
+ PTR_ERR(root->fs_info->fs_root));
|
||||
close_ctree(root);
|
||||
return NULL;
|
||||
}
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
@ -0,0 +1,32 @@
|
||||
From a657103b449bfae0cc67dc9d7153ee19c20d9115 Mon Sep 17 00:00:00 2001
|
||||
From: Josef Bacik <josef@redhat.com>
|
||||
Date: Wed, 4 Jan 2012 10:50:31 -0500
|
||||
Subject: [PATCH 41/43] Btrfs-progs: print the objectid of the root we find
|
||||
when doing find-root
|
||||
|
||||
We need to know if we find a valid fs tree when doing find root, so print the
|
||||
objectid of the roots we find when we find a tree root. Thanks,
|
||||
|
||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
||||
---
|
||||
find-root.c | 4 +++-
|
||||
1 files changed, 3 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/find-root.c b/find-root.c
|
||||
index 43cb778..bc7440a 100644
|
||||
--- a/find-root.c
|
||||
+++ b/find-root.c
|
||||
@@ -138,7 +138,9 @@ static int dump_root_bytenr(struct btrfs_root *root, u64 bytenr, u64 gen)
|
||||
|
||||
offset = btrfs_item_ptr_offset(leaf, slot);
|
||||
read_extent_buffer(leaf, &ri, offset, sizeof(ri));
|
||||
- printf("Generation: %Lu Root bytenr: %Lu\n", gen, btrfs_root_bytenr(&ri));
|
||||
+ printf("Generation: %Lu Root bytenr: %Lu "
|
||||
+ "Root objectid: %Lu\n", gen,
|
||||
+ btrfs_root_bytenr(&ri), found_key.objectid);
|
||||
}
|
||||
path->slots[0]++;
|
||||
}
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
170
0145-Btrfs-progs-make-specifying-root-objectid-work-if-th.patch
Normal file
170
0145-Btrfs-progs-make-specifying-root-objectid-work-if-th.patch
Normal file
@ -0,0 +1,170 @@
|
||||
From 87edb6fbf4991e47e7563c4589197aa88befe266 Mon Sep 17 00:00:00 2001
|
||||
From: Josef Bacik <josef@redhat.com>
|
||||
Date: Wed, 4 Jan 2012 11:50:55 -0500
|
||||
Subject: [PATCH 42/43] Btrfs-progs: make specifying root objectid work if the
|
||||
fs is broken
|
||||
|
||||
We need to be able to handle the case where we want to restore from a specific
|
||||
root if the fs is really really really toast, this patch does that. Thanks,
|
||||
|
||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
||||
---
|
||||
restore.c | 109 +++++++++++++++++++++++++++++++++++++++----------------------
|
||||
1 files changed, 70 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/restore.c b/restore.c
|
||||
index abc66ca..5aa35ae 100644
|
||||
--- a/restore.c
|
||||
+++ b/restore.c
|
||||
@@ -837,7 +837,35 @@ static int do_list_roots(struct btrfs_root *root)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_mirror, int list_roots)
|
||||
+static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
|
||||
+ u32 stripesize, struct btrfs_root *root,
|
||||
+ struct btrfs_fs_info *fs_info, u64 objectid)
|
||||
+{
|
||||
+ root->node = NULL;
|
||||
+ root->commit_root = NULL;
|
||||
+ root->sectorsize = sectorsize;
|
||||
+ root->nodesize = nodesize;
|
||||
+ root->leafsize = leafsize;
|
||||
+ root->stripesize = stripesize;
|
||||
+ root->ref_cows = 0;
|
||||
+ root->track_dirty = 0;
|
||||
+
|
||||
+ root->fs_info = fs_info;
|
||||
+ root->objectid = objectid;
|
||||
+ root->last_trans = 0;
|
||||
+ root->highest_inode = 0;
|
||||
+ root->last_inode_alloc = 0;
|
||||
+
|
||||
+ INIT_LIST_HEAD(&root->dirty_list);
|
||||
+ memset(&root->root_key, 0, sizeof(root->root_key));
|
||||
+ memset(&root->root_item, 0, sizeof(root->root_item));
|
||||
+ root->root_key.objectid = objectid;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct btrfs_root *open_fs(const char *dev, u64 root_location,
|
||||
+ u64 fs_location, u64 root_objectid,
|
||||
+ int super_mirror, int list_roots)
|
||||
{
|
||||
struct btrfs_key key;
|
||||
struct btrfs_root *root;
|
||||
@@ -889,23 +917,51 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_
|
||||
if (list_roots)
|
||||
goto out;
|
||||
|
||||
- key.objectid = BTRFS_FS_TREE_OBJECTID;
|
||||
- key.type = BTRFS_ROOT_ITEM_KEY;
|
||||
- key.offset = (u64)-1;
|
||||
+ if (!root_objectid)
|
||||
+ root_objectid = BTRFS_FS_TREE_OBJECTID;
|
||||
|
||||
- root->fs_info->fs_root = btrfs_read_fs_root_no_cache(root->fs_info, &key);
|
||||
- if (IS_ERR(root->fs_info->fs_root)) {
|
||||
- fprintf(stderr, "Couldn't read fs_root: %d\n",
|
||||
- PTR_ERR(root->fs_info->fs_root));
|
||||
- close_ctree(root);
|
||||
- return NULL;
|
||||
- }
|
||||
out:
|
||||
+ if (fs_location) {
|
||||
+ struct btrfs_root *fs_root = root->fs_info->fs_root;
|
||||
+ if (fs_root) {
|
||||
+ free_extent_buffer(fs_root->node);
|
||||
+ } else {
|
||||
+ fs_root = malloc(sizeof(struct btrfs_root));
|
||||
+ if (!fs_root) {
|
||||
+ fprintf(stderr, "Out of memory\n");
|
||||
+ close_ctree(root);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ __setup_root(4096, 4096, 4096, 4096, fs_root,
|
||||
+ root->fs_info, root_objectid);
|
||||
+ root->fs_info->fs_root = fs_root;
|
||||
+ }
|
||||
+ fs_root->node = read_tree_block(root, fs_location, 4096, 0);
|
||||
+ if (!fs_root->node) {
|
||||
+ fprintf(stderr, "Failed to read fs location\n");
|
||||
+ close_ctree(root);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ } else if (root_objectid) {
|
||||
+ key.objectid = root_objectid;
|
||||
+ key.type = BTRFS_ROOT_ITEM_KEY;
|
||||
+ key.offset = (u64)-1;
|
||||
+
|
||||
+ root->fs_info->fs_root =
|
||||
+ btrfs_read_fs_root_no_cache(root->fs_info, &key);
|
||||
+ if (IS_ERR(root->fs_info->fs_root)) {
|
||||
+ fprintf(stderr, "Error reading fs root %d\n",
|
||||
+ PTR_ERR(root->fs_info->fs_root));
|
||||
+ close_ctree(root);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (list_roots) {
|
||||
int ret = do_list_roots(root);
|
||||
if (ret) {
|
||||
- root = NULL;
|
||||
close_ctree(root);
|
||||
+ return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1074,22 +1130,14 @@ int main(int argc, char **argv)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
- root = open_fs(argv[optind], tree_location, super_mirror, list_roots);
|
||||
+ root = open_fs(argv[optind], tree_location, fs_location, root_objectid,
|
||||
+ super_mirror, list_roots);
|
||||
if (root == NULL)
|
||||
return 1;
|
||||
|
||||
if (list_roots)
|
||||
goto out;
|
||||
|
||||
- if (fs_location != 0) {
|
||||
- free_extent_buffer(root->node);
|
||||
- root->node = read_tree_block(root, fs_location, 4096, 0);
|
||||
- if (!root->node) {
|
||||
- fprintf(stderr, "Failed to read fs location\n");
|
||||
- goto out;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
memset(path_name, 0, 4096);
|
||||
|
||||
strncpy(dir_name, argv[optind + 1], 128);
|
||||
@@ -1102,23 +1150,6 @@ int main(int argc, char **argv)
|
||||
dir_name[len - 1] = '\0';
|
||||
}
|
||||
|
||||
- if (root_objectid != 0) {
|
||||
- struct btrfs_root *orig_root = root;
|
||||
-
|
||||
- key.objectid = root_objectid;
|
||||
- key.type = BTRFS_ROOT_ITEM_KEY;
|
||||
- key.offset = (u64)-1;
|
||||
- root = btrfs_read_fs_root(orig_root->fs_info, &key);
|
||||
- if (IS_ERR(root)) {
|
||||
- fprintf(stderr, "Error reading root\n");
|
||||
- root = orig_root;
|
||||
- ret = 1;
|
||||
- goto out;
|
||||
- }
|
||||
- key.type = 0;
|
||||
- key.offset = 0;
|
||||
- }
|
||||
-
|
||||
if (find_dir) {
|
||||
ret = find_first_dir(root, &key.objectid);
|
||||
if (ret)
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
31
0146-Btrfs-progs-don-t-free-the-existing-node.patch
Normal file
31
0146-Btrfs-progs-don-t-free-the-existing-node.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From 77ac61128a0722cab89c785f5f2247304133b214 Mon Sep 17 00:00:00 2001
|
||||
From: Josef Bacik <josef@redhat.com>
|
||||
Date: Wed, 4 Jan 2012 11:55:43 -0500
|
||||
Subject: [PATCH 43/43] Btrfs-progs: don't free the existing node
|
||||
|
||||
It may be used elsewhere and in the case of a broken fs it won't be there at all
|
||||
and it makes an assertion trip. Thanks,
|
||||
|
||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
||||
---
|
||||
restore.c | 4 +---
|
||||
1 files changed, 1 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/restore.c b/restore.c
|
||||
index 5aa35ae..a2c2931 100644
|
||||
--- a/restore.c
|
||||
+++ b/restore.c
|
||||
@@ -923,9 +923,7 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location,
|
||||
out:
|
||||
if (fs_location) {
|
||||
struct btrfs_root *fs_root = root->fs_info->fs_root;
|
||||
- if (fs_root) {
|
||||
- free_extent_buffer(fs_root->node);
|
||||
- } else {
|
||||
+ if (!fs_root) {
|
||||
fs_root = malloc(sizeof(struct btrfs_root));
|
||||
if (!fs_root) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
@ -0,0 +1,97 @@
|
||||
From 7e2b203768ae87b3614149e99e00afe4fa9394ab Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kara <jack@suse.cz>
|
||||
Date: Thu, 26 Jan 2012 17:03:05 +0100
|
||||
Subject: [PATCH] mkfs: Handle creation of filesystem larger than the first
|
||||
device
|
||||
|
||||
make_btrfs() function takes a size of filesystem as an argument. It uses this
|
||||
value to set the size of the first device as well which is wrong for
|
||||
filesystems larger than this device. It results in 'attemp to access beyond end
|
||||
of device' messages from the kernel. So add size of the first device as an
|
||||
argument to make_btrfs().
|
||||
|
||||
CC: David Sterba <dsterba@suse.cz>
|
||||
Signed-off-by: Jan Kara <jack@suse.cz>
|
||||
---
|
||||
convert.c | 2 +-
|
||||
mkfs.c | 6 ++++--
|
||||
utils.c | 4 ++--
|
||||
utils.h | 2 +-
|
||||
4 files changed, 8 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/convert.c b/convert.c
|
||||
index c036f46..13f3ece 100644
|
||||
--- a/convert.c
|
||||
+++ b/convert.c
|
||||
@@ -2374,7 +2374,7 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr)
|
||||
goto fail;
|
||||
}
|
||||
ret = make_btrfs(fd, devname, ext2_fs->super->s_volume_name,
|
||||
- blocks, total_bytes, blocksize, blocksize,
|
||||
+ blocks, total_bytes, total_bytes, blocksize, blocksize,
|
||||
blocksize, blocksize);
|
||||
if (ret) {
|
||||
fprintf(stderr, "unable to create initial ctree\n");
|
||||
diff --git a/mkfs.c b/mkfs.c
|
||||
index be236d0..97481bd 100644
|
||||
--- a/mkfs.c
|
||||
+++ b/mkfs.c
|
||||
@@ -1302,8 +1302,10 @@ int main(int ac, char **av)
|
||||
first_file = file;
|
||||
source_dir_size = size_sourcedir(source_dir, sectorsize,
|
||||
&num_of_meta_chunks, &size_of_data);
|
||||
- if(block_count < source_dir_size)
|
||||
+ if (block_count < source_dir_size)
|
||||
block_count = source_dir_size;
|
||||
+ dev_block_count = block_count;
|
||||
+
|
||||
ret = zero_output_file(fd, block_count, sectorsize);
|
||||
if (ret) {
|
||||
fprintf(stderr, "unable to zero the output file\n");
|
||||
@@ -1329,7 +1331,7 @@ int main(int ac, char **av)
|
||||
leafsize * i;
|
||||
}
|
||||
|
||||
- ret = make_btrfs(fd, file, label, blocks, block_count,
|
||||
+ ret = make_btrfs(fd, file, label, blocks, block_count, dev_block_count,
|
||||
nodesize, leafsize,
|
||||
sectorsize, stripesize);
|
||||
if (ret) {
|
||||
diff --git a/utils.c b/utils.c
|
||||
index 6c96548..a2be9c9 100644
|
||||
--- a/utils.c
|
||||
+++ b/utils.c
|
||||
@@ -74,7 +74,7 @@ static u64 reference_root_table[] = {
|
||||
};
|
||||
|
||||
int make_btrfs(int fd, const char *device, const char *label,
|
||||
- u64 blocks[7], u64 num_bytes, u32 nodesize,
|
||||
+ u64 blocks[7], u64 num_bytes, u64 dev_num_bytes, u32 nodesize,
|
||||
u32 leafsize, u32 sectorsize, u32 stripesize)
|
||||
{
|
||||
struct btrfs_super_block super;
|
||||
@@ -276,7 +276,7 @@ int make_btrfs(int fd, const char *device, const char *label,
|
||||
dev_item = btrfs_item_ptr(buf, nritems, struct btrfs_dev_item);
|
||||
btrfs_set_device_id(buf, dev_item, 1);
|
||||
btrfs_set_device_generation(buf, dev_item, 0);
|
||||
- btrfs_set_device_total_bytes(buf, dev_item, num_bytes);
|
||||
+ btrfs_set_device_total_bytes(buf, dev_item, dev_num_bytes);
|
||||
btrfs_set_device_bytes_used(buf, dev_item,
|
||||
BTRFS_MKFS_SYSTEM_GROUP_SIZE);
|
||||
btrfs_set_device_io_align(buf, dev_item, sectorsize);
|
||||
diff --git a/utils.h b/utils.h
|
||||
index c5f55e1..bf2d5a4 100644
|
||||
--- a/utils.h
|
||||
+++ b/utils.h
|
||||
@@ -22,7 +22,7 @@
|
||||
#define BTRFS_MKFS_SYSTEM_GROUP_SIZE (4 * 1024 * 1024)
|
||||
|
||||
int make_btrfs(int fd, const char *device, const char *label,
|
||||
- u64 blocks[6], u64 num_bytes, u32 nodesize,
|
||||
+ u64 blocks[6], u64 num_bytes, u64 dev_num_bytes, u32 nodesize,
|
||||
u32 leafsize, u32 sectorsize, u32 stripesize);
|
||||
int btrfs_make_root_dir(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root, u64 objectid);
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
@ -0,0 +1,45 @@
|
||||
From c250b72ed982832cb8833dd962afed6ec7c5b27e Mon Sep 17 00:00:00 2001
|
||||
From: Phillip Susi <psusi@cfl.rr.com>
|
||||
Date: Mon, 9 Jan 2012 10:18:55 -0500
|
||||
Subject: [PATCH 150/151] btrfs-progs: removed extraneous whitespace from mkfs
|
||||
man page
|
||||
|
||||
There were extra spaces around some of the arguments in the man
|
||||
page for mkfs.
|
||||
|
||||
Signed-off-by: Phillip Susi <psusi@cfl.rr.com>
|
||||
---
|
||||
man/mkfs.btrfs.8.in | 22 +++++++++++-----------
|
||||
1 files changed, 11 insertions(+), 11 deletions(-)
|
||||
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/man/mkfs.btrfs.8.in
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/man/mkfs.btrfs.8.in
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/man/mkfs.btrfs.8.in
|
||||
@@ -5,16 +5,16 @@ mkfs.btrfs \- create an btrfs filesystem
|
||||
.B mkfs.btrfs
|
||||
[ \fB\-A\fP\fI alloc-start\fP ]
|
||||
[ \fB\-b\fP\fI byte-count\fP ]
|
||||
-[ \fB \-d\fP\fI data-profile\fP ]
|
||||
-[ \fB \-f\fP ]
|
||||
-[ \fB \-l\fP\fI leafsize\fP ]
|
||||
-[ \fB \-L\fP\fI label\fP ]
|
||||
-[ \fB \-m\fP\fI metadata profile\fP ]
|
||||
-[ \fB \-M\fP\fI mixed data+metadata\fP ]
|
||||
-[ \fB \-n\fP\fI nodesize\fP ]
|
||||
-[ \fB \-s\fP\fI sectorsize\fP ]
|
||||
-[ \fB \-h\fP ]
|
||||
-[ \fB \-V\fP ] \fI device\fP [ \fI device ...\fP ]
|
||||
+[ \fB\-d\fP\fI data-profile\fP ]
|
||||
+[ \fB\-f\fP ]
|
||||
+[ \fB\-l\fP\fI leafsize\fP ]
|
||||
+[ \fB\-L\fP\fI label\fP ]
|
||||
+[ \fB\-m\fP\fI metadata profile\fP ]
|
||||
+[ \fB\-M\fP\fI mixed data+metadata\fP ]
|
||||
+[ \fB\-n\fP\fI nodesize\fP ]
|
||||
+[ \fB\-s\fP\fI sectorsize\fP ]
|
||||
+[ \fB\-h\fP ]
|
||||
+[ \fB\-V\fP ] \fI device\fP [ \fI device ...\fP ]
|
||||
.SH DESCRIPTION
|
||||
.B mkfs.btrfs
|
||||
is used to create an btrfs filesystem (usually in a disk partition, or an array
|
32
0151-btrfs-progs-document-rootdir-mkfs-switch.patch
Normal file
32
0151-btrfs-progs-document-rootdir-mkfs-switch.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From 3a858a5e19255c402f7c97f492d0b2ac69cf286a Mon Sep 17 00:00:00 2001
|
||||
From: Phillip Susi <psusi@cfl.rr.com>
|
||||
Date: Mon, 9 Jan 2012 10:18:56 -0500
|
||||
Subject: [PATCH 151/151] btrfs-progs: document --rootdir mkfs switch
|
||||
|
||||
Signed-off-by: Phillip Susi <psusi@cfl.rr.com>
|
||||
---
|
||||
man/mkfs.btrfs.8.in | 4 ++++
|
||||
1 files changed, 4 insertions(+), 0 deletions(-)
|
||||
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/man/mkfs.btrfs.8.in
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/man/mkfs.btrfs.8.in
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/man/mkfs.btrfs.8.in
|
||||
@@ -13,6 +13,7 @@ mkfs.btrfs \- create an btrfs filesystem
|
||||
[ \fB\-M\fP\fI mixed data+metadata\fP ]
|
||||
[ \fB\-n\fP\fI nodesize\fP ]
|
||||
[ \fB\-s\fP\fI sectorsize\fP ]
|
||||
+[ \fB\-r\fP\fI rootdir\fP ]
|
||||
[ \fB\-h\fP ]
|
||||
[ \fB\-V\fP ] \fI device\fP [ \fI device ...\fP ]
|
||||
.SH DESCRIPTION
|
||||
@@ -62,6 +63,9 @@ Specify the nodesize. By default the val
|
||||
\fB\-s\fR, \fB\-\-sectorsize \fIsize\fR
|
||||
Specify the sectorsize, the minimum block allocation.
|
||||
.TP
|
||||
+\fB\-r\fR, \fB\-\-rootdir \fIrootdir\fR
|
||||
+Specify a directory to copy into the newly created fs.
|
||||
+.TP
|
||||
\fB\-V\fR, \fB\-\-version\fR
|
||||
Print the \fBmkfs.btrfs\fP version and exit.
|
||||
.SH AVAILABILITY
|
409
0152-Add-open_ctree_fs_info-for-partial-FS-opens.patch
Normal file
409
0152-Add-open_ctree_fs_info-for-partial-FS-opens.patch
Normal file
@ -0,0 +1,409 @@
|
||||
From bffb42193524b984ec8407773a0997707bb20cbf Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Sun, 5 Feb 2012 16:11:48 -0500
|
||||
Subject: [PATCH 01/18] Add open_ctree_fs_info for partial FS opens
|
||||
|
||||
fsck needs to be able to open a damaged FS, which means open_ctree needs
|
||||
to be able to return a damaged FS.
|
||||
|
||||
This adds a new open_ctree_fs_info which can be used to open any and all
|
||||
roots that are valid. btrfs-debug-tree is changed to use it.
|
||||
|
||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||
---
|
||||
btrfsck.c | 7 +++-
|
||||
debug-tree.c | 59 +++++++++++++++++++++++++-------------
|
||||
disk-io.c | 90 ++++++++++++++++++++++++++++++++++++---------------------
|
||||
disk-io.h | 3 ++
|
||||
extent_io.c | 3 ++
|
||||
5 files changed, 107 insertions(+), 55 deletions(-)
|
||||
|
||||
diff --git a/btrfsck.c b/btrfsck.c
|
||||
index 509ab72..40eb407 100644
|
||||
--- a/btrfsck.c
|
||||
+++ b/btrfsck.c
|
||||
@@ -2809,6 +2809,7 @@ int main(int ac, char **av)
|
||||
{
|
||||
struct cache_tree root_cache;
|
||||
struct btrfs_root *root;
|
||||
+ struct btrfs_fs_info *info;
|
||||
u64 bytenr = 0;
|
||||
int ret;
|
||||
int num;
|
||||
@@ -2846,11 +2847,13 @@ int main(int ac, char **av)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
- root = open_ctree(av[optind], bytenr, 0);
|
||||
+ info = open_ctree_fs_info(av[optind], bytenr, 0, 0);
|
||||
|
||||
- if (root == NULL)
|
||||
+ if (info == NULL)
|
||||
return 1;
|
||||
|
||||
+ root = info->fs_root;
|
||||
+
|
||||
ret = check_extents(root);
|
||||
if (ret)
|
||||
goto out;
|
||||
diff --git a/debug-tree.c b/debug-tree.c
|
||||
index 2aeabfd..c497892 100644
|
||||
--- a/debug-tree.c
|
||||
+++ b/debug-tree.c
|
||||
@@ -104,6 +104,7 @@ static void print_old_roots(struct btrfs_super_block *super)
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
struct btrfs_root *root;
|
||||
+ struct btrfs_fs_info *info;
|
||||
struct btrfs_path path;
|
||||
struct btrfs_key key;
|
||||
struct btrfs_root_item ri;
|
||||
@@ -152,12 +153,18 @@ int main(int ac, char **av)
|
||||
if (ac != 1)
|
||||
print_usage();
|
||||
|
||||
- root = open_ctree(av[optind], 0, 0);
|
||||
- if (!root) {
|
||||
+ info = open_ctree_fs_info(av[optind], 0, 0, 1);
|
||||
+ if (!info) {
|
||||
fprintf(stderr, "unable to open %s\n", av[optind]);
|
||||
exit(1);
|
||||
}
|
||||
+ root = info->fs_root;
|
||||
+
|
||||
if (block_only) {
|
||||
+ if (!root) {
|
||||
+ fprintf(stderr, "unable to open %s\n", av[optind]);
|
||||
+ exit(1);
|
||||
+ }
|
||||
leaf = read_tree_block(root,
|
||||
block_only,
|
||||
root->leafsize, 0);
|
||||
@@ -184,25 +191,32 @@ int main(int ac, char **av)
|
||||
if (!extent_only) {
|
||||
if (roots_only) {
|
||||
printf("root tree: %llu level %d\n",
|
||||
- (unsigned long long)root->fs_info->tree_root->node->start,
|
||||
- btrfs_header_level(root->fs_info->tree_root->node));
|
||||
+ (unsigned long long)info->tree_root->node->start,
|
||||
+ btrfs_header_level(info->tree_root->node));
|
||||
printf("chunk tree: %llu level %d\n",
|
||||
- (unsigned long long)root->fs_info->chunk_root->node->start,
|
||||
- btrfs_header_level(root->fs_info->chunk_root->node));
|
||||
+ (unsigned long long)info->chunk_root->node->start,
|
||||
+ btrfs_header_level(info->chunk_root->node));
|
||||
} else {
|
||||
- printf("root tree\n");
|
||||
- btrfs_print_tree(root->fs_info->tree_root,
|
||||
- root->fs_info->tree_root->node, 1);
|
||||
+ if (info->tree_root->node) {
|
||||
+ printf("root tree\n");
|
||||
+ btrfs_print_tree(info->tree_root,
|
||||
+ info->tree_root->node, 1);
|
||||
+ }
|
||||
|
||||
- printf("chunk tree\n");
|
||||
- btrfs_print_tree(root->fs_info->chunk_root,
|
||||
- root->fs_info->chunk_root->node, 1);
|
||||
+ if (info->chunk_root->node) {
|
||||
+ printf("chunk tree\n");
|
||||
+ btrfs_print_tree(info->chunk_root,
|
||||
+ info->chunk_root->node, 1);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
- tree_root_scan = root->fs_info->tree_root;
|
||||
+ tree_root_scan = info->tree_root;
|
||||
|
||||
btrfs_init_path(&path);
|
||||
again:
|
||||
+ if (!extent_buffer_uptodate(tree_root_scan->node))
|
||||
+ goto no_node;
|
||||
+
|
||||
key.offset = 0;
|
||||
key.objectid = 0;
|
||||
btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
|
||||
@@ -232,6 +246,9 @@ again:
|
||||
btrfs_level_size(tree_root_scan,
|
||||
btrfs_root_level(&ri)),
|
||||
0);
|
||||
+ if (!extent_buffer_uptodate(buf))
|
||||
+ goto next;
|
||||
+
|
||||
switch(found_key.objectid) {
|
||||
case BTRFS_ROOT_TREE_OBJECTID:
|
||||
if (!skip)
|
||||
@@ -320,13 +337,15 @@ again:
|
||||
}
|
||||
}
|
||||
}
|
||||
+next:
|
||||
path.slots[0]++;
|
||||
}
|
||||
+no_node:
|
||||
btrfs_release_path(root, &path);
|
||||
|
||||
- if (tree_root_scan == root->fs_info->tree_root &&
|
||||
- root->fs_info->log_root_tree) {
|
||||
- tree_root_scan = root->fs_info->log_root_tree;
|
||||
+ if (tree_root_scan == info->tree_root &&
|
||||
+ info->log_root_tree) {
|
||||
+ tree_root_scan = info->log_root_tree;
|
||||
goto again;
|
||||
}
|
||||
|
||||
@@ -334,14 +353,14 @@ again:
|
||||
return 0;
|
||||
|
||||
if (root_backups)
|
||||
- print_old_roots(&root->fs_info->super_copy);
|
||||
+ print_old_roots(&info->super_copy);
|
||||
|
||||
printf("total bytes %llu\n",
|
||||
- (unsigned long long)btrfs_super_total_bytes(&root->fs_info->super_copy));
|
||||
+ (unsigned long long)btrfs_super_total_bytes(&info->super_copy));
|
||||
printf("bytes used %llu\n",
|
||||
- (unsigned long long)btrfs_super_bytes_used(&root->fs_info->super_copy));
|
||||
+ (unsigned long long)btrfs_super_bytes_used(&info->super_copy));
|
||||
uuidbuf[36] = '\0';
|
||||
- uuid_unparse(root->fs_info->super_copy.fsid, uuidbuf);
|
||||
+ uuid_unparse(info->super_copy.fsid, uuidbuf);
|
||||
printf("uuid %s\n", uuidbuf);
|
||||
printf("%s\n", BTRFS_BUILD_VERSION);
|
||||
return 0;
|
||||
diff --git a/disk-io.c b/disk-io.c
|
||||
index b0b9502..e9fdba8 100644
|
||||
--- a/disk-io.c
|
||||
+++ b/disk-io.c
|
||||
@@ -445,8 +445,9 @@ static int find_and_setup_root(struct btrfs_root *tree_root,
|
||||
generation = btrfs_root_generation(&root->root_item);
|
||||
root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
|
||||
blocksize, generation);
|
||||
- if (!root->node)
|
||||
- return -ENOENT;
|
||||
+ if (!extent_buffer_uptodate(root->node))
|
||||
+ return -EIO;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -473,7 +474,9 @@ static int find_and_setup_log_root(struct btrfs_root *tree_root,
|
||||
btrfs_super_generation(disk_super) + 1);
|
||||
|
||||
fs_info->log_root_tree = log_root;
|
||||
- BUG_ON(!log_root->node);
|
||||
+
|
||||
+ if (!extent_buffer_uptodate(log_root->node))
|
||||
+ return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -603,9 +606,9 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
|
||||
return root;
|
||||
}
|
||||
|
||||
-struct btrfs_root *__open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
|
||||
+static struct btrfs_fs_info *__open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
|
||||
u64 root_tree_bytenr, int writes,
|
||||
- int use_earliest_bdev)
|
||||
+ int use_earliest_bdev, int partial)
|
||||
{
|
||||
u32 sectorsize;
|
||||
u32 nodesize;
|
||||
@@ -742,7 +745,7 @@ struct btrfs_root *__open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
|
||||
chunk_root->node = read_tree_block(chunk_root,
|
||||
btrfs_super_chunk_root(disk_super),
|
||||
blocksize, generation);
|
||||
- if (!chunk_root->node) {
|
||||
+ if (!extent_buffer_uptodate(chunk_root->node)) {
|
||||
printk("Couldn't read chunk root\n");
|
||||
goto out_devices;
|
||||
}
|
||||
@@ -754,7 +757,7 @@ struct btrfs_root *__open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
|
||||
if (!(btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_METADUMP)) {
|
||||
ret = btrfs_read_chunk_tree(chunk_root);
|
||||
if (ret)
|
||||
- goto out_chunk;
|
||||
+ goto out_failed;
|
||||
}
|
||||
|
||||
blocksize = btrfs_level_size(tree_root,
|
||||
@@ -766,15 +769,15 @@ struct btrfs_root *__open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
|
||||
tree_root->node = read_tree_block(tree_root,
|
||||
root_tree_bytenr,
|
||||
blocksize, generation);
|
||||
- if (!tree_root->node) {
|
||||
+ if (!extent_buffer_uptodate(tree_root->node)) {
|
||||
printk("Couldn't read tree root\n");
|
||||
- goto out_chunk;
|
||||
+ goto out_failed;
|
||||
}
|
||||
ret = find_and_setup_root(tree_root, fs_info,
|
||||
BTRFS_EXTENT_TREE_OBJECTID, extent_root);
|
||||
if (ret) {
|
||||
printk("Couldn't setup extent tree\n");
|
||||
- goto out_tree;
|
||||
+ goto out_failed;
|
||||
}
|
||||
extent_root->track_dirty = 1;
|
||||
|
||||
@@ -782,7 +785,7 @@ struct btrfs_root *__open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
|
||||
BTRFS_DEV_TREE_OBJECTID, dev_root);
|
||||
if (ret) {
|
||||
printk("Couldn't setup device tree\n");
|
||||
- goto out_extent;
|
||||
+ goto out_failed;
|
||||
}
|
||||
dev_root->track_dirty = 1;
|
||||
|
||||
@@ -790,7 +793,7 @@ struct btrfs_root *__open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
|
||||
BTRFS_CSUM_TREE_OBJECTID, csum_root);
|
||||
if (ret) {
|
||||
printk("Couldn't setup csum tree\n");
|
||||
- goto out_dev;
|
||||
+ goto out_failed;
|
||||
}
|
||||
csum_root->track_dirty = 1;
|
||||
|
||||
@@ -806,23 +809,28 @@ struct btrfs_root *__open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
|
||||
fs_info->fs_root = btrfs_read_fs_root(fs_info, &key);
|
||||
|
||||
if (!fs_info->fs_root)
|
||||
- goto out_csum;
|
||||
+ goto out_failed;
|
||||
|
||||
fs_info->data_alloc_profile = (u64)-1;
|
||||
fs_info->metadata_alloc_profile = (u64)-1;
|
||||
fs_info->system_alloc_profile = fs_info->metadata_alloc_profile;
|
||||
|
||||
- return fs_info->fs_root;
|
||||
-out_csum:
|
||||
- free_extent_buffer(fs_info->csum_root->node);
|
||||
-out_dev:
|
||||
- free_extent_buffer(fs_info->dev_root->node);
|
||||
-out_extent:
|
||||
- free_extent_buffer(fs_info->extent_root->node);
|
||||
-out_tree:
|
||||
- free_extent_buffer(fs_info->tree_root->node);
|
||||
-out_chunk:
|
||||
- free_extent_buffer(fs_info->chunk_root->node);
|
||||
+ return fs_info;
|
||||
+
|
||||
+out_failed:
|
||||
+ if (partial)
|
||||
+ return fs_info;
|
||||
+
|
||||
+ if (fs_info->csum_root)
|
||||
+ free_extent_buffer(fs_info->csum_root->node);
|
||||
+ if (fs_info->dev_root)
|
||||
+ free_extent_buffer(fs_info->dev_root->node);
|
||||
+ if (fs_info->extent_root)
|
||||
+ free_extent_buffer(fs_info->extent_root->node);
|
||||
+ if (fs_info->tree_root)
|
||||
+ free_extent_buffer(fs_info->tree_root->node);
|
||||
+ if (fs_info->chunk_root)
|
||||
+ free_extent_buffer(fs_info->chunk_root->node);
|
||||
out_devices:
|
||||
close_all_devices(fs_info);
|
||||
out_cleanup:
|
||||
@@ -842,10 +850,12 @@ out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-struct btrfs_root *open_ctree(const char *filename, u64 sb_bytenr, int writes)
|
||||
+struct btrfs_fs_info *open_ctree_fs_info(const char *filename,
|
||||
+ u64 sb_bytenr, int writes,
|
||||
+ int partial)
|
||||
{
|
||||
int fp;
|
||||
- struct btrfs_root *root;
|
||||
+ struct btrfs_fs_info *info;
|
||||
int flags = O_CREAT | O_RDWR;
|
||||
|
||||
if (!writes)
|
||||
@@ -856,33 +866,47 @@ struct btrfs_root *open_ctree(const char *filename, u64 sb_bytenr, int writes)
|
||||
fprintf (stderr, "Could not open %s\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
- root = __open_ctree_fd(fp, filename, sb_bytenr, 0, writes, 0);
|
||||
+ info = __open_ctree_fd(fp, filename, sb_bytenr, 0, writes, 0, partial);
|
||||
close(fp);
|
||||
+ return info;
|
||||
+}
|
||||
|
||||
- return root;
|
||||
+struct btrfs_root *open_ctree(const char *filename, u64 sb_bytenr, int writes)
|
||||
+{
|
||||
+ struct btrfs_fs_info *info;
|
||||
+
|
||||
+ info = open_ctree_fs_info(filename, sb_bytenr, writes, 0);
|
||||
+ if (!info)
|
||||
+ return NULL;
|
||||
+ return info->fs_root;
|
||||
}
|
||||
|
||||
struct btrfs_root *open_ctree_recovery(const char *filename, u64 sb_bytenr,
|
||||
u64 root_tree_bytenr)
|
||||
{
|
||||
int fp;
|
||||
- struct btrfs_root *root;
|
||||
+ struct btrfs_fs_info *info;
|
||||
|
||||
fp = open(filename, O_RDONLY);
|
||||
if (fp < 0) {
|
||||
fprintf (stderr, "Could not open %s\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
- root = __open_ctree_fd(fp, filename, sb_bytenr, root_tree_bytenr, 0, 0);
|
||||
+ info = __open_ctree_fd(fp, filename, sb_bytenr, root_tree_bytenr, 0, 0, 0);
|
||||
close(fp);
|
||||
-
|
||||
- return root;
|
||||
+ if (!info)
|
||||
+ return NULL;
|
||||
+ return info->fs_root;
|
||||
}
|
||||
|
||||
struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
|
||||
int writes, int use_earliest_bdev)
|
||||
{
|
||||
- return __open_ctree_fd(fp, path, sb_bytenr, 0, writes, use_earliest_bdev);
|
||||
+ struct btrfs_fs_info *info;
|
||||
+ info = __open_ctree_fd(fp, path, sb_bytenr, 0, writes, use_earliest_bdev, 0);
|
||||
+ if (!info)
|
||||
+ return NULL;
|
||||
+ return info->fs_root;
|
||||
}
|
||||
|
||||
struct btrfs_root *open_ctree_broken(int fd, const char *device)
|
||||
diff --git a/disk-io.h b/disk-io.h
|
||||
index 2b1fcd5..664cabd 100644
|
||||
--- a/disk-io.h
|
||||
+++ b/disk-io.h
|
||||
@@ -48,6 +48,9 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
|
||||
int writes, int use_earliest_bdev);
|
||||
struct btrfs_root *open_ctree_recovery(const char *filename, u64 sb_bytenr,
|
||||
u64 root_tree_bytenr);
|
||||
+struct btrfs_fs_info *open_ctree_fs_info(const char *filename,
|
||||
+ u64 sb_bytenr, int writes,
|
||||
+ int partial);
|
||||
struct btrfs_root *open_ctree_broken(int fd, const char *device);
|
||||
int close_ctree(struct btrfs_root *root);
|
||||
int write_all_supers(struct btrfs_root *root);
|
||||
diff --git a/extent_io.c b/extent_io.c
|
||||
index 973e918..9990338 100644
|
||||
--- a/extent_io.c
|
||||
+++ b/extent_io.c
|
||||
@@ -706,6 +706,9 @@ int clear_extent_buffer_uptodate(struct extent_io_tree *tree,
|
||||
|
||||
int extent_buffer_uptodate(struct extent_buffer *eb)
|
||||
{
|
||||
+ if (!eb)
|
||||
+ return 0;
|
||||
+
|
||||
if (eb->flags & EXTENT_UPTODATE)
|
||||
return 1;
|
||||
return 0;
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
@ -0,0 +1,34 @@
|
||||
From bed79b9cd39caf88f5bf8fe9340afa539924a8cc Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Mon, 6 Feb 2012 05:05:59 -0500
|
||||
Subject: [PATCH 02/18] btrfsck: print some progress Signed-off-by: Chris
|
||||
Mason <chris.mason@oracle.com>
|
||||
|
||||
---
|
||||
btrfsck.c | 3 +++
|
||||
1 files changed, 3 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/btrfsck.c b/btrfsck.c
|
||||
index 40eb407..a3c6286 100644
|
||||
--- a/btrfsck.c
|
||||
+++ b/btrfsck.c
|
||||
@@ -2854,13 +2854,16 @@ int main(int ac, char **av)
|
||||
|
||||
root = info->fs_root;
|
||||
|
||||
+ fprintf(stderr, "checking extents\n");
|
||||
ret = check_extents(root);
|
||||
if (ret)
|
||||
goto out;
|
||||
+ fprintf(stderr, "checking fs roots\n");
|
||||
ret = check_fs_roots(root, &root_cache);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
+ fprintf(stderr, "checking root refs\n");
|
||||
ret = check_root_refs(root, &root_cache);
|
||||
out:
|
||||
free_root_recs(&root_cache);
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
54
0154-Allow-extent_buffers-to-use-more-ram.patch
Normal file
54
0154-Allow-extent_buffers-to-use-more-ram.patch
Normal file
@ -0,0 +1,54 @@
|
||||
From 769671c6aeef3359498100f0ef31975706d99fca Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Mon, 6 Feb 2012 05:06:18 -0500
|
||||
Subject: [PATCH 03/18] Allow extent_buffers to use more ram
|
||||
|
||||
This changes free_some_buffers (called each time we allocate an extent
|
||||
buffer) to allow a higher hard limit on the number of extent buffers
|
||||
in use.
|
||||
|
||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||
---
|
||||
extent_io.c | 10 ++++++----
|
||||
1 files changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/extent_io.c b/extent_io.c
|
||||
index 9990338..ebb35b2 100644
|
||||
--- a/extent_io.c
|
||||
+++ b/extent_io.c
|
||||
@@ -28,7 +28,8 @@
|
||||
#include "extent_io.h"
|
||||
#include "list.h"
|
||||
|
||||
-u64 cache_max = 1024 * 1024 * 32;
|
||||
+u64 cache_soft_max = 1024 * 1024 * 256;
|
||||
+u64 cache_hard_max = 1 * 1024 * 1024 * 1024;
|
||||
|
||||
void extent_io_tree_init(struct extent_io_tree *tree)
|
||||
{
|
||||
@@ -540,18 +541,19 @@ static int free_some_buffers(struct extent_io_tree *tree)
|
||||
struct extent_buffer *eb;
|
||||
struct list_head *node, *next;
|
||||
|
||||
- if (tree->cache_size < cache_max)
|
||||
+ if (tree->cache_size < cache_soft_max)
|
||||
return 0;
|
||||
+
|
||||
list_for_each_safe(node, next, &tree->lru) {
|
||||
eb = list_entry(node, struct extent_buffer, lru);
|
||||
if (eb->refs == 1) {
|
||||
free_extent_buffer(eb);
|
||||
- if (tree->cache_size < cache_max)
|
||||
+ if (tree->cache_size < cache_hard_max)
|
||||
break;
|
||||
} else {
|
||||
list_move_tail(&eb->lru, &tree->lru);
|
||||
}
|
||||
- if (nrscan++ > 64)
|
||||
+ if (nrscan++ > 64 && tree->cache_size < cache_hard_max)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
32
0155-btrfsck-don-t-BUG-on-corrupted-extent-records.patch
Normal file
32
0155-btrfsck-don-t-BUG-on-corrupted-extent-records.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From ab19832dce62c53452454897fe1d2eaf2e1dbd59 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Mon, 6 Feb 2012 08:53:43 -0500
|
||||
Subject: [PATCH 04/18] btrfsck: don't BUG on corrupted extent records
|
||||
|
||||
---
|
||||
btrfsck.c | 5 ++++-
|
||||
1 files changed, 4 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/btrfsck.c b/btrfsck.c
|
||||
index a3c6286..90e9c80 100644
|
||||
--- a/btrfsck.c
|
||||
+++ b/btrfsck.c
|
||||
@@ -2441,11 +2441,14 @@ static int process_extent_item(struct cache_tree *extent_cache,
|
||||
0);
|
||||
break;
|
||||
default:
|
||||
- BUG();
|
||||
+ fprintf(stderr, "corrupt extent record: key %Lu %u %Lu\n",
|
||||
+ key.objectid, key.type, key.offset);
|
||||
+ goto out;
|
||||
}
|
||||
ptr += btrfs_extent_inline_ref_size(type);
|
||||
}
|
||||
WARN_ON(ptr > end);
|
||||
+out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
194
0156-btrfs-corrupt-block-add-e-option-to-corrupt-the-exte.patch
Normal file
194
0156-btrfs-corrupt-block-add-e-option-to-corrupt-the-exte.patch
Normal file
@ -0,0 +1,194 @@
|
||||
From a0e60b027576e8e3e3d77b77eaff1360a374af60 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Mon, 6 Feb 2012 08:54:05 -0500
|
||||
Subject: [PATCH 05/18] btrfs-corrupt-block: add -e option to corrupt the
|
||||
extent record
|
||||
|
||||
This will zero out the extent allocation tree records for the extent.
|
||||
|
||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||
---
|
||||
btrfs-corrupt-block.c | 115 ++++++++++++++++++++++++++++++++-----------------
|
||||
1 files changed, 76 insertions(+), 39 deletions(-)
|
||||
|
||||
diff --git a/btrfs-corrupt-block.c b/btrfs-corrupt-block.c
|
||||
index ace61c1..59e7cb4 100644
|
||||
--- a/btrfs-corrupt-block.c
|
||||
+++ b/btrfs-corrupt-block.c
|
||||
@@ -32,11 +32,6 @@
|
||||
#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_corrupt_block(struct btrfs_root *root, u64 bytenr,
|
||||
u32 blocksize, int copy)
|
||||
{
|
||||
@@ -62,7 +57,7 @@ struct extent_buffer *debug_corrupt_block(struct btrfs_root *root, u64 bytenr,
|
||||
device->total_ios++;
|
||||
eb->dev_bytenr = multi->stripes[0].physical;
|
||||
|
||||
- fprintf(info_file, "mirror %d logical %Lu physical %Lu "
|
||||
+ fprintf(stdout, "mirror %d logical %Lu physical %Lu "
|
||||
"device %s\n", mirror_num, (unsigned long long)bytenr,
|
||||
(unsigned long long)eb->dev_bytenr, device->name);
|
||||
kfree(multi);
|
||||
@@ -106,24 +101,88 @@ static struct option long_options[] = {
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
+static int corrupt_extent(struct btrfs_root *root, u64 bytenr, int copy)
|
||||
+{
|
||||
+ struct btrfs_trans_handle *trans;
|
||||
+ struct btrfs_key key;
|
||||
+ struct extent_buffer *leaf;
|
||||
+ u32 item_size;
|
||||
+ unsigned long ptr;
|
||||
+ struct btrfs_path *path;
|
||||
+ int ret;
|
||||
+ int slot;
|
||||
+
|
||||
+ trans = btrfs_start_transaction(root, 1);
|
||||
+ path = btrfs_alloc_path();
|
||||
+
|
||||
+ key.objectid = bytenr;
|
||||
+ key.type = (u8)-1;
|
||||
+ key.offset = (u64)-1;
|
||||
+
|
||||
+ while(1) {
|
||||
+ ret = btrfs_search_slot(trans, root->fs_info->extent_root,
|
||||
+ &key, path, 0, 1);
|
||||
+ if (ret < 0)
|
||||
+ break;
|
||||
+
|
||||
+ if (ret > 0) {
|
||||
+ if (path->slots[0] == 0)
|
||||
+ break;
|
||||
+ path->slots[0]--;
|
||||
+ }
|
||||
+ leaf = path->nodes[0];
|
||||
+ slot = path->slots[0];
|
||||
+ btrfs_item_key_to_cpu(leaf, &key, slot);
|
||||
+ if (key.objectid != bytenr)
|
||||
+ break;
|
||||
+
|
||||
+ if (key.type != BTRFS_EXTENT_ITEM_KEY &&
|
||||
+ key.type != BTRFS_TREE_BLOCK_REF_KEY &&
|
||||
+ key.type != BTRFS_EXTENT_DATA_REF_KEY &&
|
||||
+ key.type != BTRFS_EXTENT_REF_V0_KEY &&
|
||||
+ key.type != BTRFS_SHARED_BLOCK_REF_KEY &&
|
||||
+ key.type != BTRFS_SHARED_DATA_REF_KEY)
|
||||
+ goto next;
|
||||
+
|
||||
+ fprintf(stderr, "corrupting extent record: key %Lu %u %Lu\n",
|
||||
+ key.objectid, key.type, key.offset);
|
||||
+
|
||||
+ ptr = btrfs_item_ptr_offset(leaf, slot);
|
||||
+ item_size = btrfs_item_size_nr(leaf, slot);
|
||||
+ memset_extent_buffer(leaf, 0, ptr, item_size);
|
||||
+ btrfs_mark_buffer_dirty(leaf);
|
||||
+next:
|
||||
+ btrfs_release_path(NULL, path);
|
||||
+
|
||||
+ if (key.offset > 0)
|
||||
+ key.offset--;
|
||||
+ if (key.offset == 0)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ btrfs_free_path(path);
|
||||
+ btrfs_commit_transaction(trans, root);
|
||||
+ ret = close_ctree(root);
|
||||
+ BUG_ON(ret);
|
||||
+ return 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 = 4096;
|
||||
- int out_fd = 0;
|
||||
- int err;
|
||||
+ int extent_rec;
|
||||
|
||||
while(1) {
|
||||
int c;
|
||||
- c = getopt_long(ac, av, "l:c:", long_options,
|
||||
+ c = getopt_long(ac, av, "l:c:e", long_options,
|
||||
&option_index);
|
||||
if (c < 0)
|
||||
break;
|
||||
@@ -152,6 +211,9 @@ int main(int ac, char **av)
|
||||
print_usage();
|
||||
}
|
||||
break;
|
||||
+ case 'e':
|
||||
+ extent_rec = 1;
|
||||
+ break;
|
||||
default:
|
||||
print_usage();
|
||||
}
|
||||
@@ -174,23 +236,9 @@ int main(int ac, char **av)
|
||||
fprintf(stderr, "Open ctree failed\n");
|
||||
exit(1);
|
||||
}
|
||||
-
|
||||
- info_file = stdout;
|
||||
- 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 (extent_rec) {
|
||||
+ ret = corrupt_extent (root, logical, 0);
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
if (bytes == 0)
|
||||
@@ -201,21 +249,10 @@ int main(int ac, char **av)
|
||||
|
||||
while (bytes > 0) {
|
||||
eb = debug_corrupt_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:
|
||||
+out:
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
892
0157-btrfsck-add-code-to-rebuild-extent-records.patch
Normal file
892
0157-btrfsck-add-code-to-rebuild-extent-records.patch
Normal file
@ -0,0 +1,892 @@
|
||||
From a3921c085c75c6d1983442dc0db35131db874d84 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Tue, 7 Feb 2012 05:13:24 -0500
|
||||
Subject: [PATCH 06/18] btrfsck: add code to rebuild extent records
|
||||
|
||||
This also includes a new --repair btrfsck option. For now it can
|
||||
only fix errors in the extent allocation tree.
|
||||
|
||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||
---
|
||||
btrfsck.c | 459 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
|
||||
ctree.h | 1 +
|
||||
extent-tree.c | 24 ++--
|
||||
print-tree.c | 2 +-
|
||||
4 files changed, 437 insertions(+), 49 deletions(-)
|
||||
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/btrfsck.c
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/btrfsck.c
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/btrfsck.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
+#include <getopt.h>
|
||||
#include "kerncompat.h"
|
||||
#include "ctree.h"
|
||||
#include "disk-io.h"
|
||||
@@ -74,9 +75,13 @@ struct extent_record {
|
||||
struct cache_extent cache;
|
||||
struct btrfs_disk_key parent_key;
|
||||
u64 start;
|
||||
+ u64 max_size;
|
||||
u64 nr;
|
||||
u64 refs;
|
||||
u64 extent_item_refs;
|
||||
+ u64 generation;
|
||||
+ u64 info_objectid;
|
||||
+ u8 info_level;
|
||||
unsigned int content_checked:1;
|
||||
unsigned int owner_ref_checked:1;
|
||||
unsigned int is_root:1;
|
||||
@@ -1082,7 +1087,9 @@ static int walk_down_tree(struct btrfs_r
|
||||
ret = btrfs_lookup_extent_info(NULL, root,
|
||||
path->nodes[*level]->start,
|
||||
path->nodes[*level]->len, &refs, NULL);
|
||||
- BUG_ON(ret);
|
||||
+ if (ret < 0)
|
||||
+ goto out;
|
||||
+
|
||||
if (refs > 1) {
|
||||
ret = enter_shared_node(root, path->nodes[*level]->start,
|
||||
refs, wc, *level);
|
||||
@@ -1109,7 +1116,8 @@ static int walk_down_tree(struct btrfs_r
|
||||
blocksize = btrfs_level_size(root, *level - 1);
|
||||
ret = btrfs_lookup_extent_info(NULL, root, bytenr, blocksize,
|
||||
&refs, NULL);
|
||||
- BUG_ON(ret);
|
||||
+ if (ret < 0)
|
||||
+ refs = 0;
|
||||
|
||||
if (refs > 1) {
|
||||
ret = enter_shared_node(root, bytenr, refs,
|
||||
@@ -1834,12 +1842,12 @@ static int all_backpointers_checked(stru
|
||||
if (!print_errs)
|
||||
goto out;
|
||||
tback = (struct tree_backref *)back;
|
||||
- fprintf(stderr, "Backref %llu %s %llu not referenced\n",
|
||||
+ fprintf(stderr, "Backref %llu %s %llu not referenced back %p\n",
|
||||
(unsigned long long)rec->start,
|
||||
back->full_backref ? "parent" : "root",
|
||||
back->full_backref ?
|
||||
(unsigned long long)tback->parent :
|
||||
- (unsigned long long)tback->root);
|
||||
+ (unsigned long long)tback->root, back);
|
||||
}
|
||||
if (back->is_data) {
|
||||
dback = (struct data_backref *)back;
|
||||
@@ -1849,7 +1857,7 @@ static int all_backpointers_checked(stru
|
||||
goto out;
|
||||
fprintf(stderr, "Incorrect local backref count"
|
||||
" on %llu %s %llu owner %llu"
|
||||
- " offset %llu found %u wanted %u\n",
|
||||
+ " offset %llu found %u wanted %u back %p\n",
|
||||
(unsigned long long)rec->start,
|
||||
back->full_backref ?
|
||||
"parent" : "root",
|
||||
@@ -1858,7 +1866,7 @@ static int all_backpointers_checked(stru
|
||||
(unsigned long long)dback->root,
|
||||
(unsigned long long)dback->owner,
|
||||
(unsigned long long)dback->offset,
|
||||
- dback->found_ref, dback->num_refs);
|
||||
+ dback->found_ref, dback->num_refs, back);
|
||||
}
|
||||
}
|
||||
if (!back->is_data) {
|
||||
@@ -1965,12 +1973,28 @@ static int check_block(struct btrfs_root
|
||||
{
|
||||
struct extent_record *rec;
|
||||
struct cache_extent *cache;
|
||||
+ struct btrfs_key key;
|
||||
int ret = 1;
|
||||
+ int level;
|
||||
|
||||
cache = find_cache_extent(extent_cache, buf->start, buf->len);
|
||||
if (!cache)
|
||||
return 1;
|
||||
rec = container_of(cache, struct extent_record, cache);
|
||||
+ rec->generation = btrfs_header_generation(buf);
|
||||
+
|
||||
+ level = btrfs_header_level(buf);
|
||||
+ if (btrfs_header_nritems(buf) > 0) {
|
||||
+
|
||||
+ if (level == 0)
|
||||
+ btrfs_item_key_to_cpu(buf, &key, 0);
|
||||
+ else
|
||||
+ btrfs_node_key_to_cpu(buf, &key, 0);
|
||||
+
|
||||
+ rec->info_objectid = key.objectid;
|
||||
+ }
|
||||
+ rec->info_level = level;
|
||||
+
|
||||
if (btrfs_is_leaf(buf)) {
|
||||
ret = check_leaf(root, &rec->parent_key, buf);
|
||||
} else {
|
||||
@@ -2035,6 +2059,7 @@ static struct tree_backref *alloc_tree_b
|
||||
ref->node.full_backref = 0;
|
||||
}
|
||||
list_add_tail(&ref->node.list, &rec->backrefs);
|
||||
+
|
||||
return ref;
|
||||
}
|
||||
|
||||
@@ -2052,7 +2077,7 @@ static struct data_backref *find_data_ba
|
||||
if (!node->is_data)
|
||||
continue;
|
||||
back = (struct data_backref *)node;
|
||||
- if (parent > 0) {
|
||||
+ if (parent > 0) {
|
||||
if (!node->full_backref)
|
||||
continue;
|
||||
if (parent == back->parent)
|
||||
@@ -2070,11 +2095,13 @@ static struct data_backref *find_data_ba
|
||||
|
||||
static struct data_backref *alloc_data_backref(struct extent_record *rec,
|
||||
u64 parent, u64 root,
|
||||
- u64 owner, u64 offset)
|
||||
+ u64 owner, u64 offset,
|
||||
+ u64 max_size)
|
||||
{
|
||||
struct data_backref *ref = malloc(sizeof(*ref));
|
||||
memset(&ref->node, 0, sizeof(ref->node));
|
||||
ref->node.is_data = 1;
|
||||
+
|
||||
if (parent > 0) {
|
||||
ref->parent = parent;
|
||||
ref->owner = 0;
|
||||
@@ -2089,13 +2116,16 @@ static struct data_backref *alloc_data_b
|
||||
ref->found_ref = 0;
|
||||
ref->num_refs = 0;
|
||||
list_add_tail(&ref->node.list, &rec->backrefs);
|
||||
+ if (max_size > rec->max_size)
|
||||
+ rec->max_size = max_size;
|
||||
return ref;
|
||||
}
|
||||
|
||||
static int add_extent_rec(struct cache_tree *extent_cache,
|
||||
struct btrfs_key *parent_key,
|
||||
u64 start, u64 nr, u64 extent_item_refs,
|
||||
- int is_root, int inc_ref, int set_checked)
|
||||
+ int is_root, int inc_ref, int set_checked,
|
||||
+ u64 max_size)
|
||||
{
|
||||
struct extent_record *rec;
|
||||
struct cache_extent *cache;
|
||||
@@ -2136,11 +2166,15 @@ static int add_extent_rec(struct cache_t
|
||||
if (parent_key)
|
||||
btrfs_cpu_key_to_disk(&rec->parent_key, parent_key);
|
||||
|
||||
+ if (rec->max_size < max_size)
|
||||
+ rec->max_size = max_size;
|
||||
+
|
||||
maybe_free_extent_rec(extent_cache, rec);
|
||||
return ret;
|
||||
}
|
||||
rec = malloc(sizeof(*rec));
|
||||
rec->start = start;
|
||||
+ rec->max_size = max_size;
|
||||
rec->nr = nr;
|
||||
rec->content_checked = 0;
|
||||
rec->owner_ref_checked = 0;
|
||||
@@ -2187,7 +2221,7 @@ static int add_tree_backref(struct cache
|
||||
|
||||
cache = find_cache_extent(extent_cache, bytenr, 1);
|
||||
if (!cache) {
|
||||
- add_extent_rec(extent_cache, NULL, bytenr, 1, 0, 0, 0, 0);
|
||||
+ add_extent_rec(extent_cache, NULL, bytenr, 1, 0, 0, 0, 0, 0);
|
||||
cache = find_cache_extent(extent_cache, bytenr, 1);
|
||||
if (!cache)
|
||||
abort();
|
||||
@@ -2226,7 +2260,7 @@ static int add_tree_backref(struct cache
|
||||
|
||||
static int add_data_backref(struct cache_tree *extent_cache, u64 bytenr,
|
||||
u64 parent, u64 root, u64 owner, u64 offset,
|
||||
- u32 num_refs, int found_ref)
|
||||
+ u32 num_refs, int found_ref, u64 max_size)
|
||||
{
|
||||
struct extent_record *rec;
|
||||
struct data_backref *back;
|
||||
@@ -2234,7 +2268,8 @@ static int add_data_backref(struct cache
|
||||
|
||||
cache = find_cache_extent(extent_cache, bytenr, 1);
|
||||
if (!cache) {
|
||||
- add_extent_rec(extent_cache, NULL, bytenr, 1, 0, 0, 0, 0);
|
||||
+ add_extent_rec(extent_cache, NULL, bytenr, 1, 0, 0, 0, 0,
|
||||
+ max_size);
|
||||
cache = find_cache_extent(extent_cache, bytenr, 1);
|
||||
if (!cache)
|
||||
abort();
|
||||
@@ -2244,9 +2279,13 @@ static int add_data_backref(struct cache
|
||||
if (rec->start != bytenr) {
|
||||
abort();
|
||||
}
|
||||
+ if (rec->max_size < max_size)
|
||||
+ rec->max_size = max_size;
|
||||
+
|
||||
back = find_data_backref(rec, parent, root, owner, offset);
|
||||
if (!back)
|
||||
- back = alloc_data_backref(rec, parent, root, owner, offset);
|
||||
+ back = alloc_data_backref(rec, parent, root, owner, offset,
|
||||
+ max_size);
|
||||
|
||||
if (found_ref) {
|
||||
BUG_ON(num_refs != 1);
|
||||
@@ -2359,11 +2398,10 @@ static int process_extent_ref_v0(struct
|
||||
btrfs_item_key_to_cpu(leaf, &key, slot);
|
||||
ref0 = btrfs_item_ptr(leaf, slot, struct btrfs_extent_ref_v0);
|
||||
if (btrfs_ref_objectid_v0(leaf, ref0) < BTRFS_FIRST_FREE_OBJECTID) {
|
||||
- add_tree_backref(extent_cache, key.objectid, key.offset,
|
||||
- 0, 0);
|
||||
+ add_tree_backref(extent_cache, key.objectid, key.offset, 0, 0);
|
||||
} else {
|
||||
add_data_backref(extent_cache, key.objectid, key.offset, 0,
|
||||
- 0, 0, btrfs_ref_count_v0(leaf, ref0), 0);
|
||||
+ 0, 0, btrfs_ref_count_v0(leaf, ref0), 0, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2396,14 +2434,14 @@ static int process_extent_item(struct ca
|
||||
BUG();
|
||||
#endif
|
||||
return add_extent_rec(extent_cache, NULL, key.objectid,
|
||||
- key.offset, refs, 0, 0, 0);
|
||||
+ key.offset, refs, 0, 0, 0, key.offset);
|
||||
}
|
||||
|
||||
ei = btrfs_item_ptr(eb, slot, struct btrfs_extent_item);
|
||||
refs = btrfs_extent_refs(eb, ei);
|
||||
|
||||
add_extent_rec(extent_cache, NULL, key.objectid, key.offset,
|
||||
- refs, 0, 0, 0);
|
||||
+ refs, 0, 0, 0, key.offset);
|
||||
|
||||
ptr = (unsigned long)(ei + 1);
|
||||
if (btrfs_extent_flags(eb, ei) & BTRFS_EXTENT_FLAG_TREE_BLOCK)
|
||||
@@ -2431,14 +2469,14 @@ static int process_extent_item(struct ca
|
||||
dref),
|
||||
btrfs_extent_data_ref_offset(eb, dref),
|
||||
btrfs_extent_data_ref_count(eb, dref),
|
||||
- 0);
|
||||
+ 0, key.offset);
|
||||
break;
|
||||
case BTRFS_SHARED_DATA_REF_KEY:
|
||||
sref = (struct btrfs_shared_data_ref *)(iref + 1);
|
||||
add_data_backref(extent_cache, key.objectid, offset,
|
||||
0, 0, 0,
|
||||
btrfs_shared_data_ref_count(eb, sref),
|
||||
- 0);
|
||||
+ 0, key.offset);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "corrupt extent record: key %Lu %u %Lu\n",
|
||||
@@ -2515,6 +2553,8 @@ static int run_next_block(struct btrfs_r
|
||||
nritems = btrfs_header_nritems(buf);
|
||||
|
||||
ret = btrfs_lookup_extent_info(NULL, root, bytenr, size, NULL, &flags);
|
||||
+ if (ret < 0)
|
||||
+ flags = BTRFS_BLOCK_FLAG_FULL_BACKREF;
|
||||
|
||||
if (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF) {
|
||||
parent = bytenr;
|
||||
@@ -2573,7 +2613,7 @@ static int run_next_block(struct btrfs_r
|
||||
ref),
|
||||
btrfs_extent_data_ref_offset(buf, ref),
|
||||
btrfs_extent_data_ref_count(buf, ref),
|
||||
- 0);
|
||||
+ 0, root->sectorsize);
|
||||
continue;
|
||||
}
|
||||
if (key.type == BTRFS_SHARED_DATA_REF_KEY) {
|
||||
@@ -2583,7 +2623,7 @@ static int run_next_block(struct btrfs_r
|
||||
add_data_backref(extent_cache,
|
||||
key.objectid, key.offset, 0, 0, 0,
|
||||
btrfs_shared_data_ref_count(buf, ref),
|
||||
- 0);
|
||||
+ 0, root->sectorsize);
|
||||
continue;
|
||||
}
|
||||
if (key.type != BTRFS_EXTENT_DATA_KEY)
|
||||
@@ -2606,26 +2646,33 @@ static int run_next_block(struct btrfs_r
|
||||
ret = add_extent_rec(extent_cache, NULL,
|
||||
btrfs_file_extent_disk_bytenr(buf, fi),
|
||||
btrfs_file_extent_disk_num_bytes(buf, fi),
|
||||
- 0, 0, 1, 1);
|
||||
+ 0, 0, 1, 1,
|
||||
+ btrfs_file_extent_disk_num_bytes(buf, fi));
|
||||
add_data_backref(extent_cache,
|
||||
btrfs_file_extent_disk_bytenr(buf, fi),
|
||||
parent, owner, key.objectid, key.offset -
|
||||
- btrfs_file_extent_offset(buf, fi), 1, 1);
|
||||
+ btrfs_file_extent_offset(buf, fi), 1, 1,
|
||||
+ btrfs_file_extent_disk_num_bytes(buf, fi));
|
||||
BUG_ON(ret);
|
||||
}
|
||||
} else {
|
||||
int level;
|
||||
+ struct btrfs_key first_key;
|
||||
+
|
||||
+ first_key.objectid = 0;
|
||||
+
|
||||
+ if (nritems > 0)
|
||||
+ btrfs_item_key_to_cpu(buf, &first_key, 0);
|
||||
level = btrfs_header_level(buf);
|
||||
for (i = 0; i < nritems; i++) {
|
||||
u64 ptr = btrfs_node_blockptr(buf, i);
|
||||
u32 size = btrfs_level_size(root, level - 1);
|
||||
btrfs_node_key_to_cpu(buf, &key, i);
|
||||
ret = add_extent_rec(extent_cache, &key,
|
||||
- ptr, size, 0, 0, 1, 0);
|
||||
+ ptr, size, 0, 0, 1, 0, size);
|
||||
BUG_ON(ret);
|
||||
|
||||
- add_tree_backref(extent_cache, ptr, parent,
|
||||
- owner, 1);
|
||||
+ add_tree_backref(extent_cache, ptr, parent, owner, 1);
|
||||
|
||||
if (level > 1) {
|
||||
add_pending(nodes, seen, ptr, size);
|
||||
@@ -2663,25 +2710,313 @@ static int add_root_to_pending(struct ex
|
||||
else
|
||||
add_pending(pending, seen, buf->start, buf->len);
|
||||
add_extent_rec(extent_cache, NULL, buf->start, buf->len,
|
||||
- 0, 1, 1, 0);
|
||||
+ 0, 1, 1, 0, buf->len);
|
||||
|
||||
if (root_key->objectid == BTRFS_TREE_RELOC_OBJECTID ||
|
||||
btrfs_header_backref_rev(buf) < BTRFS_MIXED_BACKREF_REV)
|
||||
- add_tree_backref(extent_cache, buf->start, buf->start, 0, 1);
|
||||
+ add_tree_backref(extent_cache, buf->start, buf->start,
|
||||
+ 0, 1);
|
||||
else
|
||||
add_tree_backref(extent_cache, buf->start, 0,
|
||||
root_key->objectid, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int delete_extent_records(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_root *root,
|
||||
+ struct btrfs_path *path,
|
||||
+ u64 bytenr)
|
||||
+{
|
||||
+ struct btrfs_key key;
|
||||
+ struct btrfs_key found_key;
|
||||
+ struct extent_buffer *leaf;
|
||||
+ int ret;
|
||||
+ int slot;
|
||||
+
|
||||
+
|
||||
+ key.objectid = bytenr;
|
||||
+ key.type = (u8)-1;
|
||||
+ key.offset = (u64)-1;
|
||||
+
|
||||
+ while(1) {
|
||||
+ ret = btrfs_search_slot(trans, root->fs_info->extent_root,
|
||||
+ &key, path, 0, 1);
|
||||
+ if (ret < 0)
|
||||
+ break;
|
||||
+
|
||||
+ if (ret > 0) {
|
||||
+ ret = 0;
|
||||
+ if (path->slots[0] == 0)
|
||||
+ break;
|
||||
+ path->slots[0]--;
|
||||
+ }
|
||||
+ ret = 0;
|
||||
+
|
||||
+ leaf = path->nodes[0];
|
||||
+ slot = path->slots[0];
|
||||
+
|
||||
+ btrfs_item_key_to_cpu(leaf, &found_key, slot);
|
||||
+ if (found_key.objectid != bytenr)
|
||||
+ break;
|
||||
+
|
||||
+ if (found_key.type != BTRFS_EXTENT_ITEM_KEY &&
|
||||
+ found_key.type != BTRFS_TREE_BLOCK_REF_KEY &&
|
||||
+ found_key.type != BTRFS_EXTENT_DATA_REF_KEY &&
|
||||
+ found_key.type != BTRFS_EXTENT_REF_V0_KEY &&
|
||||
+ found_key.type != BTRFS_SHARED_BLOCK_REF_KEY &&
|
||||
+ found_key.type != BTRFS_SHARED_DATA_REF_KEY) {
|
||||
+ btrfs_release_path(NULL, path);
|
||||
+ if (found_key.type == 0) {
|
||||
+ if (found_key.offset == 0)
|
||||
+ break;
|
||||
+ key.offset = found_key.offset - 1;
|
||||
+ key.type = found_key.type;
|
||||
+ }
|
||||
+ key.type = found_key.type - 1;
|
||||
+ key.offset = (u64)-1;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ fprintf(stderr, "repair deleting extent record: key %Lu %u %Lu\n",
|
||||
+ found_key.objectid, found_key.type, found_key.offset);
|
||||
+
|
||||
+ ret = btrfs_del_item(trans, root->fs_info->extent_root, path);
|
||||
+ if (ret)
|
||||
+ break;
|
||||
+ btrfs_release_path(NULL, path);
|
||||
+
|
||||
+ if (found_key.type == BTRFS_EXTENT_ITEM_KEY) {
|
||||
+ ret = btrfs_update_block_group(trans, root, bytenr,
|
||||
+ found_key.offset, 0, 1);
|
||||
+ if (ret)
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ btrfs_release_path(NULL, path);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * for a single backref, this will allocate a new extent
|
||||
+ * and add the backref to it.
|
||||
+ */
|
||||
+static int record_extent(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_fs_info *info,
|
||||
+ struct btrfs_path *path,
|
||||
+ struct extent_record *rec,
|
||||
+ struct extent_backref *back,
|
||||
+ int allocated, u64 flags)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct btrfs_root *extent_root = info->extent_root;
|
||||
+ struct extent_buffer *leaf;
|
||||
+ struct btrfs_key ins_key;
|
||||
+ struct btrfs_extent_item *ei;
|
||||
+ struct tree_backref *tback;
|
||||
+ struct data_backref *dback;
|
||||
+ struct btrfs_tree_block_info *bi;
|
||||
+
|
||||
+ if (!back->is_data)
|
||||
+ rec->max_size = max_t(u64, rec->max_size,
|
||||
+ info->extent_root->leafsize);
|
||||
+
|
||||
+ if (!allocated) {
|
||||
+ u32 item_size = sizeof(*ei);
|
||||
+
|
||||
+ if (!back->is_data)
|
||||
+ item_size += sizeof(*bi);
|
||||
+
|
||||
+ ins_key.objectid = rec->start;
|
||||
+ ins_key.offset = rec->max_size;
|
||||
+ ins_key.type = BTRFS_EXTENT_ITEM_KEY;
|
||||
+
|
||||
+ ret = btrfs_insert_empty_item(trans, extent_root, path,
|
||||
+ &ins_key, item_size);
|
||||
+ if (ret)
|
||||
+ goto fail;
|
||||
+
|
||||
+ leaf = path->nodes[0];
|
||||
+ ei = btrfs_item_ptr(leaf, path->slots[0],
|
||||
+ struct btrfs_extent_item);
|
||||
+
|
||||
+ btrfs_set_extent_refs(leaf, ei, 0);
|
||||
+ btrfs_set_extent_generation(leaf, ei, rec->generation);
|
||||
+
|
||||
+ if (back->is_data) {
|
||||
+ btrfs_set_extent_flags(leaf, ei,
|
||||
+ BTRFS_EXTENT_FLAG_DATA);
|
||||
+ } else {
|
||||
+ struct btrfs_disk_key copy_key;;
|
||||
+
|
||||
+ tback = (struct tree_backref *)back;
|
||||
+ bi = (struct btrfs_tree_block_info *)(ei + 1);
|
||||
+ memset_extent_buffer(leaf, 0, (unsigned long)bi,
|
||||
+ sizeof(*bi));
|
||||
+ memset(©_key, 0, sizeof(copy_key));
|
||||
+
|
||||
+ copy_key.objectid = le64_to_cpu(rec->info_objectid);
|
||||
+ btrfs_set_tree_block_level(leaf, bi, rec->info_level);
|
||||
+ btrfs_set_tree_block_key(leaf, bi, ©_key);
|
||||
+
|
||||
+ btrfs_set_extent_flags(leaf, ei,
|
||||
+ BTRFS_EXTENT_FLAG_TREE_BLOCK | flags);
|
||||
+ }
|
||||
+
|
||||
+ btrfs_mark_buffer_dirty(leaf);
|
||||
+ ret = btrfs_update_block_group(trans, extent_root, rec->start,
|
||||
+ rec->max_size, 1, 0);
|
||||
+ if (ret)
|
||||
+ goto fail;
|
||||
+ btrfs_release_path(NULL, path);
|
||||
+ }
|
||||
+
|
||||
+ if (back->is_data) {
|
||||
+ u64 parent;
|
||||
+ int i;
|
||||
+
|
||||
+ dback = (struct data_backref *)back;
|
||||
+ if (back->full_backref)
|
||||
+ parent = dback->parent;
|
||||
+ else
|
||||
+ parent = 0;
|
||||
+
|
||||
+ for (i = 0; i < dback->found_ref; i++) {
|
||||
+ /* if parent != 0, we're doing a full backref
|
||||
+ * passing BTRFS_FIRST_FREE_OBJECTID as the owner
|
||||
+ * just makes the backref allocator create a data
|
||||
+ * backref
|
||||
+ */
|
||||
+ ret = btrfs_inc_extent_ref(trans, info->extent_root,
|
||||
+ rec->start, rec->max_size,
|
||||
+ parent,
|
||||
+ dback->root,
|
||||
+ parent ?
|
||||
+ BTRFS_FIRST_FREE_OBJECTID :
|
||||
+ dback->owner,
|
||||
+ dback->offset);
|
||||
+ if (ret)
|
||||
+ break;
|
||||
+ }
|
||||
+ fprintf(stderr, "adding new data backref"
|
||||
+ " on %llu %s %llu owner %llu"
|
||||
+ " offset %llu found %d\n",
|
||||
+ (unsigned long long)rec->start,
|
||||
+ back->full_backref ?
|
||||
+ "parent" : "root",
|
||||
+ back->full_backref ?
|
||||
+ (unsigned long long)parent :
|
||||
+ (unsigned long long)dback->root,
|
||||
+ (unsigned long long)dback->owner,
|
||||
+ (unsigned long long)dback->offset,
|
||||
+ dback->found_ref);
|
||||
+ } else {
|
||||
+ u64 parent;
|
||||
+
|
||||
+ tback = (struct tree_backref *)back;
|
||||
+ if (back->full_backref)
|
||||
+ parent = tback->parent;
|
||||
+ else
|
||||
+ parent = 0;
|
||||
+
|
||||
+ ret = btrfs_inc_extent_ref(trans, info->extent_root,
|
||||
+ rec->start, rec->max_size,
|
||||
+ parent, tback->root, 0, 0);
|
||||
+ fprintf(stderr, "adding new tree backref on "
|
||||
+ "start %llu len %llu parent %llu root %llu\n",
|
||||
+ rec->start, rec->max_size, tback->parent, tback->root);
|
||||
+ }
|
||||
+ if (ret)
|
||||
+ goto fail;
|
||||
+fail:
|
||||
+ btrfs_release_path(NULL, path);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * when an incorrect extent item is found, this will delete
|
||||
+ * all of the existing entries for it and recreate them
|
||||
+ * based on what the tree scan found.
|
||||
+ */
|
||||
+static int fixup_extent_refs(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_fs_info *info,
|
||||
+ struct extent_record *rec)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct btrfs_path *path;
|
||||
+ struct list_head *cur = rec->backrefs.next;
|
||||
+ struct extent_backref *back;
|
||||
+ int allocated = 0;
|
||||
+ u64 flags = 0;
|
||||
+
|
||||
+ /* remember our flags for recreating the extent */
|
||||
+ ret = btrfs_lookup_extent_info(NULL, info->extent_root, rec->start,
|
||||
+ rec->max_size, NULL, &flags);
|
||||
+ if (ret < 0)
|
||||
+ flags = BTRFS_BLOCK_FLAG_FULL_BACKREF;
|
||||
+
|
||||
+ path = btrfs_alloc_path();
|
||||
+
|
||||
+ /* step one, delete all the existing records */
|
||||
+ ret = delete_extent_records(trans, info->extent_root, path,
|
||||
+ rec->start);
|
||||
+
|
||||
+ if (ret < 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ /* step two, recreate all the refs we did find */
|
||||
+ while(cur != &rec->backrefs) {
|
||||
+ back = list_entry(cur, struct extent_backref, list);
|
||||
+ cur = cur->next;
|
||||
+
|
||||
+ /*
|
||||
+ * if we didn't find any references, don't create a
|
||||
+ * new extent record
|
||||
+ */
|
||||
+ if (!back->found_ref)
|
||||
+ continue;
|
||||
+
|
||||
+ ret = record_extent(trans, info, path, rec, back, allocated, flags);
|
||||
+ allocated = 1;
|
||||
+
|
||||
+ if (ret)
|
||||
+ goto out;
|
||||
+ }
|
||||
+out:
|
||||
+ btrfs_free_path(path);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static int check_extent_refs(struct btrfs_root *root,
|
||||
- struct cache_tree *extent_cache)
|
||||
+ struct cache_tree *extent_cache, int repair)
|
||||
{
|
||||
struct extent_record *rec;
|
||||
struct cache_extent *cache;
|
||||
+ struct btrfs_trans_handle *trans = NULL;
|
||||
int err = 0;
|
||||
+ int ret = 0;
|
||||
+ int fixed = 0;
|
||||
|
||||
+ if (repair)
|
||||
+ trans = btrfs_start_transaction(root, 1);
|
||||
+
|
||||
+ if (repair) {
|
||||
+ /*
|
||||
+ * if we're doing a repair, we have to make sure
|
||||
+ * we don't allocate from the problem extents.
|
||||
+ * In the worst case, this will be all the
|
||||
+ * extents in the FS
|
||||
+ */
|
||||
+ cache = find_first_cache_extent(extent_cache, 0);
|
||||
+ while(cache) {
|
||||
+ rec = container_of(cache, struct extent_record, cache);
|
||||
+ btrfs_pin_extent(root->fs_info,
|
||||
+ rec->start, rec->nr);
|
||||
+ cache = next_cache_extent(cache);
|
||||
+ }
|
||||
+ }
|
||||
while(1) {
|
||||
+ fixed = 0;
|
||||
cache = find_first_cache_extent(extent_cache, 0);
|
||||
if (!cache)
|
||||
break;
|
||||
@@ -2693,19 +3028,39 @@ static int check_extent_refs(struct btrf
|
||||
fprintf(stderr, "extent item %llu, found %llu\n",
|
||||
(unsigned long long)rec->extent_item_refs,
|
||||
(unsigned long long)rec->refs);
|
||||
+ if (!fixed && repair) {
|
||||
+ ret = fixup_extent_refs(trans, root->fs_info, rec);
|
||||
+ if (ret)
|
||||
+ goto repair_abort;
|
||||
+ fixed = 1;
|
||||
+ }
|
||||
err = 1;
|
||||
+
|
||||
}
|
||||
if (all_backpointers_checked(rec, 1)) {
|
||||
fprintf(stderr, "backpointer mismatch on [%llu %llu]\n",
|
||||
(unsigned long long)rec->start,
|
||||
(unsigned long long)rec->nr);
|
||||
|
||||
+ if (!fixed && repair) {
|
||||
+ ret = fixup_extent_refs(trans, root->fs_info, rec);
|
||||
+ if (ret)
|
||||
+ goto repair_abort;
|
||||
+ fixed = 1;
|
||||
+ }
|
||||
+
|
||||
err = 1;
|
||||
}
|
||||
if (!rec->owner_ref_checked) {
|
||||
fprintf(stderr, "owner ref check failed [%llu %llu]\n",
|
||||
(unsigned long long)rec->start,
|
||||
(unsigned long long)rec->nr);
|
||||
+ if (!fixed && repair) {
|
||||
+ ret = fixup_extent_refs(trans, root->fs_info, rec);
|
||||
+ if (ret)
|
||||
+ goto repair_abort;
|
||||
+ fixed = 1;
|
||||
+ }
|
||||
err = 1;
|
||||
}
|
||||
|
||||
@@ -2713,10 +3068,18 @@ static int check_extent_refs(struct btrf
|
||||
free_all_extent_backrefs(rec);
|
||||
free(rec);
|
||||
}
|
||||
+repair_abort:
|
||||
+ if (repair) {
|
||||
+ if (ret) {
|
||||
+ fprintf(stderr, "failed to repair damaged filesystem, aborting\n");
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ btrfs_commit_transaction(trans, root);
|
||||
+ }
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int check_extents(struct btrfs_root *root)
|
||||
+static int check_extents(struct btrfs_root *root, int repair)
|
||||
{
|
||||
struct cache_tree extent_cache;
|
||||
struct cache_tree seen;
|
||||
@@ -2797,7 +3160,7 @@ static int check_extents(struct btrfs_ro
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
- ret = check_extent_refs(root, &extent_cache);
|
||||
+ ret = check_extent_refs(root, &extent_cache, repair);
|
||||
free(bits);
|
||||
return ret;
|
||||
}
|
||||
@@ -2809,6 +3172,12 @@ static void print_usage(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+static struct option long_options[] = {
|
||||
+ { "super", 1, NULL, 's' },
|
||||
+ { "repair", 0, NULL, 0 },
|
||||
+ { 0, 0, 0, 0}
|
||||
+};
|
||||
+
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
struct cache_tree root_cache;
|
||||
@@ -2817,10 +3186,13 @@ int main(int ac, char **av)
|
||||
u64 bytenr = 0;
|
||||
int ret;
|
||||
int num;
|
||||
+ int repair = 0;
|
||||
+ int option_index = 0;
|
||||
|
||||
while(1) {
|
||||
int c;
|
||||
- c = getopt(ac, av, "as:");
|
||||
+ c = getopt_long(ac, av, "a", long_options,
|
||||
+ &option_index);
|
||||
if (c < 0)
|
||||
break;
|
||||
switch(c) {
|
||||
@@ -2831,9 +3203,14 @@ int main(int ac, char **av)
|
||||
printf("using SB copy %d, bytenr %llu\n", num,
|
||||
(unsigned long long)bytenr);
|
||||
break;
|
||||
- default:
|
||||
+ case '?':
|
||||
print_usage();
|
||||
}
|
||||
+ if (option_index == 1) {
|
||||
+ printf("enabling repair mode\n");
|
||||
+ repair = 1;
|
||||
+ }
|
||||
+
|
||||
}
|
||||
ac = ac - optind;
|
||||
|
||||
@@ -2851,15 +3228,23 @@ int main(int ac, char **av)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
- info = open_ctree_fs_info(av[optind], bytenr, 0, 0);
|
||||
+ info = open_ctree_fs_info(av[optind], bytenr, repair, 1);
|
||||
|
||||
if (info == NULL)
|
||||
return 1;
|
||||
|
||||
+ if (!extent_buffer_uptodate(info->tree_root->node) ||
|
||||
+ !extent_buffer_uptodate(info->dev_root->node) ||
|
||||
+ !extent_buffer_uptodate(info->extent_root->node) ||
|
||||
+ !extent_buffer_uptodate(info->chunk_root->node)) {
|
||||
+ fprintf(stderr, "Critical roots corrupted, unable to fsck the FS\n");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
root = info->fs_root;
|
||||
|
||||
fprintf(stderr, "checking extents\n");
|
||||
- ret = check_extents(root);
|
||||
+ ret = check_extents(root, repair);
|
||||
if (ret)
|
||||
goto out;
|
||||
fprintf(stderr, "checking fs roots\n");
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/ctree.h
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/ctree.h
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/ctree.h
|
||||
@@ -1785,6 +1785,7 @@ static inline u32 btrfs_level_size(struc
|
||||
btrfs_item_offset_nr(leaf, slot)))
|
||||
|
||||
/* extent-tree.c */
|
||||
+void btrfs_pin_extent(struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes);
|
||||
int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root);
|
||||
int btrfs_copy_pinned(struct btrfs_root *root, struct extent_io_tree *copy);
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/extent-tree.c
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/extent-tree.c
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/extent-tree.c
|
||||
@@ -1041,8 +1041,6 @@ static int lookup_inline_extent_backref(
|
||||
}
|
||||
if (ret) {
|
||||
printf("Failed to find [%llu, %u, %llu]\n", key.objectid, key.type, key.offset);
|
||||
- btrfs_print_leaf(root, path->nodes[0]);
|
||||
- btrfs_free_path(path);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
@@ -1067,8 +1065,9 @@ static int lookup_inline_extent_backref(
|
||||
}
|
||||
#endif
|
||||
if (item_size < sizeof(*ei)) {
|
||||
- printf("Size is %u, needs to be %u, slot %d\n", item_size,
|
||||
- (u32)sizeof(*ei), path->slots[0]);
|
||||
+ printf("Size is %u, needs to be %u, slot %d\n",
|
||||
+ (unsigned)item_size,
|
||||
+ (unsigned)sizeof(*ei), path->slots[0]);
|
||||
btrfs_print_leaf(root, leaf);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1460,10 +1459,8 @@ int btrfs_lookup_extent_info(struct btrf
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (ret != 0) {
|
||||
- btrfs_print_leaf(root, path->nodes[0]);
|
||||
- printk("failed to find block number %Lu\n",
|
||||
- (unsigned long long)bytenr);
|
||||
- BUG();
|
||||
+ ret = -EIO;
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
l = path->nodes[0];
|
||||
@@ -1484,9 +1481,8 @@ int btrfs_lookup_extent_info(struct btrf
|
||||
extent_flags = BTRFS_BLOCK_FLAG_FULL_BACKREF;
|
||||
#else
|
||||
BUG();
|
||||
-#endif
|
||||
- }
|
||||
- BUG_ON(num_refs == 0);
|
||||
+#endif
|
||||
+ }
|
||||
item = btrfs_item_ptr(l, path->slots[0], struct btrfs_extent_item);
|
||||
if (refs)
|
||||
*refs = num_refs;
|
||||
@@ -2033,6 +2029,12 @@ pinit:
|
||||
return 0;
|
||||
}
|
||||
|
||||
+void btrfs_pin_extent(struct btrfs_fs_info *fs_info,
|
||||
+ u64 bytenr, u64 num_bytes)
|
||||
+{
|
||||
+ update_pinned_extents(fs_info->extent_root, bytenr, num_bytes, 1);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* remove an extent from the root, returns 0 on success
|
||||
*/
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/print-tree.c
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/print-tree.c
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/print-tree.c
|
||||
@@ -239,7 +239,7 @@ static void print_extent_item(struct ext
|
||||
btrfs_shared_data_ref_count(eb, sref));
|
||||
break;
|
||||
default:
|
||||
- BUG();
|
||||
+ return;
|
||||
}
|
||||
ptr += btrfs_extent_inline_ref_size(type);
|
||||
}
|
277
0158-btrfs-corrupt-block-add-E-option-to-randomly-corrupt.patch
Normal file
277
0158-btrfs-corrupt-block-add-E-option-to-randomly-corrupt.patch
Normal file
@ -0,0 +1,277 @@
|
||||
From 395fb7119f0aa110a2b8988e68159ff1fcf1f7f0 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Tue, 7 Feb 2012 08:36:38 -0500
|
||||
Subject: [PATCH 07/18] btrfs-corrupt-block: add -E option to randomly corrupt
|
||||
the extent_root
|
||||
|
||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||
---
|
||||
btrfs-corrupt-block.c | 132 +++++++++++++++++++++++++++++++++++++++----------
|
||||
extent-tree.c | 9 ++-
|
||||
2 files changed, 111 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/btrfs-corrupt-block.c b/btrfs-corrupt-block.c
|
||||
index 59e7cb4..9ad3e05 100644
|
||||
--- a/btrfs-corrupt-block.c
|
||||
+++ b/btrfs-corrupt-block.c
|
||||
@@ -93,17 +93,9 @@ static void print_usage(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
-static struct option long_options[] = {
|
||||
- /* { "byte-count", 1, NULL, 'b' }, */
|
||||
- { "logical", 1, NULL, 'l' },
|
||||
- { "copy", 1, NULL, 'c' },
|
||||
- { "bytes", 1, NULL, 'b' },
|
||||
- { 0, 0, 0, 0}
|
||||
-};
|
||||
-
|
||||
-static int corrupt_extent(struct btrfs_root *root, u64 bytenr, int copy)
|
||||
+static int corrupt_extent(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_root *root, u64 bytenr, int copy)
|
||||
{
|
||||
- struct btrfs_trans_handle *trans;
|
||||
struct btrfs_key key;
|
||||
struct extent_buffer *leaf;
|
||||
u32 item_size;
|
||||
@@ -111,8 +103,8 @@ static int corrupt_extent(struct btrfs_root *root, u64 bytenr, int copy)
|
||||
struct btrfs_path *path;
|
||||
int ret;
|
||||
int slot;
|
||||
+ int should_del = rand() % 3;
|
||||
|
||||
- trans = btrfs_start_transaction(root, 1);
|
||||
path = btrfs_alloc_path();
|
||||
|
||||
key.objectid = bytenr;
|
||||
@@ -121,7 +113,7 @@ static int corrupt_extent(struct btrfs_root *root, u64 bytenr, int copy)
|
||||
|
||||
while(1) {
|
||||
ret = btrfs_search_slot(trans, root->fs_info->extent_root,
|
||||
- &key, path, 0, 1);
|
||||
+ &key, path, -1, 1);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
@@ -129,6 +121,7 @@ static int corrupt_extent(struct btrfs_root *root, u64 bytenr, int copy)
|
||||
if (path->slots[0] == 0)
|
||||
break;
|
||||
path->slots[0]--;
|
||||
+ ret = 0;
|
||||
}
|
||||
leaf = path->nodes[0];
|
||||
slot = path->slots[0];
|
||||
@@ -144,13 +137,26 @@ static int corrupt_extent(struct btrfs_root *root, u64 bytenr, int copy)
|
||||
key.type != BTRFS_SHARED_DATA_REF_KEY)
|
||||
goto next;
|
||||
|
||||
- fprintf(stderr, "corrupting extent record: key %Lu %u %Lu\n",
|
||||
- key.objectid, key.type, key.offset);
|
||||
+ if (should_del) {
|
||||
+ fprintf(stderr, "deleting extent record: key %Lu %u %Lu\n",
|
||||
+ key.objectid, key.type, key.offset);
|
||||
|
||||
- ptr = btrfs_item_ptr_offset(leaf, slot);
|
||||
- item_size = btrfs_item_size_nr(leaf, slot);
|
||||
- memset_extent_buffer(leaf, 0, ptr, item_size);
|
||||
- btrfs_mark_buffer_dirty(leaf);
|
||||
+ if (key.type == BTRFS_EXTENT_ITEM_KEY) {
|
||||
+ /* make sure this extent doesn't get
|
||||
+ * reused for other purposes */
|
||||
+ btrfs_pin_extent(root->fs_info,
|
||||
+ key.objectid, key.offset);
|
||||
+ }
|
||||
+
|
||||
+ btrfs_del_item(trans, root, path);
|
||||
+ } else {
|
||||
+ fprintf(stderr, "corrupting extent record: key %Lu %u %Lu\n",
|
||||
+ key.objectid, key.type, key.offset);
|
||||
+ ptr = btrfs_item_ptr_offset(leaf, slot);
|
||||
+ item_size = btrfs_item_size_nr(leaf, slot);
|
||||
+ memset_extent_buffer(leaf, 0, ptr, item_size);
|
||||
+ btrfs_mark_buffer_dirty(leaf);
|
||||
+ }
|
||||
next:
|
||||
btrfs_release_path(NULL, path);
|
||||
|
||||
@@ -161,12 +167,65 @@ next:
|
||||
}
|
||||
|
||||
btrfs_free_path(path);
|
||||
- btrfs_commit_transaction(trans, root);
|
||||
- ret = close_ctree(root);
|
||||
- BUG_ON(ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void btrfs_corrupt_extent_leaf(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_root *root, struct extent_buffer *eb)
|
||||
+{
|
||||
+ u32 nr = btrfs_header_nritems(eb);
|
||||
+ u32 victim = rand() % nr;
|
||||
+ u64 objectid;
|
||||
+ struct btrfs_key key;
|
||||
+
|
||||
+ btrfs_item_key_to_cpu(eb, &key, victim);
|
||||
+ objectid = key.objectid;
|
||||
+ corrupt_extent(trans, root, objectid, 1);
|
||||
+}
|
||||
+
|
||||
+static void btrfs_corrupt_extent_tree(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_root *root, struct extent_buffer *eb)
|
||||
+{
|
||||
+ int i;
|
||||
+ u32 nr;
|
||||
+
|
||||
+ if (!eb)
|
||||
+ return;
|
||||
+
|
||||
+ nr = btrfs_header_nritems(eb);
|
||||
+ if (btrfs_is_leaf(eb)) {
|
||||
+ btrfs_corrupt_extent_leaf(trans, root, eb);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (btrfs_header_level(eb) == 1 && eb != root->node) {
|
||||
+ if (rand() % 5)
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < nr; i++) {
|
||||
+ struct extent_buffer *next;
|
||||
+
|
||||
+ next = read_tree_block(root, btrfs_node_blockptr(eb, i),
|
||||
+ root->leafsize, btrfs_node_ptr_generation(eb, i));
|
||||
+ if (!next)
|
||||
+ continue;
|
||||
+ btrfs_corrupt_extent_tree(trans, root, next);
|
||||
+ free_extent_buffer(next);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static struct option long_options[] = {
|
||||
+ /* { "byte-count", 1, NULL, 'b' }, */
|
||||
+ { "logical", 1, NULL, 'l' },
|
||||
+ { "copy", 1, NULL, 'c' },
|
||||
+ { "bytes", 1, NULL, 'b' },
|
||||
+ { "extent-record", 0, NULL, 'e' },
|
||||
+ { "extent-tree", 0, NULL, 'E' },
|
||||
+ { 0, 0, 0, 0}
|
||||
+};
|
||||
+
|
||||
+
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
struct cache_tree root_cache;
|
||||
@@ -178,11 +237,14 @@ int main(int ac, char **av)
|
||||
int option_index = 0;
|
||||
int copy = 0;
|
||||
u64 bytes = 4096;
|
||||
- int extent_rec;
|
||||
+ int extent_rec = 0;
|
||||
+ int extent_tree = 0;
|
||||
+
|
||||
+ srand(128);
|
||||
|
||||
while(1) {
|
||||
int c;
|
||||
- c = getopt_long(ac, av, "l:c:e", long_options,
|
||||
+ c = getopt_long(ac, av, "l:c:eE", long_options,
|
||||
&option_index);
|
||||
if (c < 0)
|
||||
break;
|
||||
@@ -214,6 +276,9 @@ int main(int ac, char **av)
|
||||
case 'e':
|
||||
extent_rec = 1;
|
||||
break;
|
||||
+ case 'E':
|
||||
+ extent_tree = 1;
|
||||
+ break;
|
||||
default:
|
||||
print_usage();
|
||||
}
|
||||
@@ -221,7 +286,7 @@ int main(int ac, char **av)
|
||||
ac = ac - optind;
|
||||
if (ac == 0)
|
||||
print_usage();
|
||||
- if (logical == 0)
|
||||
+ if (logical == 0 && !extent_tree)
|
||||
print_usage();
|
||||
if (copy < 0)
|
||||
print_usage();
|
||||
@@ -237,8 +302,19 @@ int main(int ac, char **av)
|
||||
exit(1);
|
||||
}
|
||||
if (extent_rec) {
|
||||
- ret = corrupt_extent (root, logical, 0);
|
||||
- goto out;
|
||||
+ struct btrfs_trans_handle *trans;
|
||||
+ trans = btrfs_start_transaction(root, 1);
|
||||
+ ret = corrupt_extent (trans, root, logical, 0);
|
||||
+ btrfs_commit_transaction(trans, root);
|
||||
+ goto out_close;
|
||||
+ }
|
||||
+ if (extent_tree) {
|
||||
+ struct btrfs_trans_handle *trans;
|
||||
+ trans = btrfs_start_transaction(root, 1);
|
||||
+ btrfs_corrupt_extent_tree(trans, root->fs_info->extent_root,
|
||||
+ root->fs_info->extent_root->node);
|
||||
+ btrfs_commit_transaction(trans, root);
|
||||
+ goto out_close;
|
||||
}
|
||||
|
||||
if (bytes == 0)
|
||||
@@ -253,6 +329,8 @@ int main(int ac, char **av)
|
||||
logical += root->sectorsize;
|
||||
bytes -= root->sectorsize;
|
||||
}
|
||||
-out:
|
||||
+ return ret;
|
||||
+out_close:
|
||||
+ close_ctree(root);
|
||||
return ret;
|
||||
}
|
||||
diff --git a/extent-tree.c b/extent-tree.c
|
||||
index 1f13992..01dfa3f 100644
|
||||
--- a/extent-tree.c
|
||||
+++ b/extent-tree.c
|
||||
@@ -1083,7 +1083,9 @@ static int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
|
||||
ptr += sizeof(struct btrfs_tree_block_info);
|
||||
BUG_ON(ptr > end);
|
||||
} else {
|
||||
- BUG_ON(!(flags & BTRFS_EXTENT_FLAG_DATA));
|
||||
+ if (!(flags & BTRFS_EXTENT_FLAG_DATA)) {
|
||||
+ return -EIO;
|
||||
+ }
|
||||
}
|
||||
|
||||
err = -ENOENT;
|
||||
@@ -2120,8 +2122,6 @@ static int __free_extent(struct btrfs_trans_handle *trans,
|
||||
extent_slot = path->slots[0];
|
||||
}
|
||||
} else {
|
||||
- btrfs_print_leaf(extent_root, path->nodes[0]);
|
||||
- WARN_ON(1);
|
||||
printk(KERN_ERR "btrfs unable to find ref byte nr %llu "
|
||||
"parent %llu root %llu owner %llu offset %llu\n",
|
||||
(unsigned long long)bytenr,
|
||||
@@ -2129,6 +2129,8 @@ static int __free_extent(struct btrfs_trans_handle *trans,
|
||||
(unsigned long long)root_objectid,
|
||||
(unsigned long long)owner_objectid,
|
||||
(unsigned long long)owner_offset);
|
||||
+ ret = -EIO;
|
||||
+ goto fail;
|
||||
}
|
||||
|
||||
leaf = path->nodes[0];
|
||||
@@ -2238,6 +2240,7 @@ static int __free_extent(struct btrfs_trans_handle *trans,
|
||||
mark_free);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
+fail:
|
||||
btrfs_free_path(path);
|
||||
finish_current_insert(trans, extent_root);
|
||||
return ret;
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
393
0159-btrfsck-fix-block-group-accounting-during-repair.patch
Normal file
393
0159-btrfsck-fix-block-group-accounting-during-repair.patch
Normal file
@ -0,0 +1,393 @@
|
||||
From 4fc0390c2bbce8a5b39fb592da80bfe1870152a4 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Wed, 8 Feb 2012 21:29:13 -0500
|
||||
Subject: [PATCH 08/18] btrfsck: fix block group accounting during repair
|
||||
|
||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||
---
|
||||
btrfsck.c | 36 +++++++++-----
|
||||
convert.c | 62 +-----------------------
|
||||
ctree.h | 3 +
|
||||
extent-tree.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
4 files changed, 174 insertions(+), 75 deletions(-)
|
||||
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/btrfsck.c
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/btrfsck.c
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/btrfsck.c
|
||||
@@ -2725,7 +2725,7 @@ static int add_root_to_pending(struct ex
|
||||
static int delete_extent_records(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root,
|
||||
struct btrfs_path *path,
|
||||
- u64 bytenr)
|
||||
+ u64 bytenr, u64 new_len)
|
||||
{
|
||||
struct btrfs_key key;
|
||||
struct btrfs_key found_key;
|
||||
@@ -2787,7 +2787,7 @@ static int delete_extent_records(struct
|
||||
|
||||
if (found_key.type == BTRFS_EXTENT_ITEM_KEY) {
|
||||
ret = btrfs_update_block_group(trans, root, bytenr,
|
||||
- found_key.offset, 0, 1);
|
||||
+ found_key.offset, 0, 0);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
@@ -2959,7 +2959,7 @@ static int fixup_extent_refs(struct btrf
|
||||
|
||||
/* step one, delete all the existing records */
|
||||
ret = delete_extent_records(trans, info->extent_root, path,
|
||||
- rec->start);
|
||||
+ rec->start, rec->max_size);
|
||||
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
@@ -2987,19 +2987,16 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int check_extent_refs(struct btrfs_root *root,
|
||||
- struct cache_tree *extent_cache, int repair)
|
||||
+static int check_extent_refs(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_root *root,
|
||||
+ struct cache_tree *extent_cache, int repair)
|
||||
{
|
||||
struct extent_record *rec;
|
||||
struct cache_extent *cache;
|
||||
- struct btrfs_trans_handle *trans = NULL;
|
||||
int err = 0;
|
||||
int ret = 0;
|
||||
int fixed = 0;
|
||||
|
||||
- if (repair)
|
||||
- trans = btrfs_start_transaction(root, 1);
|
||||
-
|
||||
if (repair) {
|
||||
/*
|
||||
* if we're doing a repair, we have to make sure
|
||||
@@ -3074,12 +3071,12 @@ repair_abort:
|
||||
fprintf(stderr, "failed to repair damaged filesystem, aborting\n");
|
||||
exit(1);
|
||||
}
|
||||
- btrfs_commit_transaction(trans, root);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int check_extents(struct btrfs_root *root, int repair)
|
||||
+static int check_extents(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_root *root, int repair)
|
||||
{
|
||||
struct cache_tree extent_cache;
|
||||
struct cache_tree seen;
|
||||
@@ -3160,7 +3157,7 @@ static int check_extents(struct btrfs_ro
|
||||
if (ret != 0)
|
||||
break;
|
||||
}
|
||||
- ret = check_extent_refs(root, &extent_cache, repair);
|
||||
+ ret = check_extent_refs(trans, root, &extent_cache, repair);
|
||||
free(bits);
|
||||
return ret;
|
||||
}
|
||||
@@ -3183,6 +3180,7 @@ int main(int ac, char **av)
|
||||
struct cache_tree root_cache;
|
||||
struct btrfs_root *root;
|
||||
struct btrfs_fs_info *info;
|
||||
+ struct btrfs_trans_handle *trans = NULL;
|
||||
u64 bytenr = 0;
|
||||
int ret;
|
||||
int num;
|
||||
@@ -3244,9 +3242,16 @@ int main(int ac, char **av)
|
||||
root = info->fs_root;
|
||||
|
||||
fprintf(stderr, "checking extents\n");
|
||||
- ret = check_extents(root, repair);
|
||||
+ if (repair)
|
||||
+ trans = btrfs_start_transaction(root, 1);
|
||||
+
|
||||
+ ret = check_extents(trans, root, repair);
|
||||
if (ret)
|
||||
goto out;
|
||||
+
|
||||
+ if (repair)
|
||||
+ btrfs_fix_block_accounting(trans, root);
|
||||
+
|
||||
fprintf(stderr, "checking fs roots\n");
|
||||
ret = check_fs_roots(root, &root_cache);
|
||||
if (ret)
|
||||
@@ -3256,6 +3261,11 @@ int main(int ac, char **av)
|
||||
ret = check_root_refs(root, &root_cache);
|
||||
out:
|
||||
free_root_recs(&root_cache);
|
||||
+ if (repair) {
|
||||
+ ret = btrfs_commit_transaction(trans, root);
|
||||
+ if (ret)
|
||||
+ exit(1);
|
||||
+ }
|
||||
close_ctree(root);
|
||||
|
||||
if (found_old_backref) {
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/convert.c
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/convert.c
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/convert.c
|
||||
@@ -1504,66 +1504,6 @@ fail:
|
||||
return new_root;
|
||||
}
|
||||
|
||||
-/*
|
||||
- * Fixup block accounting. The initial block accounting created by
|
||||
- * make_block_groups isn't accuracy in this case.
|
||||
- */
|
||||
-static int fixup_block_accounting(struct btrfs_trans_handle *trans,
|
||||
- struct btrfs_root *root)
|
||||
-{
|
||||
- int ret;
|
||||
- int slot;
|
||||
- u64 start = 0;
|
||||
- u64 bytes_used = 0;
|
||||
- struct btrfs_path path;
|
||||
- struct btrfs_key key;
|
||||
- struct extent_buffer *leaf;
|
||||
- struct btrfs_block_group_cache *cache;
|
||||
- struct btrfs_fs_info *fs_info = root->fs_info;
|
||||
-
|
||||
- while(1) {
|
||||
- cache = btrfs_lookup_block_group(fs_info, start);
|
||||
- if (!cache)
|
||||
- break;
|
||||
- start = cache->key.objectid + cache->key.offset;
|
||||
- btrfs_set_block_group_used(&cache->item, 0);
|
||||
- cache->space_info->bytes_used = 0;
|
||||
- }
|
||||
-
|
||||
- btrfs_init_path(&path);
|
||||
- key.offset = 0;
|
||||
- key.objectid = 0;
|
||||
- btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
|
||||
- ret = btrfs_search_slot(trans, root->fs_info->extent_root,
|
||||
- &key, &path, 0, 0);
|
||||
- if (ret < 0)
|
||||
- return ret;
|
||||
- while(1) {
|
||||
- leaf = path.nodes[0];
|
||||
- slot = path.slots[0];
|
||||
- if (slot >= btrfs_header_nritems(leaf)) {
|
||||
- ret = btrfs_next_leaf(root, &path);
|
||||
- if (ret < 0)
|
||||
- return ret;
|
||||
- if (ret > 0)
|
||||
- break;
|
||||
- leaf = path.nodes[0];
|
||||
- slot = path.slots[0];
|
||||
- }
|
||||
- btrfs_item_key_to_cpu(leaf, &key, slot);
|
||||
- if (key.type == BTRFS_EXTENT_ITEM_KEY) {
|
||||
- bytes_used += key.offset;
|
||||
- ret = btrfs_update_block_group(trans, root,
|
||||
- key.objectid, key.offset, 1, 0);
|
||||
- BUG_ON(ret);
|
||||
- }
|
||||
- path.slots[0]++;
|
||||
- }
|
||||
- btrfs_set_super_bytes_used(&root->fs_info->super_copy, bytes_used);
|
||||
- btrfs_release_path(root, &path);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static int create_chunk_mapping(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root)
|
||||
{
|
||||
@@ -1735,7 +1675,7 @@ static int init_btrfs(struct btrfs_root
|
||||
ret = btrfs_make_block_groups(trans, root);
|
||||
if (ret)
|
||||
goto err;
|
||||
- ret = fixup_block_accounting(trans, root);
|
||||
+ ret = btrfs_fixup_block_accounting(trans, root);
|
||||
if (ret)
|
||||
goto err;
|
||||
ret = create_chunk_mapping(trans, root);
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/ctree.h
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/ctree.h
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/ctree.h
|
||||
@@ -1785,6 +1785,9 @@ static inline u32 btrfs_level_size(struc
|
||||
btrfs_item_offset_nr(leaf, slot)))
|
||||
|
||||
/* extent-tree.c */
|
||||
+int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_root *root);
|
||||
+int btrfs_check_block_accounting(struct btrfs_root *root);
|
||||
void btrfs_pin_extent(struct btrfs_fs_info *fs_info, u64 bytenr, u64 num_bytes);
|
||||
int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root);
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/extent-tree.c
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/extent-tree.c
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/extent-tree.c
|
||||
@@ -1734,7 +1734,12 @@ static int update_space_info(struct btrf
|
||||
if (found) {
|
||||
found->total_bytes += total_bytes;
|
||||
found->bytes_used += bytes_used;
|
||||
- WARN_ON(found->total_bytes < found->bytes_used);
|
||||
+ if (found->total_bytes < found->bytes_used) {
|
||||
+ fprintf(stderr, "warning, bad space info total_bytes "
|
||||
+ "%llu used %llu\n",
|
||||
+ (unsigned long long)found->total_bytes,
|
||||
+ (unsigned long long)found->bytes_used);
|
||||
+ }
|
||||
*space_info = found;
|
||||
return 0;
|
||||
}
|
||||
@@ -1853,6 +1858,7 @@ static int update_block_group(struct btr
|
||||
|
||||
old_val = btrfs_block_group_used(&cache->item);
|
||||
num_bytes = min(total, cache->key.offset - byte_in_group);
|
||||
+
|
||||
if (alloc) {
|
||||
old_val += num_bytes;
|
||||
cache->space_info->bytes_used += num_bytes;
|
||||
@@ -3274,3 +3280,143 @@ int btrfs_update_block_group(struct btrf
|
||||
return update_block_group(trans, root, bytenr, num_bytes,
|
||||
alloc, mark_free);
|
||||
}
|
||||
+
|
||||
+static int btrfs_count_extents_in_block_group(struct btrfs_root *root,
|
||||
+ struct btrfs_path *path, u64 start,
|
||||
+ u64 len,
|
||||
+ u64 *total)
|
||||
+{
|
||||
+ struct btrfs_key key;
|
||||
+ struct extent_buffer *leaf;
|
||||
+ u64 bytes_used = 0;
|
||||
+ int ret;
|
||||
+ int slot;
|
||||
+
|
||||
+ key.offset = 0;
|
||||
+ key.objectid = start;
|
||||
+ btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
|
||||
+ ret = btrfs_search_slot(NULL, root->fs_info->extent_root,
|
||||
+ &key, path, 0, 0);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ while(1) {
|
||||
+ leaf = path->nodes[0];
|
||||
+ slot = path->slots[0];
|
||||
+ if (slot >= btrfs_header_nritems(leaf)) {
|
||||
+ ret = btrfs_next_leaf(root, path);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ if (ret > 0)
|
||||
+ break;
|
||||
+ leaf = path->nodes[0];
|
||||
+ slot = path->slots[0];
|
||||
+ }
|
||||
+ btrfs_item_key_to_cpu(leaf, &key, slot);
|
||||
+ if (key.objectid > start + len)
|
||||
+ break;
|
||||
+ if (key.type == BTRFS_EXTENT_ITEM_KEY)
|
||||
+ bytes_used += key.offset;
|
||||
+ path->slots[0]++;
|
||||
+ }
|
||||
+ *total = bytes_used;
|
||||
+ btrfs_release_path(root, path);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int btrfs_check_block_accounting(struct btrfs_root *root)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u64 start = 0;
|
||||
+ u64 bytes_used = 0;
|
||||
+ struct btrfs_path path;
|
||||
+ struct btrfs_block_group_cache *cache;
|
||||
+ struct btrfs_fs_info *fs_info = root->fs_info;
|
||||
+
|
||||
+ btrfs_init_path(&path);
|
||||
+
|
||||
+ while(1) {
|
||||
+ cache = btrfs_lookup_block_group(fs_info, start);
|
||||
+ if (!cache)
|
||||
+ break;
|
||||
+
|
||||
+ ret = btrfs_count_extents_in_block_group(root, &path,
|
||||
+ cache->key.objectid,
|
||||
+ cache->key.offset,
|
||||
+ &bytes_used);
|
||||
+
|
||||
+ if (ret == 0) {
|
||||
+ u64 on_disk = btrfs_block_group_used(&cache->item);
|
||||
+ if (on_disk != bytes_used) {
|
||||
+ fprintf(stderr, "bad block group accounting found %llu "
|
||||
+ "expected %llu block group %llu\n",
|
||||
+ (unsigned long long)bytes_used,
|
||||
+ (unsigned long long)on_disk,
|
||||
+ (unsigned long long)cache->key.objectid);
|
||||
+ }
|
||||
+ }
|
||||
+ start = cache->key.objectid + cache->key.offset;
|
||||
+
|
||||
+ cache->space_info->bytes_used = 0;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Fixup block accounting. The initial block accounting created by
|
||||
+ * make_block_groups isn't accuracy in this case.
|
||||
+ */
|
||||
+int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_root *root)
|
||||
+{
|
||||
+ int ret;
|
||||
+ int slot;
|
||||
+ u64 start = 0;
|
||||
+ u64 bytes_used = 0;
|
||||
+ struct btrfs_path path;
|
||||
+ struct btrfs_key key;
|
||||
+ struct extent_buffer *leaf;
|
||||
+ struct btrfs_block_group_cache *cache;
|
||||
+ struct btrfs_fs_info *fs_info = root->fs_info;
|
||||
+
|
||||
+ while(1) {
|
||||
+ cache = btrfs_lookup_block_group(fs_info, start);
|
||||
+ if (!cache)
|
||||
+ break;
|
||||
+ start = cache->key.objectid + cache->key.offset;
|
||||
+ btrfs_set_block_group_used(&cache->item, 0);
|
||||
+ cache->space_info->bytes_used = 0;
|
||||
+ }
|
||||
+
|
||||
+ btrfs_init_path(&path);
|
||||
+ key.offset = 0;
|
||||
+ key.objectid = 0;
|
||||
+ btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
|
||||
+ ret = btrfs_search_slot(trans, root->fs_info->extent_root,
|
||||
+ &key, &path, 0, 0);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ while(1) {
|
||||
+ leaf = path.nodes[0];
|
||||
+ slot = path.slots[0];
|
||||
+ if (slot >= btrfs_header_nritems(leaf)) {
|
||||
+ ret = btrfs_next_leaf(root, &path);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ if (ret > 0)
|
||||
+ break;
|
||||
+ leaf = path.nodes[0];
|
||||
+ slot = path.slots[0];
|
||||
+ }
|
||||
+ btrfs_item_key_to_cpu(leaf, &key, slot);
|
||||
+ if (key.type == BTRFS_EXTENT_ITEM_KEY) {
|
||||
+ bytes_used += key.offset;
|
||||
+ ret = btrfs_update_block_group(trans, root,
|
||||
+ key.objectid, key.offset, 1, 0);
|
||||
+ BUG_ON(ret);
|
||||
+ }
|
||||
+ path.slots[0]++;
|
||||
+ }
|
||||
+ btrfs_set_super_bytes_used(&root->fs_info->super_copy, bytes_used);
|
||||
+ btrfs_release_path(root, &path);
|
||||
+ return 0;
|
||||
+}
|
26
0160-Turn-off-some-commands-in-Makefile.patch
Normal file
26
0160-Turn-off-some-commands-in-Makefile.patch
Normal file
@ -0,0 +1,26 @@
|
||||
From 6608cffe25fb1d1c3c33caffc98f2f9ba59ed2e6 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Wed, 8 Feb 2012 21:38:20 -0500
|
||||
Subject: [PATCH 09/18] Turn off some commands in Makefile
|
||||
|
||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||
---
|
||||
Makefile | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 055d2d6..930500e 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -17,7 +17,7 @@ LIBS=-luuid
|
||||
RESTORE_LIBS=-lz -llzo2
|
||||
|
||||
progs = btrfsctl mkfs.btrfs btrfs-debug-tree btrfs-show btrfs-vol btrfsck \
|
||||
- btrfs btrfs-map-logical restore find-root calc-size btrfs-corrupt-block \
|
||||
+ btrfs btrfs-map-logical btrfs-image btrfs-zero-log \
|
||||
btrfs-dump-super
|
||||
|
||||
btrfs_man_page_source = btrfs.c btrfs_cmds.c scrub.c
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
@ -0,0 +1,78 @@
|
||||
From 46f7f481f4270304f358c4c6a0020ca0ca7b9e97 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Wed, 8 Feb 2012 22:26:26 -0500
|
||||
Subject: [PATCH 10/18] Fix btrfs-convert, btrfs-restore and btrfs-find-root
|
||||
build
|
||||
|
||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||
|
||||
fixit
|
||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||
---
|
||||
Makefile | 14 +++++++-------
|
||||
convert.c | 2 +-
|
||||
2 files changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 930500e..556bcce 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -17,7 +17,8 @@ LIBS=-luuid
|
||||
RESTORE_LIBS=-lz -llzo2
|
||||
|
||||
progs = btrfsctl mkfs.btrfs btrfs-debug-tree btrfs-show btrfs-vol btrfsck \
|
||||
- btrfs btrfs-map-logical btrfs-image btrfs-zero-log \
|
||||
+ btrfs btrfs-map-logical btrfs-image btrfs-zero-log btrfs-convert \
|
||||
+ btrfs-find-root btrfs-restore btrfstune \
|
||||
btrfs-dump-super
|
||||
|
||||
btrfs_man_page_source = btrfs.c btrfs_cmds.c scrub.c
|
||||
@@ -47,11 +48,11 @@ btrfs: $(objects) btrfs.o btrfs_cmds.o scrub.o helpmsg.o
|
||||
calc-size: $(objects) calc-size.o
|
||||
gcc $(CFLAGS) -o calc-size calc-size.o $(objects) $(LDFLAGS) $(LIBS)
|
||||
|
||||
-find-root: $(objects) find-root.o
|
||||
- gcc $(CFLAGS) -o find-root find-root.o $(objects) $(LDFLAGS) $(LIBS)
|
||||
+btrfs-find-root: $(objects) find-root.o
|
||||
+ gcc $(CFLAGS) -o btrfs-find-root find-root.o $(objects) $(LDFLAGS) $(LIBS)
|
||||
|
||||
-restore: $(objects) restore.o
|
||||
- gcc $(CFLAGS) -o restore restore.o $(objects) $(LDFLAGS) $(LIBS) $(RESTORE_LIBS)
|
||||
+btrfs-restore: $(objects) restore.o
|
||||
+ gcc $(CFLAGS) -o btrfs-restore restore.o $(objects) $(LDFLAGS) $(LIBS) $(RESTORE_LIBS)
|
||||
|
||||
btrfsctl: $(objects) btrfsctl.o
|
||||
$(CC) $(CFLAGS) -o btrfsctl btrfsctl.o $(objects) $(LDFLAGS) $(LIBS)
|
||||
@@ -98,7 +99,7 @@ dir-test: $(objects) dir-test.o
|
||||
quick-test: $(objects) quick-test.o
|
||||
$(CC) $(CFLAGS) -o quick-test $(objects) quick-test.o $(LDFLAGS) $(LIBS)
|
||||
|
||||
-convert: $(objects) convert.o
|
||||
+btrfs-convert: $(objects) convert.o
|
||||
$(CC) $(CFLAGS) -o btrfs-convert $(objects) convert.o -lext2fs -lcom_err $(LDFLAGS) $(LIBS)
|
||||
|
||||
ioctl-test: $(objects) ioctl-test.o
|
||||
@@ -140,7 +141,6 @@ clean :
|
||||
install: $(progs) install-man
|
||||
$(INSTALL) -m755 -d $(DESTDIR)$(bindir)
|
||||
$(INSTALL) $(progs) $(DESTDIR)$(bindir)
|
||||
- if [ -e btrfs-convert ]; then $(INSTALL) btrfs-convert $(DESTDIR)$(bindir); fi
|
||||
|
||||
test: test-userspace test-root
|
||||
|
||||
diff --git a/convert.c b/convert.c
|
||||
index a2f7925..5afcc45 100644
|
||||
--- a/convert.c
|
||||
+++ b/convert.c
|
||||
@@ -1675,7 +1675,7 @@ static int init_btrfs(struct btrfs_root *root)
|
||||
ret = btrfs_make_block_groups(trans, root);
|
||||
if (ret)
|
||||
goto err;
|
||||
- ret = btrfs_fixup_block_accounting(trans, root);
|
||||
+ ret = btrfs_fix_block_accounting(trans, root);
|
||||
if (ret)
|
||||
goto err;
|
||||
ret = create_chunk_mapping(trans, root);
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
@ -0,0 +1,43 @@
|
||||
From 494ba283ed46df812d56652d6ccc1b548bb5fe17 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Thu, 9 Feb 2012 09:29:19 -0500
|
||||
Subject: [PATCH 11/18] btrfsck: make sure to dirty all block groups as we fix
|
||||
accounting
|
||||
|
||||
The code that corrects the count of bytes used in each block group
|
||||
was only marking block groups dirty when they contained extents. This
|
||||
fixes things to dirty all the block groups, so any empty block groups
|
||||
are written with their correct (zero) count.
|
||||
|
||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||
---
|
||||
extent-tree.c | 6 ++++++
|
||||
1 files changed, 6 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/extent-tree.c b/extent-tree.c
|
||||
index 544ab2f..5c4057e 100644
|
||||
--- a/extent-tree.c
|
||||
+++ b/extent-tree.c
|
||||
@@ -3378,6 +3378,8 @@ int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_block_group_cache *cache;
|
||||
struct btrfs_fs_info *fs_info = root->fs_info;
|
||||
|
||||
+ root = root->fs_info->extent_root;
|
||||
+
|
||||
while(1) {
|
||||
cache = btrfs_lookup_block_group(fs_info, start);
|
||||
if (!cache)
|
||||
@@ -3385,6 +3387,10 @@ int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans,
|
||||
start = cache->key.objectid + cache->key.offset;
|
||||
btrfs_set_block_group_used(&cache->item, 0);
|
||||
cache->space_info->bytes_used = 0;
|
||||
+ set_extent_bits(&root->fs_info->block_group_cache,
|
||||
+ cache->key.objectid,
|
||||
+ cache->key.objectid + cache->key.offset -1,
|
||||
+ BLOCK_GROUP_DIRTY, GFP_NOFS);
|
||||
}
|
||||
|
||||
btrfs_init_path(&path);
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
179
0163-btrfsck-add-init-csum-tree-to-replace-the-csum-root-.patch
Normal file
179
0163-btrfsck-add-init-csum-tree-to-replace-the-csum-root-.patch
Normal file
@ -0,0 +1,179 @@
|
||||
From 80a0a84e46d07d2b2b07991ee2813b017301786c Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Thu, 9 Feb 2012 10:38:05 -0500
|
||||
Subject: [PATCH 12/18] btrfsck: add --init-csum-tree to replace the csum root
|
||||
with an empty one
|
||||
|
||||
This will effectively delete all of your crcs, but at least you'll
|
||||
be able to mount the FS with nodatasum.
|
||||
|
||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||
---
|
||||
btrfsck.c | 27 ++++++++++++++++++++++-----
|
||||
ctree.c | 40 ++++++++++++++++++++++++++++++++++++++++
|
||||
ctree.h | 2 ++
|
||||
disk-io.c | 3 ++-
|
||||
4 files changed, 66 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/btrfsck.c b/btrfsck.c
|
||||
index 1320238..a451397 100644
|
||||
--- a/btrfsck.c
|
||||
+++ b/btrfsck.c
|
||||
@@ -3171,6 +3171,7 @@ static void print_usage(void)
|
||||
static struct option long_options[] = {
|
||||
{ "super", 1, NULL, 's' },
|
||||
{ "repair", 0, NULL, 0 },
|
||||
+ { "init-csum-tree", 0, NULL, 0 },
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -3185,6 +3186,8 @@ int main(int ac, char **av)
|
||||
int num;
|
||||
int repair = 0;
|
||||
int option_index = 0;
|
||||
+ int init_csum_tree = 0;
|
||||
+ int rw = 0;
|
||||
|
||||
while(1) {
|
||||
int c;
|
||||
@@ -3206,6 +3209,11 @@ int main(int ac, char **av)
|
||||
if (option_index == 1) {
|
||||
printf("enabling repair mode\n");
|
||||
repair = 1;
|
||||
+ rw = 1;
|
||||
+ } else if (option_index == 2) {
|
||||
+ printf("Creating a new CRC tree\n");
|
||||
+ init_csum_tree = 1;
|
||||
+ rw = 1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3225,7 +3233,7 @@ int main(int ac, char **av)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
- info = open_ctree_fs_info(av[optind], bytenr, repair, 1);
|
||||
+ info = open_ctree_fs_info(av[optind], bytenr, rw, 1);
|
||||
|
||||
if (info == NULL)
|
||||
return 1;
|
||||
@@ -3241,9 +3249,19 @@ int main(int ac, char **av)
|
||||
root = info->fs_root;
|
||||
|
||||
fprintf(stderr, "checking extents\n");
|
||||
- if (repair)
|
||||
+ if (rw)
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
|
||||
+ if (init_csum_tree) {
|
||||
+ fprintf(stderr, "Reinit crc root\n");
|
||||
+ ret = btrfs_fsck_reinit_root(trans, info->csum_root);
|
||||
+ if (ret) {
|
||||
+ fprintf(stderr, "crc root initialization failed\n");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
ret = check_extents(trans, root, repair);
|
||||
if (ret)
|
||||
goto out;
|
||||
@@ -3260,15 +3278,14 @@ int main(int ac, char **av)
|
||||
ret = check_root_refs(root, &root_cache);
|
||||
out:
|
||||
free_root_recs(&root_cache);
|
||||
- if (repair) {
|
||||
+ if (rw) {
|
||||
ret = btrfs_commit_transaction(trans, root);
|
||||
if (ret)
|
||||
exit(1);
|
||||
}
|
||||
close_ctree(root);
|
||||
|
||||
- if (found_old_backref) {
|
||||
- /*
|
||||
+ if (found_old_backref) { /*
|
||||
* there was a disk format change when mixed
|
||||
* backref was in testing tree. The old format
|
||||
* existed about one week.
|
||||
diff --git a/ctree.c b/ctree.c
|
||||
index 005550f..282c868 100644
|
||||
--- a/ctree.c
|
||||
+++ b/ctree.c
|
||||
@@ -138,6 +138,46 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int btrfs_fsck_reinit_root(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_root *root)
|
||||
+{
|
||||
+ struct extent_buffer *c;
|
||||
+ struct extent_buffer *old = root->node;
|
||||
+ int level;
|
||||
+ struct btrfs_disk_key disk_key = {0,0,0};
|
||||
+
|
||||
+ level = 0;
|
||||
+
|
||||
+ c = btrfs_alloc_free_block(trans, root,
|
||||
+ btrfs_level_size(root, 0),
|
||||
+ root->root_key.objectid,
|
||||
+ &disk_key, level, 0, 0);
|
||||
+ if (IS_ERR(c))
|
||||
+ return PTR_ERR(c);
|
||||
+
|
||||
+ memset_extent_buffer(c, 0, 0, sizeof(struct btrfs_header));
|
||||
+ btrfs_set_header_level(c, level);
|
||||
+ btrfs_set_header_bytenr(c, c->start);
|
||||
+ btrfs_set_header_generation(c, trans->transid);
|
||||
+ btrfs_set_header_backref_rev(c, BTRFS_MIXED_BACKREF_REV);
|
||||
+ btrfs_set_header_owner(c, root->root_key.objectid);
|
||||
+
|
||||
+ write_extent_buffer(c, root->fs_info->fsid,
|
||||
+ (unsigned long)btrfs_header_fsid(c),
|
||||
+ BTRFS_FSID_SIZE);
|
||||
+
|
||||
+ write_extent_buffer(c, root->fs_info->chunk_tree_uuid,
|
||||
+ (unsigned long)btrfs_header_chunk_tree_uuid(c),
|
||||
+ BTRFS_UUID_SIZE);
|
||||
+
|
||||
+ btrfs_mark_buffer_dirty(c);
|
||||
+
|
||||
+ free_extent_buffer(old);
|
||||
+ root->node = c;
|
||||
+ add_root_to_dirty_list(root);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* check if the tree block can be shared by multiple trees
|
||||
*/
|
||||
diff --git a/ctree.h b/ctree.h
|
||||
index 6f12869..c53f65a 100644
|
||||
--- a/ctree.h
|
||||
+++ b/ctree.h
|
||||
@@ -1851,6 +1851,8 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root, u64 bytenr, u64 num,
|
||||
int alloc, int mark_free);
|
||||
/* ctree.c */
|
||||
+int btrfs_fsck_reinit_root(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_root *root);
|
||||
void reada_for_search(struct btrfs_root *root, struct btrfs_path *path,
|
||||
int level, int slot, u64 objectid);
|
||||
struct extent_buffer *read_node_slot(struct btrfs_root *root,
|
||||
diff --git a/disk-io.c b/disk-io.c
|
||||
index e9fdba8..d9df313 100644
|
||||
--- a/disk-io.c
|
||||
+++ b/disk-io.c
|
||||
@@ -793,7 +793,8 @@ static struct btrfs_fs_info *__open_ctree_fd(int fp, const char *path, u64 sb_by
|
||||
BTRFS_CSUM_TREE_OBJECTID, csum_root);
|
||||
if (ret) {
|
||||
printk("Couldn't setup csum tree\n");
|
||||
- goto out_failed;
|
||||
+ if (!partial)
|
||||
+ goto out_failed;
|
||||
}
|
||||
csum_root->track_dirty = 1;
|
||||
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
@ -0,0 +1,93 @@
|
||||
From 1cc34194f336d77e96bc11baec9bea765fdc9849 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Thu, 9 Feb 2012 11:53:33 -0500
|
||||
Subject: [PATCH 13/18] btrfsck: make sure we fix the block group accounting
|
||||
during repair
|
||||
|
||||
The block group accounting is fixed after we check the extent back
|
||||
references. This makes sure the accounting is fixed unless we
|
||||
were not able to repair the backrefs.
|
||||
|
||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||
---
|
||||
btrfsck.c | 12 ++++++++----
|
||||
extent-tree.c | 24 ++++++++++++++++++++++++
|
||||
2 files changed, 32 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/btrfsck.c b/btrfsck.c
|
||||
index a451397..3aa19ae 100644
|
||||
--- a/btrfsck.c
|
||||
+++ b/btrfsck.c
|
||||
@@ -3070,7 +3070,12 @@ repair_abort:
|
||||
if (ret) {
|
||||
fprintf(stderr, "failed to repair damaged filesystem, aborting\n");
|
||||
exit(1);
|
||||
+ } else {
|
||||
+ btrfs_fix_block_accounting(trans, root);
|
||||
}
|
||||
+ if (err)
|
||||
+ fprintf(stderr, "repaired damaged extent references\n");
|
||||
+ return ret;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
@@ -3263,11 +3268,10 @@ int main(int ac, char **av)
|
||||
}
|
||||
|
||||
ret = check_extents(trans, root, repair);
|
||||
- if (ret)
|
||||
+ if (ret) {
|
||||
+ fprintf(stderr, "check extents failed with %d!!!!!!!!!\n", ret);
|
||||
goto out;
|
||||
-
|
||||
- if (repair)
|
||||
- btrfs_fix_block_accounting(trans, root);
|
||||
+ }
|
||||
|
||||
fprintf(stderr, "checking fs roots\n");
|
||||
ret = check_fs_roots(root, &root_cache);
|
||||
diff --git a/extent-tree.c b/extent-tree.c
|
||||
index 5c4057e..dd593fe 100644
|
||||
--- a/extent-tree.c
|
||||
+++ b/extent-tree.c
|
||||
@@ -1953,6 +1953,21 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int extent_root_pending_ops(struct btrfs_fs_info *info)
|
||||
+{
|
||||
+ u64 start;
|
||||
+ u64 end;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = find_first_extent_bit(&info->extent_ins, 0, &start,
|
||||
+ &end, EXTENT_LOCKED);
|
||||
+ if (!ret) {
|
||||
+ ret = find_first_extent_bit(&info->pending_del, 0, &start, &end,
|
||||
+ EXTENT_LOCKED);
|
||||
+ }
|
||||
+ return ret == 0;
|
||||
+
|
||||
+}
|
||||
static int finish_current_insert(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *extent_root)
|
||||
{
|
||||
@@ -3380,6 +3395,15 @@ int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans,
|
||||
|
||||
root = root->fs_info->extent_root;
|
||||
|
||||
+ while(extent_root_pending_ops(fs_info)) {
|
||||
+ ret = finish_current_insert(trans, root);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ ret = del_pending_extents(trans, root);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
while(1) {
|
||||
cache = btrfs_lookup_block_group(fs_info, start);
|
||||
if (!cache)
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
209
0165-btrfsck-remove-extents-from-the-fsck-reference-track.patch
Normal file
209
0165-btrfsck-remove-extents-from-the-fsck-reference-track.patch
Normal file
@ -0,0 +1,209 @@
|
||||
From a84a34ca88e7157fda4306ab87a6372e0825628d Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Fri, 10 Feb 2012 13:28:50 -0500
|
||||
Subject: [PATCH 14/18] btrfsck: remove extents from the fsck reference
|
||||
tracker as they are freed
|
||||
|
||||
During btrfsck --repair, we make an index of extents that have incorrect
|
||||
reference counts. Once we've collect the whole index, we go through
|
||||
and modify the extent allocation tree to reflect the correct results.
|
||||
|
||||
Changing the extent allocation tree may free blocks, and so it may
|
||||
end up removing a block that had a missing reference structure. The
|
||||
fsck code may then circle back around and add the reference back.
|
||||
|
||||
The result is an extent that isn't actually used, but is recorded in the
|
||||
extent allocation tree.
|
||||
|
||||
This commit adds a hook called as extents are freed. The hook searches
|
||||
the index of incorrect references and updates it to reflect the freeing
|
||||
of the extent.
|
||||
|
||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||
---
|
||||
btrfsck.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
|
||||
ctree.h | 6 ++++
|
||||
extent-tree.c | 6 ++++
|
||||
3 files changed, 99 insertions(+), 7 deletions(-)
|
||||
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/btrfsck.c
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/btrfsck.c
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/btrfsck.c
|
||||
@@ -2137,7 +2137,7 @@ static int add_extent_rec(struct cache_t
|
||||
if (inc_ref)
|
||||
rec->refs++;
|
||||
if (rec->nr == 1)
|
||||
- rec->nr = nr;
|
||||
+ rec->nr = max(nr, max_size);
|
||||
|
||||
if (start != rec->start) {
|
||||
fprintf(stderr, "warning, start mismatch %llu %llu\n",
|
||||
@@ -2175,7 +2175,7 @@ static int add_extent_rec(struct cache_t
|
||||
rec = malloc(sizeof(*rec));
|
||||
rec->start = start;
|
||||
rec->max_size = max_size;
|
||||
- rec->nr = nr;
|
||||
+ rec->nr = max(nr, max_size);
|
||||
rec->content_checked = 0;
|
||||
rec->owner_ref_checked = 0;
|
||||
INIT_LIST_HEAD(&rec->backrefs);
|
||||
@@ -2722,6 +2722,77 @@ static int add_root_to_pending(struct ex
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/* as we fix the tree, we might be deleting blocks that
|
||||
+ * we're tracking for repair. This hook makes sure we
|
||||
+ * remove any backrefs for blocks as we are fixing them.
|
||||
+ */
|
||||
+static int free_extent_hook(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_root *root,
|
||||
+ u64 bytenr, u64 num_bytes, u64 parent,
|
||||
+ u64 root_objectid, u64 owner, u64 offset,
|
||||
+ int refs_to_drop)
|
||||
+{
|
||||
+ struct extent_record *rec;
|
||||
+ struct cache_extent *cache;
|
||||
+ int is_data;
|
||||
+ struct cache_tree *extent_cache = root->fs_info->fsck_extent_cache;
|
||||
+
|
||||
+ is_data = owner >= BTRFS_FIRST_FREE_OBJECTID;
|
||||
+ cache = find_cache_extent(extent_cache, bytenr, num_bytes);
|
||||
+ if (!cache)
|
||||
+ return 0;
|
||||
+
|
||||
+ rec = container_of(cache, struct extent_record, cache);
|
||||
+ if (is_data) {
|
||||
+ struct data_backref *back;
|
||||
+ back = find_data_backref(rec, parent, root_objectid, owner,
|
||||
+ offset);
|
||||
+ if (!back)
|
||||
+ goto out;
|
||||
+ if (back->node.found_ref) {
|
||||
+ back->found_ref -= refs_to_drop;
|
||||
+ if (rec->refs)
|
||||
+ rec->refs -= refs_to_drop;
|
||||
+ }
|
||||
+ if (back->node.found_extent_tree) {
|
||||
+ back->num_refs -= refs_to_drop;
|
||||
+ if (rec->extent_item_refs)
|
||||
+ rec->extent_item_refs -= refs_to_drop;
|
||||
+ }
|
||||
+ if (back->found_ref == 0)
|
||||
+ back->node.found_ref = 0;
|
||||
+ if (back->num_refs == 0)
|
||||
+ back->node.found_extent_tree = 0;
|
||||
+
|
||||
+ if (!back->node.found_extent_tree && back->node.found_ref) {
|
||||
+ list_del(&back->node.list);
|
||||
+ free(back);
|
||||
+ }
|
||||
+ } else {
|
||||
+ struct tree_backref *back;
|
||||
+ back = find_tree_backref(rec, parent, root_objectid);
|
||||
+ if (!back)
|
||||
+ goto out;
|
||||
+ if (back->node.found_ref) {
|
||||
+ if (rec->refs)
|
||||
+ rec->refs--;
|
||||
+ back->node.found_ref = 0;
|
||||
+ }
|
||||
+ if (back->node.found_extent_tree) {
|
||||
+ if (rec->extent_item_refs)
|
||||
+ rec->extent_item_refs--;
|
||||
+ back->node.found_extent_tree = 0;
|
||||
+ }
|
||||
+ if (!back->node.found_extent_tree && back->node.found_ref) {
|
||||
+ list_del(&back->node.list);
|
||||
+ free(back);
|
||||
+ }
|
||||
+ }
|
||||
+ maybe_free_extent_rec(extent_cache, rec);
|
||||
+out:
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int delete_extent_records(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root,
|
||||
struct btrfs_path *path,
|
||||
@@ -3008,7 +3079,7 @@ static int check_extent_refs(struct btrf
|
||||
while(cache) {
|
||||
rec = container_of(cache, struct extent_record, cache);
|
||||
btrfs_pin_extent(root->fs_info,
|
||||
- rec->start, rec->nr);
|
||||
+ rec->start, rec->max_size);
|
||||
cache = next_cache_extent(cache);
|
||||
}
|
||||
}
|
||||
@@ -3105,6 +3176,11 @@ static int check_extents(struct btrfs_tr
|
||||
cache_tree_init(&nodes);
|
||||
cache_tree_init(&reada);
|
||||
|
||||
+ if (repair) {
|
||||
+ root->fs_info->fsck_extent_cache = &extent_cache;
|
||||
+ root->fs_info->free_extent_hook = free_extent_hook;
|
||||
+ }
|
||||
+
|
||||
bits_nr = 1024;
|
||||
bits = malloc(bits_nr * sizeof(struct block_info));
|
||||
if (!bits) {
|
||||
@@ -3163,6 +3239,12 @@ static int check_extents(struct btrfs_tr
|
||||
break;
|
||||
}
|
||||
ret = check_extent_refs(trans, root, &extent_cache, repair);
|
||||
+
|
||||
+ if (repair) {
|
||||
+ root->fs_info->fsck_extent_cache = NULL;
|
||||
+ root->fs_info->free_extent_hook = NULL;
|
||||
+ }
|
||||
+
|
||||
free(bits);
|
||||
return ret;
|
||||
}
|
||||
@@ -3269,10 +3351,8 @@ int main(int ac, char **av)
|
||||
}
|
||||
|
||||
ret = check_extents(trans, root, repair);
|
||||
- if (ret) {
|
||||
- fprintf(stderr, "check extents failed with %d!!!!!!!!!\n", ret);
|
||||
- goto out;
|
||||
- }
|
||||
+ if (ret)
|
||||
+ fprintf(stderr, "Errors found in extent allocation tree\n");
|
||||
|
||||
fprintf(stderr, "checking fs roots\n");
|
||||
ret = check_fs_roots(root, &root_cache);
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/ctree.h
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/ctree.h
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/ctree.h
|
||||
@@ -797,6 +797,12 @@ struct btrfs_fs_info {
|
||||
struct list_head space_info;
|
||||
int system_allocs;
|
||||
int readonly;
|
||||
+ int (*free_extent_hook)(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_root *root,
|
||||
+ u64 bytenr, u64 num_bytes, u64 parent,
|
||||
+ u64 root_objectid, u64 owner, u64 offset,
|
||||
+ int refs_to_drop);
|
||||
+ struct cache_tree * fsck_extent_cache;
|
||||
};
|
||||
|
||||
/*
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/extent-tree.c
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/extent-tree.c
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/extent-tree.c
|
||||
@@ -2083,6 +2083,12 @@ static int __free_extent(struct btrfs_tr
|
||||
u32 item_size;
|
||||
u64 refs;
|
||||
|
||||
+ if (root->fs_info->free_extent_hook) {
|
||||
+ root->fs_info->free_extent_hook(trans, root, bytenr, num_bytes,
|
||||
+ parent, root_objectid, owner_objectid,
|
||||
+ owner_offset, refs_to_drop);
|
||||
+
|
||||
+ }
|
||||
path = btrfs_alloc_path();
|
||||
if (!path)
|
||||
return -ENOMEM;
|
974
0166-Btrfsck-add-the-ability-to-prune-corrupt-extent-allo.patch
Normal file
974
0166-Btrfsck-add-the-ability-to-prune-corrupt-extent-allo.patch
Normal file
@ -0,0 +1,974 @@
|
||||
From 6ee262863cbe668c340bc9b61ebce4ee77f06d8c Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Tue, 21 Feb 2012 14:37:21 -0500
|
||||
Subject: [PATCH 15/18] Btrfsck: add the ability to prune corrupt extent
|
||||
allocation tree blocks
|
||||
|
||||
When we discover bad blocks in the extent allocation tree, repair can
|
||||
now discard them and recreate the references from the rest of the trees.
|
||||
|
||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||
---
|
||||
Makefile | 2 +-
|
||||
btrfs-corrupt-block.c | 71 +++++++++++++-
|
||||
btrfsck.c | 269 +++++++++++++++++++++++++++++++++----------------
|
||||
ctree.c | 222 +++++++++++++++++-----------------------
|
||||
ctree.h | 11 ++-
|
||||
repair.c | 50 +++++++++
|
||||
repair.h | 32 ++++++
|
||||
7 files changed, 439 insertions(+), 218 deletions(-)
|
||||
create mode 100644 repair.c
|
||||
create mode 100644 repair.h
|
||||
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/Makefile
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/Makefile
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/Makefile
|
||||
@@ -4,7 +4,7 @@ CFLAGS = -g -O0
|
||||
objects = ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \
|
||||
root-tree.o dir-item.o file-item.o inode-item.o \
|
||||
inode-map.o crc32c.o rbtree.o extent-cache.o extent_io.o \
|
||||
- volumes.o utils.o btrfs-list.o btrfslabel.o
|
||||
+ volumes.o utils.o btrfs-list.o btrfslabel.o repair.o
|
||||
|
||||
CHECKFLAGS= -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise \
|
||||
-Wuninitialized -Wshadow -Wundef
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/btrfs-corrupt-block.c
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/btrfs-corrupt-block.c
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/btrfs-corrupt-block.c
|
||||
@@ -93,6 +93,56 @@ static void print_usage(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+static void corrupt_keys(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_root *root,
|
||||
+ struct extent_buffer *eb)
|
||||
+{
|
||||
+ int slot;
|
||||
+ int bad_slot;
|
||||
+ int nr;
|
||||
+ struct btrfs_disk_key bad_key;;
|
||||
+
|
||||
+ nr = btrfs_header_nritems(eb);
|
||||
+ if (nr == 0)
|
||||
+ return;
|
||||
+
|
||||
+ slot = rand() % nr;
|
||||
+ bad_slot = rand() % nr;
|
||||
+
|
||||
+ if (bad_slot == slot)
|
||||
+ return;
|
||||
+
|
||||
+ fprintf(stderr, "corrupting keys in block %llu slot %d swapping with %d\n",
|
||||
+ (unsigned long long)eb->start, slot, bad_slot);
|
||||
+
|
||||
+ if (btrfs_header_level(eb) == 0) {
|
||||
+ btrfs_item_key(eb, &bad_key, bad_slot);
|
||||
+ btrfs_set_item_key(eb, &bad_key, slot);
|
||||
+ } else {
|
||||
+ btrfs_node_key(eb, &bad_key, bad_slot);
|
||||
+ btrfs_set_node_key(eb, &bad_key, slot);
|
||||
+ }
|
||||
+ btrfs_mark_buffer_dirty(eb);
|
||||
+ if (!trans) {
|
||||
+ csum_tree_block(root, eb, 0);
|
||||
+ write_extent_to_disk(eb);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int corrupt_keys_in_block(struct btrfs_root *root, u64 bytenr)
|
||||
+{
|
||||
+ struct extent_buffer *eb;
|
||||
+
|
||||
+ eb = read_tree_block(root, bytenr, root->leafsize, 0);
|
||||
+ if (!eb)
|
||||
+ return -EIO;;
|
||||
+
|
||||
+ corrupt_keys(NULL, root, eb);
|
||||
+ free_extent_buffer(eb);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int corrupt_extent(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root, u64 bytenr, int copy)
|
||||
{
|
||||
@@ -192,6 +242,11 @@ static void btrfs_corrupt_extent_tree(st
|
||||
if (!eb)
|
||||
return;
|
||||
|
||||
+ if ((rand() % 10) == 0) {
|
||||
+ corrupt_keys(trans, root, eb);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
nr = btrfs_header_nritems(eb);
|
||||
if (btrfs_is_leaf(eb)) {
|
||||
btrfs_corrupt_extent_leaf(trans, root, eb);
|
||||
@@ -222,6 +277,7 @@ static struct option long_options[] = {
|
||||
{ "bytes", 1, NULL, 'b' },
|
||||
{ "extent-record", 0, NULL, 'e' },
|
||||
{ "extent-tree", 0, NULL, 'E' },
|
||||
+ { "keys", 0, NULL, 'k' },
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -239,12 +295,13 @@ int main(int ac, char **av)
|
||||
u64 bytes = 4096;
|
||||
int extent_rec = 0;
|
||||
int extent_tree = 0;
|
||||
+ int corrupt_block_keys = 0;
|
||||
|
||||
srand(128);
|
||||
|
||||
while(1) {
|
||||
int c;
|
||||
- c = getopt_long(ac, av, "l:c:eE", long_options,
|
||||
+ c = getopt_long(ac, av, "l:c:eEk", long_options,
|
||||
&option_index);
|
||||
if (c < 0)
|
||||
break;
|
||||
@@ -279,6 +336,9 @@ int main(int ac, char **av)
|
||||
case 'E':
|
||||
extent_tree = 1;
|
||||
break;
|
||||
+ case 'k':
|
||||
+ corrupt_block_keys = 1;
|
||||
+ break;
|
||||
default:
|
||||
print_usage();
|
||||
}
|
||||
@@ -324,8 +384,13 @@ int main(int ac, char **av)
|
||||
bytes *= root->sectorsize;
|
||||
|
||||
while (bytes > 0) {
|
||||
- eb = debug_corrupt_block(root, logical, root->sectorsize, copy);
|
||||
- free_extent_buffer(eb);
|
||||
+ if (corrupt_block_keys) {
|
||||
+ corrupt_keys_in_block(root, logical);
|
||||
+ } else {
|
||||
+ eb = debug_corrupt_block(root, logical,
|
||||
+ root->sectorsize, copy);
|
||||
+ free_extent_buffer(eb);
|
||||
+ }
|
||||
logical += root->sectorsize;
|
||||
bytes -= root->sectorsize;
|
||||
}
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/btrfsck.c
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/btrfsck.c
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/btrfsck.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <getopt.h>
|
||||
#include "kerncompat.h"
|
||||
#include "ctree.h"
|
||||
+#include "repair.h"
|
||||
#include "disk-io.h"
|
||||
#include "print-tree.h"
|
||||
#include "transaction.h"
|
||||
@@ -1718,86 +1719,6 @@ static int check_fs_roots(struct btrfs_r
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int check_node(struct btrfs_root *root,
|
||||
- struct btrfs_disk_key *parent_key,
|
||||
- struct extent_buffer *buf)
|
||||
-{
|
||||
- int i;
|
||||
- struct btrfs_key cpukey;
|
||||
- struct btrfs_disk_key key;
|
||||
- u32 nritems = btrfs_header_nritems(buf);
|
||||
-
|
||||
- if (nritems == 0 || nritems > BTRFS_NODEPTRS_PER_BLOCK(root))
|
||||
- return 1;
|
||||
- if (parent_key->type) {
|
||||
- btrfs_node_key(buf, &key, 0);
|
||||
- if (memcmp(parent_key, &key, sizeof(key)))
|
||||
- return 1;
|
||||
- }
|
||||
- for (i = 0; nritems > 1 && i < nritems - 2; i++) {
|
||||
- btrfs_node_key(buf, &key, i);
|
||||
- btrfs_node_key_to_cpu(buf, &cpukey, i + 1);
|
||||
- if (btrfs_comp_keys(&key, &cpukey) >= 0)
|
||||
- return 1;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int check_leaf(struct btrfs_root *root,
|
||||
- struct btrfs_disk_key *parent_key,
|
||||
- struct extent_buffer *buf)
|
||||
-{
|
||||
- int i;
|
||||
- struct btrfs_key cpukey;
|
||||
- struct btrfs_disk_key key;
|
||||
- u32 nritems = btrfs_header_nritems(buf);
|
||||
-
|
||||
- if (btrfs_header_level(buf) != 0) {
|
||||
- fprintf(stderr, "leaf is not a leaf %llu\n",
|
||||
- (unsigned long long)btrfs_header_bytenr(buf));
|
||||
- return 1;
|
||||
- }
|
||||
- if (btrfs_leaf_free_space(root, buf) < 0) {
|
||||
- fprintf(stderr, "leaf free space incorrect %llu %d\n",
|
||||
- (unsigned long long)btrfs_header_bytenr(buf),
|
||||
- btrfs_leaf_free_space(root, buf));
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- if (nritems == 0)
|
||||
- return 0;
|
||||
-
|
||||
- btrfs_item_key(buf, &key, 0);
|
||||
- if (parent_key->type && memcmp(parent_key, &key, sizeof(key))) {
|
||||
- fprintf(stderr, "leaf parent key incorrect %llu\n",
|
||||
- (unsigned long long)btrfs_header_bytenr(buf));
|
||||
- return 1;
|
||||
- }
|
||||
- for (i = 0; nritems > 1 && i < nritems - 2; i++) {
|
||||
- btrfs_item_key(buf, &key, i);
|
||||
- btrfs_item_key_to_cpu(buf, &cpukey, i + 1);
|
||||
- if (btrfs_comp_keys(&key, &cpukey) >= 0) {
|
||||
- fprintf(stderr, "bad key ordering %d %d\n", i, i+1);
|
||||
- return 1;
|
||||
- }
|
||||
- if (btrfs_item_offset_nr(buf, i) !=
|
||||
- btrfs_item_end_nr(buf, i + 1)) {
|
||||
- fprintf(stderr, "incorrect offsets %u %u\n",
|
||||
- btrfs_item_offset_nr(buf, i),
|
||||
- btrfs_item_end_nr(buf, i + 1));
|
||||
- return 1;
|
||||
- }
|
||||
- if (i == 0 && btrfs_item_end_nr(buf, i) !=
|
||||
- BTRFS_LEAF_DATA_SIZE(root)) {
|
||||
- fprintf(stderr, "bad item end %u wanted %u\n",
|
||||
- btrfs_item_end_nr(buf, i),
|
||||
- (unsigned)BTRFS_LEAF_DATA_SIZE(root));
|
||||
- return 1;
|
||||
- }
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static int all_backpointers_checked(struct extent_record *rec, int print_errs)
|
||||
{
|
||||
struct list_head *cur = rec->backrefs.next;
|
||||
@@ -1954,7 +1875,7 @@ static int check_owner_ref(struct btrfs_
|
||||
btrfs_item_key_to_cpu(buf, &key, 0);
|
||||
else
|
||||
btrfs_node_key_to_cpu(buf, &key, 0);
|
||||
-
|
||||
+
|
||||
btrfs_init_path(&path);
|
||||
path.lowest_level = level + 1;
|
||||
btrfs_search_slot(NULL, ref_root, &key, &path, 0, 0);
|
||||
@@ -1967,6 +1888,48 @@ static int check_owner_ref(struct btrfs_
|
||||
return found ? 0 : 1;
|
||||
}
|
||||
|
||||
+static int is_extent_tree_record(struct extent_record *rec)
|
||||
+{
|
||||
+ struct list_head *cur = rec->backrefs.next;
|
||||
+ struct extent_backref *node;
|
||||
+ struct tree_backref *back;
|
||||
+ int is_extent = 0;
|
||||
+
|
||||
+ while(cur != &rec->backrefs) {
|
||||
+ node = list_entry(cur, struct extent_backref, list);
|
||||
+ cur = cur->next;
|
||||
+ if (node->is_data)
|
||||
+ return 0;
|
||||
+ back = (struct tree_backref *)node;
|
||||
+ if (node->full_backref)
|
||||
+ return 0;
|
||||
+ if (back->root == BTRFS_EXTENT_TREE_OBJECTID)
|
||||
+ is_extent = 1;
|
||||
+ }
|
||||
+ return is_extent;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int record_bad_block_io(struct btrfs_fs_info *info,
|
||||
+ struct cache_tree *extent_cache,
|
||||
+ u64 start, u64 len)
|
||||
+{
|
||||
+ struct extent_record *rec;
|
||||
+ struct cache_extent *cache;
|
||||
+ struct btrfs_key key;
|
||||
+
|
||||
+ cache = find_cache_extent(extent_cache, start, len);
|
||||
+ if (!cache)
|
||||
+ return 0;
|
||||
+
|
||||
+ rec = container_of(cache, struct extent_record, cache);
|
||||
+ if (!is_extent_tree_record(rec))
|
||||
+ return 0;
|
||||
+
|
||||
+ btrfs_disk_key_to_cpu(&key, &rec->parent_key);
|
||||
+ return btrfs_add_corrupt_extent_record(info, &key, start, len, 0);
|
||||
+}
|
||||
+
|
||||
static int check_block(struct btrfs_root *root,
|
||||
struct cache_tree *extent_cache,
|
||||
struct extent_buffer *buf, u64 flags)
|
||||
@@ -1995,11 +1958,11 @@ static int check_block(struct btrfs_root
|
||||
}
|
||||
rec->info_level = level;
|
||||
|
||||
- if (btrfs_is_leaf(buf)) {
|
||||
- ret = check_leaf(root, &rec->parent_key, buf);
|
||||
- } else {
|
||||
- ret = check_node(root, &rec->parent_key, buf);
|
||||
- }
|
||||
+ if (btrfs_is_leaf(buf))
|
||||
+ ret = btrfs_check_leaf(root, &rec->parent_key, buf);
|
||||
+ else
|
||||
+ ret = btrfs_check_node(root, &rec->parent_key, buf);
|
||||
+
|
||||
if (ret) {
|
||||
fprintf(stderr, "bad block %llu\n",
|
||||
(unsigned long long)buf->start);
|
||||
@@ -2550,6 +2513,13 @@ static int run_next_block(struct btrfs_r
|
||||
|
||||
/* fixme, get the real parent transid */
|
||||
buf = read_tree_block(root, bytenr, size, 0);
|
||||
+ if (!extent_buffer_uptodate(buf)) {
|
||||
+ record_bad_block_io(root->fs_info,
|
||||
+ extent_cache, bytenr, size);
|
||||
+ free_extent_buffer(buf);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
nritems = btrfs_header_nritems(buf);
|
||||
|
||||
ret = btrfs_lookup_extent_info(NULL, root, bytenr, size, NULL, &flags);
|
||||
@@ -2565,6 +2535,8 @@ static int run_next_block(struct btrfs_r
|
||||
}
|
||||
|
||||
ret = check_block(root, extent_cache, buf, flags);
|
||||
+ if (ret)
|
||||
+ goto out;
|
||||
|
||||
if (btrfs_is_leaf(buf)) {
|
||||
btree_space_waste += btrfs_leaf_free_space(root, buf);
|
||||
@@ -2691,6 +2663,7 @@ static int run_next_block(struct btrfs_r
|
||||
btrfs_header_backref_rev(buf) == BTRFS_MIXED_BACKREF_REV &&
|
||||
!btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC))
|
||||
found_old_backref = 1;
|
||||
+out:
|
||||
free_extent_buffer(buf);
|
||||
return 0;
|
||||
}
|
||||
@@ -3016,6 +2989,7 @@ static int fixup_extent_refs(struct btrf
|
||||
int ret;
|
||||
struct btrfs_path *path;
|
||||
struct list_head *cur = rec->backrefs.next;
|
||||
+ struct cache_extent *cache;
|
||||
struct extent_backref *back;
|
||||
int allocated = 0;
|
||||
u64 flags = 0;
|
||||
@@ -3035,6 +3009,13 @@ static int fixup_extent_refs(struct btrf
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
+ /* was this block corrupt? If so, don't add references to it */
|
||||
+ cache = find_cache_extent(info->corrupt_blocks, rec->start, rec->max_size);
|
||||
+ if (cache) {
|
||||
+ ret = 0;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
/* step two, recreate all the refs we did find */
|
||||
while(cur != &rec->backrefs) {
|
||||
back = list_entry(cur, struct extent_backref, list);
|
||||
@@ -3058,6 +3039,107 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+/* right now we only prune from the extent allocation tree */
|
||||
+static int prune_one_block(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_fs_info *info,
|
||||
+ struct btrfs_corrupt_block *corrupt)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct btrfs_path path;
|
||||
+ struct extent_buffer *eb;
|
||||
+ u64 found;
|
||||
+ int slot;
|
||||
+ int nritems;
|
||||
+ int level = corrupt->level + 1;
|
||||
+
|
||||
+ btrfs_init_path(&path);
|
||||
+again:
|
||||
+ /* we want to stop at the parent to our busted block */
|
||||
+ path.lowest_level = level;
|
||||
+
|
||||
+ ret = btrfs_search_slot(trans, info->extent_root,
|
||||
+ &corrupt->key, &path, -1, 1);
|
||||
+
|
||||
+ if (ret < 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ eb = path.nodes[level];
|
||||
+ if (!eb) {
|
||||
+ ret = -ENOENT;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * hopefully the search gave us the block we want to prune,
|
||||
+ * lets try that first
|
||||
+ */
|
||||
+ slot = path.slots[level];
|
||||
+ found = btrfs_node_blockptr(eb, slot);
|
||||
+ if (found == corrupt->cache.start)
|
||||
+ goto del_ptr;
|
||||
+
|
||||
+ nritems = btrfs_header_nritems(eb);
|
||||
+
|
||||
+ /* the search failed, lets scan this node and hope we find it */
|
||||
+ for (slot = 0; slot < nritems; slot++) {
|
||||
+ found = btrfs_node_blockptr(eb, slot);
|
||||
+ if (found == corrupt->cache.start)
|
||||
+ goto del_ptr;
|
||||
+ }
|
||||
+ /*
|
||||
+ * we couldn't find the bad block. TODO, search all the nodes for pointers
|
||||
+ * to this block
|
||||
+ */
|
||||
+ if (eb == info->extent_root->node) {
|
||||
+ ret = -ENOENT;
|
||||
+ goto out;
|
||||
+ } else {
|
||||
+ level++;
|
||||
+ btrfs_release_path(NULL, &path);
|
||||
+ goto again;
|
||||
+ }
|
||||
+
|
||||
+del_ptr:
|
||||
+ printk("deleting pointer to block %Lu\n", corrupt->cache.start);
|
||||
+ ret = btrfs_del_ptr(trans, info->extent_root, &path, level, slot);
|
||||
+
|
||||
+out:
|
||||
+ btrfs_release_path(NULL, &path);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int prune_corrupt_blocks(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_fs_info *info)
|
||||
+{
|
||||
+ struct cache_extent *cache;
|
||||
+ struct btrfs_corrupt_block *corrupt;
|
||||
+
|
||||
+ cache = find_first_cache_extent(info->corrupt_blocks, 0);
|
||||
+ while (1) {
|
||||
+ if (!cache)
|
||||
+ break;
|
||||
+ corrupt = container_of(cache, struct btrfs_corrupt_block, cache);
|
||||
+ prune_one_block(trans, info, corrupt);
|
||||
+ cache = next_cache_extent(cache);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void free_corrupt_blocks(struct btrfs_fs_info *info)
|
||||
+{
|
||||
+ struct cache_extent *cache;
|
||||
+ struct btrfs_corrupt_block *corrupt;
|
||||
+
|
||||
+ while (1) {
|
||||
+ cache = find_first_cache_extent(info->corrupt_blocks, 0);
|
||||
+ if (!cache)
|
||||
+ break;
|
||||
+ corrupt = container_of(cache, struct btrfs_corrupt_block, cache);
|
||||
+ remove_cache_extent(info->corrupt_blocks, cache);
|
||||
+ free(corrupt);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int check_extent_refs(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root,
|
||||
struct cache_tree *extent_cache, int repair)
|
||||
@@ -3082,6 +3164,16 @@ static int check_extent_refs(struct btrf
|
||||
rec->start, rec->max_size);
|
||||
cache = next_cache_extent(cache);
|
||||
}
|
||||
+
|
||||
+ /* pin down all the corrupted blocks too */
|
||||
+ cache = find_first_cache_extent(root->fs_info->corrupt_blocks, 0);
|
||||
+ while(cache) {
|
||||
+ rec = container_of(cache, struct extent_record, cache);
|
||||
+ btrfs_pin_extent(root->fs_info,
|
||||
+ rec->start, rec->max_size);
|
||||
+ cache = next_cache_extent(cache);
|
||||
+ }
|
||||
+ prune_corrupt_blocks(trans, root->fs_info);
|
||||
}
|
||||
while(1) {
|
||||
fixed = 0;
|
||||
@@ -3159,6 +3251,7 @@ static int check_extents(struct btrfs_tr
|
||||
struct cache_tree pending;
|
||||
struct cache_tree reada;
|
||||
struct cache_tree nodes;
|
||||
+ struct cache_tree corrupt_blocks;
|
||||
struct btrfs_path path;
|
||||
struct btrfs_key key;
|
||||
struct btrfs_key found_key;
|
||||
@@ -3175,10 +3268,12 @@ static int check_extents(struct btrfs_tr
|
||||
cache_tree_init(&pending);
|
||||
cache_tree_init(&nodes);
|
||||
cache_tree_init(&reada);
|
||||
+ cache_tree_init(&corrupt_blocks);
|
||||
|
||||
if (repair) {
|
||||
root->fs_info->fsck_extent_cache = &extent_cache;
|
||||
root->fs_info->free_extent_hook = free_extent_hook;
|
||||
+ root->fs_info->corrupt_blocks = &corrupt_blocks;
|
||||
}
|
||||
|
||||
bits_nr = 1024;
|
||||
@@ -3241,8 +3336,10 @@ static int check_extents(struct btrfs_tr
|
||||
ret = check_extent_refs(trans, root, &extent_cache, repair);
|
||||
|
||||
if (repair) {
|
||||
+ free_corrupt_blocks(root->fs_info);
|
||||
root->fs_info->fsck_extent_cache = NULL;
|
||||
root->fs_info->free_extent_hook = NULL;
|
||||
+ root->fs_info->corrupt_blocks = NULL;
|
||||
}
|
||||
|
||||
free(bits);
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/ctree.c
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/ctree.c
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/ctree.c
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "disk-io.h"
|
||||
#include "transaction.h"
|
||||
#include "print-tree.h"
|
||||
+#include "repair.h"
|
||||
|
||||
static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
*root, struct btrfs_path *path, int level);
|
||||
@@ -32,8 +33,6 @@ static int balance_node_right(struct btr
|
||||
struct btrfs_root *root,
|
||||
struct extent_buffer *dst_buf,
|
||||
struct extent_buffer *src_buf);
|
||||
-static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||
- struct btrfs_path *path, int level, int slot);
|
||||
|
||||
inline void btrfs_init_path(struct btrfs_path *p)
|
||||
{
|
||||
@@ -589,156 +588,125 @@ static inline unsigned int leaf_data_end
|
||||
return btrfs_item_offset_nr(leaf, nr - 1);
|
||||
}
|
||||
|
||||
-static int check_node(struct btrfs_root *root, struct btrfs_path *path,
|
||||
- int level)
|
||||
+int btrfs_check_node(struct btrfs_root *root,
|
||||
+ struct btrfs_disk_key *parent_key,
|
||||
+ struct extent_buffer *buf)
|
||||
{
|
||||
- struct extent_buffer *parent = NULL;
|
||||
- struct extent_buffer *node = path->nodes[level];
|
||||
- struct btrfs_disk_key parent_key;
|
||||
- struct btrfs_disk_key node_key;
|
||||
- int parent_slot;
|
||||
- int slot;
|
||||
+ int i;
|
||||
struct btrfs_key cpukey;
|
||||
- u32 nritems = btrfs_header_nritems(node);
|
||||
+ struct btrfs_disk_key key;
|
||||
+ u32 nritems = btrfs_header_nritems(buf);
|
||||
|
||||
- if (path->nodes[level + 1])
|
||||
- parent = path->nodes[level + 1];
|
||||
+ if (nritems == 0 || nritems > BTRFS_NODEPTRS_PER_BLOCK(root))
|
||||
+ goto fail;
|
||||
|
||||
- slot = path->slots[level];
|
||||
- BUG_ON(nritems == 0);
|
||||
- if (parent) {
|
||||
- parent_slot = path->slots[level + 1];
|
||||
- btrfs_node_key(parent, &parent_key, parent_slot);
|
||||
- btrfs_node_key(node, &node_key, 0);
|
||||
- BUG_ON(memcmp(&parent_key, &node_key,
|
||||
- sizeof(struct btrfs_disk_key)));
|
||||
- BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
|
||||
- btrfs_header_bytenr(node));
|
||||
- }
|
||||
- BUG_ON(nritems > BTRFS_NODEPTRS_PER_BLOCK(root));
|
||||
- if (slot != 0) {
|
||||
- btrfs_node_key_to_cpu(node, &cpukey, slot - 1);
|
||||
- btrfs_node_key(node, &node_key, slot);
|
||||
- BUG_ON(btrfs_comp_keys(&node_key, &cpukey) <= 0);
|
||||
- }
|
||||
- if (slot < nritems - 1) {
|
||||
- btrfs_node_key_to_cpu(node, &cpukey, slot + 1);
|
||||
- btrfs_node_key(node, &node_key, slot);
|
||||
- BUG_ON(btrfs_comp_keys(&node_key, &cpukey) >= 0);
|
||||
+ if (parent_key && parent_key->type) {
|
||||
+ btrfs_node_key(buf, &key, 0);
|
||||
+ if (memcmp(parent_key, &key, sizeof(key)))
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ for (i = 0; nritems > 1 && i < nritems - 2; i++) {
|
||||
+ btrfs_node_key(buf, &key, i);
|
||||
+ btrfs_node_key_to_cpu(buf, &cpukey, i + 1);
|
||||
+ if (btrfs_comp_keys(&key, &cpukey) >= 0)
|
||||
+ goto fail;
|
||||
}
|
||||
return 0;
|
||||
+fail:
|
||||
+ if (btrfs_header_owner(buf) == BTRFS_EXTENT_TREE_OBJECTID) {
|
||||
+ if (parent_key)
|
||||
+ btrfs_disk_key_to_cpu(&cpukey, parent_key);
|
||||
+ else
|
||||
+ btrfs_node_key_to_cpu(buf, &cpukey, 0);
|
||||
+ btrfs_add_corrupt_extent_record(root->fs_info, &cpukey,
|
||||
+ buf->start, buf->len,
|
||||
+ btrfs_header_level(buf));
|
||||
+ }
|
||||
+ return -EIO;
|
||||
}
|
||||
|
||||
-static int check_leaf(struct btrfs_root *root, struct btrfs_path *path,
|
||||
- int level)
|
||||
+int btrfs_check_leaf(struct btrfs_root *root,
|
||||
+ struct btrfs_disk_key *parent_key,
|
||||
+ struct extent_buffer *buf)
|
||||
{
|
||||
- struct extent_buffer *leaf = path->nodes[level];
|
||||
- struct extent_buffer *parent = NULL;
|
||||
- int parent_slot;
|
||||
+ int i;
|
||||
struct btrfs_key cpukey;
|
||||
- struct btrfs_disk_key parent_key;
|
||||
- struct btrfs_disk_key leaf_key;
|
||||
- int slot = path->slots[0];
|
||||
-
|
||||
- u32 nritems = btrfs_header_nritems(leaf);
|
||||
+ struct btrfs_disk_key key;
|
||||
+ u32 nritems = btrfs_header_nritems(buf);
|
||||
|
||||
- if (path->nodes[level + 1])
|
||||
- parent = path->nodes[level + 1];
|
||||
+ if (btrfs_header_level(buf) != 0) {
|
||||
+ fprintf(stderr, "leaf is not a leaf %llu\n",
|
||||
+ (unsigned long long)btrfs_header_bytenr(buf));
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ if (btrfs_leaf_free_space(root, buf) < 0) {
|
||||
+ fprintf(stderr, "leaf free space incorrect %llu %d\n",
|
||||
+ (unsigned long long)btrfs_header_bytenr(buf),
|
||||
+ btrfs_leaf_free_space(root, buf));
|
||||
+ goto fail;
|
||||
+ }
|
||||
|
||||
if (nritems == 0)
|
||||
return 0;
|
||||
|
||||
- if (parent) {
|
||||
- parent_slot = path->slots[level + 1];
|
||||
- btrfs_node_key(parent, &parent_key, parent_slot);
|
||||
- btrfs_item_key(leaf, &leaf_key, 0);
|
||||
-
|
||||
- BUG_ON(memcmp(&parent_key, &leaf_key,
|
||||
- sizeof(struct btrfs_disk_key)));
|
||||
- BUG_ON(btrfs_node_blockptr(parent, parent_slot) !=
|
||||
- btrfs_header_bytenr(leaf));
|
||||
+ btrfs_item_key(buf, &key, 0);
|
||||
+ if (parent_key && parent_key->type &&
|
||||
+ memcmp(parent_key, &key, sizeof(key))) {
|
||||
+ fprintf(stderr, "leaf parent key incorrect %llu\n",
|
||||
+ (unsigned long long)btrfs_header_bytenr(buf));
|
||||
+ goto fail;
|
||||
}
|
||||
-#if 0
|
||||
for (i = 0; nritems > 1 && i < nritems - 2; i++) {
|
||||
- btrfs_item_key_to_cpu(leaf, &cpukey, i + 1);
|
||||
- btrfs_item_key(leaf, &leaf_key, i);
|
||||
- if (comp_keys(&leaf_key, &cpukey) >= 0) {
|
||||
- btrfs_print_leaf(root, leaf);
|
||||
- printk("slot %d offset bad key\n", i);
|
||||
- BUG_ON(1);
|
||||
- }
|
||||
- if (btrfs_item_offset_nr(leaf, i) !=
|
||||
- btrfs_item_end_nr(leaf, i + 1)) {
|
||||
- btrfs_print_leaf(root, leaf);
|
||||
- printk("slot %d offset bad\n", i);
|
||||
- BUG_ON(1);
|
||||
- }
|
||||
- if (i == 0) {
|
||||
- if (btrfs_item_offset_nr(leaf, i) +
|
||||
- btrfs_item_size_nr(leaf, i) !=
|
||||
- BTRFS_LEAF_DATA_SIZE(root)) {
|
||||
- btrfs_print_leaf(root, leaf);
|
||||
- printk("slot %d first offset bad\n", i);
|
||||
- BUG_ON(1);
|
||||
- }
|
||||
+ btrfs_item_key(buf, &key, i);
|
||||
+ btrfs_item_key_to_cpu(buf, &cpukey, i + 1);
|
||||
+ if (btrfs_comp_keys(&key, &cpukey) >= 0) {
|
||||
+ fprintf(stderr, "bad key ordering %d %d\n", i, i+1);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ if (btrfs_item_offset_nr(buf, i) !=
|
||||
+ btrfs_item_end_nr(buf, i + 1)) {
|
||||
+ fprintf(stderr, "incorrect offsets %u %u\n",
|
||||
+ btrfs_item_offset_nr(buf, i),
|
||||
+ btrfs_item_end_nr(buf, i + 1));
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ if (i == 0 && btrfs_item_end_nr(buf, i) !=
|
||||
+ BTRFS_LEAF_DATA_SIZE(root)) {
|
||||
+ fprintf(stderr, "bad item end %u wanted %u\n",
|
||||
+ btrfs_item_end_nr(buf, i),
|
||||
+ (unsigned)BTRFS_LEAF_DATA_SIZE(root));
|
||||
+ goto fail;
|
||||
}
|
||||
}
|
||||
- if (nritems > 0) {
|
||||
- if (btrfs_item_size_nr(leaf, nritems - 1) > 4096) {
|
||||
- btrfs_print_leaf(root, leaf);
|
||||
- printk("slot %d bad size \n", nritems - 1);
|
||||
- BUG_ON(1);
|
||||
- }
|
||||
- }
|
||||
-#endif
|
||||
- if (slot != 0 && slot < nritems - 1) {
|
||||
- btrfs_item_key(leaf, &leaf_key, slot);
|
||||
- btrfs_item_key_to_cpu(leaf, &cpukey, slot - 1);
|
||||
- if (btrfs_comp_keys(&leaf_key, &cpukey) <= 0) {
|
||||
- btrfs_print_leaf(root, leaf);
|
||||
- printk("slot %d offset bad key\n", slot);
|
||||
- BUG_ON(1);
|
||||
- }
|
||||
- if (btrfs_item_offset_nr(leaf, slot - 1) !=
|
||||
- btrfs_item_end_nr(leaf, slot)) {
|
||||
- btrfs_print_leaf(root, leaf);
|
||||
- printk("slot %d offset bad\n", slot);
|
||||
- BUG_ON(1);
|
||||
- }
|
||||
- }
|
||||
- if (slot < nritems - 1) {
|
||||
- btrfs_item_key(leaf, &leaf_key, slot);
|
||||
- btrfs_item_key_to_cpu(leaf, &cpukey, slot + 1);
|
||||
- BUG_ON(btrfs_comp_keys(&leaf_key, &cpukey) >= 0);
|
||||
- if (btrfs_item_offset_nr(leaf, slot) !=
|
||||
- btrfs_item_end_nr(leaf, slot + 1)) {
|
||||
- btrfs_print_leaf(root, leaf);
|
||||
- printk("slot %d offset bad\n", slot);
|
||||
- BUG_ON(1);
|
||||
- }
|
||||
- }
|
||||
- BUG_ON(btrfs_item_offset_nr(leaf, 0) +
|
||||
- btrfs_item_size_nr(leaf, 0) != BTRFS_LEAF_DATA_SIZE(root));
|
||||
return 0;
|
||||
+fail:
|
||||
+ if (btrfs_header_owner(buf) == BTRFS_EXTENT_TREE_OBJECTID) {
|
||||
+ if (parent_key)
|
||||
+ btrfs_disk_key_to_cpu(&cpukey, parent_key);
|
||||
+ else
|
||||
+ btrfs_item_key_to_cpu(buf, &cpukey, 0);
|
||||
+
|
||||
+ btrfs_add_corrupt_extent_record(root->fs_info, &cpukey,
|
||||
+ buf->start, buf->len, 0);
|
||||
+ }
|
||||
+ return -EIO;
|
||||
}
|
||||
|
||||
static int noinline check_block(struct btrfs_root *root,
|
||||
struct btrfs_path *path, int level)
|
||||
{
|
||||
- return 0;
|
||||
-#if 0
|
||||
- struct extent_buffer *buf = path->nodes[level];
|
||||
+ struct btrfs_disk_key key;
|
||||
+ struct btrfs_disk_key *key_ptr = NULL;
|
||||
+ struct extent_buffer *parent;
|
||||
|
||||
- if (memcmp_extent_buffer(buf, root->fs_info->fsid,
|
||||
- (unsigned long)btrfs_header_fsid(buf),
|
||||
- BTRFS_FSID_SIZE)) {
|
||||
- printk("warning bad block %Lu\n", buf->start);
|
||||
- return 1;
|
||||
+ if (path->nodes[level + 1]) {
|
||||
+ parent = path->nodes[level + 1];
|
||||
+ btrfs_node_key(parent, &key, path->slots[level + 1]);
|
||||
+ key_ptr = &key;
|
||||
}
|
||||
-#endif
|
||||
if (level == 0)
|
||||
- return check_leaf(root, path, level);
|
||||
- return check_node(root, path, level);
|
||||
+ return btrfs_check_leaf(root, key_ptr, path->nodes[0]);
|
||||
+ return btrfs_check_node(root, key_ptr, path->nodes[level]);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -924,8 +892,8 @@ static int balance_level(struct btrfs_tr
|
||||
wait_on_tree_block_writeback(root, right);
|
||||
free_extent_buffer(right);
|
||||
right = NULL;
|
||||
- wret = del_ptr(trans, root, path, level + 1, pslot +
|
||||
- 1);
|
||||
+ wret = btrfs_del_ptr(trans, root, path,
|
||||
+ level + 1, pslot + 1);
|
||||
if (wret)
|
||||
ret = wret;
|
||||
wret = btrfs_free_extent(trans, root, bytenr,
|
||||
@@ -972,7 +940,7 @@ static int balance_level(struct btrfs_tr
|
||||
wait_on_tree_block_writeback(root, mid);
|
||||
free_extent_buffer(mid);
|
||||
mid = NULL;
|
||||
- wret = del_ptr(trans, root, path, level + 1, pslot);
|
||||
+ wret = btrfs_del_ptr(trans, root, path, level + 1, pslot);
|
||||
if (wret)
|
||||
ret = wret;
|
||||
wret = btrfs_free_extent(trans, root, bytenr, blocksize,
|
||||
@@ -2699,7 +2667,7 @@ int btrfs_insert_item(struct btrfs_trans
|
||||
* continuing all the way the root if required. The root is converted into
|
||||
* a leaf if all the nodes are emptied.
|
||||
*/
|
||||
-static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||
+int btrfs_del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||
struct btrfs_path *path, int level, int slot)
|
||||
{
|
||||
struct extent_buffer *parent = path->nodes[level];
|
||||
@@ -2751,7 +2719,7 @@ static noinline int btrfs_del_leaf(struc
|
||||
int ret;
|
||||
|
||||
WARN_ON(btrfs_header_generation(leaf) != trans->transid);
|
||||
- ret = del_ptr(trans, root, path, 1, path->slots[1]);
|
||||
+ ret = btrfs_del_ptr(trans, root, path, 1, path->slots[1]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/ctree.h
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/ctree.h
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/ctree.h
|
||||
@@ -802,7 +802,8 @@ struct btrfs_fs_info {
|
||||
u64 bytenr, u64 num_bytes, u64 parent,
|
||||
u64 root_objectid, u64 owner, u64 offset,
|
||||
int refs_to_drop);
|
||||
- struct cache_tree * fsck_extent_cache;
|
||||
+ struct cache_tree *fsck_extent_cache;
|
||||
+ struct cache_tree *corrupt_blocks;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -1857,6 +1858,14 @@ int btrfs_update_block_group(struct btrf
|
||||
struct btrfs_root *root, u64 bytenr, u64 num,
|
||||
int alloc, int mark_free);
|
||||
/* ctree.c */
|
||||
+int btrfs_del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||
+ struct btrfs_path *path, int level, int slot);
|
||||
+int btrfs_check_node(struct btrfs_root *root,
|
||||
+ struct btrfs_disk_key *parent_key,
|
||||
+ struct extent_buffer *buf);
|
||||
+int btrfs_check_leaf(struct btrfs_root *root,
|
||||
+ struct btrfs_disk_key *parent_key,
|
||||
+ struct extent_buffer *buf);
|
||||
int btrfs_fsck_reinit_root(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root);
|
||||
void reada_for_search(struct btrfs_root *root, struct btrfs_path *path,
|
||||
diff --git a/repair.c b/repair.c
|
||||
new file mode 100644
|
||||
index 0000000..e640465
|
||||
--- /dev/null
|
||||
+++ b/repair.c
|
||||
@@ -0,0 +1,50 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2012 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.
|
||||
+ */
|
||||
+
|
||||
+#include "ctree.h"
|
||||
+#include "extent-cache.h"
|
||||
+#include "utils.h"
|
||||
+#include "repair.h"
|
||||
+
|
||||
+int btrfs_add_corrupt_extent_record(struct btrfs_fs_info *info,
|
||||
+ struct btrfs_key *first_key,
|
||||
+ u64 start, u64 len, int level)
|
||||
+
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ struct btrfs_corrupt_block *corrupt;
|
||||
+
|
||||
+ if (!info->corrupt_blocks)
|
||||
+ return 0;
|
||||
+
|
||||
+ corrupt = malloc(sizeof(*corrupt));
|
||||
+ if (!corrupt)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ memcpy(&corrupt->key, first_key, sizeof(*first_key));
|
||||
+ corrupt->cache.start = start;
|
||||
+ corrupt->cache.size = len;
|
||||
+ corrupt->level = level;
|
||||
+
|
||||
+ ret = insert_existing_cache_extent(info->corrupt_blocks, &corrupt->cache);
|
||||
+ if (ret)
|
||||
+ free(corrupt);
|
||||
+ BUG_ON(ret && ret != -EEXIST);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
diff --git a/repair.h b/repair.h
|
||||
new file mode 100644
|
||||
index 0000000..3d0dcb9
|
||||
--- /dev/null
|
||||
+++ b/repair.h
|
||||
@@ -0,0 +1,32 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2012 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.
|
||||
+ */
|
||||
+
|
||||
+#ifndef __BTRFS_REPAIR__
|
||||
+#define __BTRFS_REPAIR__
|
||||
+
|
||||
+struct btrfs_corrupt_block {
|
||||
+ struct cache_extent cache;
|
||||
+ struct btrfs_key key;
|
||||
+ int level;
|
||||
+};
|
||||
+
|
||||
+int btrfs_add_corrupt_extent_record(struct btrfs_fs_info *info,
|
||||
+ struct btrfs_key *first_key,
|
||||
+ u64 start, u64 len, int level);
|
||||
+
|
||||
+#endif
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
@ -0,0 +1,36 @@
|
||||
From 8ded348cf85fd8572d4ee7fc9d0cad150f4fc2be Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Tue, 21 Feb 2012 15:33:20 -0500
|
||||
Subject: [PATCH 16/18] Btrfs: use /proc/partitions scanning for
|
||||
btrfs_scan_for_fsid
|
||||
|
||||
btrfs_scan_for_fsid is used by open_ctree and by mkfs when it is
|
||||
checking for mounted devices. It currently scans all of /dev,
|
||||
which is rarely the right answer.
|
||||
|
||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||
---
|
||||
utils.c | 7 ++++++-
|
||||
1 files changed, 6 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/utils.c b/utils.c
|
||||
index cfb8fde..2d82342 100644
|
||||
--- a/utils.c
|
||||
+++ b/utils.c
|
||||
@@ -1052,7 +1052,12 @@ fail:
|
||||
int btrfs_scan_for_fsid(struct btrfs_fs_devices *fs_devices, u64 total_devs,
|
||||
int run_ioctls)
|
||||
{
|
||||
- return btrfs_scan_one_dir("/dev", run_ioctls);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = btrfs_scan_block_devices(run_ioctls);
|
||||
+ if (ret)
|
||||
+ ret = btrfs_scan_one_dir("/dev", run_ioctls);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
int btrfs_device_already_in_root(struct btrfs_root *root, int fd,
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
93
0168-Scan-dev-md-and-device-mapper-devices-last.patch
Normal file
93
0168-Scan-dev-md-and-device-mapper-devices-last.patch
Normal file
@ -0,0 +1,93 @@
|
||||
From bde44c1e4808c8b3d7291d2ad22536d4b5d7e2f5 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Tue, 21 Feb 2012 15:56:10 -0500
|
||||
Subject: [PATCH 17/18] Scan /dev/md and device mapper devices last
|
||||
|
||||
When we're using multipath or raid0, it is possible
|
||||
that btrfs dev scan will find one of the component devices
|
||||
instead of the proper virtual device the kernel creates.
|
||||
|
||||
We want to make sure the kernel scans the virtual devices last,
|
||||
since it always remembers the last device it finds with a given fsid.
|
||||
|
||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||
---
|
||||
utils.c | 25 ++++++++++++++++++++++++-
|
||||
volumes.c | 9 ++++++++-
|
||||
2 files changed, 32 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/utils.c b/utils.c
|
||||
index 2d82342..0beaf80 100644
|
||||
--- a/utils.c
|
||||
+++ b/utils.c
|
||||
@@ -1156,7 +1156,10 @@ int btrfs_scan_block_devices(int run_ioctl)
|
||||
int i;
|
||||
char buf[1024];
|
||||
char fullpath[110];
|
||||
+ int scans = 0;
|
||||
+ int special;
|
||||
|
||||
+scan_again:
|
||||
proc_partitions = fopen("/proc/partitions","r");
|
||||
if (!proc_partitions) {
|
||||
fprintf(stderr, "Unable to open '/proc/partitions' for scanning\n");
|
||||
@@ -1172,8 +1175,23 @@ int btrfs_scan_block_devices(int run_ioctl)
|
||||
|
||||
strcpy(fullpath,"/dev/");
|
||||
while(fgets(buf, 1023, proc_partitions)) {
|
||||
-
|
||||
i = sscanf(buf," %*d %*d %*d %99s", fullpath+5);
|
||||
+
|
||||
+ /*
|
||||
+ * multipath and MD devices may register as a btrfs filesystem
|
||||
+ * both through the original block device and through
|
||||
+ * the special (/dev/mapper or /dev/mdX) entry.
|
||||
+ * This scans the special entries last
|
||||
+ */
|
||||
+ special = strncmp(fullpath, "/dev/dm-", strlen("/dev/dm-")) == 0;
|
||||
+ if (!special)
|
||||
+ special = strncmp(fullpath, "/dev/md", strlen("/dev/md")) == 0;
|
||||
+
|
||||
+ if (scans == 0 && special)
|
||||
+ continue;
|
||||
+ if (scans > 0 && !special)
|
||||
+ continue;
|
||||
+
|
||||
ret = lstat(fullpath, &st);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "failed to stat %s\n", fullpath);
|
||||
@@ -1198,6 +1216,11 @@ int btrfs_scan_block_devices(int run_ioctl)
|
||||
}
|
||||
|
||||
fclose(proc_partitions);
|
||||
+
|
||||
+ if (scans == 0) {
|
||||
+ scans++;
|
||||
+ goto scan_again;
|
||||
+ }
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/volumes.c b/volumes.c
|
||||
index 74c88de..e7f4c3e 100644
|
||||
--- a/volumes.c
|
||||
+++ b/volumes.c
|
||||
@@ -130,7 +130,14 @@ static int device_list_add(const char *path,
|
||||
btrfs_stack_device_bytes_used(&disk_super->dev_item);
|
||||
list_add(&device->dev_list, &fs_devices->devices);
|
||||
device->fs_devices = fs_devices;
|
||||
- }
|
||||
+ } else if (!device->name || strcmp(device->name, path)) {
|
||||
+ char *name = strdup(path);
|
||||
+ if (!name)
|
||||
+ return -ENOMEM;
|
||||
+ kfree(device->name);
|
||||
+ device->name = name;
|
||||
+ }
|
||||
+
|
||||
|
||||
if (found_transid > fs_devices->latest_trans) {
|
||||
fs_devices->latest_devid = devid;
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
285
0169-btrfsck-add-early-code-to-handle-corrupted-block-gro.patch
Normal file
285
0169-btrfsck-add-early-code-to-handle-corrupted-block-gro.patch
Normal file
@ -0,0 +1,285 @@
|
||||
From 6d1e1b7a4cfd1e0ab93efa42c14759848a26a6d4 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Mason <chris.mason@oracle.com>
|
||||
Date: Tue, 21 Feb 2012 21:20:54 -0500
|
||||
Subject: [PATCH 18/18] btrfsck: add early code to handle corrupted block
|
||||
groups
|
||||
|
||||
This is mostly disabled, but it is step one in handling
|
||||
corrupted block groups in the extent allocation tree.
|
||||
|
||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
||||
---
|
||||
btrfs-corrupt-block.c | 5 ----
|
||||
btrfsck.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
ctree.c | 8 +++++-
|
||||
extent-tree.c | 19 ++++++----------
|
||||
volumes.c | 12 ----------
|
||||
volumes.h | 13 +++++++++++
|
||||
6 files changed, 81 insertions(+), 32 deletions(-)
|
||||
|
||||
diff --git a/btrfs-corrupt-block.c b/btrfs-corrupt-block.c
|
||||
index 980a006..7051e99 100644
|
||||
--- a/btrfs-corrupt-block.c
|
||||
+++ b/btrfs-corrupt-block.c
|
||||
@@ -242,11 +242,6 @@ static void btrfs_corrupt_extent_tree(struct btrfs_trans_handle *trans,
|
||||
if (!eb)
|
||||
return;
|
||||
|
||||
- if ((rand() % 10) == 0) {
|
||||
- corrupt_keys(trans, root, eb);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
nr = btrfs_header_nritems(eb);
|
||||
if (btrfs_is_leaf(eb)) {
|
||||
btrfs_corrupt_extent_leaf(trans, root, eb);
|
||||
diff --git a/btrfsck.c b/btrfsck.c
|
||||
index 7dc84b5..c1a28bc 100644
|
||||
--- a/btrfsck.c
|
||||
+++ b/btrfsck.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <getopt.h>
|
||||
#include "kerncompat.h"
|
||||
#include "ctree.h"
|
||||
+#include "volumes.h"
|
||||
#include "repair.h"
|
||||
#include "disk-io.h"
|
||||
#include "print-tree.h"
|
||||
@@ -3140,6 +3141,55 @@ static void free_corrupt_blocks(struct btrfs_fs_info *info)
|
||||
}
|
||||
}
|
||||
|
||||
+static int check_block_group(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_fs_info *info,
|
||||
+ struct map_lookup *map,
|
||||
+ int *reinit)
|
||||
+{
|
||||
+ struct btrfs_key key;
|
||||
+ struct btrfs_path path;
|
||||
+ int ret;
|
||||
+
|
||||
+ key.objectid = map->ce.start;
|
||||
+ key.offset = map->ce.size;
|
||||
+ key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
|
||||
+
|
||||
+ btrfs_init_path(&path);
|
||||
+ ret = btrfs_search_slot(NULL, info->extent_root,
|
||||
+ &key, &path, 0, 0);
|
||||
+ btrfs_release_path(NULL, &path);
|
||||
+ if (ret <= 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ ret = btrfs_make_block_group(trans, info->extent_root, 0, map->type,
|
||||
+ BTRFS_FIRST_CHUNK_TREE_OBJECTID,
|
||||
+ key.objectid, key.offset);
|
||||
+ *reinit = 1;
|
||||
+out:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int check_block_groups(struct btrfs_trans_handle *trans,
|
||||
+ struct btrfs_fs_info *info, int *reinit)
|
||||
+{
|
||||
+ struct cache_extent *ce;
|
||||
+ struct map_lookup *map;
|
||||
+ struct btrfs_mapping_tree *map_tree = &info->mapping_tree;
|
||||
+
|
||||
+ /* this isn't quite working */
|
||||
+ return 0;
|
||||
+
|
||||
+ ce = find_first_cache_extent(&map_tree->cache_tree, 0);
|
||||
+ while (1) {
|
||||
+ if (!ce)
|
||||
+ break;
|
||||
+ map = container_of(ce, struct map_lookup, ce);
|
||||
+ check_block_group(trans, info, map, reinit);
|
||||
+ ce = next_cache_extent(ce);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int check_extent_refs(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root,
|
||||
struct cache_tree *extent_cache, int repair)
|
||||
@@ -3149,6 +3199,7 @@ static int check_extent_refs(struct btrfs_trans_handle *trans,
|
||||
int err = 0;
|
||||
int ret = 0;
|
||||
int fixed = 0;
|
||||
+ int reinit = 0;
|
||||
|
||||
if (repair) {
|
||||
/*
|
||||
@@ -3174,6 +3225,9 @@ static int check_extent_refs(struct btrfs_trans_handle *trans,
|
||||
cache = next_cache_extent(cache);
|
||||
}
|
||||
prune_corrupt_blocks(trans, root->fs_info);
|
||||
+ check_block_groups(trans, root->fs_info, &reinit);
|
||||
+ if (reinit)
|
||||
+ btrfs_read_block_groups(root->fs_info->extent_root);
|
||||
}
|
||||
while(1) {
|
||||
fixed = 0;
|
||||
@@ -3356,6 +3410,7 @@ static struct option long_options[] = {
|
||||
{ "super", 1, NULL, 's' },
|
||||
{ "repair", 0, NULL, 0 },
|
||||
{ "init-csum-tree", 0, NULL, 0 },
|
||||
+ { "init-extent-tree", 0, NULL, 0 },
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -3445,7 +3500,6 @@ int main(int ac, char **av)
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
-
|
||||
ret = check_extents(trans, root, repair);
|
||||
if (ret)
|
||||
fprintf(stderr, "Errors found in extent allocation tree\n");
|
||||
diff --git a/ctree.c b/ctree.c
|
||||
index a49bce4..2d86b1e 100644
|
||||
--- a/ctree.c
|
||||
+++ b/ctree.c
|
||||
@@ -151,8 +151,10 @@ int btrfs_fsck_reinit_root(struct btrfs_trans_handle *trans,
|
||||
btrfs_level_size(root, 0),
|
||||
root->root_key.objectid,
|
||||
&disk_key, level, 0, 0);
|
||||
- if (IS_ERR(c))
|
||||
- return PTR_ERR(c);
|
||||
+ if (IS_ERR(c)) {
|
||||
+ c = old;
|
||||
+ extent_buffer_get(c);
|
||||
+ }
|
||||
|
||||
memset_extent_buffer(c, 0, 0, sizeof(struct btrfs_header));
|
||||
btrfs_set_header_level(c, level);
|
||||
@@ -1262,6 +1264,8 @@ again:
|
||||
key->objectid);
|
||||
|
||||
b = read_node_slot(root, b, slot);
|
||||
+ if (!extent_buffer_uptodate(b))
|
||||
+ return -EIO;
|
||||
} else {
|
||||
p->slots[level] = slot;
|
||||
if (ins_len > 0 &&
|
||||
diff --git a/extent-tree.c b/extent-tree.c
|
||||
index ee87f1f..20cdffa 100644
|
||||
--- a/extent-tree.c
|
||||
+++ b/extent-tree.c
|
||||
@@ -1703,7 +1703,6 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
|
||||
|
||||
cache = (struct btrfs_block_group_cache *)(unsigned long)ptr;
|
||||
ret = write_one_cache_group(trans, root, path, cache);
|
||||
- BUG_ON(ret);
|
||||
}
|
||||
btrfs_free_path(path);
|
||||
return 0;
|
||||
@@ -1894,6 +1893,10 @@ static int update_pinned_extents(struct btrfs_root *root,
|
||||
}
|
||||
while (num > 0) {
|
||||
cache = btrfs_lookup_block_group(fs_info, bytenr);
|
||||
+ if (!cache) {
|
||||
+ len = min((u64)root->sectorsize, num);
|
||||
+ goto next;
|
||||
+ }
|
||||
WARN_ON(!cache);
|
||||
len = min(num, cache->key.offset -
|
||||
(bytenr - cache->key.objectid));
|
||||
@@ -1906,6 +1909,7 @@ static int update_pinned_extents(struct btrfs_root *root,
|
||||
cache->space_info->bytes_pinned -= len;
|
||||
fs_info->total_pinned -= len;
|
||||
}
|
||||
+next:
|
||||
bytenr += len;
|
||||
num -= len;
|
||||
}
|
||||
@@ -2263,9 +2267,7 @@ static int __free_extent(struct btrfs_trans_handle *trans,
|
||||
BUG_ON(ret);
|
||||
}
|
||||
|
||||
- ret = update_block_group(trans, root, bytenr, num_bytes, 0,
|
||||
- mark_free);
|
||||
- BUG_ON(ret);
|
||||
+ update_block_group(trans, root, bytenr, num_bytes, 0, mark_free);
|
||||
}
|
||||
fail:
|
||||
btrfs_free_path(path);
|
||||
@@ -2596,13 +2598,7 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
|
||||
|
||||
ret = update_block_group(trans, root, ins->objectid, ins->offset,
|
||||
1, 0);
|
||||
- if (ret) {
|
||||
- printk(KERN_ERR "btrfs update block group failed for %llu "
|
||||
- "%llu\n", (unsigned long long)ins->objectid,
|
||||
- (unsigned long long)ins->offset);
|
||||
- BUG();
|
||||
- }
|
||||
- return ret;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static int alloc_tree_block(struct btrfs_trans_handle *trans,
|
||||
@@ -3185,7 +3181,6 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
|
||||
|
||||
finish_current_insert(trans, extent_root);
|
||||
ret = del_pending_extents(trans, extent_root);
|
||||
- BUG_ON(ret);
|
||||
set_avail_alloc_bits(extent_root->fs_info, type);
|
||||
return 0;
|
||||
}
|
||||
diff --git a/volumes.c b/volumes.c
|
||||
index e7f4c3e..088f639 100644
|
||||
--- a/volumes.c
|
||||
+++ b/volumes.c
|
||||
@@ -35,18 +35,6 @@ struct stripe {
|
||||
u64 physical;
|
||||
};
|
||||
|
||||
-struct map_lookup {
|
||||
- struct cache_extent ce;
|
||||
- u64 type;
|
||||
- int io_align;
|
||||
- int io_width;
|
||||
- int stripe_len;
|
||||
- int sector_size;
|
||||
- int num_stripes;
|
||||
- int sub_stripes;
|
||||
- struct btrfs_bio_stripe stripes[];
|
||||
-};
|
||||
-
|
||||
#define map_lookup_size(n) (sizeof(struct map_lookup) + \
|
||||
(sizeof(struct btrfs_bio_stripe) * (n)))
|
||||
|
||||
diff --git a/volumes.h b/volumes.h
|
||||
index c34af74..4755176 100644
|
||||
--- a/volumes.h
|
||||
+++ b/volumes.h
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#ifndef __BTRFS_VOLUMES_
|
||||
#define __BTRFS_VOLUMES_
|
||||
+
|
||||
struct btrfs_device {
|
||||
struct list_head dev_list;
|
||||
struct btrfs_root *dev_root;
|
||||
@@ -92,6 +93,18 @@ struct btrfs_multi_bio {
|
||||
struct btrfs_bio_stripe stripes[];
|
||||
};
|
||||
|
||||
+struct map_lookup {
|
||||
+ struct cache_extent ce;
|
||||
+ u64 type;
|
||||
+ int io_align;
|
||||
+ int io_width;
|
||||
+ int stripe_len;
|
||||
+ int sector_size;
|
||||
+ int num_stripes;
|
||||
+ int sub_stripes;
|
||||
+ struct btrfs_bio_stripe stripes[];
|
||||
+};
|
||||
+
|
||||
#define btrfs_multi_bio_size(n) (sizeof(struct btrfs_multi_bio) + \
|
||||
(sizeof(struct btrfs_bio_stripe) * (n)))
|
||||
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
38
0170-Btrfs-progs-btrfs-map-logical-Fix-typo-in-usage.patch
Normal file
38
0170-Btrfs-progs-btrfs-map-logical-Fix-typo-in-usage.patch
Normal file
@ -0,0 +1,38 @@
|
||||
From 863db40c3f7cc3a3f7c035ea5747e84c9e2b8747 Mon Sep 17 00:00:00 2001
|
||||
From: Miao Xie <miaox@cn.fujitsu.com>
|
||||
Date: Thu, 23 Feb 2012 15:51:09 +0800
|
||||
Subject: [PATCH 1/3] Btrfs-progs, btrfs-map-logical: Fix typo in usage
|
||||
|
||||
The right option is 'o' not 'c'. And this tool is used for the block devices
|
||||
on which there is a btrfs file system, so change "mount_point" to "device".
|
||||
|
||||
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
|
||||
---
|
||||
btrfs-map-logical.c | 4 ++--
|
||||
1 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/btrfs-map-logical.c b/btrfs-map-logical.c
|
||||
index d79a73a..fa4fb3f 100644
|
||||
--- a/btrfs-map-logical.c
|
||||
+++ b/btrfs-map-logical.c
|
||||
@@ -84,7 +84,7 @@ struct extent_buffer *debug_read_block(struct btrfs_root *root, u64 bytenr,
|
||||
|
||||
static void print_usage(void)
|
||||
{
|
||||
- fprintf(stderr, "usage: btrfs-map-logical [options] mount_point\n");
|
||||
+ fprintf(stderr, "usage: btrfs-map-logical [options] device\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");
|
||||
@@ -96,7 +96,7 @@ static struct option long_options[] = {
|
||||
/* { "byte-count", 1, NULL, 'b' }, */
|
||||
{ "logical", 1, NULL, 'l' },
|
||||
{ "copy", 1, NULL, 'c' },
|
||||
- { "output", 1, NULL, 'c' },
|
||||
+ { "output", 1, NULL, 'o' },
|
||||
{ "bytes", 1, NULL, 'b' },
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
@ -0,0 +1,48 @@
|
||||
From 2b0d4908db8a2b6120be1617b50187b32b79e56e Mon Sep 17 00:00:00 2001
|
||||
From: Miao Xie <miaox@cn.fujitsu.com>
|
||||
Date: Thu, 23 Feb 2012 15:52:05 +0800
|
||||
Subject: [PATCH 2/3] Btrfs-progs, btrfs-corrupt-block: fix the wrong usage
|
||||
|
||||
The old usage is a copy of btrfs-map-logical, it's wrong, fix it.
|
||||
|
||||
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
|
||||
---
|
||||
btrfs-corrupt-block.c | 15 +++++++++------
|
||||
1 files changed, 9 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/btrfs-corrupt-block.c b/btrfs-corrupt-block.c
|
||||
index 7051e99..124fb38 100644
|
||||
--- a/btrfs-corrupt-block.c
|
||||
+++ b/btrfs-corrupt-block.c
|
||||
@@ -85,11 +85,14 @@ struct extent_buffer *debug_corrupt_block(struct btrfs_root *root, u64 bytenr,
|
||||
|
||||
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-b Number of bytes to read\n");
|
||||
+ fprintf(stderr, "usage: btrfs-corrupt-block [options] device\n");
|
||||
+ fprintf(stderr, "\t-l Logical extent to be corrupted\n");
|
||||
+ fprintf(stderr, "\t-c Copy of the extent to be corrupted"
|
||||
+ " (usually 1 or 2, default: 0)\n");
|
||||
+ fprintf(stderr, "\t-b Number of bytes to be corrupted\n");
|
||||
+ fprintf(stderr, "\t-e Extent to be corrupted\n");
|
||||
+ fprintf(stderr, "\t-E The whole extent free to be corrupted\n");
|
||||
+ fprintf(stderr, "\t-k Corrupt keys\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -296,7 +299,7 @@ int main(int ac, char **av)
|
||||
|
||||
while(1) {
|
||||
int c;
|
||||
- c = getopt_long(ac, av, "l:c:eEk", long_options,
|
||||
+ c = getopt_long(ac, av, "l:c:b:eEk", long_options,
|
||||
&option_index);
|
||||
if (c < 0)
|
||||
break;
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
116
0172-Btrfs-progs-fix-btrfsck-s-snapshot-wrong-unresolved-.patch
Normal file
116
0172-Btrfs-progs-fix-btrfsck-s-snapshot-wrong-unresolved-.patch
Normal file
@ -0,0 +1,116 @@
|
||||
From c1d427d2a7b8557265a641a6d199f1b9436d27af Mon Sep 17 00:00:00 2001
|
||||
From: Miao Xie <miaox@cn.fujitsu.com>
|
||||
Date: Thu, 23 Feb 2012 15:52:58 +0800
|
||||
Subject: [PATCH 3/3] Btrfs-progs: fix btrfsck's snapshot wrong "unresolved
|
||||
refs"
|
||||
|
||||
If the fs/file tree is not the parent of the snapshot, it is reasonable
|
||||
that we can not find the relative reference and back reference. But btrfsck
|
||||
doesn't consider this case, and reports "unresolved refs" message, it's wrong,
|
||||
fix it.
|
||||
|
||||
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
|
||||
---
|
||||
btrfsck.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
|
||||
1 files changed, 67 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/btrfsck.c b/btrfsck.c
|
||||
index c1a28bc..2f1a515 100644
|
||||
--- a/btrfsck.c
|
||||
+++ b/btrfsck.c
|
||||
@@ -747,7 +747,65 @@ static int leave_shared_node(struct btrfs_root *root,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int process_dir_item(struct extent_buffer *eb,
|
||||
+static int is_child_root(struct btrfs_root *root, u64 parent_root_id,
|
||||
+ u64 child_root_id)
|
||||
+{
|
||||
+ struct btrfs_path path;
|
||||
+ struct btrfs_key key;
|
||||
+ struct extent_buffer *leaf;
|
||||
+ int has_parent = 0;
|
||||
+ int ret;
|
||||
+
|
||||
+ btrfs_init_path(&path);
|
||||
+
|
||||
+ key.objectid = parent_root_id;
|
||||
+ key.type = BTRFS_ROOT_REF_KEY;
|
||||
+ key.offset = child_root_id;
|
||||
+ ret = btrfs_search_slot(NULL, root->fs_info->tree_root, &key, &path,
|
||||
+ 0, 0);
|
||||
+ BUG_ON(ret < 0);
|
||||
+ btrfs_release_path(root, &path);
|
||||
+ if (!ret)
|
||||
+ return 1;
|
||||
+
|
||||
+ key.objectid = child_root_id;
|
||||
+ key.type = BTRFS_ROOT_BACKREF_KEY;
|
||||
+ key.offset = 0;
|
||||
+ ret = btrfs_search_slot(NULL, root->fs_info->tree_root, &key, &path,
|
||||
+ 0, 0);
|
||||
+ BUG_ON(ret <= 0);
|
||||
+
|
||||
+ while (1) {
|
||||
+ leaf = path.nodes[0];
|
||||
+ if (path.slots[0] >= btrfs_header_nritems(leaf)) {
|
||||
+ ret = btrfs_next_leaf(root->fs_info->tree_root, &path);
|
||||
+ BUG_ON(ret < 0);
|
||||
+
|
||||
+ if (ret > 0)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ btrfs_item_key_to_cpu(leaf, &key, path.slots[0]);
|
||||
+ if (key.objectid != child_root_id ||
|
||||
+ key.type != BTRFS_ROOT_BACKREF_KEY)
|
||||
+ break;
|
||||
+
|
||||
+ has_parent = 1;
|
||||
+
|
||||
+ if (key.offset == parent_root_id) {
|
||||
+ btrfs_release_path(root, &path);
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ path.slots[0]++;
|
||||
+ }
|
||||
+
|
||||
+ btrfs_release_path(root, &path);
|
||||
+ return has_parent? 0 : -1;
|
||||
+}
|
||||
+
|
||||
+static int process_dir_item(struct btrfs_root *root,
|
||||
+ struct extent_buffer *eb,
|
||||
int slot, struct btrfs_key *key,
|
||||
struct shared_node *active_node)
|
||||
{
|
||||
@@ -795,9 +853,13 @@ 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) {
|
||||
- add_inode_backref(root_cache, location.objectid,
|
||||
- key->objectid, key->offset, namebuf,
|
||||
- len, filetype, key->type, error);
|
||||
+ u64 parent = root->objectid;
|
||||
+
|
||||
+ if (is_child_root(root, parent, location.objectid))
|
||||
+ 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__);
|
||||
}
|
||||
@@ -1028,7 +1090,7 @@ static int process_one_leaf(struct btrfs_root *root, struct extent_buffer *eb,
|
||||
switch (key.type) {
|
||||
case BTRFS_DIR_ITEM_KEY:
|
||||
case BTRFS_DIR_INDEX_KEY:
|
||||
- ret = process_dir_item(eb, i, &key, active_node);
|
||||
+ ret = process_dir_item(root, eb, i, &key, active_node);
|
||||
break;
|
||||
case BTRFS_INODE_REF_KEY:
|
||||
ret = process_inode_ref(eb, i, &key, active_node);
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,750 +0,0 @@
|
||||
From 927d075e63d7c21038c53eae1e1b1edbdb01cdcf Mon Sep 17 00:00:00 2001
|
||||
From: David Sterba <dsterba@suse.cz>
|
||||
Date: Wed, 14 Dec 2011 18:46:02 +0100
|
||||
Subject: [PATCH] Revert "Btrfs-progs: add restriper commands"
|
||||
|
||||
This reverts commit 192484f121dbbffd004303a760ef8b4dbd470ce2.
|
||||
---
|
||||
btrfs.c | 21 ---
|
||||
btrfs_cmds.c | 505 +---------------------------------------------------------
|
||||
btrfs_cmds.h | 5 -
|
||||
ctree.h | 9 -
|
||||
ioctl.h | 46 +-----
|
||||
print-tree.c | 3 -
|
||||
volumes.h | 42 -----
|
||||
7 files changed, 3 insertions(+), 628 deletions(-)
|
||||
|
||||
diff --git a/btrfs.c b/btrfs.c
|
||||
index 52af8f7..66b0d80 100644
|
||||
--- a/btrfs.c
|
||||
+++ b/btrfs.c
|
||||
@@ -329,27 +329,6 @@ static struct Command commands[] = {
|
||||
"Show status of running or finished scrub.",
|
||||
NULL
|
||||
},
|
||||
- { do_restripe, -1,
|
||||
- "filesystem restripe start", "[-d [filters]] [-m [filters]] "
|
||||
- "[-s [filters]] [-vf] <path>\n"
|
||||
- "Start restriper."
|
||||
- },
|
||||
- { do_restripe_cancel, 1,
|
||||
- "filesystem restripe cancel", "<path>\n"
|
||||
- "Cancel restriper."
|
||||
- },
|
||||
- { do_restripe_pause, 1,
|
||||
- "filesystem restripe pause", "<path>\n"
|
||||
- "Pause restriper."
|
||||
- },
|
||||
- { do_restripe_resume, 1,
|
||||
- "filesystem restripe resume", "<path>\n"
|
||||
- "Resume interrupted restripe operation."
|
||||
- },
|
||||
- { do_restripe_progress, -1,
|
||||
- "filesystem restripe status", "[-v] <path>\n"
|
||||
- "Show status of running or paused restripe operation."
|
||||
- },
|
||||
{ do_scan, 999,
|
||||
"device scan", "[<device>...]\n"
|
||||
"Scan all device for or the passed device for a btrfs\n"
|
||||
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
|
||||
index e4c5592..1bfc669 100644
|
||||
--- a/btrfs_cmds.c
|
||||
+++ b/btrfs_cmds.c
|
||||
@@ -1094,515 +1094,14 @@ int do_balance(int argc, char **argv)
|
||||
e = errno;
|
||||
close(fdmnt);
|
||||
if(ret<0){
|
||||
- if (e == ECANCELED) {
|
||||
- fprintf(stderr, "restripe interrupted by user\n");
|
||||
- } else {
|
||||
- fprintf(stderr, "ERROR: error during restriping '%s' "
|
||||
- "- %s\n", path, strerror(e));
|
||||
- return 19;
|
||||
- }
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int parse_one_profile(char *profile, u64 *flags)
|
||||
-{
|
||||
- if (!strcmp(profile, "raid0")) {
|
||||
- *flags |= BTRFS_BLOCK_GROUP_RAID0;
|
||||
- } else if (!strcmp(profile, "raid1")) {
|
||||
- *flags |= BTRFS_BLOCK_GROUP_RAID1;
|
||||
- } else if (!strcmp(profile, "raid10")) {
|
||||
- *flags |= BTRFS_BLOCK_GROUP_RAID10;
|
||||
- } else if (!strcmp(profile, "dup")) {
|
||||
- *flags |= BTRFS_BLOCK_GROUP_DUP;
|
||||
- } else if (!strcmp(profile, "single")) {
|
||||
- *flags |= BTRFS_AVAIL_ALLOC_BIT_SINGLE;
|
||||
- } else {
|
||||
- fprintf(stderr, "Unknown profile '%s'\n", profile);
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int parse_profiles(char *profiles, u64 *flags)
|
||||
-{
|
||||
- char *this_char;
|
||||
- char *save_ptr;
|
||||
-
|
||||
- for (this_char = strtok_r(profiles, "|", &save_ptr);
|
||||
- this_char != NULL;
|
||||
- this_char = strtok_r(NULL, "|", &save_ptr)) {
|
||||
- if (parse_one_profile(this_char, flags))
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int parse_range(char *range, u64 *start, u64 *end)
|
||||
-{
|
||||
- char *dots;
|
||||
-
|
||||
- dots = strstr(range, "..");
|
||||
- if (dots) {
|
||||
- const char *rest = dots + 2;
|
||||
- int skipped = 0;
|
||||
-
|
||||
- *dots = 0;
|
||||
-
|
||||
- if (!*rest) {
|
||||
- *end = (u64)-1;
|
||||
- skipped++;
|
||||
- } else {
|
||||
- *end = strtoull(rest, (char **)NULL, 10);
|
||||
- }
|
||||
- if (dots == range) {
|
||||
- *start = 0;
|
||||
- skipped++;
|
||||
- } else {
|
||||
- *start = strtoull(range, (char **)NULL, 10);
|
||||
- }
|
||||
-
|
||||
- if (skipped <= 1)
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- return 1;
|
||||
-}
|
||||
-
|
||||
-static int parse_filters(char *filters, struct btrfs_restripe_args *rargs)
|
||||
-{
|
||||
- char *this_char;
|
||||
- char *value;
|
||||
- char *save_ptr;
|
||||
-
|
||||
- if (!filters)
|
||||
- return 0;
|
||||
-
|
||||
- for (this_char = strtok_r(filters, ",", &save_ptr);
|
||||
- this_char != NULL;
|
||||
- this_char = strtok_r(NULL, ",", &save_ptr)) {
|
||||
- if ((value = strchr(this_char, '=')) != NULL)
|
||||
- *value++ = 0;
|
||||
- if (!strcmp(this_char, "profiles")) {
|
||||
- if (!value || !*value) {
|
||||
- fprintf(stderr, "the profiles filter requires "
|
||||
- "an argument\n");
|
||||
- return 1;
|
||||
- }
|
||||
- if (parse_profiles(value, &rargs->profiles)) {
|
||||
- fprintf(stderr, "Invalid profiles argument\n");
|
||||
- return 1;
|
||||
- }
|
||||
- rargs->flags |= BTRFS_RESTRIPE_ARGS_PROFILES;
|
||||
- } else if (!strcmp(this_char, "usage")) {
|
||||
- if (!value || !*value) {
|
||||
- fprintf(stderr, "the usage filter requires "
|
||||
- "an argument\n");
|
||||
- return 1;
|
||||
- }
|
||||
- rargs->usage = strtoull(value, (char **)NULL, 10);
|
||||
- if (rargs->usage < 1 || rargs->usage > 100) {
|
||||
- fprintf(stderr, "Invalid usage argument: %s\n",
|
||||
- value);
|
||||
- return 1;
|
||||
- }
|
||||
- rargs->flags |= BTRFS_RESTRIPE_ARGS_USAGE;
|
||||
- } else if (!strcmp(this_char, "devid")) {
|
||||
- if (!value || !*value) {
|
||||
- fprintf(stderr, "the devid filter requires "
|
||||
- "an argument\n");
|
||||
- return 1;
|
||||
- }
|
||||
- rargs->devid = strtoull(value, (char **)NULL, 10);
|
||||
- if (rargs->devid == 0) {
|
||||
- fprintf(stderr, "Invalid devid argument: %s\n",
|
||||
- value);
|
||||
- return 1;
|
||||
- }
|
||||
- rargs->flags |= BTRFS_RESTRIPE_ARGS_DEVID;
|
||||
- } else if (!strcmp(this_char, "drange")) {
|
||||
- if (!value || !*value) {
|
||||
- fprintf(stderr, "the drange filter requires "
|
||||
- "an argument\n");
|
||||
- return 1;
|
||||
- }
|
||||
- if (parse_range(value, &rargs->pstart, &rargs->pend)) {
|
||||
- fprintf(stderr, "Invalid drange argument\n");
|
||||
- return 1;
|
||||
- }
|
||||
- rargs->flags |= BTRFS_RESTRIPE_ARGS_DRANGE;
|
||||
- } else if (!strcmp(this_char, "vrange")) {
|
||||
- if (!value || !*value) {
|
||||
- fprintf(stderr, "the vrange filter requires "
|
||||
- "an argument\n");
|
||||
- return 1;
|
||||
- }
|
||||
- if (parse_range(value, &rargs->vstart, &rargs->vend)) {
|
||||
- fprintf(stderr, "Invalid vrange argument\n");
|
||||
- return 1;
|
||||
- }
|
||||
- rargs->flags |= BTRFS_RESTRIPE_ARGS_VRANGE;
|
||||
- } else if (!strcmp(this_char, "convert")) {
|
||||
- if (!value || !*value) {
|
||||
- fprintf(stderr, "the convert option requires "
|
||||
- "an argument\n");
|
||||
- return 1;
|
||||
- }
|
||||
- if (parse_one_profile(value, &rargs->target)) {
|
||||
- fprintf(stderr, "Invalid convert argument\n");
|
||||
- return 1;
|
||||
- }
|
||||
- rargs->flags |= BTRFS_RESTRIPE_ARGS_CONVERT;
|
||||
- } else if (!strcmp(this_char, "soft")) {
|
||||
- rargs->flags |= BTRFS_RESTRIPE_ARGS_SOFT;
|
||||
- } else {
|
||||
- fprintf(stderr, "Unrecognized restripe option '%s'\n",
|
||||
- this_char);
|
||||
- return 1;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static void dump_ioctl_restripe_args(struct btrfs_ioctl_restripe_args *args);
|
||||
-
|
||||
-static struct option restripe_longopts[] = {
|
||||
- { "data", 2, NULL, 'd'},
|
||||
- { "metadata", 2, NULL, 'm' },
|
||||
- { "system", 2, NULL, 's' },
|
||||
- { "force", 0, NULL, 'f' },
|
||||
- { "verbose", 0, NULL, 'v' },
|
||||
- { 0, 0, 0, 0}
|
||||
-};
|
||||
-
|
||||
-/*
|
||||
- * [-d [filters]] [-m [filters]] [-s [filters]] [-vf]
|
||||
- */
|
||||
-int do_restripe(int ac, char **av)
|
||||
-{
|
||||
- int fd;
|
||||
- char *path;
|
||||
- struct btrfs_ioctl_restripe_args args;
|
||||
- struct btrfs_restripe_args *ptrs[] = { &args.data, &args.sys,
|
||||
- &args.meta, NULL };
|
||||
- int force = 0;
|
||||
- int verbose = 0;
|
||||
- int nofilters = 1;
|
||||
- int i;
|
||||
- int longindex;
|
||||
- int ret;
|
||||
- int e;
|
||||
-
|
||||
- memset(&args, 0, sizeof(args));
|
||||
-
|
||||
- while (1) {
|
||||
- int opt = getopt_long(ac, av, "d::s::m::fv", restripe_longopts,
|
||||
- &longindex);
|
||||
- if (opt < 0)
|
||||
- break;
|
||||
-
|
||||
- switch (opt) {
|
||||
- case 'd':
|
||||
- nofilters = 0;
|
||||
- args.flags |= BTRFS_RESTRIPE_DATA;
|
||||
-
|
||||
- if (parse_filters(optarg, &args.data))
|
||||
- return 1;
|
||||
- break;
|
||||
- case 's':
|
||||
- nofilters = 0;
|
||||
- args.flags |= BTRFS_RESTRIPE_SYSTEM;
|
||||
-
|
||||
- if (parse_filters(optarg, &args.sys))
|
||||
- return 1;
|
||||
- break;
|
||||
- case 'm':
|
||||
- nofilters = 0;
|
||||
- args.flags |= BTRFS_RESTRIPE_METADATA;
|
||||
-
|
||||
- if (parse_filters(optarg, &args.meta))
|
||||
- return 1;
|
||||
- break;
|
||||
- case 'f':
|
||||
- force = 1;
|
||||
- break;
|
||||
- case 'v':
|
||||
- verbose = 1;
|
||||
- break;
|
||||
- default:
|
||||
- fprintf(stderr, "Invalid arguments for restripe\n");
|
||||
- return 1;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (ac - optind != 1) {
|
||||
- fprintf(stderr, "Invalid arguments for restripe\n");
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- if (nofilters) {
|
||||
- /* relocate everything - no filters */
|
||||
- args.flags |= BTRFS_RESTRIPE_TYPE_MASK;
|
||||
- }
|
||||
-
|
||||
- /* drange makes sense only when devid is set */
|
||||
- for (i = 0; ptrs[i]; i++) {
|
||||
- if ((ptrs[i]->flags & BTRFS_RESTRIPE_ARGS_DRANGE) &&
|
||||
- !(ptrs[i]->flags & BTRFS_RESTRIPE_ARGS_DEVID)) {
|
||||
- fprintf(stderr, "drange filter can be used only if "
|
||||
- "devid filter is used\n");
|
||||
- return 1;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- /* soft makes sense only when convert for corresponding type is set */
|
||||
- for (i = 0; ptrs[i]; i++) {
|
||||
- if ((ptrs[i]->flags & BTRFS_RESTRIPE_ARGS_SOFT) &&
|
||||
- !(ptrs[i]->flags & BTRFS_RESTRIPE_ARGS_CONVERT)) {
|
||||
- fprintf(stderr, "'soft' option can be used only if "
|
||||
- "changing profiles\n");
|
||||
- return 1;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- path = av[optind];
|
||||
- fd = open_file_or_dir(path);
|
||||
- if (fd < 0) {
|
||||
- fprintf(stderr, "ERROR: can't access to '%s'\n", path);
|
||||
- return 12;
|
||||
- }
|
||||
-
|
||||
- if (force)
|
||||
- args.flags |= BTRFS_RESTRIPE_FORCE;
|
||||
- if (verbose)
|
||||
- dump_ioctl_restripe_args(&args);
|
||||
-
|
||||
- ret = ioctl(fd, BTRFS_IOC_RESTRIPE, &args);
|
||||
- e = errno;
|
||||
- close(fd);
|
||||
-
|
||||
- if (ret < 0) {
|
||||
- if (e == ECANCELED) {
|
||||
- fprintf(stderr, "restripe interrupted by user\n");
|
||||
- } else {
|
||||
- fprintf(stderr, "ERROR: error during restriping '%s' "
|
||||
- "- %s\n", path, strerror(e));
|
||||
- return 19;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-int do_restripe_cancel(int ac, char **av)
|
||||
-{
|
||||
- int fd;
|
||||
- char *path = av[1];
|
||||
- int ret;
|
||||
- int e;
|
||||
-
|
||||
- fd = open_file_or_dir(path);
|
||||
- if (fd < 0) {
|
||||
- fprintf(stderr, "ERROR: can't access to '%s'\n", path);
|
||||
- return 12;
|
||||
- }
|
||||
-
|
||||
- ret = ioctl(fd, BTRFS_IOC_RESTRIPE_CTL, BTRFS_RESTRIPE_CTL_CANCEL);
|
||||
- e = errno;
|
||||
- close(fd);
|
||||
-
|
||||
- if (ret < 0) {
|
||||
- fprintf(stderr, "ERROR: restripe cancel on '%s' failed - %s\n",
|
||||
- path, (e == ENOTCONN) ? "Not in progress" : strerror(e));
|
||||
- return 19;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-int do_restripe_pause(int ac, char **av)
|
||||
-{
|
||||
- int fd;
|
||||
- char *path = av[1];
|
||||
- int ret;
|
||||
- int e;
|
||||
-
|
||||
- fd = open_file_or_dir(path);
|
||||
- if (fd < 0) {
|
||||
- fprintf(stderr, "ERROR: can't access to '%s'\n", path);
|
||||
- return 12;
|
||||
- }
|
||||
-
|
||||
- ret = ioctl(fd, BTRFS_IOC_RESTRIPE_CTL, BTRFS_RESTRIPE_CTL_PAUSE);
|
||||
- e = errno;
|
||||
- close(fd);
|
||||
-
|
||||
- if (ret < 0) {
|
||||
- fprintf(stderr, "ERROR: restripe pause on '%s' failed - %s\n",
|
||||
- path, (e == ENOTCONN) ? "Not running" : strerror(e));
|
||||
- return 19;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-int do_restripe_resume(int ac, char **av)
|
||||
-{
|
||||
- int fd;
|
||||
- char *path = av[1];
|
||||
- int ret;
|
||||
- int e;
|
||||
-
|
||||
- fd = open_file_or_dir(path);
|
||||
- if (fd < 0) {
|
||||
- fprintf(stderr, "ERROR: can't access to '%s'\n", path);
|
||||
- return 12;
|
||||
- }
|
||||
-
|
||||
- ret = ioctl(fd, BTRFS_IOC_RESTRIPE_CTL, BTRFS_RESTRIPE_CTL_RESUME);
|
||||
- e = errno;
|
||||
- close(fd);
|
||||
-
|
||||
- if (ret < 0) {
|
||||
- if (e == ECANCELED) {
|
||||
- fprintf(stderr, "restripe interrupted by user\n");
|
||||
- } else if (e == ENOTCONN || e == EINPROGRESS) {
|
||||
- fprintf(stderr, "ERROR: restripe resume on '%s' "
|
||||
- "failed - %s\n", path,
|
||||
- (e == ENOTCONN) ? "Not in progress" :
|
||||
- "Already running");
|
||||
- return 19;
|
||||
- } else {
|
||||
- fprintf(stderr, "ERROR: error during restriping '%s' "
|
||||
- "- %s\n", path, strerror(e));
|
||||
- return 19;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static struct option restripe_progress_longopts[] = {
|
||||
- { "verbose", 0, NULL, 'v' },
|
||||
- { 0, 0, 0, 0}
|
||||
-};
|
||||
-
|
||||
-int do_restripe_progress(int ac, char **av)
|
||||
-{
|
||||
- int fd;
|
||||
- char *path;
|
||||
- struct btrfs_ioctl_restripe_args args;
|
||||
- int verbose = 0;
|
||||
- int longindex;
|
||||
- int ret;
|
||||
- int e;
|
||||
-
|
||||
- while (1) {
|
||||
- int opt = getopt_long(ac, av, "v", restripe_progress_longopts,
|
||||
- &longindex);
|
||||
- if (opt < 0)
|
||||
- break;
|
||||
-
|
||||
- switch (opt) {
|
||||
- case 'v':
|
||||
- verbose = 1;
|
||||
- break;
|
||||
- default:
|
||||
- fprintf(stderr, "Invalid arguments for restripe "
|
||||
- "status\n");
|
||||
- return 1;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (ac - optind != 1) {
|
||||
- fprintf(stderr, "Invalid arguments for restripe status\n");
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
- path = av[optind];
|
||||
- fd = open_file_or_dir(path);
|
||||
- if (fd < 0) {
|
||||
- fprintf(stderr, "ERROR: can't access to '%s'\n", path);
|
||||
- return 12;
|
||||
- }
|
||||
-
|
||||
- ret = ioctl(fd, BTRFS_IOC_RESTRIPE_PROGRESS, &args);
|
||||
- e = errno;
|
||||
- close(fd);
|
||||
+ fprintf(stderr, "ERROR: error during balancing '%s' - %s\n",
|
||||
+ path, strerror(e));
|
||||
|
||||
- if (ret < 0) {
|
||||
- fprintf(stderr, "ERROR: restripe status on '%s' failed - %s\n",
|
||||
- path, (e == ENOTCONN) ? "Not in progress" : strerror(e));
|
||||
return 19;
|
||||
}
|
||||
-
|
||||
- if (args.state & BTRFS_RESTRIPE_ST_RUNNING) {
|
||||
- printf("Restripe on '%s' is running", path);
|
||||
- if (args.state & BTRFS_RESTRIPE_ST_CANCEL_REQ)
|
||||
- printf(", cancel requested\n");
|
||||
- else if (args.state & BTRFS_RESTRIPE_ST_PAUSE_REQ)
|
||||
- printf(", pause requested\n");
|
||||
- else
|
||||
- printf("\n");
|
||||
- } else {
|
||||
- printf("Restripe on '%s' is paused\n", path);
|
||||
- }
|
||||
-
|
||||
- printf("%llu out of about %llu chunks restriped (%llu considered), "
|
||||
- "%3.f%% left\n", args.stat.completed, args.stat.expected,
|
||||
- args.stat.considered,
|
||||
- 100 * (1 - (float)args.stat.completed/args.stat.expected));
|
||||
-
|
||||
- if (verbose)
|
||||
- dump_ioctl_restripe_args(&args);
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void dump_restripe_args(struct btrfs_restripe_args *args)
|
||||
-{
|
||||
- if (args->flags & BTRFS_RESTRIPE_ARGS_CONVERT) {
|
||||
- printf("converting, target=%llu, soft is %s", args->target,
|
||||
- (args->flags & BTRFS_RESTRIPE_ARGS_SOFT) ? "on" : "off");
|
||||
- } else {
|
||||
- printf("balancing");
|
||||
- }
|
||||
-
|
||||
- if (args->flags & BTRFS_RESTRIPE_ARGS_PROFILES)
|
||||
- printf(", profiles=%llu", args->profiles);
|
||||
- if (args->flags & BTRFS_RESTRIPE_ARGS_USAGE)
|
||||
- printf(", usage=%llu", args->usage);
|
||||
- if (args->flags & BTRFS_RESTRIPE_ARGS_DEVID)
|
||||
- printf(", devid=%llu", args->devid);
|
||||
- if (args->flags & BTRFS_RESTRIPE_ARGS_DRANGE)
|
||||
- printf(", drange=%llu..%llu", args->pstart, args->pend);
|
||||
- if (args->flags & BTRFS_RESTRIPE_ARGS_VRANGE)
|
||||
- printf(", vrange=%llu..%llu", args->vstart, args->vend);
|
||||
-
|
||||
- printf("\n");
|
||||
-}
|
||||
-
|
||||
-static void dump_ioctl_restripe_args(struct btrfs_ioctl_restripe_args *args)
|
||||
-{
|
||||
- printf("Dumping filters: flags 0x%llx, state 0x%llx, force is %s\n",
|
||||
- args->flags, args->state,
|
||||
- (args->flags & BTRFS_RESTRIPE_FORCE) ? "on" : "off");
|
||||
- if (args->flags & BTRFS_RESTRIPE_DATA) {
|
||||
- printf(" DATA (flags 0x%llx): ", args->data.flags);
|
||||
- dump_restripe_args(&args->data);
|
||||
- }
|
||||
- if (args->flags & BTRFS_RESTRIPE_METADATA) {
|
||||
- printf(" METADATA (flags 0x%llx): ", args->meta.flags);
|
||||
- dump_restripe_args(&args->meta);
|
||||
- }
|
||||
- if (args->flags & BTRFS_RESTRIPE_SYSTEM) {
|
||||
- printf(" SYSTEM (flags 0x%llx): ", args->sys.flags);
|
||||
- dump_restripe_args(&args->sys);
|
||||
- }
|
||||
-}
|
||||
|
||||
|
||||
/**** man: btrfs device delete
|
||||
diff --git a/btrfs_cmds.h b/btrfs_cmds.h
|
||||
index 2cd0ac1..81182b1 100644
|
||||
--- a/btrfs_cmds.h
|
||||
+++ b/btrfs_cmds.h
|
||||
@@ -27,11 +27,6 @@ int do_scrub_start(int nargs, char **argv);
|
||||
int do_scrub_status(int argc, char **argv);
|
||||
int do_scrub_resume(int argc, char **argv);
|
||||
int do_scrub_cancel(int nargs, char **argv);
|
||||
-int do_restripe(int ac, char **av);
|
||||
-int do_restripe_cancel(int ac, char **av);
|
||||
-int do_restripe_pause(int ac, char **av);
|
||||
-int do_restripe_resume(int ac, char **av);
|
||||
-int do_restripe_progress(int ac, char **av);
|
||||
int do_remove_volume(int nargs, char **args);
|
||||
int do_scan(int nargs, char **argv);
|
||||
int do_resize(int nargs, char **argv);
|
||||
diff --git a/ctree.h b/ctree.h
|
||||
index 58ea3d3..54748c8 100644
|
||||
--- a/ctree.h
|
||||
+++ b/ctree.h
|
||||
@@ -61,9 +61,6 @@ struct btrfs_trans_handle;
|
||||
#define BTRFS_CSUM_TREE_OBJECTID 7ULL
|
||||
|
||||
|
||||
-/* for storing restripe params in the root tree */
|
||||
-#define BTRFS_RESTRIPE_OBJECTID -4ULL
|
||||
-
|
||||
/* oprhan objectid for tracking unlinked/truncated files */
|
||||
#define BTRFS_ORPHAN_OBJECTID -5ULL
|
||||
|
||||
@@ -708,12 +705,6 @@ struct btrfs_csum_item {
|
||||
#define BTRFS_BLOCK_GROUP_DUP (1 << 5)
|
||||
#define BTRFS_BLOCK_GROUP_RAID10 (1 << 6)
|
||||
|
||||
-/*
|
||||
- * to avoid troubles..
|
||||
- */
|
||||
-#define BTRFS_AVAIL_ALLOC_BIT_SINGLE (1 << 7)
|
||||
-#define BTRFS_BLOCK_GROUP_RESERVED (1 << 7)
|
||||
-
|
||||
struct btrfs_block_group_item {
|
||||
__le64 used;
|
||||
__le64 chunk_objectid;
|
||||
diff --git a/ioctl.h b/ioctl.h
|
||||
index af8b18b..1ae7537 100644
|
||||
--- a/ioctl.h
|
||||
+++ b/ioctl.h
|
||||
@@ -91,45 +91,6 @@ struct btrfs_ioctl_fs_info_args {
|
||||
__u64 reserved[124]; /* pad to 1k */
|
||||
};
|
||||
|
||||
-#define BTRFS_RESTRIPE_CTL_CANCEL 1
|
||||
-#define BTRFS_RESTRIPE_CTL_PAUSE 2
|
||||
-#define BTRFS_RESTRIPE_CTL_RESUME 3
|
||||
-
|
||||
-struct btrfs_restripe_args {
|
||||
- __u64 profiles;
|
||||
- __u64 usage;
|
||||
- __u64 devid;
|
||||
- __u64 pstart;
|
||||
- __u64 pend;
|
||||
- __u64 vstart;
|
||||
- __u64 vend;
|
||||
-
|
||||
- __u64 target;
|
||||
-
|
||||
- __u64 flags;
|
||||
-
|
||||
- __u64 unused[8];
|
||||
-} __attribute__ ((__packed__));
|
||||
-
|
||||
-struct btrfs_restripe_progress {
|
||||
- __u64 expected;
|
||||
- __u64 considered;
|
||||
- __u64 completed;
|
||||
-};
|
||||
-
|
||||
-struct btrfs_ioctl_restripe_args {
|
||||
- __u64 flags;
|
||||
- __u64 state;
|
||||
-
|
||||
- struct btrfs_restripe_args data;
|
||||
- struct btrfs_restripe_args sys;
|
||||
- struct btrfs_restripe_args meta;
|
||||
-
|
||||
- struct btrfs_restripe_progress stat;
|
||||
-
|
||||
- __u64 unused[72]; /* pad to 1k */
|
||||
-};
|
||||
-
|
||||
struct btrfs_ioctl_search_key {
|
||||
/* which root are we searching. 0 is the tree of tree roots */
|
||||
__u64 tree_id;
|
||||
@@ -311,15 +272,10 @@ struct btrfs_ioctl_logical_ino_args {
|
||||
#define BTRFS_IOC_DEV_INFO _IOWR(BTRFS_IOCTL_MAGIC, 30, \
|
||||
struct btrfs_ioctl_dev_info_args)
|
||||
#define BTRFS_IOC_FS_INFO _IOR(BTRFS_IOCTL_MAGIC, 31, \
|
||||
- struct btrfs_ioctl_fs_info_args)
|
||||
+ struct btrfs_ioctl_fs_info_args)
|
||||
#define BTRFS_IOC_INO_PATHS _IOWR(BTRFS_IOCTL_MAGIC, 35, \
|
||||
struct btrfs_ioctl_ino_path_args)
|
||||
#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
|
||||
struct btrfs_ioctl_ino_path_args)
|
||||
|
||||
-#define BTRFS_IOC_RESTRIPE _IOW(BTRFS_IOCTL_MAGIC, 32, \
|
||||
- struct btrfs_ioctl_restripe_args)
|
||||
-#define BTRFS_IOC_RESTRIPE_CTL _IOW(BTRFS_IOCTL_MAGIC, 33, int)
|
||||
-#define BTRFS_IOC_RESTRIPE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 34, \
|
||||
- struct btrfs_ioctl_restripe_args)
|
||||
#endif
|
||||
diff --git a/print-tree.c b/print-tree.c
|
||||
index 49f98af..6039699 100644
|
||||
--- a/print-tree.c
|
||||
+++ b/print-tree.c
|
||||
@@ -391,9 +391,6 @@ static void print_objectid(unsigned long long objectid, u8 type)
|
||||
case BTRFS_CSUM_TREE_OBJECTID:
|
||||
printf("CSUM_TREE");
|
||||
break;
|
||||
- case BTRFS_RESTRIPE_OBJECTID:
|
||||
- printf("RESTRIPE");
|
||||
- break;
|
||||
case BTRFS_ORPHAN_OBJECTID:
|
||||
printf("ORPHAN");
|
||||
break;
|
||||
diff --git a/volumes.h b/volumes.h
|
||||
index 5845c1d..08c53e4 100644
|
||||
--- a/volumes.h
|
||||
+++ b/volumes.h
|
||||
@@ -95,48 +95,6 @@ struct btrfs_multi_bio {
|
||||
#define btrfs_multi_bio_size(n) (sizeof(struct btrfs_multi_bio) + \
|
||||
(sizeof(struct btrfs_bio_stripe) * (n)))
|
||||
|
||||
-/*
|
||||
- * Restriper's general "type" filter. Shares bits with chunk type for
|
||||
- * simplicity, RESTRIPE prefix is used to avoid confusion.
|
||||
- */
|
||||
-#define BTRFS_RESTRIPE_DATA (1ULL << 0)
|
||||
-#define BTRFS_RESTRIPE_SYSTEM (1ULL << 1)
|
||||
-#define BTRFS_RESTRIPE_METADATA (1ULL << 2)
|
||||
-
|
||||
-#define BTRFS_RESTRIPE_TYPE_MASK (BTRFS_RESTRIPE_DATA | \
|
||||
- BTRFS_RESTRIPE_SYSTEM | \
|
||||
- BTRFS_RESTRIPE_METADATA)
|
||||
-
|
||||
-#define BTRFS_RESTRIPE_FORCE (1ULL << 3)
|
||||
-
|
||||
-/*
|
||||
- * Restripe filters
|
||||
- */
|
||||
-#define BTRFS_RESTRIPE_ARGS_PROFILES (1ULL << 0)
|
||||
-#define BTRFS_RESTRIPE_ARGS_USAGE (1ULL << 1)
|
||||
-#define BTRFS_RESTRIPE_ARGS_DEVID (1ULL << 2)
|
||||
-#define BTRFS_RESTRIPE_ARGS_DRANGE (1ULL << 3)
|
||||
-#define BTRFS_RESTRIPE_ARGS_VRANGE (1ULL << 4)
|
||||
-
|
||||
-/*
|
||||
- * Profile changing flags. When SOFT is set we won't relocate chunk if
|
||||
- * it already has the target profile (even though it may be
|
||||
- * half-filled).
|
||||
- */
|
||||
-#define BTRFS_RESTRIPE_ARGS_CONVERT (1ULL << 8)
|
||||
-#define BTRFS_RESTRIPE_ARGS_SOFT (1ULL << 9)
|
||||
-
|
||||
-/*
|
||||
- * Restripe state bits
|
||||
- */
|
||||
-#define RESTRIPE_RUNNING 0
|
||||
-#define RESTRIPE_CANCEL_REQ 1
|
||||
-#define RESTRIPE_PAUSE_REQ 2
|
||||
-
|
||||
-#define BTRFS_RESTRIPE_ST_RUNNING (1ULL << RESTRIPE_RUNNING)
|
||||
-#define BTRFS_RESTRIPE_ST_CANCEL_REQ (1ULL << RESTRIPE_CANCEL_REQ)
|
||||
-#define BTRFS_RESTRIPE_ST_PAUSE_REQ (1ULL << RESTRIPE_PAUSE_REQ)
|
||||
-
|
||||
int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_device *device,
|
||||
u64 chunk_tree, u64 chunk_objectid,
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
|
@ -1,10 +1,10 @@
|
||||
#!/bin/bash -e
|
||||
#%stage: block
|
||||
#%stage: filesystem
|
||||
#%if: "$rootfstype" = "btrfs"
|
||||
#%programs: /sbin/btrfs /sbin/btrfs-zero-log /sbin/btrfs-convert /sbin/btrfs-select-super /sbin/btrfs-image /sbin/btrfstune /sbin/btrfs-restore /sbin/btrfs-find-root /sbin/btrfsck /sbin/mkfs.btrfs /sbin/btrfs-dump-super
|
||||
|
||||
modprobe btrfs
|
||||
|
||||
if [ -x /sbin/btrfs ]; then
|
||||
/sbin/btrfs dev scan >& /dev/null
|
||||
if [ -x /usr/sbin/btrfs ]; then
|
||||
/usr/sbin/btrfs dev scan >& /dev/null
|
||||
fi
|
||||
|
70
btrfs-dev-clear-sb
Normal file
70
btrfs-dev-clear-sb
Normal file
@ -0,0 +1,70 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# clear btrfs signature from a device
|
||||
|
||||
use Fcntl;
|
||||
|
||||
use constant BTRFS_SUPER_INFO_OFFSET => 64 * 1024;
|
||||
use constant BTRFS_SUPER_INFO_SIZE => 4096;
|
||||
|
||||
use constant BTRFS_SUPER_MIRROR_MAX => 3;
|
||||
use constant BTRFS_SUPER_MIRROR_SHIFT => 12;
|
||||
|
||||
use constant BTRFS_MAGIC => "_BHRfS_M";
|
||||
use constant BTRFS_DEAD => '_BHRf$_M';
|
||||
|
||||
sub btrfs_sb_offset($) {
|
||||
my $mirror =$_[0];
|
||||
my $start = 16 * 1024;
|
||||
if ($mirror>0) {
|
||||
return $start << (BTRFS_SUPER_MIRROR_SHIFT * $mirror);
|
||||
}
|
||||
return BTRFS_SUPER_INFO_OFFSET;
|
||||
}
|
||||
|
||||
my $dbg=1;
|
||||
my $savesb=0;
|
||||
|
||||
# main
|
||||
my $dev=$ARGV[0];
|
||||
my $size;
|
||||
if(!-b $dev) {
|
||||
print("Not a block device: $dev\n");
|
||||
$size=(stat($dev))[7];
|
||||
} else {
|
||||
$size=`blkdev --getsize64 "$dev"`;
|
||||
}
|
||||
sysopen(F, $dev, O_EXCL | O_RDWR) or die("Cannot open $dev exclusively: $!");
|
||||
sysseek(F, 0, 2);
|
||||
$size=tell(F);
|
||||
print("Device size: $size\n") if($dbg);
|
||||
for(my $i=0;$i<6;$i++) {
|
||||
my $off=btrfs_sb_offset($i);
|
||||
if($off > $size) {
|
||||
print("Offset for SB $i beyond EOF\n") if($dbg);
|
||||
last;
|
||||
}
|
||||
print("Offset $i is $off\n") if($dbg);
|
||||
sysseek(F, $off, 0);
|
||||
sysread(F, $buf, BTRFS_SUPER_INFO_SIZE);
|
||||
if($savesb) {
|
||||
open(Q,">SB$i");
|
||||
print Q ($buf);
|
||||
close(Q);
|
||||
}
|
||||
my $sbmagic=substr($buf, 0x40, length(BTRFS_MAGIC));
|
||||
print("SB magic: $sbmagic\n") if($dbg);
|
||||
if(BTRFS_MAGIC eq $sbmagic) {
|
||||
print("Found a valid signature of superblock $i\n");
|
||||
sysseek(F, $off + 0x40, 0);
|
||||
print("Clearing...\n");
|
||||
syswrite(F, BTRFS_DEAD, length(BTRFS_DEAD));
|
||||
} elsif(BTRFS_DEAD eq $sbmagic) {
|
||||
print("Found a signature of a dead superblock $i\n");
|
||||
} else {
|
||||
print("Superblock $i does not look like a btrfs one\n");
|
||||
}
|
||||
}
|
||||
close(F);
|
||||
print("Syncing dev\n");
|
||||
system("fsync \'$dev\'");
|
130
btrfs-man-update
Normal file
130
btrfs-man-update
Normal file
@ -0,0 +1,130 @@
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/man/btrfs.8.in
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/man/btrfs.8.in
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/man/btrfs.8.in
|
||||
@@ -29,15 +29,36 @@ btrfs \- control a btrfs filesystem
|
||||
\fB\fBbtrfs\fP \fBfilesystem sync\fP\fI <path> \fP
|
||||
\fP
|
||||
.PP
|
||||
-\fB\fBbtrfs\fP \fBscrub cancel\fP {\fI<path>\fP|\fI<device>\fP}
|
||||
+\fB\fBbtrfs\fP \fBfilesystem df\fP\fI <path> \fP
|
||||
\fP
|
||||
.PP
|
||||
-\fB\fBbtrfs\fP \fBscrub resume\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP}
|
||||
+\fB\fBbtrfs\fP \fBfilesystem balance start [-d [filters]] [-m [filters]] [-s [filters]] [-vf]\fP\fI <path> \fP
|
||||
+\fP
|
||||
+.PP
|
||||
+\fB\fBbtrfs\fP \fBfilesystem balance pause\fP\fI <path> \fP
|
||||
+\fP
|
||||
+.PP
|
||||
+\fB\fBbtrfs\fP \fBfilesystem balance cancel\fP\fI <path> \fP
|
||||
+\fP
|
||||
+.PP
|
||||
+\fB\fBbtrfs\fP \fBfilesystem balance resume\fP\fI <path> \fP
|
||||
+\fP
|
||||
+.PP
|
||||
+\fB\fBbtrfs\fP \fBfilesystem balance status [-v]\fP\fI <path> \fP
|
||||
+\fP
|
||||
+.PP
|
||||
+\fB\fBbtrfs\fP \fBfilesystem csize [-s start] [-e end]\fP\fI <file> \fP
|
||||
\fP
|
||||
.PP
|
||||
\fB\fBbtrfs\fP \fBscrub start\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP}
|
||||
\fP
|
||||
.PP
|
||||
+\fB\fBbtrfs\fP \fBscrub cancel\fP {\fI<path>\fP|\fI<device>\fP}
|
||||
+\fP
|
||||
+.PP
|
||||
+\fB\fBbtrfs\fP \fBscrub resume\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP}
|
||||
+\fP
|
||||
+.PP
|
||||
\fB\fBbtrfs\fP \fBscrub status\fP [-d] {\fI<path>\fP|\fI<device>\fP}
|
||||
\fP
|
||||
.PP
|
||||
@@ -56,9 +77,18 @@ btrfs \- control a btrfs filesystem
|
||||
\fB\fBbtrfs\fP \fBsubvolume set-default\fP\fI <id> <path>\fP
|
||||
\fP
|
||||
.PP
|
||||
+\fB\fBbtrfs\fP \fBsubvolume get-default\fP\fI <path>\fP
|
||||
+\fP
|
||||
+.PP
|
||||
\fB\fBbtrfs\fP \fBsubvolume snapshot\fP\fI [-r] <source> [<dest>/]<name>\fP
|
||||
\fP
|
||||
.PP
|
||||
+\fB\fBbtrfs\fP \fBinspect-internal inode-resolve [-v] <inode> \fP\fI<path>\fP
|
||||
+\fP
|
||||
+.PP
|
||||
+\fB\fBbtrfs\fP \fBinspect-internal logical-resolve [-v] [-P] <logical> \fP\fI<path>\fP
|
||||
+\fP
|
||||
+.PP
|
||||
.SH DESCRIPTION
|
||||
\fBbtrfs\fP is used to control the filesystem and the files and directories
|
||||
stored. It is the tool to create or destroy a snapshot or a subvolume for
|
||||
@@ -171,24 +201,26 @@ otherwise the devices list is extracted
|
||||
Force a sync for the filesystem identified by \fI<path>\fP.
|
||||
|
||||
.TP
|
||||
-\fBbtrfs\fP \fBscrub cancel\fP {\fI<path>\fP|\fI<device>\fP}
|
||||
-If a scrub is running on the filesystem identified by \fI<path>\fP, cancel it.
|
||||
-Progress is saved in the scrub progress file and scrubbing can be resumed later
|
||||
-using the \fBscrub resume\fP command.
|
||||
-If a \fI<device>\fP is given, the corresponding filesystem is found and
|
||||
-\fBscrub cancel\fP behaves as if it was called on that filesystem.
|
||||
+\fBbtrfs\fP \fBfilesystem df\fP\fI <path> \fP
|
||||
+Show space usage information for the filesystem identified by \fI<path>\fP.
|
||||
|
||||
.TP
|
||||
-\fBbtrfs\fP \fBscrub resume\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP}
|
||||
-Resume a canceled or interrupted scrub cycle on the filesystem identified by
|
||||
-\fI<path>\fP or on a given \fI<device>\fP. Does not start a new scrub if the
|
||||
-last scrub finished successfully.
|
||||
-.RS
|
||||
+\fBbtrfs\fP \fBfilesystem balance\fP\fI <path> \fP
|
||||
+
|
||||
+Balance chunks across the devices, control by subcommands \fIstart\fP,
|
||||
+\fIpause\fP, \fIcancel\fP, \fIresume\fP and read \fIstatus\fP. See section
|
||||
+BALANCE FILTERS for more details.
|
||||
|
||||
-\fIOptions\fP
|
||||
.TP
|
||||
-see \fBscrub start\fP.
|
||||
-.RE
|
||||
+\fB\fBbtrfs\fP \fBfilesystem csize [-s start] [-e end]\fP\fI <file> \fP
|
||||
+Read regular and compressed size of extents in the range \fI[start,end)\fP.
|
||||
+
|
||||
+\fB-s start\fP
|
||||
+range start inclusive, accepts K/M/G modifiers
|
||||
+\fB-e end\fP
|
||||
+range end exclusive, accepts K/M/G modifiers
|
||||
+
|
||||
+No range reads whole file, no end of range reads up to the end of file.
|
||||
|
||||
.TP
|
||||
\fBbtrfs\fP \fBscrub start\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP}
|
||||
@@ -213,6 +245,26 @@ Scrub unused space as well. (NOT IMPLEME
|
||||
.RE
|
||||
|
||||
.TP
|
||||
+\fBbtrfs\fP \fBscrub cancel\fP {\fI<path>\fP|\fI<device>\fP}
|
||||
+If a scrub is running on the filesystem identified by \fI<path>\fP, cancel it.
|
||||
+Progress is saved in the scrub progress file and scrubbing can be resumed later
|
||||
+using the \fBscrub resume\fP command.
|
||||
+If a \fI<device>\fP is given, the corresponding filesystem is found and
|
||||
+\fBscrub cancel\fP behaves as if it was called on that filesystem.
|
||||
+
|
||||
+.TP
|
||||
+\fBbtrfs\fP \fBscrub resume\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP}
|
||||
+Resume a canceled or interrupted scrub cycle on the filesystem identified by
|
||||
+\fI<path>\fP or on a given \fI<device>\fP. Does not start a new scrub if the
|
||||
+last scrub finished successfully.
|
||||
+.RS
|
||||
+
|
||||
+\fIOptions\fP
|
||||
+.TP
|
||||
+see \fBscrub start\fP.
|
||||
+.RE
|
||||
+
|
||||
+.TP
|
||||
\fBbtrfs\fP \fBscrub status\fP [-d] {\fI<path>\fP|\fI<device>\fP}
|
||||
Show status of a running scrub for the filesystem identified by \fI<path>\fP or
|
||||
for the specified \fI<device>\fP.
|
28
btrfs-mkfs-update-disclaimer.patch
Normal file
28
btrfs-mkfs-update-disclaimer.patch
Normal file
@ -0,0 +1,28 @@
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/mkfs.c
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/mkfs.c
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/mkfs.c
|
||||
@@ -1297,8 +1297,13 @@ int main(int ac, char **av)
|
||||
if (ac == 0)
|
||||
print_usage();
|
||||
|
||||
- printf("\nWARNING! - %s IS EXPERIMENTAL\n", BTRFS_BUILD_VERSION);
|
||||
- printf("WARNING! - see http://btrfs.wiki.kernel.org before using\n\n");
|
||||
+ printf("\n%s\n", BTRFS_BUILD_VERSION);
|
||||
+ printf("\n\
|
||||
+ATTENTION:\n\
|
||||
+\n\
|
||||
+mkfs.btrfs is not intended to be used directly. Please use the\n\
|
||||
+YaST partitioner to create and manage btrfs filesystems to be\n\
|
||||
+in a supported state on SUSE Linux Enterprise systems.\n\n");
|
||||
|
||||
if (source_dir == 0) {
|
||||
file = av[optind++];
|
||||
@@ -1456,7 +1461,6 @@ raid_groups:
|
||||
pretty_buf = pretty_sizes(btrfs_super_total_bytes(&root->fs_info->super_copy)));
|
||||
free(pretty_buf);
|
||||
|
||||
- printf("%s\n", BTRFS_BUILD_VERSION);
|
||||
btrfs_commit_transaction(trans, root);
|
||||
|
||||
if (source_dir_set) {
|
47
btrfs-reorder-commands-help
Normal file
47
btrfs-reorder-commands-help
Normal file
@ -0,0 +1,47 @@
|
||||
Index: btrfs-progs-v0.19-118-gfdb6c04/btrfs.c
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/btrfs.c
|
||||
+++ btrfs-progs-v0.19-118-gfdb6c04/btrfs.c
|
||||
@@ -231,17 +231,17 @@ static struct Command commands[] = {
|
||||
"the name <name> in the <dest> directory.",
|
||||
NULL
|
||||
},
|
||||
- { do_delete_subvolume, 1,
|
||||
- "subvolume delete", "<subvolume>\n"
|
||||
- "Delete the subvolume <subvolume>.",
|
||||
- NULL
|
||||
- },
|
||||
{ do_create_subvol, 1,
|
||||
"subvolume create", "[<dest>/]<name>\n"
|
||||
"Create a subvolume in <dest> (or the current directory if\n"
|
||||
"not passed).",
|
||||
NULL
|
||||
},
|
||||
+ { do_delete_subvolume, 1,
|
||||
+ "subvolume delete", "<subvolume>\n"
|
||||
+ "Delete the subvolume <subvolume>.",
|
||||
+ NULL
|
||||
+ },
|
||||
{ do_subvol_list, -1, "subvolume list", "[-p] <path>\n"
|
||||
"List the snapshot/subvolume of a filesystem.",
|
||||
"[-p] <path>\n"
|
||||
@@ -254,6 +254,9 @@ static struct Command commands[] = {
|
||||
"as default.",
|
||||
NULL
|
||||
},
|
||||
+ { do_get_default_subvol, 1, "subvolume get-default", "<path>\n"
|
||||
+ "Get the default subvolume of a filesystem."
|
||||
+ },
|
||||
{ do_find_newer, 2, "subvolume find-new", "<path> <last_gen>\n"
|
||||
"List the recently modified files in a filesystem.",
|
||||
NULL
|
||||
@@ -270,9 +273,6 @@ static struct Command commands[] = {
|
||||
"-l len defragment only up to len bytes\n"
|
||||
"-t size minimal size of file to be considered for defragmenting\n"
|
||||
},
|
||||
- { do_get_default_subvol, 1, "subvolume get-default", "<path>\n"
|
||||
- "Get the default subvolume of a filesystem."
|
||||
- },
|
||||
{ do_fssync, 1,
|
||||
"filesystem sync", "<path>\n"
|
||||
"Force a sync on the filesystem <path>.",
|
@ -1,3 +1,23 @@
|
||||
-------------------------------------------------------------------
|
||||
Fri Mar 9 16:26:20 UTC 2012 - rschweikert@suse.com
|
||||
|
||||
- place binaries in /usr tree (UsrMerge project)
|
||||
- adjust mkinitrd scrippt accordingly
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Mar 5 13:06:43 CET 2012 - dsterba@suse.cz
|
||||
|
||||
- add btrfsck repair options for:
|
||||
- rebuild extent records
|
||||
- fix block group accounting
|
||||
- reset csums for rescue nodatasum mount
|
||||
- prune corrupt extent allocation tree blocks
|
||||
- device scanning fixes for dm and multipath
|
||||
- initrd support: move btrfs device scan after block device setup
|
||||
- documentation updates
|
||||
- add csize for file commpressed size
|
||||
- updated restore utility
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Feb 13 10:44:43 UTC 2012 - coolo@suse.com
|
||||
|
||||
|
163
btrfsprogs.spec
163
btrfsprogs.spec
@ -28,6 +28,7 @@ Supplements: filesystem(btrfs)
|
||||
# git archive --format=tar --prefix=btrfs-progs-`git describe`/ HEAD > %D/btrfs-progs-`git describe`.tar
|
||||
Source: btrfs-progs-%{tar_version}.tar.bz2
|
||||
Source1: boot-btrfs.sh
|
||||
Source2: btrfs-dev-clear-sb
|
||||
Patch0: memleak-fix.diff
|
||||
Patch1: Plug-Memory-leak-in-find_and_setup_log_root.patch
|
||||
Patch1000: local-version-override.patch
|
||||
@ -46,9 +47,9 @@ Patch109: 0109-helpextract-tool-to-extract-the-info-for-the-help-fr.patch
|
||||
Patch110: 0110-Update-the-makefile-for-generating-the-man-page.patch
|
||||
Patch111: 0111-Show-the-help-messages-from-the-info-in-the-comment.patch
|
||||
Patch112: 0112-Update-the-makefile-for-generating-the-help-messages.patch
|
||||
Patch113: 0113-Btrfs-progs-add-restriper-commands.patch
|
||||
Patch114: 0114-btrfs-progs-add-qgroup-commands.patch
|
||||
Patch115: 0115-btrfs-progs-fixup-is_mounted-checks.patch
|
||||
Patch113: 0113-Btrfs-progs-add-restriper-commands.patch
|
||||
Patch114: 0114-btrfs-progs-Add-ioctl-to-read-compressed-size-of-a-f.patch
|
||||
# + josef's restore utility fixes
|
||||
Patch116: 0116-Btrfs-progs-add-an-option-for-specifying-the-root-to.patch
|
||||
Patch117: 0117-Btrfs-progs-try-other-mirrors-if-decomression-fails.patch
|
||||
@ -69,17 +70,50 @@ Patch131: 0131-Btrfs-progs-don-t-bug-out-if-we-can-t-find-the-last-.patch
|
||||
Patch132: 0132-Btrfs-progs-make-find_and_setup_root-return-an-error.patch
|
||||
Patch133: 0133-Btrfs-progs-check-return-value-properly.patch
|
||||
Patch134: 0134-Btrfs-progs-give-restore-a-list-roots-option.patch
|
||||
Patch139: 0139-Btrfs-progs-make-find-root-spit-out-the-size-of-the-.patch
|
||||
Patch140: 0140-Btrfs-progs-add-some-verbose-output-to-find-root.patch
|
||||
Patch141: 0141-Btrfs-progs-fix-restore-to-actually-use-the-root-loc.patch
|
||||
Patch142: 0142-Btrfs-progs-remove-the-physical-disk-size-check-from.patch
|
||||
Patch143: 0143-Btrfs-progs-fix-error-output-and-dont-read-from-cach.patch
|
||||
Patch144: 0144-Btrfs-progs-print-the-objectid-of-the-root-we-find-w.patch
|
||||
Patch145: 0145-Btrfs-progs-make-specifying-root-objectid-work-if-th.patch
|
||||
Patch146: 0146-Btrfs-progs-don-t-free-the-existing-node.patch
|
||||
Patch147: 0147-mkfs-Handle-creation-of-filesystem-larger-than-the-f.patch
|
||||
Patch150: 0150-btrfs-progs-removed-extraneous-whitespace-from-mkfs-.patch
|
||||
Patch151: 0151-btrfs-progs-document-rootdir-mkfs-switch.patch
|
||||
Patch152: 0152-Add-open_ctree_fs_info-for-partial-FS-opens.patch
|
||||
Patch153: 0153-btrfsck-print-some-progress-Signed-off-by-Chris-Maso.patch
|
||||
Patch154: 0154-Allow-extent_buffers-to-use-more-ram.patch
|
||||
Patch155: 0155-btrfsck-don-t-BUG-on-corrupted-extent-records.patch
|
||||
Patch156: 0156-btrfs-corrupt-block-add-e-option-to-corrupt-the-exte.patch
|
||||
Patch157: 0157-btrfsck-add-code-to-rebuild-extent-records.patch
|
||||
Patch158: 0158-btrfs-corrupt-block-add-E-option-to-randomly-corrupt.patch
|
||||
Patch159: 0159-btrfsck-fix-block-group-accounting-during-repair.patch
|
||||
Patch160: 0160-Turn-off-some-commands-in-Makefile.patch
|
||||
Patch161: 0161-Fix-btrfs-convert-btrfs-restore-and-btrfs-find-root-.patch
|
||||
Patch162: 0162-btrfsck-make-sure-to-dirty-all-block-groups-as-we-fi.patch
|
||||
Patch163: 0163-btrfsck-add-init-csum-tree-to-replace-the-csum-root-.patch
|
||||
Patch164: 0164-btrfsck-make-sure-we-fix-the-block-group-accounting-.patch
|
||||
Patch165: 0165-btrfsck-remove-extents-from-the-fsck-reference-track.patch
|
||||
Patch166: 0166-Btrfsck-add-the-ability-to-prune-corrupt-extent-allo.patch
|
||||
Patch167: 0167-Btrfs-use-proc-partitions-scanning-for-btrfs_scan_fo.patch
|
||||
Patch168: 0168-Scan-dev-md-and-device-mapper-devices-last.patch
|
||||
Patch169: 0169-btrfsck-add-early-code-to-handle-corrupted-block-gro.patch
|
||||
Patch170: 0170-Btrfs-progs-btrfs-map-logical-Fix-typo-in-usage.patch
|
||||
Patch171: 0171-Btrfs-progs-btrfs-corrupt-block-fix-the-wrong-usage.patch
|
||||
Patch172: 0172-Btrfs-progs-fix-btrfsck-s-snapshot-wrong-unresolved-.patch
|
||||
|
||||
# other fixes
|
||||
Patch135: 0135-Btrfs-progs-fix-compiler-warning-of-extent-tree.c.patch
|
||||
Patch136: 0136-Btrfs-progs-change-the-way-mkfs-picks-raid-profiles.patch
|
||||
Patch137: 0137-Btrfs-progs-fail-gracefully-on-error-from-open_ctree.patch
|
||||
Patch138: 0138-Btrfs-progs-bugfix-for-scrubbing-single-devices.patch
|
||||
|
||||
#
|
||||
Patch150: btrfs-progs-fix-open_ctree_usage_segfaults.patch
|
||||
|
||||
# - missing kernel features: qgroups
|
||||
Patch900: 0900-Revert-btrfs-progs-add-qgroup-commands.patch
|
||||
Patch901: 0901-Revert-Btrfs-progs-add-restriper-commands.patch
|
||||
Patch250: btrfs-progs-fix-open_ctree_usage_segfaults.patch
|
||||
Patch251: btrfs-mkfs-update-disclaimer.patch
|
||||
Source252: btrfs-man-update
|
||||
Patch253: btrfs-reorder-commands-help
|
||||
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
BuildRequires: libacl-devel
|
||||
@ -110,9 +144,10 @@ Utilities needed to create and maintain btrfs file systems under Linux.
|
||||
%patch110 -p1
|
||||
%patch111 -p1
|
||||
%patch112 -p1
|
||||
%patch113 -p1
|
||||
%patch114 -p1
|
||||
%patch115 -p1
|
||||
%patch114 -p1
|
||||
%patch113 -p1
|
||||
# josef's tree
|
||||
%patch116 -p1
|
||||
%patch117 -p1
|
||||
%patch118 -p1
|
||||
@ -132,48 +167,100 @@ Utilities needed to create and maintain btrfs file systems under Linux.
|
||||
%patch132 -p1
|
||||
%patch133 -p1
|
||||
%patch134 -p1
|
||||
%patch139 -p1
|
||||
%patch140 -p1
|
||||
%patch141 -p1
|
||||
%patch142 -p1
|
||||
%patch143 -p1
|
||||
%patch144 -p1
|
||||
%patch145 -p1
|
||||
%patch146 -p1
|
||||
%patch147 -p1
|
||||
%patch150 -p1
|
||||
%patch151 -p1
|
||||
# other fixes
|
||||
%patch135 -p1
|
||||
%patch136 -p1
|
||||
%patch137 -p1
|
||||
%patch138 -p1
|
||||
%patch150 -p1
|
||||
%patch900 -p1
|
||||
%patch901 -p1
|
||||
%patch152 -p1
|
||||
%patch153 -p1
|
||||
%patch154 -p1
|
||||
%patch155 -p1
|
||||
%patch156 -p1
|
||||
%patch157 -p1
|
||||
%patch158 -p1
|
||||
%patch159 -p1
|
||||
%patch160 -p1
|
||||
%patch161 -p1
|
||||
%patch162 -p1
|
||||
%patch163 -p1
|
||||
%patch164 -p1
|
||||
%patch165 -p1
|
||||
%patch166 -p1
|
||||
%patch167 -p1
|
||||
%patch168 -p1
|
||||
%patch169 -p1
|
||||
%patch170 -p1
|
||||
%patch171 -p1
|
||||
%patch172 -p1
|
||||
%patch250 -p1
|
||||
%patch251 -p1
|
||||
#%patch252 -p1
|
||||
%patch253 -p1
|
||||
|
||||
%build
|
||||
make %{?_smp_mflags} CFLAGS="%{optflags}" all convert \
|
||||
make %{?_smp_mflags} CFLAGS="%{optflags}" all btrfs-convert \
|
||||
btrfs-zero-log btrfs-select-super btrfs-image btrfstune \
|
||||
restore find-root btrfs-dump-super
|
||||
btrfs-find-root btrfs-restore btrfs-dump-super
|
||||
|
||||
patch -p1 < %{S:252}
|
||||
|
||||
%install
|
||||
make install DESTDIR=${RPM_BUILD_ROOT} prefix=%{_prefix} bindir=/sbin mandir=%{_mandir}
|
||||
install -m 0755 -d ${RPM_BUILD_ROOT}/sbin
|
||||
make install DESTDIR=${RPM_BUILD_ROOT} prefix=%{_prefix} bindir=%{_sbindir} mandir=%{_mandir}
|
||||
install -m 0755 -d ${RPM_BUILD_ROOT}/%{_sbindir}
|
||||
install -m 0755 -d ${RPM_BUILD_ROOT}/%{_bindir}
|
||||
# remove dangerous and unwanted tools
|
||||
rm ${RPM_BUILD_ROOT}/sbin/btrfs-corrupt-block
|
||||
rm ${RPM_BUILD_ROOT}/sbin/calc-size
|
||||
# add btrfs- prefix to generic names
|
||||
mv ${RPM_BUILD_ROOT}/sbin/restore ${RPM_BUILD_ROOT}/sbin/btrfs-restore
|
||||
mv ${RPM_BUILD_ROOT}/sbin/find-root ${RPM_BUILD_ROOT}/sbin/btrfs-find-root
|
||||
# move some utilities out of /sbin
|
||||
mv ${RPM_BUILD_ROOT}/sbin/{btrfs-show,btrfs-vol,btrfsctl} ${RPM_BUILD_ROOT}/%{_bindir}
|
||||
mv ${RPM_BUILD_ROOT}/sbin/{btrfs-map-logical,btrfs-debug-tree} ${RPM_BUILD_ROOT}/%{_bindir}
|
||||
# move some utilities out of /usr/sbin
|
||||
mv ${RPM_BUILD_ROOT}/%{_sbindir}/{btrfs-show,btrfs-vol,btrfsctl} ${RPM_BUILD_ROOT}/%{_bindir}
|
||||
mv ${RPM_BUILD_ROOT}/%{_sbindir}/{btrfs-map-logical,btrfs-debug-tree} ${RPM_BUILD_ROOT}/%{_bindir}
|
||||
# mkinitrd rescue utilities
|
||||
install -m 0755 btrfs-zero-log ${RPM_BUILD_ROOT}/sbin
|
||||
install -m 0755 btrfs-select-super ${RPM_BUILD_ROOT}/sbin
|
||||
install -m 0755 btrfs-image ${RPM_BUILD_ROOT}/sbin
|
||||
install -m 0755 btrfstune ${RPM_BUILD_ROOT}/sbin
|
||||
install -m 0755 btrfs-dump-super ${RPM_BUILD_ROOT}/sbin
|
||||
install -m 0755 btrfs-zero-log ${RPM_BUILD_ROOT}/%{_sbindir}
|
||||
install -m 0755 btrfs-select-super ${RPM_BUILD_ROOT}/%{_sbindir}
|
||||
install -m 0755 btrfs-image ${RPM_BUILD_ROOT}/%{_sbindir}
|
||||
install -m 0755 btrfstune ${RPM_BUILD_ROOT}/%{_sbindir}
|
||||
install -m 0755 btrfs-dump-super ${RPM_BUILD_ROOT}/%{_sbindir}
|
||||
install -m 0755 btrfs-restore ${RPM_BUILD_ROOT}/%{_sbindir}
|
||||
install -m 0755 btrfs-find-root ${RPM_BUILD_ROOT}/%{_sbindir}
|
||||
#UsrMerge
|
||||
install -m 0755 -d ${RPM_BUILD_ROOT}/sbin
|
||||
ln -s %{_sbindir}/btrfs ${RPM_BUILD_ROOT}/sbin
|
||||
ln -s %{_sbindir}/btrfs-zero-log ${RPM_BUILD_ROOT}/sbin
|
||||
ln -s %{_sbindir}/btrfs-convert ${RPM_BUILD_ROOT}/sbin
|
||||
ln -s %{_sbindir}/btrfs-select-super ${RPM_BUILD_ROOT}/sbin
|
||||
ln -s %{_sbindir}/btrfs-image ${RPM_BUILD_ROOT}/sbin
|
||||
ln -s %{_sbindir}/btrfstune ${RPM_BUILD_ROOT}/sbin
|
||||
ln -s %{_sbindir}/btrfsck ${RPM_BUILD_ROOT}/sbin
|
||||
ln -s %{_sbindir}/btrfs-restore ${RPM_BUILD_ROOT}/sbin
|
||||
ln -s %{_sbindir}/btrfs-find-root ${RPM_BUILD_ROOT}/sbin
|
||||
ln -s %{_sbindir}/btrfs-dump-super ${RPM_BUILD_ROOT}/sbin
|
||||
ln -s %{_sbindir}/mkfs.btrfs ${RPM_BUILD_ROOT}/sbin
|
||||
#EndUsrMerge
|
||||
# command line options are not compatible (bnc#599224)
|
||||
# copy needed if /bin is different fs from /sbin
|
||||
cp /bin/true ${RPM_BUILD_ROOT}/sbin/fsck.btrfs
|
||||
cp %{_bindir}/true ${RPM_BUILD_ROOT}/%{_sbindir}/fsck.btrfs
|
||||
#UsrMerge
|
||||
ln -s %{_sbindir}/fsck.btrfs ${RPM_BUILD_ROOT}/sbin
|
||||
#EndUsrMerge
|
||||
install -d -m0755 ${RPM_BUILD_ROOT}/lib/mkinitrd/scripts/
|
||||
cp %{S:1} ${RPM_BUILD_ROOT}/lib/mkinitrd/scripts/
|
||||
install -m 0755 %{S:1} ${RPM_BUILD_ROOT}/lib/mkinitrd/scripts/
|
||||
install -m 0755 %{S:2} ${RPM_BUILD_ROOT}/usr/sbin/
|
||||
|
||||
%files
|
||||
%defattr(-, root, root)
|
||||
/sbin/fsck.btrfs
|
||||
# mkinitrd utils
|
||||
#UsrMerge
|
||||
/sbin/btrfs
|
||||
/sbin/btrfs-zero-log
|
||||
/sbin/btrfs-convert
|
||||
@ -185,6 +272,20 @@ cp %{S:1} ${RPM_BUILD_ROOT}/lib/mkinitrd/scripts/
|
||||
/sbin/btrfs-find-root
|
||||
/sbin/btrfs-dump-super
|
||||
/sbin/mkfs.btrfs
|
||||
#EndUsrMerge
|
||||
%{_sbindir}/btrfs
|
||||
%{_sbindir}/btrfs-zero-log
|
||||
%{_sbindir}/btrfs-convert
|
||||
%{_sbindir}/btrfs-select-super
|
||||
%{_sbindir}/btrfs-image
|
||||
%{_sbindir}/btrfstune
|
||||
%{_sbindir}/btrfsck
|
||||
%{_sbindir}/btrfs-restore
|
||||
%{_sbindir}/btrfs-find-root
|
||||
%{_sbindir}/btrfs-dump-super
|
||||
%{_sbindir}/fsck.btrfs
|
||||
%{_sbindir}/mkfs.btrfs
|
||||
/usr/sbin/btrfs-dev-clear-sb
|
||||
/lib/mkinitrd/scripts/boot-btrfs.sh
|
||||
# other
|
||||
/usr/bin/btrfs-map-logical
|
||||
|
@ -1,7 +1,7 @@
|
||||
Index: btrfs-progs-v0.19-35-g1b444cd/version.sh
|
||||
Index: btrfs-progs-v0.19-116-g13eced9/version.sh
|
||||
===================================================================
|
||||
--- btrfs-progs-v0.19-35-g1b444cd.orig/version.sh
|
||||
+++ btrfs-progs-v0.19-35-g1b444cd/version.sh
|
||||
--- btrfs-progs-v0.19-116-g13eced9.orig/version.sh
|
||||
+++ btrfs-progs-v0.19-116-g13eced9/version.sh
|
||||
@@ -6,7 +6,7 @@
|
||||
# Copyright 2008, Oracle
|
||||
# Released under the GNU GPLv2
|
||||
|
Loading…
Reference in New Issue
Block a user