Accepting request 184455 from filesystems
- Simplify checks in mkinitrd scripts. They are always true because they come from the same package Use relative paths to binaries - Move udev rules to /usr. - Adjust rules to call binary from /usr - Simplify fsck.btrfs, its just a dummy until fixed - update to upstream master (f00dd8386a57d241d0f7c) OBS-URL: https://build.opensuse.org/request/show/184455 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/btrfsprogs?expand=0&rev=30
This commit is contained in:
commit
ef5b405e60
@ -0,0 +1,33 @@
|
|||||||
|
From 5ca1ded494d7d58b71877bf1f774ac313fabe35f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Date: Thu, 2 May 2013 11:20:22 -0500
|
||||||
|
Subject: [PATCH 10/48] Btrfs-progs: make btrfsck a hardlink at install time
|
||||||
|
|
||||||
|
btrfsck gets hardlinked to btrfs during the build, but the
|
||||||
|
install phase simply copies them both to the destination without
|
||||||
|
preserving the link.
|
||||||
|
|
||||||
|
Just force-link btrfsck in the destination again during install
|
||||||
|
so that the installed btrfsck is a link as well.
|
||||||
|
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
---
|
||||||
|
Makefile | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index da7438e..0f0b1ac 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -193,6 +193,8 @@ clean :
|
||||||
|
install: $(libs) $(progs) install-man
|
||||||
|
$(INSTALL) -m755 -d $(DESTDIR)$(bindir)
|
||||||
|
$(INSTALL) $(progs) $(DESTDIR)$(bindir)
|
||||||
|
+ # btrfsck is a link to btrfs in the src tree, make it so for installed file as well
|
||||||
|
+ $(LN) -f $(DESTDIR)$(bindir)/btrfs $(DESTDIR)$(bindir)/btrfsck
|
||||||
|
$(INSTALL) -m755 -d $(DESTDIR)$(libdir)
|
||||||
|
$(INSTALL) $(libs) $(DESTDIR)$(libdir)
|
||||||
|
cp -a $(lib_links) $(DESTDIR)$(libdir)
|
||||||
|
--
|
||||||
|
1.8.2
|
||||||
|
|
@ -0,0 +1,27 @@
|
|||||||
|
From 86f2f0e7742ccbfaf62e2d6415bf170a85c71c0e Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
||||||
|
Date: Sun, 12 May 2013 16:33:44 +0100
|
||||||
|
Subject: [PATCH 12/48] libbtrfs: Set SONAME to "libbtrfs.so.0" (instead of
|
||||||
|
"libbtrfs.so").
|
||||||
|
|
||||||
|
Signed-off-by: Richard W.M. Jones <rjones@redhat.com>
|
||||||
|
---
|
||||||
|
Makefile | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 0f0b1ac..7a49174 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -100,7 +100,7 @@ version.h:
|
||||||
|
$(libs_shared): $(libbtrfs_objects) $(lib_links) send.h
|
||||||
|
@echo " [LD] $@"
|
||||||
|
$(Q)$(CC) $(CFLAGS) $(libbtrfs_objects) $(LDFLAGS) $(lib_LIBS) \
|
||||||
|
- -shared -Wl,-soname,libbtrfs.so -o libbtrfs.so.0.1
|
||||||
|
+ -shared -Wl,-soname,libbtrfs.so.0 -o libbtrfs.so.0.1
|
||||||
|
|
||||||
|
$(libs_static): $(libbtrfs_objects)
|
||||||
|
@echo " [AR] $@"
|
||||||
|
--
|
||||||
|
1.8.2
|
||||||
|
|
@ -1,37 +0,0 @@
|
|||||||
From a6aa706ee793b406761baeaa7cde78d1250f2d2b Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Sterba <dsterba@suse.cz>
|
|
||||||
Date: Wed, 12 Oct 2011 13:36:13 +0200
|
|
||||||
Subject: [PATCH 01/35] btrfs-progs: ignore -a option in mkfs
|
|
||||||
|
|
||||||
Let mkfs accept '-a' option and not complain. When a partition has non-zero
|
|
||||||
value in the fs_passno filed in /etc/fstab, the fsck is run but fails and boot
|
|
||||||
stops. As fsck does not break things currently, it's safe to ignore the option
|
|
||||||
and let the boot proceed.
|
|
||||||
|
|
||||||
Reference: https://bugzilla.novell.com/show_bug.cgi?id=655906
|
|
||||||
|
|
||||||
Signed-off-by: David Sterba <dsterba@suse.cz>
|
|
||||||
---
|
|
||||||
btrfsck.c | 3 ++-
|
|
||||||
1 files changed, 2 insertions(+), 1 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfsck.c b/btrfsck.c
|
|
||||||
index 3a23e66..509ab72 100644
|
|
||||||
--- a/btrfsck.c
|
|
||||||
+++ b/btrfsck.c
|
|
||||||
@@ -2815,10 +2815,11 @@ int main(int ac, char **av)
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
int c;
|
|
||||||
- c = getopt(ac, av, "s:");
|
|
||||||
+ c = getopt(ac, av, "as:");
|
|
||||||
if (c < 0)
|
|
||||||
break;
|
|
||||||
switch(c) {
|
|
||||||
+ case 'a': /* ignored */ break;
|
|
||||||
case 's':
|
|
||||||
num = atol(optarg);
|
|
||||||
bytenr = btrfs_sb_offset(num);
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,108 +0,0 @@
|
|||||||
From 8456dc84b0c7548ca4f83c4e58e8e9dd443b7686 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Goffredo Baroncelli <kreijack@inwind.it>
|
|
||||||
Date: Mon, 3 Jan 2011 19:51:46 +0100
|
|
||||||
Subject: [PATCH 03/35] Add the --force option.
|
|
||||||
|
|
||||||
Add the --force option to not check if a device is already mounted.
|
|
||||||
---
|
|
||||||
mkfs.c | 46 ++++++++++++++++++++++++++++------------------
|
|
||||||
1 files changed, 28 insertions(+), 18 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/mkfs.c b/mkfs.c
|
|
||||||
index e3ced19..be236d0 100644
|
|
||||||
--- a/mkfs.c
|
|
||||||
+++ b/mkfs.c
|
|
||||||
@@ -303,6 +303,7 @@ static void print_usage(void)
|
|
||||||
fprintf(stderr, "\t -A --alloc-start the offset to start the FS\n");
|
|
||||||
fprintf(stderr, "\t -b --byte-count total number of bytes in the FS\n");
|
|
||||||
fprintf(stderr, "\t -d --data data profile, raid0, raid1, raid10 or single\n");
|
|
||||||
+ fprintf(stderr, "\t -f --force don't check if a device is already mounted\n");
|
|
||||||
fprintf(stderr, "\t -l --leafsize size of btree leaves\n");
|
|
||||||
fprintf(stderr, "\t -L --label set a label\n");
|
|
||||||
fprintf(stderr, "\t -m --metadata metadata profile, values like data profile\n");
|
|
||||||
@@ -368,6 +369,7 @@ static struct option long_options[] = {
|
|
||||||
{ "data", 1, NULL, 'd' },
|
|
||||||
{ "version", 0, NULL, 'V' },
|
|
||||||
{ "rootdir", 1, NULL, 'r' },
|
|
||||||
+ { "force", 0, NULL, 'f' },
|
|
||||||
{ 0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1191,10 +1193,11 @@ int main(int ac, char **av)
|
|
||||||
u64 size_of_data = 0;
|
|
||||||
u64 source_dir_size = 0;
|
|
||||||
char *pretty_buf;
|
|
||||||
+ int force=0;
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
int c;
|
|
||||||
- c = getopt_long(ac, av, "A:b:l:n:s:m:d:L:r:VM", long_options,
|
|
||||||
+ c = getopt_long(ac, av, "A:b:l:n:s:m:d:L:r:VMf", long_options,
|
|
||||||
&option_index);
|
|
||||||
if (c < 0)
|
|
||||||
break;
|
|
||||||
@@ -1240,6 +1243,8 @@ int main(int ac, char **av)
|
|
||||||
case 'r':
|
|
||||||
source_dir = optarg;
|
|
||||||
source_dir_set = 1;
|
|
||||||
+ case 'f':
|
|
||||||
+ force=1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
print_usage();
|
|
||||||
@@ -1263,14 +1268,17 @@ int main(int ac, char **av)
|
|
||||||
|
|
||||||
if (source_dir == 0) {
|
|
||||||
file = av[optind++];
|
|
||||||
- ret = check_mounted(file);
|
|
||||||
- if (ret < 0) {
|
|
||||||
- fprintf(stderr, "error checking %s mount status\n", file);
|
|
||||||
- exit(1);
|
|
||||||
- }
|
|
||||||
- if (ret == 1) {
|
|
||||||
- fprintf(stderr, "%s is mounted\n", file);
|
|
||||||
- exit(1);
|
|
||||||
+ if(!force){
|
|
||||||
+ ret = check_mounted(file);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ fprintf(stderr,
|
|
||||||
+ "error checking %s mount status\n", file);
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
+ if (ret == 1) {
|
|
||||||
+ fprintf(stderr, "%s is mounted\n", file);
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
ac--;
|
|
||||||
fd = open(file, O_RDWR);
|
|
||||||
@@ -1353,15 +1361,17 @@ int main(int ac, char **av)
|
|
||||||
int old_mixed = mixed;
|
|
||||||
|
|
||||||
file = av[optind++];
|
|
||||||
- ret = check_mounted(file);
|
|
||||||
- if (ret < 0) {
|
|
||||||
- fprintf(stderr, "error checking %s mount status\n",
|
|
||||||
- file);
|
|
||||||
- exit(1);
|
|
||||||
- }
|
|
||||||
- if (ret == 1) {
|
|
||||||
- fprintf(stderr, "%s is mounted\n", file);
|
|
||||||
- exit(1);
|
|
||||||
+ if(!force){
|
|
||||||
+ ret = check_mounted(file);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ fprintf(stderr, "error checking %s"
|
|
||||||
+ " mount status\n",file);
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
+ if (ret == 1) {
|
|
||||||
+ fprintf(stderr, "%s is mounted\n", file);
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
fd = open(file, O_RDWR);
|
|
||||||
if (fd < 0) {
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
|||||||
From fdd55a58d661cede927b741e57abc4f564bb7bd6 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Goffredo Baroncelli <kreijack@inwind.it>
|
|
||||||
Date: Mon, 3 Jan 2011 19:53:05 +0100
|
|
||||||
Subject: [PATCH 04/35] mkfs.btrfs man page: document the --force option.
|
|
||||||
|
|
||||||
Add the --force option to not check if a device is already mounted.
|
|
||||||
---
|
|
||||||
man/mkfs.btrfs.8.in | 4 ++++
|
|
||||||
1 files changed, 4 insertions(+), 0 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/man/mkfs.btrfs.8.in b/man/mkfs.btrfs.8.in
|
|
||||||
index 432db1b..2610e9d 100644
|
|
||||||
--- a/man/mkfs.btrfs.8.in
|
|
||||||
+++ b/man/mkfs.btrfs.8.in
|
|
||||||
@@ -6,6 +6,7 @@ mkfs.btrfs \- create an btrfs filesystem
|
|
||||||
[ \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 ]
|
|
||||||
@@ -35,6 +36,9 @@ mkfs.btrfs uses all the available storage for the filesystem.
|
|
||||||
Specify how the data must be spanned across the devices specified. Valid
|
|
||||||
values are raid0, raid1, raid10 or single.
|
|
||||||
.TP
|
|
||||||
+\fB\-f\fR, \fB\-\-force \fR
|
|
||||||
+Don't check if the device is already mounted.
|
|
||||||
+.TP
|
|
||||||
\fB\-l\fR, \fB\-\-leafsize \fIsize\fR
|
|
||||||
Specify the leaf size, the least data item in which btrfs stores data. The
|
|
||||||
default value is the page size.
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
|||||||
From da911929cf232b81a4e2dcffbb26dc3cc6f222af Mon Sep 17 00:00:00 2001
|
|
||||||
From: Goffredo Baroncelli <kreijack@inwind.it>
|
|
||||||
Date: Fri, 21 Oct 2011 19:00:28 +0200
|
|
||||||
Subject: [PATCH 05/35] Ignore the error ENXIO and ENOMEDIUM during a devs
|
|
||||||
scan
|
|
||||||
|
|
||||||
Ignore the error ENXIO (device don't exists) and ENOMEDIUM (
|
|
||||||
No medium found -> like a cd tray empty) in the function
|
|
||||||
btrfs_scan_one_dir.
|
|
||||||
This avoids spurios errors due to an empty CD or a block device node
|
|
||||||
without a device (which is frequent in a static /dev).
|
|
||||||
|
|
||||||
|
|
||||||
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
|
|
||||||
---
|
|
||||||
utils.c | 10 ++++++++--
|
|
||||||
1 files changed, 8 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/utils.c b/utils.c
|
|
||||||
index 178d1b9..1c27e14 100644
|
|
||||||
--- a/utils.c
|
|
||||||
+++ b/utils.c
|
|
||||||
@@ -1003,8 +1003,14 @@ again:
|
|
||||||
}
|
|
||||||
fd = open(fullpath, O_RDONLY);
|
|
||||||
if (fd < 0) {
|
|
||||||
- fprintf(stderr, "failed to read %s: %s\n", fullpath,
|
|
||||||
- strerror(errno));
|
|
||||||
+ /* ignore the following errors:
|
|
||||||
+ ENXIO (device don't exists)
|
|
||||||
+ ENOMEDIUM (No medium found ->
|
|
||||||
+ like a cd tray empty)
|
|
||||||
+ */
|
|
||||||
+ if(errno != ENXIO && errno != ENOMEDIUM)
|
|
||||||
+ fprintf(stderr, "failed to read %s: %s\n",
|
|
||||||
+ fullpath, strerror(errno));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ret = btrfs_scan_one_device(fd, fullpath, &tmp_devices,
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,275 +0,0 @@
|
|||||||
From 8ed24be618165f2f76851e007347408ab9013d30 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Hugo Mills <hugo@carfax.org.uk>
|
|
||||||
Date: Thu, 27 Oct 2011 22:14:26 +0100
|
|
||||||
Subject: [PATCH 06/35] Regression tests
|
|
||||||
|
|
||||||
Add a shell-script based test harness for performing regression tests
|
|
||||||
on btrfs tools. This is not intended as a test system for kernel
|
|
||||||
issues, but instead to put the userspace tools through their paces.
|
|
||||||
|
|
||||||
Currently implemented tests are compilation of all tools, and checking
|
|
||||||
argument counting on "btrfs sub snap". Other tests will follow.
|
|
||||||
|
|
||||||
Signed-off-by: Hugo Mills <hugo@carfax.org.uk>
|
|
||||||
---
|
|
||||||
Makefile | 8 +++
|
|
||||||
test/001u.sh | 23 ++++++++++
|
|
||||||
test/002s.sh | 42 +++++++++++++++++
|
|
||||||
test/functions.sh | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
test/run-tests | 13 +++++
|
|
||||||
5 files changed, 214 insertions(+), 0 deletions(-)
|
|
||||||
create mode 100755 test/001u.sh
|
|
||||||
create mode 100755 test/002s.sh
|
|
||||||
create mode 100644 test/functions.sh
|
|
||||||
create mode 100755 test/run-tests
|
|
||||||
|
|
||||||
diff --git a/Makefile b/Makefile
|
|
||||||
index 7a5e2c1..5f25d66 100644
|
|
||||||
--- a/Makefile
|
|
||||||
+++ b/Makefile
|
|
||||||
@@ -113,4 +113,12 @@ install: $(progs) install-man
|
|
||||||
$(INSTALL) $(progs) $(DESTDIR)$(bindir)
|
|
||||||
if [ -e btrfs-convert ]; then $(INSTALL) btrfs-convert $(DESTDIR)$(bindir); fi
|
|
||||||
|
|
||||||
+test: test-userspace test-root
|
|
||||||
+
|
|
||||||
+test-userspace:
|
|
||||||
+ ./test/run-tests
|
|
||||||
+
|
|
||||||
+test-root:
|
|
||||||
+ sudo ./test/run-tests
|
|
||||||
+
|
|
||||||
-include .*.d
|
|
||||||
diff --git a/test/001u.sh b/test/001u.sh
|
|
||||||
new file mode 100755
|
|
||||||
index 0000000..d2cadff
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/test/001u.sh
|
|
||||||
@@ -0,0 +1,23 @@
|
|
||||||
+#!/bin/bash
|
|
||||||
+
|
|
||||||
+. test/functions.sh
|
|
||||||
+
|
|
||||||
+unset BTRFS_TESTS_VOLUMES
|
|
||||||
+
|
|
||||||
+announce compilation
|
|
||||||
+
|
|
||||||
+export CC=gcc-4.6
|
|
||||||
+catchclean
|
|
||||||
+make clean >/dev/null 2>&1
|
|
||||||
+
|
|
||||||
+catch make || fail Plain make failed
|
|
||||||
+#catch make dir-test || fail Failed to make dir-test
|
|
||||||
+catch make btrfs-zero-log || fail Failed to make btrfs-zero-log
|
|
||||||
+catch make btrfs-select-super || fail Failed to make btrfs-select-super
|
|
||||||
+catch make btrfstune || fail Failed to make btrfstune
|
|
||||||
+catch make btrfs-image || fail Failed to make btrfsimage
|
|
||||||
+catch make quick-test || fail Failed to make quick-test
|
|
||||||
+catch make convert || fail Failed to make btrfs-convert
|
|
||||||
+catch make ioctl-test || fail Failed to make ioctl-test
|
|
||||||
+
|
|
||||||
+summarise
|
|
||||||
diff --git a/test/002s.sh b/test/002s.sh
|
|
||||||
new file mode 100755
|
|
||||||
index 0000000..2c715b7
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/test/002s.sh
|
|
||||||
@@ -0,0 +1,42 @@
|
|
||||||
+#!/bin/bash
|
|
||||||
+
|
|
||||||
+. test/functions.sh
|
|
||||||
+
|
|
||||||
+MNT=./test-mountpoint
|
|
||||||
+
|
|
||||||
+function setup() {
|
|
||||||
+ setup_mkfs btrfs-tests $MNT
|
|
||||||
+
|
|
||||||
+ ./btrfs subvolume create $MNT/source >/dev/null || return 1
|
|
||||||
+ dd if=/dev/urandom of=$MNT/source/file1 \
|
|
||||||
+ bs=1M count=1 >/dev/null 2>&1 || return 1
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+function teardown() {
|
|
||||||
+ teardown_rmfs $MNT
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+announce snapshot
|
|
||||||
+catchclean
|
|
||||||
+
|
|
||||||
+function test_ro() {
|
|
||||||
+ ./btrfs subvolume snapshot -r $MNT/source $MNT/destination
|
|
||||||
+ echo foo >$MNT/destination/foo.txt
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+# Success modes
|
|
||||||
+catch ./btrfs subvolume snapshot $MNT/source $MNT/destination \
|
|
||||||
+ || fail Failed to create rw snapshot
|
|
||||||
+catch ./btrfs subvolume snapshot -r $MNT/source $MNT/destination \
|
|
||||||
+ || fail Failed to create ro snapshot
|
|
||||||
+catch test_ro && fail Failed to use read-only flag
|
|
||||||
+
|
|
||||||
+# Failure modes
|
|
||||||
+catch ./btrfs subvolume snapshot \
|
|
||||||
+ && fail Accepted incorrect parameters \(0 params\)
|
|
||||||
+catch ./btrfs subvolume snapshot $MNT/source \
|
|
||||||
+ && fail Accepted incorrect parameters \(1 param\)
|
|
||||||
+catch ./btrfs subvolume snapshot -r $MNT/source \
|
|
||||||
+ && fail Accepted incorrect parameters \(1 param, ro\)
|
|
||||||
+
|
|
||||||
+summarise
|
|
||||||
diff --git a/test/functions.sh b/test/functions.sh
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..ca89c67
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/test/functions.sh
|
|
||||||
@@ -0,0 +1,128 @@
|
|
||||||
+BTRFS_TESTS_VOLUMES="test1.img test2.img test3.img test4.img"
|
|
||||||
+TESTS_RUN=0
|
|
||||||
+TESTS_SUCCEEDED=0
|
|
||||||
+
|
|
||||||
+if [ -f .tests.conf ]; then
|
|
||||||
+ . .tests.conf
|
|
||||||
+fi
|
|
||||||
+
|
|
||||||
+function announce()
|
|
||||||
+{
|
|
||||||
+ echo --- $(basename $0) --- Testing "$@"
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+function summarise()
|
|
||||||
+{
|
|
||||||
+ echo === ${TESTS_RUN} tests run
|
|
||||||
+ echo === ${TESTS_SUCCEEDED} successes
|
|
||||||
+ echo === $((${TESTS_RUN}-${TESTS_SUCCEEDED})) failures
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+function catchclean()
|
|
||||||
+{
|
|
||||||
+ export SUITE=$(basename "$0" .sh)
|
|
||||||
+ rm -f ${SUITE}.out ${SUITE}.err
|
|
||||||
+ touch ${SUITE}.out ${SUITE}.err
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+# Internal function: set up/check the test volumes as requested
|
|
||||||
+function local_setup()
|
|
||||||
+{
|
|
||||||
+ # Set up for this test
|
|
||||||
+ VOLUMES=
|
|
||||||
+ for vol in $BTRFS_TESTS_VOLUMES; do
|
|
||||||
+ if [ ! -e $vol ]; then
|
|
||||||
+ dd if=/dev/zero of=$vol count=0 seek=4G bs=1 >/dev/null 2>&1 || return 1
|
|
||||||
+ fi
|
|
||||||
+ if [ -f $vol ]; then
|
|
||||||
+ vol=$(losetup -f --show $vol) || return 1
|
|
||||||
+ VOLUMES="$VOLUMES $vol"
|
|
||||||
+ elif [ -b $vol ]; then
|
|
||||||
+ VOLUMES="$VOLUMES $vol"
|
|
||||||
+ else
|
|
||||||
+ echo Don\'t know what to do with $vol
|
|
||||||
+ fi
|
|
||||||
+ done
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+# Internal function: destroy test volumes if we created them
|
|
||||||
+function local_teardown()
|
|
||||||
+{
|
|
||||||
+ for vol in $VOLUMES; do
|
|
||||||
+ if [ -b $vol ]; then
|
|
||||||
+ if losetup $vol >/dev/null 2>&1; then
|
|
||||||
+ file=$(losetup $vol | sed -e 's/^.* (\(.*\)).*$/\1/')
|
|
||||||
+ losetup -d $vol
|
|
||||||
+ rm $file
|
|
||||||
+ fi
|
|
||||||
+ fi
|
|
||||||
+ done
|
|
||||||
+ return 0
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+trap local_teardown EXIT
|
|
||||||
+
|
|
||||||
+function catch()
|
|
||||||
+{
|
|
||||||
+ TESTS_RUN=$((${TESTS_RUN}+1))
|
|
||||||
+
|
|
||||||
+ local_setup
|
|
||||||
+ if ! setup; then
|
|
||||||
+ teardown
|
|
||||||
+ local_teardown
|
|
||||||
+ return 1
|
|
||||||
+ fi
|
|
||||||
+
|
|
||||||
+ # Preemptively increase the success count: if we call fail, we'll
|
|
||||||
+ # decrease it again
|
|
||||||
+ TESTS_SUCCEEDED=$((${TESTS_SUCCEEDED}+1))
|
|
||||||
+
|
|
||||||
+ "$@" >>${SUITE}.out 2>>${SUITE}.err
|
|
||||||
+ rv=$?
|
|
||||||
+
|
|
||||||
+ # Undo any setup we did earlier
|
|
||||||
+ teardown
|
|
||||||
+ local_teardown
|
|
||||||
+
|
|
||||||
+ return ${rv}
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+function fail()
|
|
||||||
+{
|
|
||||||
+ echo "$@"
|
|
||||||
+ TESTS_SUCCEEDED=$((${TESTS_SUCCEEDED}-1))
|
|
||||||
+ summarise
|
|
||||||
+ exit 1
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+function setup()
|
|
||||||
+{
|
|
||||||
+ echo -n
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+function teardown()
|
|
||||||
+{
|
|
||||||
+ echo -n
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+function setup_mkfs()
|
|
||||||
+{
|
|
||||||
+ LABEL=$1
|
|
||||||
+ MNT=$2
|
|
||||||
+
|
|
||||||
+ mkdir -p $MNT
|
|
||||||
+ ./mkfs.btrfs -L $LABEL $VOLUMES >/dev/null || return 1
|
|
||||||
+ mount LABEL=$LABEL $MNT || return 1
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+function teardown_rmfs()
|
|
||||||
+{
|
|
||||||
+ MNT=$1
|
|
||||||
+
|
|
||||||
+ sleeptime=1
|
|
||||||
+ while ! umount $MNT 2>/dev/null; do
|
|
||||||
+ sleep ${sleeptime}
|
|
||||||
+ sleeptime=$((${sleeptime}+2))
|
|
||||||
+ done
|
|
||||||
+ rmdir $MNT
|
|
||||||
+}
|
|
||||||
diff --git a/test/run-tests b/test/run-tests
|
|
||||||
new file mode 100755
|
|
||||||
index 0000000..981fc22
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/test/run-tests
|
|
||||||
@@ -0,0 +1,13 @@
|
|
||||||
+#!/bin/bash
|
|
||||||
+
|
|
||||||
+testdir=$(dirname $0)
|
|
||||||
+
|
|
||||||
+if [ $UID -eq 0 ]; then
|
|
||||||
+ type=s
|
|
||||||
+else
|
|
||||||
+ type=u
|
|
||||||
+fi
|
|
||||||
+
|
|
||||||
+for test in ${testdir}/[0-9][0-9][0-9]${type}.sh; do
|
|
||||||
+ ${test}
|
|
||||||
+done
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
|||||||
From 33be6f1695e8bd450be2e22fbf88b826488186a1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Hugo Mills <hugo@carfax.org.uk>
|
|
||||||
Date: Sun, 30 Oct 2011 20:17:07 +0000
|
|
||||||
Subject: [PATCH 07/35] Fix sub snap parameter handling
|
|
||||||
|
|
||||||
btrfs sub snap uses a local copy of optind, which causes the number of
|
|
||||||
parameters to be miscounted, preventing it from working properly. This
|
|
||||||
patch, originally from Arne Jansen <sensille@gmx.net>, fixes it.
|
|
||||||
|
|
||||||
Signed-off-by: Hugo Mills <hugo@carfax.org.uk>
|
|
||||||
---
|
|
||||||
btrfs_cmds.c | 23 ++++++++++++-----------
|
|
||||||
1 files changed, 12 insertions(+), 11 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
|
|
||||||
index b59e9cb..9252ffa 100644
|
|
||||||
--- a/btrfs_cmds.c
|
|
||||||
+++ b/btrfs_cmds.c
|
|
||||||
@@ -304,7 +304,8 @@ int do_subvol_list(int argc, char **argv)
|
|
||||||
int ret;
|
|
||||||
int print_parent = 0;
|
|
||||||
char *subvol;
|
|
||||||
- int optind = 1;
|
|
||||||
+
|
|
||||||
+ optind = 1;
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
int c = getopt(argc, argv, "p");
|
|
||||||
@@ -312,7 +313,6 @@ int do_subvol_list(int argc, char **argv)
|
|
||||||
switch(c) {
|
|
||||||
case 'p':
|
|
||||||
print_parent = 1;
|
|
||||||
- optind++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -347,11 +347,13 @@ int do_subvol_list(int argc, char **argv)
|
|
||||||
|
|
||||||
int do_clone(int argc, char **argv)
|
|
||||||
{
|
|
||||||
- char *subvol, *dst;
|
|
||||||
- int res, fd, fddst, len, e, optind = 0, readonly = 0;
|
|
||||||
- char *newname;
|
|
||||||
- char *dstdir;
|
|
||||||
- struct btrfs_ioctl_vol_args_v2 args;
|
|
||||||
+ char *subvol, *dst;
|
|
||||||
+ int res, fd, fddst, len, e, readonly = 0;
|
|
||||||
+ char *newname;
|
|
||||||
+ char *dstdir;
|
|
||||||
+ struct btrfs_ioctl_vol_args_v2 args;
|
|
||||||
+
|
|
||||||
+ optind = 1;
|
|
||||||
|
|
||||||
memset(&args, 0, sizeof(args));
|
|
||||||
|
|
||||||
@@ -362,7 +364,6 @@ int do_clone(int argc, char **argv)
|
|
||||||
break;
|
|
||||||
switch (c) {
|
|
||||||
case 'r':
|
|
||||||
- optind++;
|
|
||||||
readonly = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
@@ -372,14 +373,14 @@ int do_clone(int argc, char **argv)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- if (argc - optind != 3) {
|
|
||||||
+ if (argc - optind != 2) {
|
|
||||||
fprintf(stderr, "Invalid arguments for subvolume snapshot\n");
|
|
||||||
free(argv);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
- subvol = argv[optind+1];
|
|
||||||
- dst = argv[optind+2];
|
|
||||||
+ subvol = argv[optind];
|
|
||||||
+ dst = argv[optind+1];
|
|
||||||
|
|
||||||
res = test_issubvolume(subvol);
|
|
||||||
if(res<0){
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,474 +0,0 @@
|
|||||||
From 18254b66cf6ff7c9eff605ac7de9b4947d39a96f Mon Sep 17 00:00:00 2001
|
|
||||||
From: Goffredo Baroncelli <kreijack@inwind.it>
|
|
||||||
Date: Sat, 16 Jul 2011 11:35:39 +0200
|
|
||||||
Subject: [PATCH 08/35] Add info for the commands.
|
|
||||||
|
|
||||||
Add info for every btrfs sub-commands in the sources.
|
|
||||||
---
|
|
||||||
btrfs_cmds.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
scrub.c | 79 +++++++++++++++++++
|
|
||||||
2 files changed, 316 insertions(+), 0 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
|
|
||||||
index 9252ffa..1bfc669 100644
|
|
||||||
--- a/btrfs_cmds.c
|
|
||||||
+++ b/btrfs_cmds.c
|
|
||||||
@@ -28,6 +28,7 @@
|
|
||||||
#include <limits.h>
|
|
||||||
#include <uuid/uuid.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
+#include <getopt.h>
|
|
||||||
|
|
||||||
#undef ULONG_MAX
|
|
||||||
|
|
||||||
@@ -155,6 +156,42 @@ static int parse_compress_type(char *s)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+/**** man: btrfs filesystem defragment
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bfilesystem defragment\b -c[zlib|lzo] [-l \Ilen\i] [-s \Istart\i] [-t \Isize\i] -[vf] <\Ifile\i>|<\Idir\i> [<\Ifile\i>|<\Idir\i>...]
|
|
||||||
+ *
|
|
||||||
+ * Defragment a file or a directory.
|
|
||||||
+ *
|
|
||||||
+ * Defragment file data and/or directory metadata. To defragment all files in a
|
|
||||||
+ * directory you have to specify each one on its own or use your shell
|
|
||||||
+ * wildcards.
|
|
||||||
+ *
|
|
||||||
+ * The start position and the number of bytes to deframention can be specified
|
|
||||||
+ * by \Istart\i and \Ilen\i. Any extent bigger than \Ithresh\i will be
|
|
||||||
+ * considered already defragged. Use 0 to take the kernel default, and use 1
|
|
||||||
+ * to say eveery single extent must be rewritten. You can also turn on
|
|
||||||
+ * compression in defragment operations.
|
|
||||||
+ *
|
|
||||||
+ * \B-v\b be verbose
|
|
||||||
+ *
|
|
||||||
+ * \B-c\b compress file contents while defragmenting
|
|
||||||
+ *
|
|
||||||
+ * \B-f\b flush filesystem after defragmenting
|
|
||||||
+ *
|
|
||||||
+ * \B-s start\b defragment only from byte \Istart\i onward
|
|
||||||
+ *
|
|
||||||
+ * \B-l len\b defragment only up to \Ilen\i bytes
|
|
||||||
+ *
|
|
||||||
+ * \B-t size\b defragment only files at least \Isize\i bytes big
|
|
||||||
+ *
|
|
||||||
+ * NOTE: defragmenting with kernels up to 2.6.37 will unlink COW-ed copies of
|
|
||||||
+ * data, don't use it if you use snapshots, have de-duplicated your data or
|
|
||||||
+ * made copies with
|
|
||||||
+ *
|
|
||||||
+ * \Bcp --reflink\b.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_defrag(int ac, char **av)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
@@ -267,6 +304,16 @@ int do_defrag(int ac, char **av)
|
|
||||||
return errors + 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+/**** man: btrfs subvolume find-new
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bsubvolume find-new\b\I <subvolume> <last_gen>\i
|
|
||||||
+ *
|
|
||||||
+ * List the recently modified files in a filesystem.
|
|
||||||
+ *
|
|
||||||
+ * List the recently modified files in a subvolume, after \I<last_gen>\i ID.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_find_newer(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
@@ -298,6 +345,25 @@ int do_find_newer(int argc, char **argv)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+/**** man: btrfs subvolume list
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bsubvolume list\b\I [-p] <path>\i
|
|
||||||
+ *
|
|
||||||
+ * List the snapshot/subvolume of a filesystem.
|
|
||||||
+ *
|
|
||||||
+ * List the subvolumes present in the filesystem \I<path>\i. For every
|
|
||||||
+ * subvolume the following information is shown by default.
|
|
||||||
+ * ID <ID> top level <ID> path <path>
|
|
||||||
+ * where path is the relative path of the subvolume to the \Itop level\i
|
|
||||||
+ * subvolume.
|
|
||||||
+ * The subvolume's ID may be used by the \Bsubvolume set-default\b command, or
|
|
||||||
+ * at mount time via the \Isubvol=\i option.
|
|
||||||
+ * If \I-p\i is given, then \Iparent <ID>\i is added to the output between ID
|
|
||||||
+ * and top level. The parent's ID may be used at mount time via the
|
|
||||||
+ * \Isubvolrootid=\i option.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_subvol_list(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
@@ -345,6 +411,20 @@ int do_subvol_list(int argc, char **argv)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+/**** man: btrfs subvolume snapshot
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bsubvolume snapshot\b\I [-r] <source> [<dest>/]<name>\i
|
|
||||||
+ *
|
|
||||||
+ * Create a writable/readonly snapshot of the subvolume <source> with
|
|
||||||
+ * the name <name> in the <dest> directory.
|
|
||||||
+ *
|
|
||||||
+ * Create a writable/readonly snapshot of the subvolume \I<source>\i with the
|
|
||||||
+ * name \I<name>\i in the \I<dest>\i directory. If \I<source>\i is not a
|
|
||||||
+ * subvolume, \Bbtrfs\b returns an error. If \I-r\i is given, the snapshot
|
|
||||||
+ * will be readonly.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_clone(int argc, char **argv)
|
|
||||||
{
|
|
||||||
char *subvol, *dst;
|
|
||||||
@@ -463,6 +543,17 @@ int do_clone(int argc, char **argv)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+/**** man: btrfs subvolume delete
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bsubvolume delete\b\I <subvolume>\i
|
|
||||||
+ *
|
|
||||||
+ * Delete the subvolume <subvolume>.
|
|
||||||
+ *
|
|
||||||
+ * Delete the subvolume \I<subvolume>\i. If \I<subvolume>\i is not a
|
|
||||||
+ * subvolume, \Bbtrfs\b returns an error.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_delete_subvolume(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int res, fd, len, e;
|
|
||||||
@@ -525,6 +616,18 @@ int do_delete_subvolume(int argc, char **argv)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+/**** man: btrfs subvolume create
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bsubvolume create\b\I [<dest>/]<name>\i
|
|
||||||
+ *
|
|
||||||
+ * Create a subvolume in <dest> (or the current directory if
|
|
||||||
+ * not passed).
|
|
||||||
+ *
|
|
||||||
+ * Create a subvolume in \I<dest>\i (or in the current directory if
|
|
||||||
+ * \I<dest>\i is omitted).
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_create_subvol(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int res, fddst, len, e;
|
|
||||||
@@ -581,6 +684,16 @@ int do_create_subvol(int argc, char **argv)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+/**** man: btrfs filesystem sync
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bfilesystem sync\b\I <path> \i
|
|
||||||
+ *
|
|
||||||
+ * Force a sync on the filesystem <path>.
|
|
||||||
+ *
|
|
||||||
+ * Force a sync for the filesystem identified by \I<path>\i.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_fssync(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int fd, res, e;
|
|
||||||
@@ -605,6 +718,21 @@ int do_fssync(int argc, char **argv)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+/**** man: btrfs device scan
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bdevice scan\b \I[--all-devices|<device> [<device>...]\i
|
|
||||||
+ *
|
|
||||||
+ * Scan all device for or the passed device for a btrfs
|
|
||||||
+ * filesystem.
|
|
||||||
+ *
|
|
||||||
+ * If one or more devices are passed, these are scanned for a btrfs filesystem.
|
|
||||||
+ * If no devices are passed, \Bbtrfs\b scans all the block devices listed
|
|
||||||
+ * in the /proc/partitions file.
|
|
||||||
+ * Finally, if \B--all-devices\b is passed, all the devices under /dev are
|
|
||||||
+ * scanned.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_scan(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int i, fd, e;
|
|
||||||
@@ -672,6 +800,32 @@ int do_scan(int argc, char **argv)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+/**** man: btrfs filesystem resize
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bfilesystem resize\b\I [+/\-]<size>[gkm]|max <path>\i
|
|
||||||
+ *
|
|
||||||
+ * Resize the file system. If 'max' is passed, the filesystem
|
|
||||||
+ * will occupe all available space on the device.
|
|
||||||
+ *
|
|
||||||
+ * Resize a filesystem identified by \I<path>\i.
|
|
||||||
+ * The \I<size>\i parameter specifies the new size of the filesystem.
|
|
||||||
+ * If the prefix \I+\i or \I\-\i is present the size is increased or decreased
|
|
||||||
+ * by the quantity \I<size>\i.
|
|
||||||
+ * If no units are specified, the unit of the \I<size>\i parameter defaults to
|
|
||||||
+ * bytes. Optionally, the size parameter may be suffixed by one of the following
|
|
||||||
+ * the units designators: 'K', 'M', or 'G', kilobytes, megabytes, or gigabytes,
|
|
||||||
+ * respectively.
|
|
||||||
+ *
|
|
||||||
+ * If 'max' is passed, the filesystem will occupy all available space on the
|
|
||||||
+ * volume(s).
|
|
||||||
+ *
|
|
||||||
+ * The \Bresize\b command \Bdoes not\b manipulate the size of underlying
|
|
||||||
+ * partition. If you wish to enlarge/reduce a filesystem, you must make sure
|
|
||||||
+ * you can expand the partition before enlarging the filesystem and shrink the
|
|
||||||
+ * partition after reducing the size of the filesystem.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_resize(int argc, char **argv)
|
|
||||||
{
|
|
||||||
|
|
||||||
@@ -762,6 +916,20 @@ static void print_one_uuid(struct btrfs_fs_devices *fs_devices)
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+/**** man: btrfs filesystem show
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bfilesystem show\b [--all-devices|<uuid>|<label>]\b
|
|
||||||
+ *
|
|
||||||
+ * Show the info of a btrfs filesystem. If no argument
|
|
||||||
+ * is passed, info of all the btrfs filesystem are shown.
|
|
||||||
+ *
|
|
||||||
+ * Show the btrfs filesystem with some additional info. If no \IUUID\i or
|
|
||||||
+ * \Ilabel\i is passed, \Bbtrfs\b show info of all the btrfs filesystem.
|
|
||||||
+ * If \B--all-devices\b is passed, all the devices under /dev are scanned;
|
|
||||||
+ * otherwise the devices list is extracted from the /proc/partitions file.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_show_filesystem(int argc, char **argv)
|
|
||||||
{
|
|
||||||
struct list_head *all_uuids;
|
|
||||||
@@ -807,6 +975,16 @@ int do_show_filesystem(int argc, char **argv)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+/**** man: btrfs device add
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bdevice add\b\I <dev> [<dev>..] <path>\i
|
|
||||||
+ *
|
|
||||||
+ * Add a device to a filesystem.
|
|
||||||
+ *
|
|
||||||
+ * Add device(s) to the filesystem identified by \I<path>\i.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_add_volume(int nargs, char **args)
|
|
||||||
{
|
|
||||||
|
|
||||||
@@ -889,6 +1067,15 @@ int do_add_volume(int nargs, char **args)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
+/**** man: btrfs filesystem balance
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bfilesystem balance\b \I<path>\i
|
|
||||||
+ *
|
|
||||||
+ * Balance chunks across the devices.
|
|
||||||
+ *
|
|
||||||
+ * Balance chunks across the devices.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_balance(int argc, char **argv)
|
|
||||||
{
|
|
||||||
|
|
||||||
@@ -914,6 +1101,18 @@ int do_balance(int argc, char **argv)
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/**** man: btrfs device delete
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bdevice delete\b\I <dev> [<dev>..] <path>\i
|
|
||||||
+ *
|
|
||||||
+ * Remove a device from a filesystem.
|
|
||||||
+ *
|
|
||||||
+ * Remove device(s) from a filesystem identified by \I<path>\i.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_remove_volume(int nargs, char **args)
|
|
||||||
{
|
|
||||||
|
|
||||||
@@ -947,6 +1146,19 @@ int do_remove_volume(int nargs, char **args)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+/**** man: btrfs subvolume set-default
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bsubvolume set-default\b\I <id> <path>\i
|
|
||||||
+ *
|
|
||||||
+ * Set the subvolume of the filesystem <path> which will be mounted
|
|
||||||
+ * as default.
|
|
||||||
+ *
|
|
||||||
+ * Set the subvolume of the filesystem \I<path>\i which is mounted as
|
|
||||||
+ * \Idefault\i. The subvolume is identified by \I<id>\i, which
|
|
||||||
+ * is returned by the \Bsubvolume list\b command.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_set_default_subvol(int nargs, char **argv)
|
|
||||||
{
|
|
||||||
int ret=0, fd, e;
|
|
||||||
@@ -976,6 +1188,31 @@ int do_set_default_subvol(int nargs, char **argv)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+/**** man: btrfs filesystem label
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bfilesystem label\b\I <dev> [newlabel]\i
|
|
||||||
+ *
|
|
||||||
+ * With one argument, get the label of filesystem on <device>.
|
|
||||||
+ * If <newlabel> is passed, set the filesystem label to <newlabel>.
|
|
||||||
+ * The filesystem must be unmounted.
|
|
||||||
+ *
|
|
||||||
+ * Show or update the label of a filesystem. \I<dev>\i is used to identify the
|
|
||||||
+ * filesystem.
|
|
||||||
+ * If a \Inewlabel\i optional argument is passed, the label is changed. The
|
|
||||||
+ * following costraints exist for a label:
|
|
||||||
+ * \t
|
|
||||||
+ * - the maximum allowable lenght shall be less or equal than 256 chars
|
|
||||||
+ * \t
|
|
||||||
+ * - the label shall not contain the '/' or '\\' characters.
|
|
||||||
+ *
|
|
||||||
+ * NOTE: Currently there are the following limitations:
|
|
||||||
+ * \t
|
|
||||||
+ * - the filesystem has to be unmounted
|
|
||||||
+ * \t
|
|
||||||
+ * - the filesystem should not have more than one device.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_change_label(int nargs, char **argv)
|
|
||||||
{
|
|
||||||
/* check the number of argument */
|
|
||||||
diff --git a/scrub.c b/scrub.c
|
|
||||||
index 9dca5f6..66761c5 100644
|
|
||||||
--- a/scrub.c
|
|
||||||
+++ b/scrub.c
|
|
||||||
@@ -1473,16 +1473,76 @@ out:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+/**** man: btrfs scrub start
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bscrub start\b [-Bdqru] {\I<path>\i|\I<device>\i}
|
|
||||||
+ *
|
|
||||||
+ * Start a new scrub.
|
|
||||||
+ *
|
|
||||||
+ * Start a scrub on all devices of the filesystem identified by \I<path>\i or on
|
|
||||||
+ * a single \I<device>\i. Without options, scrub is started as a background
|
|
||||||
+ * process. Progress can be obtained with the \Bscrub status\b command.
|
|
||||||
+ * Scrubbing involves reading all data from all disks and verifying checksums.
|
|
||||||
+ * Errors are corrected along the way if possible.
|
|
||||||
+ * \w
|
|
||||||
+ *
|
|
||||||
+ * \IOptions\i
|
|
||||||
+ * \t -B 5
|
|
||||||
+ * Do not background and print scrub statistics when finished.
|
|
||||||
+ * \t -d 5
|
|
||||||
+ * Print separate statistics for each device of the filesystem (-B only).
|
|
||||||
+ * \t -q 5
|
|
||||||
+ * Quiet. Omit error messages and statistics.
|
|
||||||
+ * \t -r 5
|
|
||||||
+ * Read only mode. Do not attempt to correct anything.
|
|
||||||
+ * \t -u 5
|
|
||||||
+ * Scrub unused space as well. (NOT IMPLEMENTED)
|
|
||||||
+ * \q
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_scrub_start(int argc, char **argv)
|
|
||||||
{
|
|
||||||
return scrub_start(argc, argv, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+/**** man: btrfs scrub resume
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bscrub resume\b [-Bdqru] {\I<path>\i|\I<device>\i}
|
|
||||||
+ *
|
|
||||||
+ * Resume previously canceled or interrupted scrub.
|
|
||||||
+ *
|
|
||||||
+ * Resume a canceled or interrupted scrub cycle on the filesystem identified by
|
|
||||||
+ * \I<path>\i or on a given \I<device>\i. Does not start a new scrub if the
|
|
||||||
+ * last scrub finished successfully.
|
|
||||||
+ * \w
|
|
||||||
+ *
|
|
||||||
+ * \IOptions\i
|
|
||||||
+ * \p
|
|
||||||
+ * see \Bscrub start\b.
|
|
||||||
+ * \q
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_scrub_resume(int argc, char **argv)
|
|
||||||
{
|
|
||||||
return scrub_start(argc, argv, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+/**** man: btrfs scrub cancel
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bscrub cancel\b {\I<path>\i|\I<device>\i}
|
|
||||||
+ *
|
|
||||||
+ * Cancel a running scrub.
|
|
||||||
+ *
|
|
||||||
+ * If a scrub is running on the filesystem identified by \I<path>\i, cancel it.
|
|
||||||
+ * Progress is saved in the scrub progress file and scrubbing can be resumed later
|
|
||||||
+ * using the \Bscrub resume\b command.
|
|
||||||
+ * If a \I<device>\i is given, the corresponding filesystem is found and
|
|
||||||
+ * \Bscrub cancel\b behaves as if it was called on that filesystem.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_scrub_cancel(int argc, char **argv)
|
|
||||||
{
|
|
||||||
char *path = argv[1];
|
|
||||||
@@ -1528,6 +1588,25 @@ again:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+/**** man: btrfs scrub status
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bscrub status\b [-d] {\I<path>\i|\I<device>\i}
|
|
||||||
+ *
|
|
||||||
+ * Show status of running or finished scrub.
|
|
||||||
+ *
|
|
||||||
+ * Show status of a running scrub for the filesystem identified by \I<path>\i or
|
|
||||||
+ * for the specified \I<device>\i.
|
|
||||||
+ * If no scrub is running, show statistics of the last finished or canceled scrub
|
|
||||||
+ * for that filesystem or device.
|
|
||||||
+ * \w
|
|
||||||
+ *
|
|
||||||
+ * \IOptions\i
|
|
||||||
+ * \t -d 5
|
|
||||||
+ * Print separate statistics for each device of the filesystem.
|
|
||||||
+ * \q
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_scrub_status(int argc, char **argv)
|
|
||||||
{
|
|
||||||
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,202 +0,0 @@
|
|||||||
From aa8bba1e2c99eb895c7e43f5092e4bf56d68d9c5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Goffredo Baroncelli <kreijack@inwind.it>
|
|
||||||
Date: Sat, 16 Jul 2011 11:11:08 +0200
|
|
||||||
Subject: [PATCH 09/35] Add the header/footer/introduction of the man page.
|
|
||||||
|
|
||||||
Add the header/footer/introduction of the man page. There is also an
|
|
||||||
introduction to the syntax recognized by the tool helpextract to format
|
|
||||||
the information.
|
|
||||||
---
|
|
||||||
btrfs.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
1 files changed, 176 insertions(+), 0 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfs.c b/btrfs.c
|
|
||||||
index 1def354..d2f6d4d 100644
|
|
||||||
--- a/btrfs.c
|
|
||||||
+++ b/btrfs.c
|
|
||||||
@@ -26,6 +26,182 @@
|
|
||||||
#define BASIC_HELP 0
|
|
||||||
#define ADVANCED_HELP 1
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ ** The comments below are used to make the man page
|
|
||||||
+ **
|
|
||||||
+ ** There are:
|
|
||||||
+ ** - Header,
|
|
||||||
+ ** - The synopsis title section (the content are extracted from other
|
|
||||||
+ ** comments)
|
|
||||||
+ ** - The synopsis format, which is a template: the '%s' is replaced by
|
|
||||||
+ ** the command line "syntax"
|
|
||||||
+ ** - The btrfs introduction section
|
|
||||||
+ ** - The btfrs command title section (the content are extracted from other
|
|
||||||
+ ** comments)
|
|
||||||
+ ** - The command format, which is a template: the first '%s' is replaced by
|
|
||||||
+ ** the command line "syntax"; the ssecond '%s' is replaced by the
|
|
||||||
+ ** detailed descritpion
|
|
||||||
+ ** - The "notes" section
|
|
||||||
+ ** - The footer (currentli empty)
|
|
||||||
+ **
|
|
||||||
+ ** The comments are the following sytax [replace '{slash}' with '/']
|
|
||||||
+ **
|
|
||||||
+ ** If the comment starts with '{slash}**** text: ', then all the text below
|
|
||||||
+ ** are used until ' ***'. The text after 'text: ' are the key used to
|
|
||||||
+ ** index teh content.
|
|
||||||
+ **
|
|
||||||
+ ** If the comment starts with '{slash}**** man: ', then below the comment are
|
|
||||||
+ ** divided in three section:
|
|
||||||
+ ** 1) (one line) command line syntax
|
|
||||||
+ ** 2) (multiple line) short description (showed in the command "btrfs help")
|
|
||||||
+ ** 3) (multiple line) detailled description (showed in the man page and
|
|
||||||
+ ** command "btrfs <subcommand> --help")
|
|
||||||
+ ** The text after 'man: ' are the key used to index the content. This must
|
|
||||||
+ ** be equal to the subcommand which the info is referred.
|
|
||||||
+ **
|
|
||||||
+ ** Below the escape sequence which may be used in the text
|
|
||||||
+ **
|
|
||||||
+ ** escape troff
|
|
||||||
+ ** sequence command
|
|
||||||
+ **
|
|
||||||
+ ** \B \fB bold
|
|
||||||
+ ** \b \fP end bold
|
|
||||||
+ ** \I \fI italic
|
|
||||||
+ ** \i \fP end italic
|
|
||||||
+ ** \c .\" comment
|
|
||||||
+ ** \P .PP start paragraph
|
|
||||||
+ ** \p .TP indented paragraph
|
|
||||||
+ ** \h .SH header
|
|
||||||
+ ** \d .BR bold regular
|
|
||||||
+ ** \e .B bold
|
|
||||||
+ ** \t .IP indented paragraph
|
|
||||||
+ ** \w .RS move the left margin
|
|
||||||
+ ** \q .RE move the left margin back
|
|
||||||
+ ** \- \- minus (it *must* escaped )
|
|
||||||
+ **
|
|
||||||
+ **
|
|
||||||
+ **/
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+/**** text: man btrfs header
|
|
||||||
+ * .TH BTRFS 8 "" "btrfs" "btrfs"
|
|
||||||
+ * .\"
|
|
||||||
+ * .\" Man page for the "btrfs" tool
|
|
||||||
+ * .\"
|
|
||||||
+ * .SH NAME
|
|
||||||
+ * btrfs \- control a btrfs filesystem
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
+/**** text: man btrfs synopsis
|
|
||||||
+ * .SH SYNOPSIS
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
+/**** text: man btrfs synopsis format
|
|
||||||
+ * \fB%s\fP
|
|
||||||
+ * .PP
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
+/**** text: btrfs introduction
|
|
||||||
+ * \h DESCRIPTION
|
|
||||||
+ * \Bbtrfs\b 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
|
|
||||||
+ * the filesystem, to defrag a file or a directory, flush the data to the disk,
|
|
||||||
+ * to resize the filesystem, to scan the device.
|
|
||||||
+ *
|
|
||||||
+ * It is possible to abbreviate the commands unless the commands are ambiguous.
|
|
||||||
+ * For example: it is possible to run
|
|
||||||
+ * \Ibtrfs sub snaps\i instead of \Ibtrfs subvolume snapshot\i. But \Ibtrfs
|
|
||||||
+ * file s\i is not allowed, because \Ifile s\i may be interpreted both as
|
|
||||||
+ * \Ifilesystem show\i and as \Ifilesystem sync\i.
|
|
||||||
+ *
|
|
||||||
+ * If a command is terminated by \I--help\i, the detailed help is showed.
|
|
||||||
+ * If the passed command matches more commands, detailed help of all the
|
|
||||||
+ * matched commands is showed. For example \Ibtrfs dev --help\i shows the
|
|
||||||
+ * help of all \Idevice*\i commands.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
+/**** text: man btrfs command format
|
|
||||||
+ *
|
|
||||||
+ * .TP
|
|
||||||
+ * %s%s
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
+/**** text: man btrfs commands
|
|
||||||
+ * .SH COMMANDS
|
|
||||||
+ * .TP
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+/**** text: btrfs notes
|
|
||||||
+ * \h BALANCE FILTERS
|
|
||||||
+ *
|
|
||||||
+ * With balance filters, it is possible to perform a balance operation on
|
|
||||||
+ * only a subset of the available chunks. Filters are specified with the
|
|
||||||
+ * \B--filter\b option of \Bbtrfs filesystem balance\b or \Bbtrfs
|
|
||||||
+ * balance start\b. Multiple filters may be given, either with multiple
|
|
||||||
+ * \B--filter\b options, or in a colon-separated list. When multiple
|
|
||||||
+ * filters are given, only the chunks meeting all of the selection
|
|
||||||
+ * critera are balanced. Help on the avaialble filters can be obtained
|
|
||||||
+ * with \B--filter=help\b.
|
|
||||||
+ *
|
|
||||||
+ *
|
|
||||||
+ * \Btype\b=[\B~\b]\I<flagname>\i[\B,\b...]
|
|
||||||
+ *
|
|
||||||
+ * Select only the chunks with the given type flag(s). Requiring a flag
|
|
||||||
+ * to be off can be specified with a \B~\b preceding the flag
|
|
||||||
+ * name. Flag names are:
|
|
||||||
+ *
|
|
||||||
+ * \Bmeta\b, \Bdata\b, \Bsys\b for metadata, file data and system
|
|
||||||
+ * chunk types.
|
|
||||||
+ *
|
|
||||||
+ * \Braid0\b, \Braid1\b, \Braid10\b, \Bdup\b for chunks of the
|
|
||||||
+ * given replication levels.
|
|
||||||
+ *
|
|
||||||
+ *
|
|
||||||
+ * \Bdevid\b=\I<n>\i
|
|
||||||
+ *
|
|
||||||
+ * Select chunks which have data on device ID \I<n>\i. This can be
|
|
||||||
+ * used, for example, to reduplicate data in a mirrored configuration
|
|
||||||
+ * where one drive has been lost due to hardware failure.
|
|
||||||
+ *
|
|
||||||
+ *
|
|
||||||
+ * \Bvrange\b=\I<start>\i,\I<end>\i
|
|
||||||
+ *
|
|
||||||
+ * Select chunks which have btrfs-internal virtual addresses within the
|
|
||||||
+ * range \I<start>\i (inclusive) to \I<end>\i (exclusive). Given the
|
|
||||||
+ * address of the last chunk moved, this filter can be used to restart a
|
|
||||||
+ * cancelled or interrupted balance operation, by supplying a range of
|
|
||||||
+ * \I0,<chunkaddr+1>\i.
|
|
||||||
+ *
|
|
||||||
+ * \Bdrange\b=\I<start>\i,\I<end>\i
|
|
||||||
+ *
|
|
||||||
+ * Select chunks which contain data in the address range \I<start>\i
|
|
||||||
+ * (inclusive) to \I<end>\i (exclusive) on \Iany\i block device in
|
|
||||||
+ * the filesystem. Can be mixed with the \Bdevid\b filter to select
|
|
||||||
+ * chunks in a given address range on a specific device.
|
|
||||||
+ *
|
|
||||||
+ * \h EXIT STATUS
|
|
||||||
+ * \Bbtrfs\b returns a zero exist status if it succeeds. Non zero is returned in
|
|
||||||
+ * case of failure.
|
|
||||||
+ *
|
|
||||||
+ * \h AVAILABILITY
|
|
||||||
+ * \Bbtrfs\b is part of btrfs-progs. Btrfs filesystem is currently under
|
|
||||||
+ * heavy development, and not suitable for any uses other than benchmarking and
|
|
||||||
+ * review.
|
|
||||||
+ *
|
|
||||||
+ * Please refer to the btrfs wiki http://btrfs.wiki.kernel.org for
|
|
||||||
+ * further details.
|
|
||||||
+ *
|
|
||||||
+ * \h SEE ALSO
|
|
||||||
+ * \Bmkfs.btrfs (8)\b
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
+/**** text: man btrfs footer
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+
|
|
||||||
typedef int (*CommandFunction)(int argc, char **argv);
|
|
||||||
|
|
||||||
struct Command {
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,458 +0,0 @@
|
|||||||
From e1825e850af190793dadf5ca78f36f394bae9e86 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Goffredo Baroncelli <kreijack@inwind.it>
|
|
||||||
Date: Sat, 16 Jul 2011 10:55:30 +0200
|
|
||||||
Subject: [PATCH 10/35] helpextract: tool to extract the info for the help
|
|
||||||
from the source.
|
|
||||||
|
|
||||||
It is created the file helpextract.c, which is the source for the tool
|
|
||||||
"helpextract". This program extract the info showed in the man page and
|
|
||||||
the help command from the sources comments.
|
|
||||||
---
|
|
||||||
helpextract.c | 435 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
1 files changed, 435 insertions(+), 0 deletions(-)
|
|
||||||
create mode 100644 helpextract.c
|
|
||||||
|
|
||||||
diff --git a/helpextract.c b/helpextract.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..9489ea0
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/helpextract.c
|
|
||||||
@@ -0,0 +1,435 @@
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <errno.h>
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+#include <string.h>
|
|
||||||
+#include <ctype.h>
|
|
||||||
+
|
|
||||||
+#define PREFIX_MAN "/**** man: "
|
|
||||||
+#define PREFIX_TEXT "/**** text: "
|
|
||||||
+#define PREFIX_END " ****"
|
|
||||||
+#define PREFIX_SKIP " * "
|
|
||||||
+
|
|
||||||
+#define LINEBUF 1024
|
|
||||||
+
|
|
||||||
+char **msgs=0;
|
|
||||||
+int nmsg=0;
|
|
||||||
+
|
|
||||||
+static char *xstrdup(char *str){
|
|
||||||
+ char *new = strdup(str);
|
|
||||||
+ if(!new){
|
|
||||||
+ fprintf(stderr,"*** Memory allocation fail ! (xstrdup)\n");
|
|
||||||
+ exit(101);
|
|
||||||
+ }
|
|
||||||
+ return new;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void *xrealloc(void *ptr, int newsize){
|
|
||||||
+ void *new = realloc(ptr, newsize);
|
|
||||||
+ if(!new){
|
|
||||||
+ fprintf(stderr,"*** Memory allocation fail ! (xrealloc)\n");
|
|
||||||
+ exit(101);
|
|
||||||
+ }
|
|
||||||
+ return new;
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static char *xstrip(char *s){
|
|
||||||
+
|
|
||||||
+ char *last=NULL;
|
|
||||||
+ char *first;
|
|
||||||
+
|
|
||||||
+ while(*s && isspace(*s) ) s++;
|
|
||||||
+
|
|
||||||
+ first=s;
|
|
||||||
+
|
|
||||||
+ while(*s){
|
|
||||||
+ if(isspace(*s)) last=s;
|
|
||||||
+ s++;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if(last) *last=0;
|
|
||||||
+ return first;
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void addtuple(char *key, char *cmdline, char *short_help,
|
|
||||||
+ char *long_help){
|
|
||||||
+
|
|
||||||
+ msgs = (char**)xrealloc(msgs, sizeof(char *)*(nmsg+1)*4);
|
|
||||||
+
|
|
||||||
+ key = xstrip(key);
|
|
||||||
+
|
|
||||||
+ if( !long_help || !strcmp(long_help,"\n"))
|
|
||||||
+ long_help = short_help;
|
|
||||||
+ else if(!short_help || !strcmp(short_help, "\n"))
|
|
||||||
+ short_help = long_help;
|
|
||||||
+
|
|
||||||
+ msgs[nmsg*4] = key;
|
|
||||||
+ msgs[nmsg*4+1] = cmdline;
|
|
||||||
+ msgs[nmsg*4+2] = short_help;
|
|
||||||
+ msgs[nmsg*4+3] = long_help;
|
|
||||||
+ nmsg++;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static int search_in_file(char *nf){
|
|
||||||
+ char buf[LINEBUF+1];
|
|
||||||
+ FILE *fp;
|
|
||||||
+ int status;
|
|
||||||
+ char *key=NULL;
|
|
||||||
+ char *cmdline=NULL;
|
|
||||||
+ char *short_help=NULL;
|
|
||||||
+ char *long_help=NULL;
|
|
||||||
+
|
|
||||||
+ fp = fopen(nf,"r");
|
|
||||||
+ if(!fp){
|
|
||||||
+ int e=errno;
|
|
||||||
+ fprintf(stderr, "*** Cannot open '%s'; error = %d - '%s'\n",
|
|
||||||
+ nf, e, strerror(e));
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ status = 0;
|
|
||||||
+ while(fgets(buf,LINEBUF,fp)){
|
|
||||||
+ // printf("status = %d, buf=%s",status, buf);
|
|
||||||
+
|
|
||||||
+ if(status == 0){
|
|
||||||
+ if(!strncmp(buf,PREFIX_MAN, strlen(PREFIX_MAN)) ){
|
|
||||||
+ key = xstrdup(buf+strlen(PREFIX_MAN));
|
|
||||||
+ status++;
|
|
||||||
+ }else if(!strncmp(buf,PREFIX_TEXT,
|
|
||||||
+ strlen(PREFIX_TEXT))){
|
|
||||||
+ key = xstrdup(buf+strlen(PREFIX_TEXT));
|
|
||||||
+ status=5;
|
|
||||||
+ }
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if( !strncmp(buf,PREFIX_END, strlen(PREFIX_END)) ||
|
|
||||||
+ strncmp(buf, PREFIX_SKIP,2)){
|
|
||||||
+
|
|
||||||
+ addtuple(key, cmdline, short_help, long_help);
|
|
||||||
+ key = cmdline = short_help = long_help = 0;
|
|
||||||
+ status = 0;
|
|
||||||
+
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ if( status == 2){
|
|
||||||
+ if(strlen(buf)>strlen(PREFIX_SKIP))
|
|
||||||
+ cmdline = xstrdup(buf+strlen(PREFIX_SKIP));
|
|
||||||
+ status++;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ if( status == 4){
|
|
||||||
+ int len;
|
|
||||||
+ int len2;
|
|
||||||
+ char *p;
|
|
||||||
+
|
|
||||||
+ if(strlen(buf)<=strlen(PREFIX_SKIP)){
|
|
||||||
+ status++;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ p=buf+3;
|
|
||||||
+ while(isspace(*p) && *p ) p++;
|
|
||||||
+ if(!*p){
|
|
||||||
+ status++;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ len2 = strlen(buf)-strlen(PREFIX_SKIP);
|
|
||||||
+
|
|
||||||
+ if(short_help)
|
|
||||||
+ len = strlen(short_help);
|
|
||||||
+ else
|
|
||||||
+ len = 0;
|
|
||||||
+ short_help = (char*)xrealloc(short_help, len+len2+1);
|
|
||||||
+ strcpy(short_help+len,buf+strlen(PREFIX_SKIP));
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ if( status == 5){
|
|
||||||
+ int len;
|
|
||||||
+ int len2 = strlen(buf)-strlen(PREFIX_SKIP);
|
|
||||||
+
|
|
||||||
+ if(long_help)
|
|
||||||
+ len = strlen(long_help);
|
|
||||||
+ else
|
|
||||||
+ len = 0;
|
|
||||||
+ long_help = (char*)xrealloc(long_help, len+len2+1);
|
|
||||||
+ strcpy(long_help+len,buf+strlen(PREFIX_SKIP));
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ if( status == 1 || status == 3 ){
|
|
||||||
+ status++;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ fprintf(stderr,"*** Internal error: status = %d\n",status);
|
|
||||||
+ exit(100);
|
|
||||||
+
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if( status != 0 ){
|
|
||||||
+ fprintf(stderr,"*** Parse error: file = '%s', "
|
|
||||||
+ "status = %d at the end of file\n",
|
|
||||||
+ nf, status);
|
|
||||||
+ exit(100);
|
|
||||||
+
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ fclose(fp);
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* remove all the escape sequence excepet \\ */
|
|
||||||
+static char * my_escape(char *src, char *filters[] ){
|
|
||||||
+
|
|
||||||
+ static char buffer[LINEBUF*5];
|
|
||||||
+
|
|
||||||
+ int i=0;
|
|
||||||
+ while(*src){
|
|
||||||
+ int j;
|
|
||||||
+ int next_char = *(src+1);
|
|
||||||
+ if(*src != '\\'){
|
|
||||||
+ buffer[i++]=*src++;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ if(!next_char){
|
|
||||||
+ buffer[i++]=*src++;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ if( !filters ){
|
|
||||||
+ src +=2;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ j=0;
|
|
||||||
+ while(filters[j]){
|
|
||||||
+ if(filters[j][0] == next_char ){
|
|
||||||
+ strcpy(buffer+i, filters[j]+2);
|
|
||||||
+ i+=strlen(filters[j]+2);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ j++;
|
|
||||||
+ }
|
|
||||||
+ if(!filters[j]){
|
|
||||||
+ char *p=src;
|
|
||||||
+ int l=40;
|
|
||||||
+ fprintf(stderr,
|
|
||||||
+ "Unknow escape sequence '\%c' in [\"",
|
|
||||||
+ next_char);
|
|
||||||
+ while(*p && l--) fputc(*p++, stderr);
|
|
||||||
+ fprintf(stderr, "\"...]\n");
|
|
||||||
+ }
|
|
||||||
+ src += 2;
|
|
||||||
+
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ buffer[i]=0;
|
|
||||||
+ return buffer;
|
|
||||||
+
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static char * escape_c_array(char *src ){
|
|
||||||
+ static char *filters[]={
|
|
||||||
+
|
|
||||||
+ /* remove the all know esc-sequence */
|
|
||||||
+
|
|
||||||
+ "B ", /* bold */
|
|
||||||
+ "b ", /* end bold */
|
|
||||||
+ "I ", /* italic */
|
|
||||||
+ "i ", /* end italic */
|
|
||||||
+ "c ", /* comment */
|
|
||||||
+ "P ", /* start paragraph */
|
|
||||||
+ "p ", /* indented paragraph */
|
|
||||||
+ "h ", /* header */
|
|
||||||
+ "d ", /* bold regular */
|
|
||||||
+ "e ", /* bold */
|
|
||||||
+ "t ", /* indented paragraph */
|
|
||||||
+ "w ", /* move the left margin */
|
|
||||||
+ "q ", /* move the left margin back */
|
|
||||||
+
|
|
||||||
+ "\\ \\\\",
|
|
||||||
+ "- -",
|
|
||||||
+
|
|
||||||
+ 0
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ return my_escape(src, filters);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static char *escape_man_page(char *src){
|
|
||||||
+ /* from Gnu troff manual */
|
|
||||||
+ static char *filters[]={
|
|
||||||
+ "B \\fB", /* bold */
|
|
||||||
+ "b \\fP", /* end bold */
|
|
||||||
+ "I \\fI", /* italic */
|
|
||||||
+ "i \\fP", /* end italic */
|
|
||||||
+ "c .\\\"", /* comment */
|
|
||||||
+ "P .PP", /* start paragraph */
|
|
||||||
+ "p .TP", /* indented paragraph */
|
|
||||||
+ "h .SH", /* header */
|
|
||||||
+ "d .BR", /* bold regular */
|
|
||||||
+ "e .B", /* bold */
|
|
||||||
+ "t .IP", /* indented paragraph */
|
|
||||||
+ "w .RS", /* move the left margin */
|
|
||||||
+ "q .RE", /* move the left margin back */
|
|
||||||
+
|
|
||||||
+ "- \\-", /* escape the minus sign */
|
|
||||||
+ "\\ \\",
|
|
||||||
+
|
|
||||||
+ 0
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ return my_escape(src, filters);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static void dump_c_array(){
|
|
||||||
+
|
|
||||||
+ int i;
|
|
||||||
+
|
|
||||||
+ printf("{");
|
|
||||||
+ for(i=0; i < nmsg*4 ; i++){
|
|
||||||
+ char *c = msgs[i];
|
|
||||||
+ int begin;
|
|
||||||
+
|
|
||||||
+ if(!(i%4) && strncmp(c,"btrfs ",5)){
|
|
||||||
+ i+=3;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if(i>0){
|
|
||||||
+ putchar(',');
|
|
||||||
+ if(!(i%4)) putchar('\n');
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if(!c){
|
|
||||||
+ printf("\n NULL");
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ c = escape_c_array(c);
|
|
||||||
+
|
|
||||||
+ begin = 1;
|
|
||||||
+ while( *c ){
|
|
||||||
+ if(begin)
|
|
||||||
+ printf("\n \"");
|
|
||||||
+ begin = 0;
|
|
||||||
+ if( *c == '\n' ){
|
|
||||||
+ printf("\\n\"");
|
|
||||||
+ begin = 1;
|
|
||||||
+ }else if( *c == '"' ){
|
|
||||||
+ printf("\\\"");
|
|
||||||
+ }else{
|
|
||||||
+ putchar(*c);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ c++;
|
|
||||||
+ }
|
|
||||||
+ if(!begin) putchar('"');
|
|
||||||
+ }
|
|
||||||
+ printf(",\n\n ");
|
|
||||||
+ for(i=0; i < 4; i++){
|
|
||||||
+ if(i>0) putchar(',');
|
|
||||||
+ printf("NULL");
|
|
||||||
+ }
|
|
||||||
+ printf("\n}\n");
|
|
||||||
+
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int my_sort_cmp(const void *p1, const void *p2){
|
|
||||||
+ return strcmp(*(char**)p1, *(char **)p2);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void my_sort(){
|
|
||||||
+ qsort(msgs, nmsg, sizeof(char*)*4, my_sort_cmp);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int find_section(char *key){
|
|
||||||
+ int i;
|
|
||||||
+ for(i = 0 ; i < nmsg ; i++ )
|
|
||||||
+ if(!strcmp( msgs[i*4],key) ) return i;
|
|
||||||
+
|
|
||||||
+ return -1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void dump_man_page(){
|
|
||||||
+
|
|
||||||
+ int i, fmt;
|
|
||||||
+
|
|
||||||
+ i = find_section("man btrfs header");
|
|
||||||
+ if( i>= 0 ) printf(msgs[i*4+3]);
|
|
||||||
+
|
|
||||||
+ i = find_section("man btrfs synopsis");
|
|
||||||
+ if( i>= 0 ) printf(msgs[i*4+3]);
|
|
||||||
+
|
|
||||||
+ fmt = find_section("man btrfs synopsis format");
|
|
||||||
+ for(i = 0; i < nmsg && fmt>=0; i++ ){
|
|
||||||
+ if( strncmp("btrfs ",msgs[i*4], 6) ||
|
|
||||||
+ !strcmp("btrfs introduction", msgs[i*4] ) ||
|
|
||||||
+ !strcmp("btrfs notes", msgs[i*4] ) )
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ printf(msgs[fmt*4+3], escape_man_page(msgs[i*4+1]));
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ i = find_section("btrfs introduction");
|
|
||||||
+ if( i>= 0 ) printf(escape_man_page(msgs[i*4+3]));
|
|
||||||
+
|
|
||||||
+ i = find_section("man btrfs commands");
|
|
||||||
+ if( i>= 0 ) printf(msgs[i*4+3]);
|
|
||||||
+
|
|
||||||
+ fmt = find_section("man btrfs command format");
|
|
||||||
+ for(i = 0; i < nmsg && fmt>=0; i++ ){
|
|
||||||
+
|
|
||||||
+ char big2[LINEBUF*5];
|
|
||||||
+ if( strncmp("btrfs ",msgs[i*4], 6) ||
|
|
||||||
+ !strcmp("btrfs introduction", msgs[i*4] ) ||
|
|
||||||
+ !strcmp("btrfs notes", msgs[i*4] ) )
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ strcpy(big2, escape_man_page(msgs[i*4+3]));
|
|
||||||
+ printf(msgs[fmt*4+3], escape_man_page(msgs[i*4+1]), big2);
|
|
||||||
+
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ i = find_section("man btrfs notes");
|
|
||||||
+ if( i>= 0 ) printf(msgs[i*4+3]);
|
|
||||||
+
|
|
||||||
+ i = find_section("btrfs notes");
|
|
||||||
+ if( i>= 0 ) printf(escape_man_page(msgs[i*4+3]));
|
|
||||||
+
|
|
||||||
+ i = find_section("man btrfs footer");
|
|
||||||
+ if( i>= 0 ) printf(msgs[i*4+3]);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void usage(char *np){
|
|
||||||
+ printf("usage: %s --man-page|--c-array <file> [<file> [...]]\n", np);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int main(int argc, char **argv ){
|
|
||||||
+
|
|
||||||
+ int i;
|
|
||||||
+ if( argc < 3 || ( strcmp(argv[1],"--man-page") &&
|
|
||||||
+ strcmp(argv[1],"--c-array") )){
|
|
||||||
+ usage(argv[0]);
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ for(i=2; i < argc ; i++)
|
|
||||||
+ search_in_file(argv[i]);
|
|
||||||
+
|
|
||||||
+ my_sort();
|
|
||||||
+
|
|
||||||
+ if(!strcmp(argv[1], "--man-page"))
|
|
||||||
+ dump_man_page();
|
|
||||||
+ else if (!strcmp(argv[1], "--c-array"))
|
|
||||||
+ dump_c_array();
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+}
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,710 +0,0 @@
|
|||||||
From e93b09f73b0914d8e0b8c2c78b6a1a8ebefa151c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Goffredo Baroncelli <kreijack@inwind.it>
|
|
||||||
Date: Sat, 16 Jul 2011 11:03:14 +0200
|
|
||||||
Subject: [PATCH 11/35] Update the makefile for generating the man page.
|
|
||||||
|
|
||||||
The makefile is update in order to generate the man/btrfs.8.in by the
|
|
||||||
helpextract tool on the basis of the sources comments. The old man page
|
|
||||||
is renamed as btrfs.8.in.old.
|
|
||||||
---
|
|
||||||
Makefile | 11 ++-
|
|
||||||
man/btrfs.8.in | 322 ----------------------------------------------------
|
|
||||||
man/btrfs.8.in.old | 322 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
3 files changed, 332 insertions(+), 323 deletions(-)
|
|
||||||
delete mode 100644 man/btrfs.8.in
|
|
||||||
create mode 100644 man/btrfs.8.in.old
|
|
||||||
|
|
||||||
diff --git a/Makefile b/Makefile
|
|
||||||
index 5f25d66..b673100 100644
|
|
||||||
--- a/Makefile
|
|
||||||
+++ b/Makefile
|
|
||||||
@@ -19,6 +19,8 @@ RESTORE_LIBS=-lz
|
|
||||||
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_man_page_source = btrfs.c btrfs_cmds.c scrub.c
|
|
||||||
+
|
|
||||||
# make C=1 to enable sparse
|
|
||||||
ifdef C
|
|
||||||
check = sparse $(CHECKFLAGS)
|
|
||||||
@@ -97,13 +99,20 @@ convert: $(objects) convert.o
|
|
||||||
ioctl-test: $(objects) ioctl-test.o
|
|
||||||
$(CC) $(CFLAGS) -o ioctl-test $(objects) ioctl-test.o $(LDFLAGS) $(LIBS)
|
|
||||||
|
|
||||||
-manpages:
|
|
||||||
+helpextract: helpextract.o
|
|
||||||
+ $(CC) $(CFLAGS) -o $@ helpextract.o
|
|
||||||
+
|
|
||||||
+man/btrfs.8.in: helpextract $(btrfs_man_page_source)
|
|
||||||
+ ./helpextract --man-page $(btrfs_man_page_source) >$@
|
|
||||||
+
|
|
||||||
+manpages: man/btrfs.8.in
|
|
||||||
cd man; make
|
|
||||||
|
|
||||||
install-man:
|
|
||||||
cd man; make install
|
|
||||||
|
|
||||||
clean :
|
|
||||||
+ rm -f man/btrfs.8.in
|
|
||||||
rm -f $(progs) cscope.out *.o .*.d btrfs-convert btrfs-image btrfs-select-super \
|
|
||||||
btrfs-zero-log btrfstune dir-test ioctl-test quick-test version.h
|
|
||||||
cd man; make clean
|
|
||||||
diff --git a/man/btrfs.8.in b/man/btrfs.8.in
|
|
||||||
deleted file mode 100644
|
|
||||||
index be478e0..0000000
|
|
||||||
--- a/man/btrfs.8.in
|
|
||||||
+++ /dev/null
|
|
||||||
@@ -1,322 +0,0 @@
|
|
||||||
-.TH BTRFS 8 "" "btrfs" "btrfs"
|
|
||||||
-.\"
|
|
||||||
-.\" Man page written by Goffredo Baroncelli <kreijack@inwind.it> (Feb 2010)
|
|
||||||
-.\"
|
|
||||||
-.SH NAME
|
|
||||||
-btrfs \- control a btrfs filesystem
|
|
||||||
-.SH SYNOPSIS
|
|
||||||
-\fBbtrfs\fP \fBsubvolume snapshot\fP\fI [-r] <source> [<dest>/]<name>\fP
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBsubvolume delete\fP\fI <subvolume>\fP
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBsubvolume create\fP\fI [<dest>/]<name>\fP
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBsubvolume list\fP\fI [-p] <path>\fP
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBsubvolume set-default\fP\fI <id> <path>\fP
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBsubvolume get-default\fP\fI <path>\fP
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBfilesystem sync\fP\fI <path> \fP
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBfilesystem resize\fP\fI [+/\-]<size>[gkm]|max <filesystem>\fP
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBfilesystem label\fP\fI <dev> [newlabel]\fP
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBfilesystem defrag\fP\fI [options] <file>|<dir> [<file>|<dir>...]\fP
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBsubvolume find-new\fP\fI <subvolume> <last_gen>\fP
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBfilesystem balance\fP\fI <path> \fP
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBfilesystem defragment\fP\fI <file>|<dir> [<file>|<dir>...]\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
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBdevice add\fP\fI <device> [<device>...] <path> \fP
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBdevice delete\fP\fI <device> [<device>...] <path> \fP
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBscrub start\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP}
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBscrub cancel\fP {\fI<path>\fP|\fI<device>\fP}
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBscrub resume\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP}
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBscrub status\fP [-d] {\fI<path>\fP|\fI<device>\fP}
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBinspect-internal inode-resolve\fP [-v] \fI<inode>\fP \fI<path>\fP
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBinspect-internal logical-resolve\fP
|
|
||||||
-[-Pv] \fI<logical>\fP \fI<path>\fP
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fBhelp|\-\-help|\-h \fP\fI\fP
|
|
||||||
-.PP
|
|
||||||
-\fBbtrfs\fP \fB<command> \-\-help \fP\fI\fP
|
|
||||||
-.PP
|
|
||||||
-.SH DESCRIPTION
|
|
||||||
-.B btrfs
|
|
||||||
-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 the
|
|
||||||
-filesystem, to defrag a file or a directory, flush the data to the disk,
|
|
||||||
-to resize the filesystem, to scan the device.
|
|
||||||
-
|
|
||||||
-It is possible to abbreviate the commands unless the commands are ambiguous.
|
|
||||||
-For example: it is possible to run
|
|
||||||
-.I btrfs sub snaps
|
|
||||||
-instead of
|
|
||||||
-.I btrfs subvolume snapshot.
|
|
||||||
-But
|
|
||||||
-.I btrfs file s
|
|
||||||
-is not allowed, because
|
|
||||||
-.I file s
|
|
||||||
-may be interpreted both as
|
|
||||||
-.I filesystem show
|
|
||||||
-and as
|
|
||||||
-.I filesystem sync.
|
|
||||||
-In this case
|
|
||||||
-.I btrfs
|
|
||||||
-returnsfilesystem sync
|
|
||||||
-If a command is terminated by
|
|
||||||
-.I --help
|
|
||||||
-, the detailed help is showed. If the passed command matches more commands,
|
|
||||||
-detailed help of all the matched commands is showed. For example
|
|
||||||
-.I btrfs dev --help
|
|
||||||
-shows the help of all
|
|
||||||
-.I device*
|
|
||||||
-commands.
|
|
||||||
-
|
|
||||||
-.SH COMMANDS
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBsubvolume snapshot\fR\fI [-r] <source> [<dest>/]<name>\fR
|
|
||||||
-Create a writable/readonly snapshot of the subvolume \fI<source>\fR with the
|
|
||||||
-name \fI<name>\fR in the \fI<dest>\fR directory. If \fI<source>\fR is not a
|
|
||||||
-subvolume, \fBbtrfs\fR returns an error. If \fI-r\fR is given, the snapshot
|
|
||||||
-will be readonly.
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBsubvolume delete\fR\fI <subvolume>\fR
|
|
||||||
-Delete the subvolume \fI<subvolume>\fR. If \fI<subvolume>\fR is not a
|
|
||||||
-subvolume, \fBbtrfs\fR returns an error.
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBsubvolume create\fR\fI [<dest>/]<name>\fR
|
|
||||||
-Create a subvolume in \fI<dest>\fR (or in the current directory if
|
|
||||||
-\fI<dest>\fR is omitted).
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBsubvolume list\fR\fI [-p] <path>\fR
|
|
||||||
-List the subvolumes present in the filesystem \fI<path>\fR. For every
|
|
||||||
-subvolume the following information is shown by default.
|
|
||||||
-ID <ID> top level <ID> path <path>
|
|
||||||
-where path is the relative path of the subvolume to the \fItop level\fR
|
|
||||||
-subvolume.
|
|
||||||
-The subvolume's ID may be used by the \fBsubvolume set-default\fR command, or
|
|
||||||
-at mount time via the \fIsubvol=\fR option.
|
|
||||||
-If \fI-p\fR is given, then \fIparent <ID>\fR is added to the output between ID
|
|
||||||
-and top level. The parent's ID may be used at mount time via the
|
|
||||||
-\fIsubvolrootid=\fR option.
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBsubvolume set-default\fR\fI <id> <path>\fR
|
|
||||||
-Set the subvolume of the filesystem \fI<path>\fR which is mounted as
|
|
||||||
-\fIdefault\fR. The subvolume is identified by \fI<id>\fR, which
|
|
||||||
-is returned by the \fBsubvolume list\fR command.
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBsubvolume get-default\fR\fI <path>\fR
|
|
||||||
-Get the default subvolume of the filesystem \fI<path>\fR. The output format
|
|
||||||
-is similar to \fBsubvolume list\fR command.
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBfilesystem defragment\fP -c[zlib|lzo] [-l \fIlen\fR] [-s \fIstart\fR] [-t \fIsize\fR] -[vf] <\fIfile\fR>|<\fIdir\fR> [<\fIfile\fR>|<\fIdir\fR>...]
|
|
||||||
-
|
|
||||||
-Defragment file data and/or directory metadata. To defragment all files in a
|
|
||||||
-directory you have to specify each one on its own or use your shell wildcards.
|
|
||||||
-
|
|
||||||
-The start position and the number of bytes to deframention can be specified by \fIstart\fR and \fIlen\fR. Any extent bigger than \fIthresh\fR will be considered already defragged. Use 0 to take the kernel default, and use 1 to say eveery single extent must be rewritten. You can also turn on compression in defragment operations.
|
|
||||||
-
|
|
||||||
-\fB-v\fP be verbose
|
|
||||||
-
|
|
||||||
-\fB-c\fP compress file contents while defragmenting
|
|
||||||
-
|
|
||||||
-\fB-f\fP flush filesystem after defragmenting
|
|
||||||
-
|
|
||||||
-\fB-s start\fP defragment only from byte \fIstart\fR onward
|
|
||||||
-
|
|
||||||
-\fB-l len\fP defragment only up to \fIlen\fR bytes
|
|
||||||
-
|
|
||||||
-\fB-t size\fP defragment only files at least \fIsize\fR bytes big
|
|
||||||
-
|
|
||||||
-NOTE: defragmenting with kernels up to 2.6.37 will unlink COW-ed copies of data, don't
|
|
||||||
-use it if you use snapshots, have de-duplicated your data or made copies with
|
|
||||||
-\fBcp --reflink\fP.
|
|
||||||
-\fBsubvolume find-new\fR\fI <subvolume> <last_gen>\fR
|
|
||||||
-List the recently modified files in a subvolume, after \fI<last_gen>\fR ID.
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBfilesystem sync\fR\fI <path> \fR
|
|
||||||
-Force a sync for the filesystem identified by \fI<path>\fR.
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-.\"
|
|
||||||
-.\" Some wording are extracted by the resize2fs man page
|
|
||||||
-.\"
|
|
||||||
-
|
|
||||||
-\fBfilesystem resize\fR\fI [+/\-]<size>[gkm]|max <path>\fR
|
|
||||||
-Resize a filesystem identified by \fI<path>\fR.
|
|
||||||
-The \fI<size>\fR parameter specifies the new size of the filesystem.
|
|
||||||
-If the prefix \fI+\fR or \fI\-\fR is present the size is increased or decreased
|
|
||||||
-by the quantity \fI<size>\fR.
|
|
||||||
-If no units are specified, the unit of the \fI<size>\fR parameter defaults to
|
|
||||||
-bytes. Optionally, the size parameter may be suffixed by one of the following
|
|
||||||
-the units designators: 'K', 'M', or 'G', kilobytes, megabytes, or gigabytes,
|
|
||||||
-respectively.
|
|
||||||
-
|
|
||||||
-If 'max' is passed, the filesystem will occupy all available space on the
|
|
||||||
-volume(s).
|
|
||||||
-
|
|
||||||
-The \fBresize\fR command \fBdoes not\fR manipulate the size of underlying
|
|
||||||
-partition. If you wish to enlarge/reduce a filesystem, you must make sure you
|
|
||||||
-can expand the partition before enlarging the filesystem and shrink the
|
|
||||||
-partition after reducing the size of the filesystem.
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBbtrfs\fP \fBfilesystem label\fP\fI <dev> [newlabel]\fP
|
|
||||||
-Show or update the label of a filesystem. \fI<dev>\fR is used to identify the
|
|
||||||
-filesystem.
|
|
||||||
-If a \fInewlabel\fR optional argument is passed, the label is changed. The
|
|
||||||
-following costraints exist for a label:
|
|
||||||
-.IP
|
|
||||||
-- the maximum allowable lenght shall be less or equal than 256 chars
|
|
||||||
-.IP
|
|
||||||
-- the label shall not contain the '/' or '\\' characters.
|
|
||||||
-
|
|
||||||
-NOTE: Currently there are the following limitations:
|
|
||||||
-.IP
|
|
||||||
-- the filesystem has to be unmounted
|
|
||||||
-.IP
|
|
||||||
-- the filesystem should not have more than one device.
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBfilesystem show\fR [--all-devices|<uuid>|<label>]\fR
|
|
||||||
-Show the btrfs filesystem with some additional info. If no \fIUUID\fP or
|
|
||||||
-\fIlabel\fP is passed, \fBbtrfs\fR show info of all the btrfs filesystem.
|
|
||||||
-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
|
|
||||||
-
|
|
||||||
-\fBdevice balance\fR \fI<path>\fR
|
|
||||||
-Balance the chunks of the filesystem identified by \fI<path>\fR
|
|
||||||
-across the devices.
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBdevice add\fR\fI <dev> [<dev>..] <path>\fR
|
|
||||||
-Add device(s) to the filesystem identified by \fI<path>\fR.
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBdevice delete\fR\fI <dev> [<dev>..] <path>\fR
|
|
||||||
-Remove device(s) from a filesystem identified by \fI<path>\fR.
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBdevice scan\fR \fI[--all-devices|<device> [<device>...]\fR
|
|
||||||
-If one or more devices are passed, these are scanned for a btrfs filesystem.
|
|
||||||
-If no devices are passed, \fBbtrfs\fR scans all the block devices listed
|
|
||||||
-in the /proc/partitions file.
|
|
||||||
-Finally, if \fB--all-devices\fP is passed, all the devices under /dev are
|
|
||||||
-scanned.
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBscrub start\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP}
|
|
||||||
-Start a scrub on all devices of the filesystem identified by \fI<path>\fR or on
|
|
||||||
-a single \fI<device>\fR. Without options, scrub is started as a background
|
|
||||||
-process. Progress can be obtained with the \fBscrub status\fR command. Scrubbing
|
|
||||||
-involves reading all data from all disks and verifying checksums. Errors are
|
|
||||||
-corrected along the way if possible.
|
|
||||||
-.RS
|
|
||||||
-
|
|
||||||
-\fIOptions\fR
|
|
||||||
-.IP -B 5
|
|
||||||
-Do not background and print scrub statistics when finished.
|
|
||||||
-.IP -d 5
|
|
||||||
-Print separate statistics for each device of the filesystem (-B only).
|
|
||||||
-.IP -q 5
|
|
||||||
-Quiet. Omit error messages and statistics.
|
|
||||||
-.IP -r 5
|
|
||||||
-Read only mode. Do not attempt to correct anything.
|
|
||||||
-.IP -u 5
|
|
||||||
-Scrub unused space as well. (NOT IMPLEMENTED)
|
|
||||||
-.RE
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBscrub cancel\fP {\fI<path>\fP|\fI<device>\fP}
|
|
||||||
-If a scrub is running on the filesystem identified by \fI<path>\fR, cancel it.
|
|
||||||
-Progress is saved in the scrub progress file and scrubbing can be resumed later
|
|
||||||
-using the \fBscrub resume\fR command.
|
|
||||||
-If a \fI<device>\fR is given, the corresponding filesystem is found and
|
|
||||||
-\fBscrub cancel\fP behaves as if it was called on that filesystem.
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBscrub resume\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP}
|
|
||||||
-Resume a canceled or interrupted scrub cycle on the filesystem identified by
|
|
||||||
-\fI<path>\fR or on a given \fI<device>\fR. Does not start a new scrub if the
|
|
||||||
-last scrub finished successfully.
|
|
||||||
-.RS
|
|
||||||
-
|
|
||||||
-\fIOptions\fR
|
|
||||||
-.TP
|
|
||||||
-see \fBscrub start\fP.
|
|
||||||
-.RE
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBscrub status\fP [-d] {\fI<path>\fP|\fI<device>\fP}
|
|
||||||
-Show status of a running scrub for the filesystem identified by \fI<path>\fR or
|
|
||||||
-for the specified \fI<device>\fR.
|
|
||||||
-If no scrub is running, show statistics of the last finished or canceled scrub
|
|
||||||
-for that filesystem or device.
|
|
||||||
-.RS
|
|
||||||
-
|
|
||||||
-\fIOptions\fR
|
|
||||||
-.IP -d 5
|
|
||||||
-Print separate statistics for each device of the filesystem.
|
|
||||||
-.RE
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBinspect-internal inode-resolve\fP [-v] \fI<inode>\fP \fI<path>\fP
|
|
||||||
-Resolves an <inode> in subvolume <path> to all filesystem paths.
|
|
||||||
-.RS
|
|
||||||
-
|
|
||||||
-\fIOptions\fR
|
|
||||||
-.IP -v 5
|
|
||||||
-verbose mode. print count of returned paths and ioctl() return value
|
|
||||||
-.RE
|
|
||||||
-.TP
|
|
||||||
-
|
|
||||||
-\fBinspect-internal logical-resolve\fP [-Pv] \fI<logical>\fP \fI<path>\fP
|
|
||||||
-Resolves a <logical> address in the filesystem mounted at <path> to all inodes.
|
|
||||||
-By default, each inode is then resolved to a file system path (similar to the
|
|
||||||
-\fBinode-resolve\fP subcommand).
|
|
||||||
-.RS
|
|
||||||
-
|
|
||||||
-\fIOptions\fR
|
|
||||||
-.IP -P 5
|
|
||||||
-skip the path resolving and print the inodes instead
|
|
||||||
-.IP -v 5
|
|
||||||
-verbose mode. print count of returned paths and all ioctl() return values
|
|
||||||
-.RE
|
|
||||||
-
|
|
||||||
-.SH EXIT STATUS
|
|
||||||
-\fBbtrfs\fR returns a zero exist status if it succeeds. Non zero is returned in
|
|
||||||
-case of failure.
|
|
||||||
-
|
|
||||||
-.SH AVAILABILITY
|
|
||||||
-.B btrfs
|
|
||||||
-is part of btrfs-progs. Btrfs filesystem is currently under heavy development,
|
|
||||||
-and not suitable for any uses other than benchmarking and review.
|
|
||||||
-Please refer to the btrfs wiki http://btrfs.wiki.kernel.org for
|
|
||||||
-further details.
|
|
||||||
-.SH SEE ALSO
|
|
||||||
-.BR mkfs.btrfs (8)
|
|
||||||
diff --git a/man/btrfs.8.in.old b/man/btrfs.8.in.old
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..be478e0
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/man/btrfs.8.in.old
|
|
||||||
@@ -0,0 +1,322 @@
|
|
||||||
+.TH BTRFS 8 "" "btrfs" "btrfs"
|
|
||||||
+.\"
|
|
||||||
+.\" Man page written by Goffredo Baroncelli <kreijack@inwind.it> (Feb 2010)
|
|
||||||
+.\"
|
|
||||||
+.SH NAME
|
|
||||||
+btrfs \- control a btrfs filesystem
|
|
||||||
+.SH SYNOPSIS
|
|
||||||
+\fBbtrfs\fP \fBsubvolume snapshot\fP\fI [-r] <source> [<dest>/]<name>\fP
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBsubvolume delete\fP\fI <subvolume>\fP
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBsubvolume create\fP\fI [<dest>/]<name>\fP
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBsubvolume list\fP\fI [-p] <path>\fP
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBsubvolume set-default\fP\fI <id> <path>\fP
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBsubvolume get-default\fP\fI <path>\fP
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBfilesystem sync\fP\fI <path> \fP
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBfilesystem resize\fP\fI [+/\-]<size>[gkm]|max <filesystem>\fP
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBfilesystem label\fP\fI <dev> [newlabel]\fP
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBfilesystem defrag\fP\fI [options] <file>|<dir> [<file>|<dir>...]\fP
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBsubvolume find-new\fP\fI <subvolume> <last_gen>\fP
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBfilesystem balance\fP\fI <path> \fP
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBfilesystem defragment\fP\fI <file>|<dir> [<file>|<dir>...]\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
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBdevice add\fP\fI <device> [<device>...] <path> \fP
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBdevice delete\fP\fI <device> [<device>...] <path> \fP
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBscrub start\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP}
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBscrub cancel\fP {\fI<path>\fP|\fI<device>\fP}
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBscrub resume\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP}
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBscrub status\fP [-d] {\fI<path>\fP|\fI<device>\fP}
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBinspect-internal inode-resolve\fP [-v] \fI<inode>\fP \fI<path>\fP
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBinspect-internal logical-resolve\fP
|
|
||||||
+[-Pv] \fI<logical>\fP \fI<path>\fP
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fBhelp|\-\-help|\-h \fP\fI\fP
|
|
||||||
+.PP
|
|
||||||
+\fBbtrfs\fP \fB<command> \-\-help \fP\fI\fP
|
|
||||||
+.PP
|
|
||||||
+.SH DESCRIPTION
|
|
||||||
+.B btrfs
|
|
||||||
+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 the
|
|
||||||
+filesystem, to defrag a file or a directory, flush the data to the disk,
|
|
||||||
+to resize the filesystem, to scan the device.
|
|
||||||
+
|
|
||||||
+It is possible to abbreviate the commands unless the commands are ambiguous.
|
|
||||||
+For example: it is possible to run
|
|
||||||
+.I btrfs sub snaps
|
|
||||||
+instead of
|
|
||||||
+.I btrfs subvolume snapshot.
|
|
||||||
+But
|
|
||||||
+.I btrfs file s
|
|
||||||
+is not allowed, because
|
|
||||||
+.I file s
|
|
||||||
+may be interpreted both as
|
|
||||||
+.I filesystem show
|
|
||||||
+and as
|
|
||||||
+.I filesystem sync.
|
|
||||||
+In this case
|
|
||||||
+.I btrfs
|
|
||||||
+returnsfilesystem sync
|
|
||||||
+If a command is terminated by
|
|
||||||
+.I --help
|
|
||||||
+, the detailed help is showed. If the passed command matches more commands,
|
|
||||||
+detailed help of all the matched commands is showed. For example
|
|
||||||
+.I btrfs dev --help
|
|
||||||
+shows the help of all
|
|
||||||
+.I device*
|
|
||||||
+commands.
|
|
||||||
+
|
|
||||||
+.SH COMMANDS
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBsubvolume snapshot\fR\fI [-r] <source> [<dest>/]<name>\fR
|
|
||||||
+Create a writable/readonly snapshot of the subvolume \fI<source>\fR with the
|
|
||||||
+name \fI<name>\fR in the \fI<dest>\fR directory. If \fI<source>\fR is not a
|
|
||||||
+subvolume, \fBbtrfs\fR returns an error. If \fI-r\fR is given, the snapshot
|
|
||||||
+will be readonly.
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBsubvolume delete\fR\fI <subvolume>\fR
|
|
||||||
+Delete the subvolume \fI<subvolume>\fR. If \fI<subvolume>\fR is not a
|
|
||||||
+subvolume, \fBbtrfs\fR returns an error.
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBsubvolume create\fR\fI [<dest>/]<name>\fR
|
|
||||||
+Create a subvolume in \fI<dest>\fR (or in the current directory if
|
|
||||||
+\fI<dest>\fR is omitted).
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBsubvolume list\fR\fI [-p] <path>\fR
|
|
||||||
+List the subvolumes present in the filesystem \fI<path>\fR. For every
|
|
||||||
+subvolume the following information is shown by default.
|
|
||||||
+ID <ID> top level <ID> path <path>
|
|
||||||
+where path is the relative path of the subvolume to the \fItop level\fR
|
|
||||||
+subvolume.
|
|
||||||
+The subvolume's ID may be used by the \fBsubvolume set-default\fR command, or
|
|
||||||
+at mount time via the \fIsubvol=\fR option.
|
|
||||||
+If \fI-p\fR is given, then \fIparent <ID>\fR is added to the output between ID
|
|
||||||
+and top level. The parent's ID may be used at mount time via the
|
|
||||||
+\fIsubvolrootid=\fR option.
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBsubvolume set-default\fR\fI <id> <path>\fR
|
|
||||||
+Set the subvolume of the filesystem \fI<path>\fR which is mounted as
|
|
||||||
+\fIdefault\fR. The subvolume is identified by \fI<id>\fR, which
|
|
||||||
+is returned by the \fBsubvolume list\fR command.
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBsubvolume get-default\fR\fI <path>\fR
|
|
||||||
+Get the default subvolume of the filesystem \fI<path>\fR. The output format
|
|
||||||
+is similar to \fBsubvolume list\fR command.
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBfilesystem defragment\fP -c[zlib|lzo] [-l \fIlen\fR] [-s \fIstart\fR] [-t \fIsize\fR] -[vf] <\fIfile\fR>|<\fIdir\fR> [<\fIfile\fR>|<\fIdir\fR>...]
|
|
||||||
+
|
|
||||||
+Defragment file data and/or directory metadata. To defragment all files in a
|
|
||||||
+directory you have to specify each one on its own or use your shell wildcards.
|
|
||||||
+
|
|
||||||
+The start position and the number of bytes to deframention can be specified by \fIstart\fR and \fIlen\fR. Any extent bigger than \fIthresh\fR will be considered already defragged. Use 0 to take the kernel default, and use 1 to say eveery single extent must be rewritten. You can also turn on compression in defragment operations.
|
|
||||||
+
|
|
||||||
+\fB-v\fP be verbose
|
|
||||||
+
|
|
||||||
+\fB-c\fP compress file contents while defragmenting
|
|
||||||
+
|
|
||||||
+\fB-f\fP flush filesystem after defragmenting
|
|
||||||
+
|
|
||||||
+\fB-s start\fP defragment only from byte \fIstart\fR onward
|
|
||||||
+
|
|
||||||
+\fB-l len\fP defragment only up to \fIlen\fR bytes
|
|
||||||
+
|
|
||||||
+\fB-t size\fP defragment only files at least \fIsize\fR bytes big
|
|
||||||
+
|
|
||||||
+NOTE: defragmenting with kernels up to 2.6.37 will unlink COW-ed copies of data, don't
|
|
||||||
+use it if you use snapshots, have de-duplicated your data or made copies with
|
|
||||||
+\fBcp --reflink\fP.
|
|
||||||
+\fBsubvolume find-new\fR\fI <subvolume> <last_gen>\fR
|
|
||||||
+List the recently modified files in a subvolume, after \fI<last_gen>\fR ID.
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBfilesystem sync\fR\fI <path> \fR
|
|
||||||
+Force a sync for the filesystem identified by \fI<path>\fR.
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+.\"
|
|
||||||
+.\" Some wording are extracted by the resize2fs man page
|
|
||||||
+.\"
|
|
||||||
+
|
|
||||||
+\fBfilesystem resize\fR\fI [+/\-]<size>[gkm]|max <path>\fR
|
|
||||||
+Resize a filesystem identified by \fI<path>\fR.
|
|
||||||
+The \fI<size>\fR parameter specifies the new size of the filesystem.
|
|
||||||
+If the prefix \fI+\fR or \fI\-\fR is present the size is increased or decreased
|
|
||||||
+by the quantity \fI<size>\fR.
|
|
||||||
+If no units are specified, the unit of the \fI<size>\fR parameter defaults to
|
|
||||||
+bytes. Optionally, the size parameter may be suffixed by one of the following
|
|
||||||
+the units designators: 'K', 'M', or 'G', kilobytes, megabytes, or gigabytes,
|
|
||||||
+respectively.
|
|
||||||
+
|
|
||||||
+If 'max' is passed, the filesystem will occupy all available space on the
|
|
||||||
+volume(s).
|
|
||||||
+
|
|
||||||
+The \fBresize\fR command \fBdoes not\fR manipulate the size of underlying
|
|
||||||
+partition. If you wish to enlarge/reduce a filesystem, you must make sure you
|
|
||||||
+can expand the partition before enlarging the filesystem and shrink the
|
|
||||||
+partition after reducing the size of the filesystem.
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBbtrfs\fP \fBfilesystem label\fP\fI <dev> [newlabel]\fP
|
|
||||||
+Show or update the label of a filesystem. \fI<dev>\fR is used to identify the
|
|
||||||
+filesystem.
|
|
||||||
+If a \fInewlabel\fR optional argument is passed, the label is changed. The
|
|
||||||
+following costraints exist for a label:
|
|
||||||
+.IP
|
|
||||||
+- the maximum allowable lenght shall be less or equal than 256 chars
|
|
||||||
+.IP
|
|
||||||
+- the label shall not contain the '/' or '\\' characters.
|
|
||||||
+
|
|
||||||
+NOTE: Currently there are the following limitations:
|
|
||||||
+.IP
|
|
||||||
+- the filesystem has to be unmounted
|
|
||||||
+.IP
|
|
||||||
+- the filesystem should not have more than one device.
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBfilesystem show\fR [--all-devices|<uuid>|<label>]\fR
|
|
||||||
+Show the btrfs filesystem with some additional info. If no \fIUUID\fP or
|
|
||||||
+\fIlabel\fP is passed, \fBbtrfs\fR show info of all the btrfs filesystem.
|
|
||||||
+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
|
|
||||||
+
|
|
||||||
+\fBdevice balance\fR \fI<path>\fR
|
|
||||||
+Balance the chunks of the filesystem identified by \fI<path>\fR
|
|
||||||
+across the devices.
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBdevice add\fR\fI <dev> [<dev>..] <path>\fR
|
|
||||||
+Add device(s) to the filesystem identified by \fI<path>\fR.
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBdevice delete\fR\fI <dev> [<dev>..] <path>\fR
|
|
||||||
+Remove device(s) from a filesystem identified by \fI<path>\fR.
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBdevice scan\fR \fI[--all-devices|<device> [<device>...]\fR
|
|
||||||
+If one or more devices are passed, these are scanned for a btrfs filesystem.
|
|
||||||
+If no devices are passed, \fBbtrfs\fR scans all the block devices listed
|
|
||||||
+in the /proc/partitions file.
|
|
||||||
+Finally, if \fB--all-devices\fP is passed, all the devices under /dev are
|
|
||||||
+scanned.
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBscrub start\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP}
|
|
||||||
+Start a scrub on all devices of the filesystem identified by \fI<path>\fR or on
|
|
||||||
+a single \fI<device>\fR. Without options, scrub is started as a background
|
|
||||||
+process. Progress can be obtained with the \fBscrub status\fR command. Scrubbing
|
|
||||||
+involves reading all data from all disks and verifying checksums. Errors are
|
|
||||||
+corrected along the way if possible.
|
|
||||||
+.RS
|
|
||||||
+
|
|
||||||
+\fIOptions\fR
|
|
||||||
+.IP -B 5
|
|
||||||
+Do not background and print scrub statistics when finished.
|
|
||||||
+.IP -d 5
|
|
||||||
+Print separate statistics for each device of the filesystem (-B only).
|
|
||||||
+.IP -q 5
|
|
||||||
+Quiet. Omit error messages and statistics.
|
|
||||||
+.IP -r 5
|
|
||||||
+Read only mode. Do not attempt to correct anything.
|
|
||||||
+.IP -u 5
|
|
||||||
+Scrub unused space as well. (NOT IMPLEMENTED)
|
|
||||||
+.RE
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBscrub cancel\fP {\fI<path>\fP|\fI<device>\fP}
|
|
||||||
+If a scrub is running on the filesystem identified by \fI<path>\fR, cancel it.
|
|
||||||
+Progress is saved in the scrub progress file and scrubbing can be resumed later
|
|
||||||
+using the \fBscrub resume\fR command.
|
|
||||||
+If a \fI<device>\fR is given, the corresponding filesystem is found and
|
|
||||||
+\fBscrub cancel\fP behaves as if it was called on that filesystem.
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBscrub resume\fP [-Bdqru] {\fI<path>\fP|\fI<device>\fP}
|
|
||||||
+Resume a canceled or interrupted scrub cycle on the filesystem identified by
|
|
||||||
+\fI<path>\fR or on a given \fI<device>\fR. Does not start a new scrub if the
|
|
||||||
+last scrub finished successfully.
|
|
||||||
+.RS
|
|
||||||
+
|
|
||||||
+\fIOptions\fR
|
|
||||||
+.TP
|
|
||||||
+see \fBscrub start\fP.
|
|
||||||
+.RE
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBscrub status\fP [-d] {\fI<path>\fP|\fI<device>\fP}
|
|
||||||
+Show status of a running scrub for the filesystem identified by \fI<path>\fR or
|
|
||||||
+for the specified \fI<device>\fR.
|
|
||||||
+If no scrub is running, show statistics of the last finished or canceled scrub
|
|
||||||
+for that filesystem or device.
|
|
||||||
+.RS
|
|
||||||
+
|
|
||||||
+\fIOptions\fR
|
|
||||||
+.IP -d 5
|
|
||||||
+Print separate statistics for each device of the filesystem.
|
|
||||||
+.RE
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBinspect-internal inode-resolve\fP [-v] \fI<inode>\fP \fI<path>\fP
|
|
||||||
+Resolves an <inode> in subvolume <path> to all filesystem paths.
|
|
||||||
+.RS
|
|
||||||
+
|
|
||||||
+\fIOptions\fR
|
|
||||||
+.IP -v 5
|
|
||||||
+verbose mode. print count of returned paths and ioctl() return value
|
|
||||||
+.RE
|
|
||||||
+.TP
|
|
||||||
+
|
|
||||||
+\fBinspect-internal logical-resolve\fP [-Pv] \fI<logical>\fP \fI<path>\fP
|
|
||||||
+Resolves a <logical> address in the filesystem mounted at <path> to all inodes.
|
|
||||||
+By default, each inode is then resolved to a file system path (similar to the
|
|
||||||
+\fBinode-resolve\fP subcommand).
|
|
||||||
+.RS
|
|
||||||
+
|
|
||||||
+\fIOptions\fR
|
|
||||||
+.IP -P 5
|
|
||||||
+skip the path resolving and print the inodes instead
|
|
||||||
+.IP -v 5
|
|
||||||
+verbose mode. print count of returned paths and all ioctl() return values
|
|
||||||
+.RE
|
|
||||||
+
|
|
||||||
+.SH EXIT STATUS
|
|
||||||
+\fBbtrfs\fR returns a zero exist status if it succeeds. Non zero is returned in
|
|
||||||
+case of failure.
|
|
||||||
+
|
|
||||||
+.SH AVAILABILITY
|
|
||||||
+.B btrfs
|
|
||||||
+is part of btrfs-progs. Btrfs filesystem is currently under heavy development,
|
|
||||||
+and not suitable for any uses other than benchmarking and review.
|
|
||||||
+Please refer to the btrfs wiki http://btrfs.wiki.kernel.org for
|
|
||||||
+further details.
|
|
||||||
+.SH SEE ALSO
|
|
||||||
+.BR mkfs.btrfs (8)
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
|||||||
From 72aba9c58e83186db249f31198c03ebd0c34d7af Mon Sep 17 00:00:00 2001
|
|
||||||
From: Goffredo Baroncelli <kreijack@inwind.it>
|
|
||||||
Date: Sat, 16 Jul 2011 12:11:06 +0200
|
|
||||||
Subject: [PATCH 12/35] Show the help messages from the info in the comment.
|
|
||||||
|
|
||||||
The makefile is update in order to use the tool "helpextract" to extract
|
|
||||||
the info from the sources comments and to generate the file "helpmsg.c"
|
|
||||||
which contains an array of string with all the information.
|
|
||||||
Then the function "print_help" prints these information.
|
|
||||||
---
|
|
||||||
btrfs.c | 34 +++++++++++++++++++++++++++++-----
|
|
||||||
1 files changed, 29 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfs.c b/btrfs.c
|
|
||||||
index d2f6d4d..66b0d80 100644
|
|
||||||
--- a/btrfs.c
|
|
||||||
+++ b/btrfs.c
|
|
||||||
@@ -358,6 +358,8 @@ static struct Command commands[] = {
|
|
||||||
{ 0, 0, 0, 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
+extern char * help_messages[];
|
|
||||||
+
|
|
||||||
static char *get_prgname(char *programname)
|
|
||||||
{
|
|
||||||
char *np;
|
|
||||||
@@ -373,21 +375,43 @@ static char *get_prgname(char *programname)
|
|
||||||
static void print_help(char *programname, struct Command *cmd, int helptype)
|
|
||||||
{
|
|
||||||
char *pc;
|
|
||||||
+ int i;
|
|
||||||
+ char *adv_help;
|
|
||||||
+ char *std_help;
|
|
||||||
+
|
|
||||||
+ /* printf("\t%s %s ", programname, cmd->verb ); */
|
|
||||||
+
|
|
||||||
+ adv_help = cmd->adv_help;
|
|
||||||
+ std_help = cmd->help;
|
|
||||||
+
|
|
||||||
+ for(i = 0; help_messages[i]; i+= 4 ){
|
|
||||||
+ if(!strncmp(help_messages[i],"btrfs ",6) &&
|
|
||||||
+ !strcmp(help_messages[i]+6,cmd->verb) ){
|
|
||||||
+ if(help_messages[i+2])
|
|
||||||
+ std_help = help_messages[i+2];
|
|
||||||
+ if(help_messages[i+3])
|
|
||||||
+ adv_help = help_messages[i+3];
|
|
||||||
+ printf("\t%s\t\t",help_messages[i+1]);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- printf("\t%s %s ", programname, cmd->verb );
|
|
||||||
+ if( !help_messages[i])
|
|
||||||
+ printf("\t%s %s ", programname, cmd->verb );
|
|
||||||
|
|
||||||
- if (helptype == ADVANCED_HELP && cmd->adv_help)
|
|
||||||
- for(pc = cmd->adv_help; *pc; pc++){
|
|
||||||
+ if (helptype == ADVANCED_HELP && adv_help){
|
|
||||||
+ for(pc = adv_help; *pc; pc++){
|
|
||||||
putchar(*pc);
|
|
||||||
if(*pc == '\n')
|
|
||||||
printf("\t\t");
|
|
||||||
}
|
|
||||||
- else
|
|
||||||
- for(pc = cmd->help; *pc; pc++){
|
|
||||||
+ }else{
|
|
||||||
+ for(pc = std_help; *pc; pc++){
|
|
||||||
putchar(*pc);
|
|
||||||
if(*pc == '\n')
|
|
||||||
printf("\t\t");
|
|
||||||
}
|
|
||||||
+ }
|
|
||||||
|
|
||||||
putchar('\n');
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
|||||||
From e2d4509137cb8713b02a030e6116b041ae82588d Mon Sep 17 00:00:00 2001
|
|
||||||
From: Goffredo Baroncelli <kreijack@inwind.it>
|
|
||||||
Date: Sat, 16 Jul 2011 12:11:52 +0200
|
|
||||||
Subject: [PATCH 13/35] Update the makefile for generating the help messages.
|
|
||||||
|
|
||||||
Update the makefile for generating the help messages.
|
|
||||||
---
|
|
||||||
Makefile | 17 ++++++++++++++++-
|
|
||||||
1 files changed, 16 insertions(+), 1 deletions(-)
|
|
||||||
|
|
||||||
Index: btrfs-progs-v0.19-118-gfdb6c04/Makefile
|
|
||||||
===================================================================
|
|
||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/Makefile
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/Makefile
|
|
||||||
@@ -38,8 +38,9 @@ all: version $(progs) manpages
|
|
||||||
version:
|
|
||||||
bash version.sh
|
|
||||||
|
|
||||||
-btrfs: $(objects) btrfs.o btrfs_cmds.o scrub.o
|
|
||||||
+btrfs: $(objects) btrfs.o btrfs_cmds.o scrub.o helpmsg.o
|
|
||||||
$(CC) $(CFLAGS) -o btrfs btrfs.o btrfs_cmds.o scrub.o \
|
|
||||||
+ helpmsg.o \
|
|
||||||
$(objects) $(LDFLAGS) $(LIBS) -lpthread
|
|
||||||
|
|
||||||
calc-size: $(objects) calc-size.o
|
|
||||||
@@ -108,6 +109,19 @@ man/btrfs.8.in: helpextract $(btrfs_man_
|
|
||||||
manpages: man/btrfs.8.in
|
|
||||||
cd man; make
|
|
||||||
|
|
||||||
+helpmsg.c: helpextract $(btrfs_man_page_source)
|
|
||||||
+ echo >$@ "/*"
|
|
||||||
+ echo >>$@ " * this file contains the help messages. It is "
|
|
||||||
+ echo >>$@ " * automatically generated. do not edit ! "
|
|
||||||
+ echo >>$@ " */"
|
|
||||||
+ echo >>$@
|
|
||||||
+ echo >>$@ "#define NULL 0"
|
|
||||||
+ echo >>$@
|
|
||||||
+
|
|
||||||
+ echo -n "char * help_messages[] = " >>$@
|
|
||||||
+ ./helpextract --c-array $(btrfs_man_page_source) >>$@
|
|
||||||
+ echo >>$@ ";"
|
|
||||||
+
|
|
||||||
install-man:
|
|
||||||
cd man; make install
|
|
||||||
|
|
||||||
@@ -115,6 +129,7 @@ clean :
|
|
||||||
rm -f man/btrfs.8.in
|
|
||||||
rm -f $(progs) cscope.out *.o .*.d btrfs-convert btrfs-image btrfs-select-super \
|
|
||||||
btrfs-zero-log btrfstune dir-test ioctl-test quick-test version.h
|
|
||||||
+ rm -f helpmsg.c
|
|
||||||
cd man; make clean
|
|
||||||
|
|
||||||
install: $(progs) install-man
|
|
@ -1,907 +0,0 @@
|
|||||||
From b35dbf547122fa2502c8c7e5646d48148ffdee44 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ilya Dryomov <idryomov@gmail.com>
|
|
||||||
Date: Mon, 16 Jan 2012 12:38:03 +0100
|
|
||||||
Subject: [PATCH 15/43] Btrfs-progs: add restriper commands
|
|
||||||
|
|
||||||
Import restriper commands under btrfs fi balance:
|
|
||||||
|
|
||||||
btrfs fi balance start
|
|
||||||
btrfs fi balance cancel
|
|
||||||
btrfs fi balance pause
|
|
||||||
btrfs fi balance resume
|
|
||||||
btrfs fi balance status
|
|
||||||
|
|
||||||
NOTE: Backwards compatibility is broken for now, to get the old "balance
|
|
||||||
everything" behaviour one has to call 'btrfs fi balance start' with no
|
|
||||||
options instead of 'btrfs fi balance'. This is because btrfs utility
|
|
||||||
sub-command parser is not flexible enough.
|
|
||||||
|
|
||||||
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
|
|
||||||
---
|
|
||||||
btrfs.c | 27 +++-
|
|
||||||
btrfs_cmds.c | 589 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
|
|
||||||
btrfs_cmds.h | 8 +-
|
|
||||||
ctree.h | 23 ++-
|
|
||||||
ioctl.h | 53 ++++++
|
|
||||||
print-tree.c | 6 +
|
|
||||||
volumes.h | 30 +++
|
|
||||||
7 files changed, 687 insertions(+), 49 deletions(-)
|
|
||||||
|
|
||||||
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
|
|
||||||
@@ -295,9 +295,30 @@ static struct Command commands[] = {
|
|
||||||
"Show space usage information for a mount point.",
|
|
||||||
NULL
|
|
||||||
},
|
|
||||||
- { do_balance, 1,
|
|
||||||
- "filesystem balance", "<path>\n"
|
|
||||||
- "Balance the chunks across the device.",
|
|
||||||
+ { do_balance, -1,
|
|
||||||
+ "filesystem balance start", "[-d [filters]] [-m [filters]] "
|
|
||||||
+ "[-s [filters]] [-vf] <path>\n"
|
|
||||||
+ "Balance chunks across the devices.",
|
|
||||||
+ NULL
|
|
||||||
+ },
|
|
||||||
+ { do_balance_pause, 1,
|
|
||||||
+ "filesystem balance pause", "<path>\n"
|
|
||||||
+ "Pause running balance.",
|
|
||||||
+ NULL
|
|
||||||
+ },
|
|
||||||
+ { do_balance_cancel, 1,
|
|
||||||
+ "filesystem balance cancel", "<path>\n"
|
|
||||||
+ "Cancel running or paused balance.",
|
|
||||||
+ NULL
|
|
||||||
+ },
|
|
||||||
+ { do_balance_resume, 1,
|
|
||||||
+ "filesystem balance resume", "<path>\n"
|
|
||||||
+ "Resume interrupted balance.",
|
|
||||||
+ NULL
|
|
||||||
+ },
|
|
||||||
+ { do_balance_progress, -1,
|
|
||||||
+ "filesystem balance status", "[-v] <path>\n"
|
|
||||||
+ "Show status of running or paused balance.",
|
|
||||||
NULL
|
|
||||||
},
|
|
||||||
{ do_change_label, -1,
|
|
||||||
Index: btrfs-progs-v0.19-118-gfdb6c04/btrfs_cmds.c
|
|
||||||
===================================================================
|
|
||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/btrfs_cmds.c
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/btrfs_cmds.c
|
|
||||||
@@ -18,6 +18,7 @@
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
+#include <getopt.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
@@ -1067,43 +1068,6 @@ int do_add_volume(int nargs, char **args
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
-/**** man: btrfs filesystem balance
|
|
||||||
- *
|
|
||||||
- * \Bbtrfs\b \Bfilesystem balance\b \I<path>\i
|
|
||||||
- *
|
|
||||||
- * Balance chunks across the devices.
|
|
||||||
- *
|
|
||||||
- * Balance chunks across the devices.
|
|
||||||
- ****/
|
|
||||||
-
|
|
||||||
-int do_balance(int argc, char **argv)
|
|
||||||
-{
|
|
||||||
-
|
|
||||||
- int fdmnt, ret=0, e;
|
|
||||||
- struct btrfs_ioctl_vol_args args;
|
|
||||||
- char *path = argv[1];
|
|
||||||
-
|
|
||||||
- fdmnt = open_file_or_dir(path);
|
|
||||||
- if (fdmnt < 0) {
|
|
||||||
- fprintf(stderr, "ERROR: can't access to '%s'\n", path);
|
|
||||||
- return 12;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- memset(&args, 0, sizeof(args));
|
|
||||||
- ret = ioctl(fdmnt, BTRFS_IOC_BALANCE, &args);
|
|
||||||
- e = errno;
|
|
||||||
- close(fdmnt);
|
|
||||||
- if(ret<0){
|
|
||||||
- fprintf(stderr, "ERROR: error during balancing '%s' - %s\n",
|
|
||||||
- path, strerror(e));
|
|
||||||
-
|
|
||||||
- return 19;
|
|
||||||
- }
|
|
||||||
- return 0;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-
|
|
||||||
/**** man: btrfs device delete
|
|
||||||
*
|
|
||||||
* \Bbtrfs\b \Bdevice delete\b\I <dev> [<dev>..] <path>\i
|
|
||||||
@@ -1188,6 +1152,575 @@ int do_set_default_subvol(int nargs, cha
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int parse_one_profile(const 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_u64(const char *str, u64 *result)
|
|
||||||
+{
|
|
||||||
+ char *endptr;
|
|
||||||
+ u64 val;
|
|
||||||
+
|
|
||||||
+ val = strtoull(str, &endptr, 10);
|
|
||||||
+ if (*endptr)
|
|
||||||
+ return 1;
|
|
||||||
+
|
|
||||||
+ *result = val;
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int parse_range(const 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 {
|
|
||||||
+ if (parse_u64(rest, end))
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+ if (dots == range) {
|
|
||||||
+ *start = 0;
|
|
||||||
+ skipped++;
|
|
||||||
+ } else {
|
|
||||||
+ if (parse_u64(range, start))
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (*start >= *end) {
|
|
||||||
+ fprintf(stderr, "Range %llu..%llu doesn't make "
|
|
||||||
+ "sense\n", (unsigned long long)*start,
|
|
||||||
+ (unsigned long long)*end);
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (skipped <= 1)
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int parse_filters(char *filters, struct btrfs_balance_args *args)
|
|
||||||
+{
|
|
||||||
+ 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, &args->profiles)) {
|
|
||||||
+ fprintf(stderr, "Invalid profiles argument\n");
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+ args->flags |= BTRFS_BALANCE_ARGS_PROFILES;
|
|
||||||
+ } else if (!strcmp(this_char, "usage")) {
|
|
||||||
+ if (!value || !*value) {
|
|
||||||
+ fprintf(stderr, "the usage filter requires "
|
|
||||||
+ "an argument\n");
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+ if (parse_u64(value, &args->usage) ||
|
|
||||||
+ args->usage < 1 || args->usage > 100) {
|
|
||||||
+ fprintf(stderr, "Invalid usage argument: %s\n",
|
|
||||||
+ value);
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+ args->flags |= BTRFS_BALANCE_ARGS_USAGE;
|
|
||||||
+ } else if (!strcmp(this_char, "devid")) {
|
|
||||||
+ if (!value || !*value) {
|
|
||||||
+ fprintf(stderr, "the devid filter requires "
|
|
||||||
+ "an argument\n");
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+ if (parse_u64(value, &args->devid) ||
|
|
||||||
+ args->devid == 0) {
|
|
||||||
+ fprintf(stderr, "Invalid devid argument: %s\n",
|
|
||||||
+ value);
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+ args->flags |= BTRFS_BALANCE_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, &args->pstart, &args->pend)) {
|
|
||||||
+ fprintf(stderr, "Invalid drange argument\n");
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+ args->flags |= BTRFS_BALANCE_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, &args->vstart, &args->vend)) {
|
|
||||||
+ fprintf(stderr, "Invalid vrange argument\n");
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+ args->flags |= BTRFS_BALANCE_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, &args->target)) {
|
|
||||||
+ fprintf(stderr, "Invalid convert argument\n");
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+ args->flags |= BTRFS_BALANCE_ARGS_CONVERT;
|
|
||||||
+ } else if (!strcmp(this_char, "soft")) {
|
|
||||||
+ args->flags |= BTRFS_BALANCE_ARGS_SOFT;
|
|
||||||
+ } else {
|
|
||||||
+ fprintf(stderr, "Unrecognized balance option '%s'\n",
|
|
||||||
+ this_char);
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void dump_ioctl_balance_args(struct btrfs_ioctl_balance_args *args);
|
|
||||||
+
|
|
||||||
+static struct option balance_longopts[] = {
|
|
||||||
+ { "data", optional_argument, NULL, 'd'},
|
|
||||||
+ { "metadata", optional_argument, NULL, 'm' },
|
|
||||||
+ { "system", optional_argument, NULL, 's' },
|
|
||||||
+ { "force", no_argument, NULL, 'f' },
|
|
||||||
+ { "verbose", no_argument, NULL, 'v' },
|
|
||||||
+ { 0, 0, 0, 0}
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * [-d [filters]] [-m [filters]] [-s [filters]] [-vf]
|
|
||||||
+ */
|
|
||||||
+int do_balance(int argc, char **argv)
|
|
||||||
+{
|
|
||||||
+ int fd;
|
|
||||||
+ char *path;
|
|
||||||
+ struct btrfs_ioctl_balance_args args;
|
|
||||||
+ struct btrfs_balance_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(argc, argv, "d::s::m::fv",
|
|
||||||
+ balance_longopts, &longindex);
|
|
||||||
+ if (opt < 0)
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ switch (opt) {
|
|
||||||
+ case 'd':
|
|
||||||
+ nofilters = 0;
|
|
||||||
+ args.flags |= BTRFS_BALANCE_DATA;
|
|
||||||
+
|
|
||||||
+ if (parse_filters(optarg, &args.data))
|
|
||||||
+ return 1;
|
|
||||||
+ break;
|
|
||||||
+ case 's':
|
|
||||||
+ nofilters = 0;
|
|
||||||
+ args.flags |= BTRFS_BALANCE_SYSTEM;
|
|
||||||
+
|
|
||||||
+ if (parse_filters(optarg, &args.sys))
|
|
||||||
+ return 1;
|
|
||||||
+ break;
|
|
||||||
+ case 'm':
|
|
||||||
+ nofilters = 0;
|
|
||||||
+ args.flags |= BTRFS_BALANCE_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 balance\n");
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (argc - optind != 1) {
|
|
||||||
+ fprintf(stderr, "Invalid arguments for balance\n");
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * allow -s only under --force, otherwise do with system chunks
|
|
||||||
+ * the same thing we were ordered to do with meta chunks
|
|
||||||
+ */
|
|
||||||
+ if (args.flags & BTRFS_BALANCE_SYSTEM) {
|
|
||||||
+ if (!force) {
|
|
||||||
+ fprintf(stderr,
|
|
||||||
+"Refusing to explicitly operate on system chunks.\n"
|
|
||||||
+"Pass --force if you really want to do that.\n");
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+ } else if (args.flags & BTRFS_BALANCE_METADATA) {
|
|
||||||
+ args.flags |= BTRFS_BALANCE_SYSTEM;
|
|
||||||
+ memcpy(&args.sys, &args.meta,
|
|
||||||
+ sizeof(struct btrfs_balance_args));
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (nofilters) {
|
|
||||||
+ /* relocate everything - no filters */
|
|
||||||
+ args.flags |= BTRFS_BALANCE_TYPE_MASK;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* drange makes sense only when devid is set */
|
|
||||||
+ for (i = 0; ptrs[i]; i++) {
|
|
||||||
+ if ((ptrs[i]->flags & BTRFS_BALANCE_ARGS_DRANGE) &&
|
|
||||||
+ !(ptrs[i]->flags & BTRFS_BALANCE_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_BALANCE_ARGS_SOFT) &&
|
|
||||||
+ !(ptrs[i]->flags & BTRFS_BALANCE_ARGS_CONVERT)) {
|
|
||||||
+ fprintf(stderr, "'soft' option can be used only if "
|
|
||||||
+ "changing profiles\n");
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ path = argv[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_BALANCE_FORCE;
|
|
||||||
+ if (verbose)
|
|
||||||
+ dump_ioctl_balance_args(&args);
|
|
||||||
+
|
|
||||||
+ ret = ioctl(fd, BTRFS_IOC_BALANCE_V2, &args);
|
|
||||||
+ e = errno;
|
|
||||||
+ close(fd);
|
|
||||||
+
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ if (e == ECANCELED) {
|
|
||||||
+ if (args.state & BTRFS_BALANCE_STATE_PAUSE_REQ)
|
|
||||||
+ fprintf(stderr, "balance paused by user\n");
|
|
||||||
+ if (args.state & BTRFS_BALANCE_STATE_CANCEL_REQ)
|
|
||||||
+ fprintf(stderr, "balance canceled by user\n");
|
|
||||||
+ } else {
|
|
||||||
+ fprintf(stderr, "ERROR: error during balancing '%s' "
|
|
||||||
+ "- %s\n", path, strerror(e));
|
|
||||||
+ if (e != EINPROGRESS)
|
|
||||||
+ fprintf(stderr, "There may be more info in "
|
|
||||||
+ "syslog - try dmesg | tail\n");
|
|
||||||
+ return 19;
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ printf("Done, had to relocate %llu out of %llu chunks\n",
|
|
||||||
+ (unsigned long long)args.stat.completed,
|
|
||||||
+ (unsigned long long)args.stat.considered);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int do_balance_pause(int argc, char **argv)
|
|
||||||
+{
|
|
||||||
+ int fd;
|
|
||||||
+ char *path = argv[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_BALANCE_CTL, BTRFS_BALANCE_CTL_PAUSE);
|
|
||||||
+ e = errno;
|
|
||||||
+ close(fd);
|
|
||||||
+
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ fprintf(stderr, "ERROR: balance pause on '%s' failed - %s\n",
|
|
||||||
+ path, (e == ENOTCONN) ? "Not running" : strerror(e));
|
|
||||||
+ return 19;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int do_balance_cancel(int argc, char **argv)
|
|
||||||
+{
|
|
||||||
+ int fd;
|
|
||||||
+ char *path = argv[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_BALANCE_CTL, BTRFS_BALANCE_CTL_CANCEL);
|
|
||||||
+ e = errno;
|
|
||||||
+ close(fd);
|
|
||||||
+
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ fprintf(stderr, "ERROR: balance cancel on '%s' failed - %s\n",
|
|
||||||
+ path, (e == ENOTCONN) ? "Not in progress" : strerror(e));
|
|
||||||
+ return 19;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int do_balance_resume(int argc, char **argv)
|
|
||||||
+{
|
|
||||||
+ int fd;
|
|
||||||
+ char *path = argv[1];
|
|
||||||
+ struct btrfs_ioctl_balance_args args;
|
|
||||||
+ 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;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ memset(&args, 0, sizeof(args));
|
|
||||||
+ args.flags |= BTRFS_BALANCE_RESUME;
|
|
||||||
+
|
|
||||||
+ ret = ioctl(fd, BTRFS_IOC_BALANCE_V2, &args);
|
|
||||||
+ e = errno;
|
|
||||||
+ close(fd);
|
|
||||||
+
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ if (e == ECANCELED) {
|
|
||||||
+ if (args.state & BTRFS_BALANCE_STATE_PAUSE_REQ)
|
|
||||||
+ fprintf(stderr, "balance paused by user\n");
|
|
||||||
+ if (args.state & BTRFS_BALANCE_STATE_CANCEL_REQ)
|
|
||||||
+ fprintf(stderr, "balance canceled by user\n");
|
|
||||||
+ } else if (e == ENOTCONN || e == EINPROGRESS) {
|
|
||||||
+ fprintf(stderr, "ERROR: balance resume on '%s' "
|
|
||||||
+ "failed - %s\n", path,
|
|
||||||
+ (e == ENOTCONN) ? "Not in progress" :
|
|
||||||
+ "Already running");
|
|
||||||
+ return 19;
|
|
||||||
+ } else {
|
|
||||||
+ fprintf(stderr,
|
|
||||||
+"ERROR: error during balancing '%s' - %s\n"
|
|
||||||
+"There may be more info in syslog - try dmesg | tail\n", path, strerror(e));
|
|
||||||
+ return 19;
|
|
||||||
+ }
|
|
||||||
+ } else {
|
|
||||||
+ printf("Done, had to relocate %llu out of %llu chunks\n",
|
|
||||||
+ (unsigned long long)args.stat.completed,
|
|
||||||
+ (unsigned long long)args.stat.considered);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static struct option balance_progress_longopts[] = {
|
|
||||||
+ { "verbose", no_argument, NULL, 'v' },
|
|
||||||
+ { 0, 0, 0, 0}
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+int do_balance_progress(int argc, char **argv)
|
|
||||||
+{
|
|
||||||
+ int fd;
|
|
||||||
+ char *path;
|
|
||||||
+ struct btrfs_ioctl_balance_args args;
|
|
||||||
+ int verbose = 0;
|
|
||||||
+ int longindex;
|
|
||||||
+ int ret;
|
|
||||||
+ int e;
|
|
||||||
+
|
|
||||||
+ while (1) {
|
|
||||||
+ int opt = getopt_long(argc, argv, "v",
|
|
||||||
+ balance_progress_longopts, &longindex);
|
|
||||||
+ if (opt < 0)
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ switch (opt) {
|
|
||||||
+ case 'v':
|
|
||||||
+ verbose = 1;
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ fprintf(stderr, "Invalid arguments for balance "
|
|
||||||
+ "status\n");
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (argc - optind != 1) {
|
|
||||||
+ fprintf(stderr, "Invalid arguments for balance status\n");
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ path = argv[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_BALANCE_PROGRESS, &args);
|
|
||||||
+ e = errno;
|
|
||||||
+ close(fd);
|
|
||||||
+
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ fprintf(stderr, "ERROR: balance status on '%s' failed - %s\n",
|
|
||||||
+ path, (e == ENOTCONN) ? "Not in progress" : strerror(e));
|
|
||||||
+ return 19;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (args.state & BTRFS_BALANCE_STATE_RUNNING) {
|
|
||||||
+ printf("Balance on '%s' is running", path);
|
|
||||||
+ if (args.state & BTRFS_BALANCE_STATE_CANCEL_REQ)
|
|
||||||
+ printf(", cancel requested\n");
|
|
||||||
+ else if (args.state & BTRFS_BALANCE_STATE_PAUSE_REQ)
|
|
||||||
+ printf(", pause requested\n");
|
|
||||||
+ else
|
|
||||||
+ printf("\n");
|
|
||||||
+ } else {
|
|
||||||
+ printf("Balance on '%s' is paused\n", path);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ printf("%llu out of about %llu chunks balanced (%llu considered), "
|
|
||||||
+ "%3.f%% left\n", (unsigned long long)args.stat.completed,
|
|
||||||
+ (unsigned long long)args.stat.expected,
|
|
||||||
+ (unsigned long long)args.stat.considered,
|
|
||||||
+ 100 * (1 - (float)args.stat.completed/args.stat.expected));
|
|
||||||
+
|
|
||||||
+ if (verbose)
|
|
||||||
+ dump_ioctl_balance_args(&args);
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void dump_balance_args(struct btrfs_balance_args *args)
|
|
||||||
+{
|
|
||||||
+ if (args->flags & BTRFS_BALANCE_ARGS_CONVERT) {
|
|
||||||
+ printf("converting, target=%llu, soft is %s",
|
|
||||||
+ (unsigned long long)args->target,
|
|
||||||
+ (args->flags & BTRFS_BALANCE_ARGS_SOFT) ? "on" : "off");
|
|
||||||
+ } else {
|
|
||||||
+ printf("balancing");
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (args->flags & BTRFS_BALANCE_ARGS_PROFILES)
|
|
||||||
+ printf(", profiles=%llu", (unsigned long long)args->profiles);
|
|
||||||
+ if (args->flags & BTRFS_BALANCE_ARGS_USAGE)
|
|
||||||
+ printf(", usage=%llu", (unsigned long long)args->usage);
|
|
||||||
+ if (args->flags & BTRFS_BALANCE_ARGS_DEVID)
|
|
||||||
+ printf(", devid=%llu", (unsigned long long)args->devid);
|
|
||||||
+ if (args->flags & BTRFS_BALANCE_ARGS_DRANGE)
|
|
||||||
+ printf(", drange=%llu..%llu",
|
|
||||||
+ (unsigned long long)args->pstart,
|
|
||||||
+ (unsigned long long)args->pend);
|
|
||||||
+ if (args->flags & BTRFS_BALANCE_ARGS_VRANGE)
|
|
||||||
+ printf(", vrange=%llu..%llu",
|
|
||||||
+ (unsigned long long)args->vstart,
|
|
||||||
+ (unsigned long long)args->vend);
|
|
||||||
+
|
|
||||||
+ printf("\n");
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void dump_ioctl_balance_args(struct btrfs_ioctl_balance_args *args)
|
|
||||||
+{
|
|
||||||
+ printf("Dumping filters: flags 0x%llx, state 0x%llx, force is %s\n",
|
|
||||||
+ (unsigned long long)args->flags, (unsigned long long)args->state,
|
|
||||||
+ (args->flags & BTRFS_BALANCE_FORCE) ? "on" : "off");
|
|
||||||
+ if (args->flags & BTRFS_BALANCE_DATA) {
|
|
||||||
+ printf(" DATA (flags 0x%llx): ",
|
|
||||||
+ (unsigned long long)args->data.flags);
|
|
||||||
+ dump_balance_args(&args->data);
|
|
||||||
+ }
|
|
||||||
+ if (args->flags & BTRFS_BALANCE_METADATA) {
|
|
||||||
+ printf(" METADATA (flags 0x%llx): ",
|
|
||||||
+ (unsigned long long)args->meta.flags);
|
|
||||||
+ dump_balance_args(&args->meta);
|
|
||||||
+ }
|
|
||||||
+ if (args->flags & BTRFS_BALANCE_SYSTEM) {
|
|
||||||
+ printf(" SYSTEM (flags 0x%llx): ",
|
|
||||||
+ (unsigned long long)args->sys.flags);
|
|
||||||
+ dump_balance_args(&args->sys);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
|
|
||||||
/**** man: btrfs filesystem label
|
|
||||||
*
|
|
||||||
Index: btrfs-progs-v0.19-118-gfdb6c04/btrfs_cmds.h
|
|
||||||
===================================================================
|
|
||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/btrfs_cmds.h
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/btrfs_cmds.h
|
|
||||||
@@ -22,12 +22,16 @@ int do_fssync(int nargs, char **argv);
|
|
||||||
int do_defrag(int argc, char **argv);
|
|
||||||
int do_show_filesystem(int nargs, char **argv);
|
|
||||||
int do_add_volume(int nargs, char **args);
|
|
||||||
-int do_balance(int nargs, char **argv);
|
|
||||||
+int do_remove_volume(int nargs, char **args);
|
|
||||||
+int do_balance(int argc, char **argv);
|
|
||||||
+int do_balance_pause(int argc, char **argv);
|
|
||||||
+int do_balance_cancel(int argc, char **argv);
|
|
||||||
+int do_balance_resume(int argc, char **argv);
|
|
||||||
+int do_balance_progress(int argc, char **argv);
|
|
||||||
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_remove_volume(int nargs, char **args);
|
|
||||||
int do_scan(int nargs, char **argv);
|
|
||||||
int do_resize(int nargs, char **argv);
|
|
||||||
int do_subvol_list(int nargs, char **argv);
|
|
||||||
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
|
|
||||||
@@ -61,6 +61,9 @@ struct btrfs_trans_handle;
|
|
||||||
#define BTRFS_CSUM_TREE_OBJECTID 7ULL
|
|
||||||
|
|
||||||
|
|
||||||
+/* for storing balance parameters in the root tree */
|
|
||||||
+#define BTRFS_BALANCE_OBJECTID -4ULL
|
|
||||||
+
|
|
||||||
/* oprhan objectid for tracking unlinked/truncated files */
|
|
||||||
#define BTRFS_ORPHAN_OBJECTID -5ULL
|
|
||||||
|
|
||||||
@@ -697,13 +700,17 @@ struct btrfs_csum_item {
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
/* tag for the radix tree of block groups in ram */
|
|
||||||
-#define BTRFS_BLOCK_GROUP_DATA (1 << 0)
|
|
||||||
-#define BTRFS_BLOCK_GROUP_SYSTEM (1 << 1)
|
|
||||||
-#define BTRFS_BLOCK_GROUP_METADATA (1 << 2)
|
|
||||||
-#define BTRFS_BLOCK_GROUP_RAID0 (1 << 3)
|
|
||||||
-#define BTRFS_BLOCK_GROUP_RAID1 (1 << 4)
|
|
||||||
-#define BTRFS_BLOCK_GROUP_DUP (1 << 5)
|
|
||||||
-#define BTRFS_BLOCK_GROUP_RAID10 (1 << 6)
|
|
||||||
+#define BTRFS_BLOCK_GROUP_DATA (1ULL << 0)
|
|
||||||
+#define BTRFS_BLOCK_GROUP_SYSTEM (1ULL << 1)
|
|
||||||
+#define BTRFS_BLOCK_GROUP_METADATA (1ULL << 2)
|
|
||||||
+#define BTRFS_BLOCK_GROUP_RAID0 (1ULL << 3)
|
|
||||||
+#define BTRFS_BLOCK_GROUP_RAID1 (1ULL << 4)
|
|
||||||
+#define BTRFS_BLOCK_GROUP_DUP (1ULL << 5)
|
|
||||||
+#define BTRFS_BLOCK_GROUP_RAID10 (1ULL << 6)
|
|
||||||
+#define BTRFS_BLOCK_GROUP_RESERVED BTRFS_AVAIL_ALLOC_BIT_SINGLE
|
|
||||||
+
|
|
||||||
+/* used in struct btrfs_balance_args fields */
|
|
||||||
+#define BTRFS_AVAIL_ALLOC_BIT_SINGLE (1ULL << 48)
|
|
||||||
|
|
||||||
struct btrfs_block_group_item {
|
|
||||||
__le64 used;
|
|
||||||
@@ -911,6 +918,8 @@ struct btrfs_root {
|
|
||||||
#define BTRFS_DEV_ITEM_KEY 216
|
|
||||||
#define BTRFS_CHUNK_ITEM_KEY 228
|
|
||||||
|
|
||||||
+#define BTRFS_BALANCE_ITEM_KEY 248
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* string items are for debugging. They just store a short string of
|
|
||||||
* data in the FS
|
|
||||||
Index: btrfs-progs-v0.19-118-gfdb6c04/ioctl.h
|
|
||||||
===================================================================
|
|
||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/ioctl.h
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/ioctl.h
|
|
||||||
@@ -91,6 +91,54 @@ struct btrfs_ioctl_fs_info_args {
|
|
||||||
__u64 reserved[124]; /* pad to 1k */
|
|
||||||
};
|
|
||||||
|
|
||||||
+/* balance control ioctl modes */
|
|
||||||
+#define BTRFS_BALANCE_CTL_PAUSE 1
|
|
||||||
+#define BTRFS_BALANCE_CTL_CANCEL 2
|
|
||||||
+#define BTRFS_BALANCE_CTL_RESUME 3
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * this is packed, because it should be exactly the same as its disk
|
|
||||||
+ * byte order counterpart (struct btrfs_disk_balance_args)
|
|
||||||
+ */
|
|
||||||
+struct btrfs_balance_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_balance_progress {
|
|
||||||
+ __u64 expected;
|
|
||||||
+ __u64 considered;
|
|
||||||
+ __u64 completed;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+#define BTRFS_BALANCE_STATE_RUNNING (1ULL << 0)
|
|
||||||
+#define BTRFS_BALANCE_STATE_PAUSE_REQ (1ULL << 1)
|
|
||||||
+#define BTRFS_BALANCE_STATE_CANCEL_REQ (1ULL << 2)
|
|
||||||
+
|
|
||||||
+struct btrfs_ioctl_balance_args {
|
|
||||||
+ __u64 flags; /* in/out */
|
|
||||||
+ __u64 state; /* out */
|
|
||||||
+
|
|
||||||
+ struct btrfs_balance_args data; /* in/out */
|
|
||||||
+ struct btrfs_balance_args meta; /* in/out */
|
|
||||||
+ struct btrfs_balance_args sys; /* in/out */
|
|
||||||
+
|
|
||||||
+ struct btrfs_balance_progress stat; /* out */
|
|
||||||
+
|
|
||||||
+ __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;
|
|
||||||
@@ -284,6 +332,11 @@ struct btrfs_ioctl_compr_size_args {
|
|
||||||
struct btrfs_ioctl_dev_info_args)
|
|
||||||
#define BTRFS_IOC_FS_INFO _IOR(BTRFS_IOCTL_MAGIC, 31, \
|
|
||||||
struct btrfs_ioctl_fs_info_args)
|
|
||||||
+#define BTRFS_IOC_BALANCE_V2 _IOWR(BTRFS_IOCTL_MAGIC, 32, \
|
|
||||||
+ struct btrfs_ioctl_balance_args)
|
|
||||||
+#define BTRFS_IOC_BALANCE_CTL _IOW(BTRFS_IOCTL_MAGIC, 33, int)
|
|
||||||
+#define BTRFS_IOC_BALANCE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 34, \
|
|
||||||
+ struct btrfs_ioctl_balance_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, \
|
|
||||||
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
|
|
||||||
@@ -351,6 +351,9 @@ static void print_key_type(u8 type)
|
|
||||||
case BTRFS_DEV_EXTENT_KEY:
|
|
||||||
printf("DEV_EXTENT");
|
|
||||||
break;
|
|
||||||
+ case BTRFS_BALANCE_ITEM_KEY:
|
|
||||||
+ printf("BALANCE_ITEM");
|
|
||||||
+ break;
|
|
||||||
case BTRFS_STRING_ITEM_KEY:
|
|
||||||
printf("STRING_ITEM");
|
|
||||||
break;
|
|
||||||
@@ -391,6 +394,9 @@ static void print_objectid(unsigned long
|
|
||||||
case BTRFS_CSUM_TREE_OBJECTID:
|
|
||||||
printf("CSUM_TREE");
|
|
||||||
break;
|
|
||||||
+ case BTRFS_BALANCE_OBJECTID:
|
|
||||||
+ printf("BALANCE");
|
|
||||||
+ break;
|
|
||||||
case BTRFS_ORPHAN_OBJECTID:
|
|
||||||
printf("ORPHAN");
|
|
||||||
break;
|
|
||||||
Index: btrfs-progs-v0.19-118-gfdb6c04/volumes.h
|
|
||||||
===================================================================
|
|
||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/volumes.h
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/volumes.h
|
|
||||||
@@ -91,6 +91,37 @@ 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
|
|
||||||
+ */
|
|
||||||
+#define BTRFS_BALANCE_DATA (1ULL << 0)
|
|
||||||
+#define BTRFS_BALANCE_SYSTEM (1ULL << 1)
|
|
||||||
+#define BTRFS_BALANCE_METADATA (1ULL << 2)
|
|
||||||
+
|
|
||||||
+#define BTRFS_BALANCE_TYPE_MASK (BTRFS_BALANCE_DATA | \
|
|
||||||
+ BTRFS_BALANCE_SYSTEM | \
|
|
||||||
+ BTRFS_BALANCE_METADATA)
|
|
||||||
+
|
|
||||||
+#define BTRFS_BALANCE_FORCE (1ULL << 3)
|
|
||||||
+#define BTRFS_BALANCE_RESUME (1ULL << 4)
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Balance filters
|
|
||||||
+ */
|
|
||||||
+#define BTRFS_BALANCE_ARGS_PROFILES (1ULL << 0)
|
|
||||||
+#define BTRFS_BALANCE_ARGS_USAGE (1ULL << 1)
|
|
||||||
+#define BTRFS_BALANCE_ARGS_DEVID (1ULL << 2)
|
|
||||||
+#define BTRFS_BALANCE_ARGS_DRANGE (1ULL << 3)
|
|
||||||
+#define BTRFS_BALANCE_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_BALANCE_ARGS_CONVERT (1ULL << 8)
|
|
||||||
+#define BTRFS_BALANCE_ARGS_SOFT (1ULL << 9)
|
|
||||||
+
|
|
||||||
int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
|
|
||||||
struct btrfs_device *device,
|
|
||||||
u64 chunk_tree, u64 chunk_objectid,
|
|
@ -1,181 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,85 +0,0 @@
|
|||||||
From 6ca37050db7e94257559da2b8e8009c2347ed798 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Chris Mason <chris.mason@oracle.com>
|
|
||||||
Date: Thu, 27 Oct 2011 16:23:14 -0400
|
|
||||||
Subject: [PATCH 16/35] btrfs-progs: fixup is_mounted checks
|
|
||||||
|
|
||||||
/proc/mounts contains device names that don't exist,
|
|
||||||
we end up erroring out because we're not able to stat
|
|
||||||
the device (that doesn't exist).
|
|
||||||
|
|
||||||
Fix this by allowing the mkfs when the target device doesn't exist.
|
|
||||||
|
|
||||||
Signed-off-by: Chris Mason <chris.mason@oracle.com>
|
|
||||||
---
|
|
||||||
utils.c | 34 +++++++++++++++++++---------------
|
|
||||||
1 files changed, 19 insertions(+), 15 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/utils.c b/utils.c
|
|
||||||
index 1c27e14..6c96548 100644
|
|
||||||
--- a/utils.c
|
|
||||||
+++ b/utils.c
|
|
||||||
@@ -674,11 +674,11 @@ int is_same_blk_file(const char* a, const char* b)
|
|
||||||
char real_a[PATH_MAX];
|
|
||||||
char real_b[PATH_MAX];
|
|
||||||
|
|
||||||
- if(!realpath(a, real_a) ||
|
|
||||||
- !realpath(b, real_b))
|
|
||||||
- {
|
|
||||||
- return -errno;
|
|
||||||
- }
|
|
||||||
+ if(!realpath(a, real_a))
|
|
||||||
+ strcpy(real_a, a);
|
|
||||||
+
|
|
||||||
+ if (!realpath(b, real_b))
|
|
||||||
+ strcpy(real_b, b);
|
|
||||||
|
|
||||||
/* Identical path? */
|
|
||||||
if(strcmp(real_a, real_b) == 0)
|
|
||||||
@@ -719,8 +719,8 @@ int is_same_loop_file(const char* a, const char* b)
|
|
||||||
{
|
|
||||||
char res_a[PATH_MAX];
|
|
||||||
char res_b[PATH_MAX];
|
|
||||||
- const char* final_a;
|
|
||||||
- const char* final_b;
|
|
||||||
+ const char* final_a = NULL;
|
|
||||||
+ const char* final_b = NULL;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* Resolve a if it is a loop device */
|
|
||||||
@@ -729,10 +729,12 @@ int is_same_loop_file(const char* a, const char* b)
|
|
||||||
return 0;
|
|
||||||
return ret;
|
|
||||||
} else if (ret) {
|
|
||||||
- if ((ret = resolve_loop_device(a, res_a, sizeof(res_a))) < 0)
|
|
||||||
- return ret;
|
|
||||||
-
|
|
||||||
- final_a = res_a;
|
|
||||||
+ if ((ret = resolve_loop_device(a, res_a, sizeof(res_a))) < 0) {
|
|
||||||
+ if (errno != EPERM)
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ final_a = res_a;
|
|
||||||
} else {
|
|
||||||
final_a = a;
|
|
||||||
}
|
|
||||||
@@ -743,10 +745,12 @@ int is_same_loop_file(const char* a, const char* b)
|
|
||||||
return 0;
|
|
||||||
return ret;
|
|
||||||
} else if (ret) {
|
|
||||||
- if((ret = resolve_loop_device(b, res_b, sizeof(res_b))) < 0)
|
|
||||||
- return ret;
|
|
||||||
-
|
|
||||||
- final_b = res_b;
|
|
||||||
+ if ((ret = resolve_loop_device(b, res_b, sizeof(res_b))) < 0) {
|
|
||||||
+ if (errno != EPERM)
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ final_b = res_b;
|
|
||||||
} else {
|
|
||||||
final_b = b;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
|||||||
From 0e6aead68455a1043aed04e0557dc14af2cd6f60 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Josef Bacik <josef@redhat.com>
|
|
||||||
Date: Tue, 1 Nov 2011 14:26:20 -0400
|
|
||||||
Subject: [PATCH 17/35] Btrfs-progs: add an option for specifying the root to
|
|
||||||
restore
|
|
||||||
|
|
||||||
If the normal fs tree is hosed and the user has multiple subvolumes it's handy
|
|
||||||
to be able to specify just one of the subvolumes to restore. It's also handy if
|
|
||||||
a user only wants to restore say /home instead of his entire disk. Thanks,
|
|
||||||
|
|
||||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
|
||||||
---
|
|
||||||
restore.c | 32 ++++++++++++++++++++++++++++----
|
|
||||||
1 files changed, 28 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/restore.c b/restore.c
|
|
||||||
index 250c9d3..38c4ded 100644
|
|
||||||
--- a/restore.c
|
|
||||||
+++ b/restore.c
|
|
||||||
@@ -760,13 +760,14 @@ int main(int argc, char **argv)
|
|
||||||
char dir_name[128];
|
|
||||||
u64 tree_location = 0;
|
|
||||||
u64 fs_location = 0;
|
|
||||||
+ u64 root_objectid = 0;
|
|
||||||
int len;
|
|
||||||
int ret;
|
|
||||||
int opt;
|
|
||||||
int super_mirror = 0;
|
|
||||||
int find_dir = 0;
|
|
||||||
|
|
||||||
- while ((opt = getopt(argc, argv, "sviot:u:df:")) != -1) {
|
|
||||||
+ while ((opt = getopt(argc, argv, "sviot:u:df:r:")) != -1) {
|
|
||||||
switch (opt) {
|
|
||||||
case 's':
|
|
||||||
get_snaps = 1;
|
|
||||||
@@ -809,6 +810,14 @@ int main(int argc, char **argv)
|
|
||||||
case 'd':
|
|
||||||
find_dir = 1;
|
|
||||||
break;
|
|
||||||
+ case 'r':
|
|
||||||
+ errno = 0;
|
|
||||||
+ root_objectid = (u64)strtoll(optarg, NULL, 10);
|
|
||||||
+ if (errno != 0) {
|
|
||||||
+ fprintf(stderr, "Root objectid not valid\n");
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
default:
|
|
||||||
usage();
|
|
||||||
exit(1);
|
|
||||||
@@ -842,8 +851,6 @@ int main(int argc, char **argv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- printf("Root objectid is %Lu\n", root->objectid);
|
|
||||||
-
|
|
||||||
memset(path_name, 0, 4096);
|
|
||||||
|
|
||||||
strncpy(dir_name, argv[optind + 1], 128);
|
|
||||||
@@ -856,6 +863,23 @@ 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)
|
|
||||||
@@ -864,7 +888,7 @@ int main(int argc, char **argv)
|
|
||||||
key.objectid = BTRFS_FIRST_FREE_OBJECTID;
|
|
||||||
}
|
|
||||||
|
|
||||||
- ret = search_dir(root->fs_info->fs_root, &key, dir_name);
|
|
||||||
+ ret = search_dir(root, &key, dir_name);
|
|
||||||
|
|
||||||
out:
|
|
||||||
close_ctree(root);
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,134 +0,0 @@
|
|||||||
From 9dee07a6365d2facddea9a501737dce92333c582 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Josef Bacik <josef@redhat.com>
|
|
||||||
Date: Fri, 4 Nov 2011 09:10:49 -0400
|
|
||||||
Subject: [PATCH 18/35] Btrfs-progs: try other mirrors if decomression fails
|
|
||||||
|
|
||||||
This will make the restore program fall back on other mirrors if it fails to
|
|
||||||
decompress an extent for whatever reason. Thanks,
|
|
||||||
|
|
||||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
|
||||||
---
|
|
||||||
restore.c | 47 +++++++++++++++++++++++++----------------------
|
|
||||||
1 files changed, 25 insertions(+), 22 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/restore.c b/restore.c
|
|
||||||
index 38c4ded..f062a2b 100644
|
|
||||||
--- a/restore.c
|
|
||||||
+++ b/restore.c
|
|
||||||
@@ -61,7 +61,7 @@ static int decompress(char *inbuf, char *outbuf, u64 compress_len,
|
|
||||||
ret = inflate(&strm, Z_NO_FLUSH);
|
|
||||||
if (ret != Z_STREAM_END) {
|
|
||||||
(void)inflateEnd(&strm);
|
|
||||||
- fprintf(stderr, "ret is %d\n", ret);
|
|
||||||
+ fprintf(stderr, "failed to inflate: %d\n", ret);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -197,6 +197,8 @@ static int copy_one_extent(struct btrfs_root *root, int fd,
|
|
||||||
int compress;
|
|
||||||
int ret;
|
|
||||||
int dev_fd;
|
|
||||||
+ int mirror_num = 0;
|
|
||||||
+ int num_copies;
|
|
||||||
|
|
||||||
compress = btrfs_file_extent_compression(leaf, fi);
|
|
||||||
bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
|
|
||||||
@@ -225,12 +227,10 @@ static int copy_one_extent(struct btrfs_root *root, int fd,
|
|
||||||
again:
|
|
||||||
length = size_left;
|
|
||||||
ret = btrfs_map_block(&root->fs_info->mapping_tree, READ,
|
|
||||||
- bytenr, &length, &multi, 0);
|
|
||||||
+ bytenr, &length, &multi, mirror_num);
|
|
||||||
if (ret) {
|
|
||||||
- free(inbuf);
|
|
||||||
- free(outbuf);
|
|
||||||
fprintf(stderr, "Error mapping block %d\n", ret);
|
|
||||||
- return ret;
|
|
||||||
+ goto out;
|
|
||||||
}
|
|
||||||
device = multi->stripes[0].dev;
|
|
||||||
dev_fd = device->fd;
|
|
||||||
@@ -244,10 +244,9 @@ again:
|
|
||||||
|
|
||||||
done = pread(dev_fd, inbuf+count, length, dev_bytenr);
|
|
||||||
if (done < length) {
|
|
||||||
- free(inbuf);
|
|
||||||
- free(outbuf);
|
|
||||||
+ ret = -1;
|
|
||||||
fprintf(stderr, "Short read %d\n", errno);
|
|
||||||
- return -1;
|
|
||||||
+ goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
count += length;
|
|
||||||
@@ -255,41 +254,46 @@ again:
|
|
||||||
if (size_left)
|
|
||||||
goto again;
|
|
||||||
|
|
||||||
-
|
|
||||||
if (compress == BTRFS_COMPRESS_NONE) {
|
|
||||||
while (total < ram_size) {
|
|
||||||
done = pwrite(fd, inbuf+total, ram_size-total,
|
|
||||||
pos+total);
|
|
||||||
if (done < 0) {
|
|
||||||
- free(inbuf);
|
|
||||||
+ ret = -1;
|
|
||||||
fprintf(stderr, "Error writing: %d %s\n", errno, strerror(errno));
|
|
||||||
- return -1;
|
|
||||||
+ goto out;
|
|
||||||
}
|
|
||||||
total += done;
|
|
||||||
}
|
|
||||||
- free(inbuf);
|
|
||||||
- return 0;
|
|
||||||
+ ret = 0;
|
|
||||||
+ goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = decompress(inbuf, outbuf, disk_size, ram_size);
|
|
||||||
- free(inbuf);
|
|
||||||
if (ret) {
|
|
||||||
- free(outbuf);
|
|
||||||
- return ret;
|
|
||||||
+ num_copies = btrfs_num_copies(&root->fs_info->mapping_tree,
|
|
||||||
+ bytenr, length);
|
|
||||||
+ mirror_num++;
|
|
||||||
+ if (mirror_num >= num_copies) {
|
|
||||||
+ ret = -1;
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ fprintf(stderr, "Trying another mirror\n");
|
|
||||||
+ goto again;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (total < ram_size) {
|
|
||||||
done = pwrite(fd, outbuf+total, ram_size-total, pos+total);
|
|
||||||
if (done < 0) {
|
|
||||||
- free(outbuf);
|
|
||||||
- fprintf(stderr, "Error writing: %d %s\n", errno, strerror(errno));
|
|
||||||
- return -1;
|
|
||||||
+ ret = -1;
|
|
||||||
+ goto out;
|
|
||||||
}
|
|
||||||
total += done;
|
|
||||||
}
|
|
||||||
+out:
|
|
||||||
+ free(inbuf);
|
|
||||||
free(outbuf);
|
|
||||||
-
|
|
||||||
- return 0;
|
|
||||||
+ return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ask_to_continue(const char *file)
|
|
||||||
@@ -385,7 +389,6 @@ static int copy_file(struct btrfs_root *root, int fd, struct btrfs_key *key,
|
|
||||||
/* No more leaves to search */
|
|
||||||
btrfs_free_path(path);
|
|
||||||
goto set_size;
|
|
||||||
- return 0;
|
|
||||||
}
|
|
||||||
leaf = path->nodes[0];
|
|
||||||
} while (!leaf);
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
|||||||
From ff0e1b17030a9b1e027c8b77f67ab44136e172ac Mon Sep 17 00:00:00 2001
|
|
||||||
From: Josef Bacik <josef@redhat.com>
|
|
||||||
Date: Mon, 7 Nov 2011 16:41:01 -0500
|
|
||||||
Subject: [PATCH 19/35] Btrfs-progs: try other mirrors on read failure
|
|
||||||
|
|
||||||
If we hit a bad disk and the read doesn't work, try other mirrors in case we
|
|
||||||
have other disks with good copies. Thanks,
|
|
||||||
|
|
||||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
|
||||||
---
|
|
||||||
restore.c | 13 ++++++++++---
|
|
||||||
1 files changed, 10 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/restore.c b/restore.c
|
|
||||||
index f062a2b..4dabae2 100644
|
|
||||||
--- a/restore.c
|
|
||||||
+++ b/restore.c
|
|
||||||
@@ -244,9 +244,16 @@ again:
|
|
||||||
|
|
||||||
done = pread(dev_fd, inbuf+count, length, dev_bytenr);
|
|
||||||
if (done < length) {
|
|
||||||
- ret = -1;
|
|
||||||
- fprintf(stderr, "Short read %d\n", errno);
|
|
||||||
- goto out;
|
|
||||||
+ num_copies = btrfs_num_copies(&root->fs_info->mapping_tree,
|
|
||||||
+ bytenr, length);
|
|
||||||
+ mirror_num++;
|
|
||||||
+ if (mirror_num >= num_copies) {
|
|
||||||
+ ret = -1;
|
|
||||||
+ fprintf(stderr, "Exhausted mirrors trying to read\n");
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ fprintf(stderr, "Trying another mirror\n");
|
|
||||||
+ goto again;
|
|
||||||
}
|
|
||||||
|
|
||||||
count += length;
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
|||||||
From 16073605bb947e6acfa3b13b6280a90fed9b717a Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Marcin <djmarcin@google.com>
|
|
||||||
Date: Wed, 9 Nov 2011 13:23:28 -0800
|
|
||||||
Subject: [PATCH 20/35] btrfs-progs: Fix error handling for failed reads in
|
|
||||||
restore tool when mirrors exist
|
|
||||||
|
|
||||||
---
|
|
||||||
restore.c | 11 +++++++----
|
|
||||||
1 files changed, 7 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/restore.c b/restore.c
|
|
||||||
index 4dabae2..389b107 100644
|
|
||||||
--- a/restore.c
|
|
||||||
+++ b/restore.c
|
|
||||||
@@ -197,7 +197,7 @@ static int copy_one_extent(struct btrfs_root *root, int fd,
|
|
||||||
int compress;
|
|
||||||
int ret;
|
|
||||||
int dev_fd;
|
|
||||||
- int mirror_num = 0;
|
|
||||||
+ int mirror_num = 1;
|
|
||||||
int num_copies;
|
|
||||||
|
|
||||||
compress = btrfs_file_extent_compression(leaf, fi);
|
|
||||||
@@ -240,14 +240,15 @@ again:
|
|
||||||
|
|
||||||
if (size_left < length)
|
|
||||||
length = size_left;
|
|
||||||
- size_left -= length;
|
|
||||||
|
|
||||||
done = pread(dev_fd, inbuf+count, length, dev_bytenr);
|
|
||||||
- if (done < length) {
|
|
||||||
+ /* Need both checks, or we miss negative values due to u64 conversion */
|
|
||||||
+ if (done < 0 || done < length) {
|
|
||||||
num_copies = btrfs_num_copies(&root->fs_info->mapping_tree,
|
|
||||||
bytenr, length);
|
|
||||||
mirror_num++;
|
|
||||||
- if (mirror_num >= num_copies) {
|
|
||||||
+ /* mirror_num is 1-indexed, so num_copies is a valid mirror. */
|
|
||||||
+ if (mirror_num > num_copies) {
|
|
||||||
ret = -1;
|
|
||||||
fprintf(stderr, "Exhausted mirrors trying to read\n");
|
|
||||||
goto out;
|
|
||||||
@@ -256,6 +257,8 @@ again:
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ mirror_num = 1;
|
|
||||||
+ size_left -= length;
|
|
||||||
count += length;
|
|
||||||
bytenr += length;
|
|
||||||
if (size_left)
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
|||||||
From a1ebf7b951c6796039748601404aa01fd283ddef Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Marcin <djmarcin@google.com>
|
|
||||||
Date: Wed, 16 Nov 2011 12:18:08 -0800
|
|
||||||
Subject: [PATCH 21/35] btrfs-progs: Check metadata mirrors in find-root.
|
|
||||||
|
|
||||||
Signed-off-by: David Marcin <djmarcin@google.com>
|
|
||||||
---
|
|
||||||
find-root.c | 13 ++++++++++++-
|
|
||||||
1 files changed, 12 insertions(+), 1 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/find-root.c b/find-root.c
|
|
||||||
index c0f38b8..2899632 100644
|
|
||||||
--- a/find-root.c
|
|
||||||
+++ b/find-root.c
|
|
||||||
@@ -361,6 +361,8 @@ static int find_root(struct btrfs_root *root)
|
|
||||||
while (1) {
|
|
||||||
u64 map_length = 4096;
|
|
||||||
u64 type;
|
|
||||||
+ int mirror_num;
|
|
||||||
+ int num_copies;
|
|
||||||
|
|
||||||
if (offset >
|
|
||||||
btrfs_super_total_bytes(&root->fs_info->super_copy)) {
|
|
||||||
@@ -377,8 +379,10 @@ static int find_root(struct btrfs_root *root)
|
|
||||||
}
|
|
||||||
offset = metadata_offset;
|
|
||||||
}
|
|
||||||
+ mirror_num = 1;
|
|
||||||
+ again:
|
|
||||||
err = __btrfs_map_block(&root->fs_info->mapping_tree, READ,
|
|
||||||
- offset, &map_length, &type, &multi, 0);
|
|
||||||
+ offset, &map_length, &type, &multi, mirror_num);
|
|
||||||
if (err) {
|
|
||||||
offset += map_length;
|
|
||||||
continue;
|
|
||||||
@@ -396,9 +400,16 @@ static int find_root(struct btrfs_root *root)
|
|
||||||
|
|
||||||
err = read_physical(root, fd, offset, bytenr, map_length);
|
|
||||||
if (!err) {
|
|
||||||
+ /* Found the root. */
|
|
||||||
ret = 0;
|
|
||||||
break;
|
|
||||||
} else if (err < 0) {
|
|
||||||
+ num_copies = btrfs_num_copies(&root->fs_info->mapping_tree,
|
|
||||||
+ offset, map_length);
|
|
||||||
+ mirror_num++;
|
|
||||||
+ if (mirror_num <= num_copies)
|
|
||||||
+ goto again;
|
|
||||||
+ /* Unrecoverable error in read. */
|
|
||||||
ret = err;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
|||||||
From 266f413a32d774c68f41f488bb79fac6ad63e930 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Peter Stuge <peter@stuge.se>
|
|
||||||
Date: Fri, 25 Nov 2011 01:03:57 +0100
|
|
||||||
Subject: [PATCH 22/35] restore: Split output directory and btrfs-local path
|
|
||||||
search_dir() parameters
|
|
||||||
|
|
||||||
search_dir() recurses down the btrfs tree, and used to take the output
|
|
||||||
path for every item (i.e. in the running system, output root directory
|
|
||||||
concatenated with btrfs-local pathname) passed as the only path
|
|
||||||
parameter. Moving the output root directory to a separate parameter
|
|
||||||
and passing the btrfs-local pathname for each file and directory
|
|
||||||
separately allows easy filtering based on the btrfs-local pathname.
|
|
||||||
|
|
||||||
Signed-off-by: Peter Stuge <peter@stuge.se>
|
|
||||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
|
||||||
---
|
|
||||||
restore.c | 15 ++++++++++-----
|
|
||||||
1 files changed, 10 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/restore.c b/restore.c
|
|
||||||
index 389b107..0b92ed5 100644
|
|
||||||
--- a/restore.c
|
|
||||||
+++ b/restore.c
|
|
||||||
@@ -35,6 +35,7 @@
|
|
||||||
#include "volumes.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
+static char fs_name[4096];
|
|
||||||
static char path_name[4096];
|
|
||||||
static int get_snaps = 0;
|
|
||||||
static int verbose = 0;
|
|
||||||
@@ -450,7 +451,7 @@ set_size:
|
|
||||||
}
|
|
||||||
|
|
||||||
static int search_dir(struct btrfs_root *root, struct btrfs_key *key,
|
|
||||||
- const char *dir)
|
|
||||||
+ const char *output_rootdir, const char *dir)
|
|
||||||
{
|
|
||||||
struct btrfs_path *path;
|
|
||||||
struct extent_buffer *leaf;
|
|
||||||
@@ -554,8 +555,11 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key,
|
|
||||||
type = btrfs_dir_type(leaf, dir_item);
|
|
||||||
btrfs_dir_item_key_to_cpu(leaf, dir_item, &location);
|
|
||||||
|
|
||||||
- snprintf(path_name, 4096, "%s/%s", dir, filename);
|
|
||||||
+ /* full path from root of btrfs being restored */
|
|
||||||
+ snprintf(fs_name, 4096, "%s/%s", dir, filename);
|
|
||||||
|
|
||||||
+ /* full path from system root */
|
|
||||||
+ snprintf(path_name, 4096, "%s%s", output_rootdir, fs_name);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* At this point we're only going to restore directories and
|
|
||||||
@@ -603,7 +607,7 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key,
|
|
||||||
}
|
|
||||||
} else if (type == BTRFS_FT_DIR) {
|
|
||||||
struct btrfs_root *search_root = root;
|
|
||||||
- char *dir = strdup(path_name);
|
|
||||||
+ char *dir = strdup(fs_name);
|
|
||||||
|
|
||||||
if (!dir) {
|
|
||||||
fprintf(stderr, "Ran out of memory\n");
|
|
||||||
@@ -664,7 +668,8 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key,
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
loops = 0;
|
|
||||||
- ret = search_dir(search_root, &location, dir);
|
|
||||||
+ ret = search_dir(search_root, &location,
|
|
||||||
+ output_rootdir, dir);
|
|
||||||
free(dir);
|
|
||||||
if (ret) {
|
|
||||||
if (ignore_errors)
|
|
||||||
@@ -901,7 +906,7 @@ int main(int argc, char **argv)
|
|
||||||
key.objectid = BTRFS_FIRST_FREE_OBJECTID;
|
|
||||||
}
|
|
||||||
|
|
||||||
- ret = search_dir(root, &key, dir_name);
|
|
||||||
+ ret = search_dir(root, &key, dir_name, "");
|
|
||||||
|
|
||||||
out:
|
|
||||||
close_ctree(root);
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,130 +0,0 @@
|
|||||||
From 2f0c2a29ab13b17ae1cc21effcf532f2447b7c8c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Peter Stuge <peter@stuge.se>
|
|
||||||
Date: Fri, 25 Nov 2011 01:03:58 +0100
|
|
||||||
Subject: [PATCH 23/35] restore: Add regex matching of paths and files to be
|
|
||||||
restored
|
|
||||||
|
|
||||||
The option -m is used to specify the regex string. -c is used to
|
|
||||||
specify case insensitive matching. -i was already taken.
|
|
||||||
|
|
||||||
In order to restore only a single folder somewhere in the btrfs
|
|
||||||
tree, it is unfortunately neccessary to construct a slightly
|
|
||||||
nontrivial regex, e.g.:
|
|
||||||
|
|
||||||
restore -m '^/(|home(|/username(|/Desktop(|/.*))))$' /dev/sdb2 /output
|
|
||||||
|
|
||||||
This is needed in order to match each directory along the way to the
|
|
||||||
Desktop directory, as well as all contents below the Desktop directory.
|
|
||||||
|
|
||||||
Signed-off-by: Peter Stuge <peter@stuge.se>
|
|
||||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
|
||||||
---
|
|
||||||
restore.c | 40 ++++++++++++++++++++++++++++++++++------
|
|
||||||
1 files changed, 34 insertions(+), 6 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/restore.c b/restore.c
|
|
||||||
index 0b92ed5..e65746a 100644
|
|
||||||
--- a/restore.c
|
|
||||||
+++ b/restore.c
|
|
||||||
@@ -25,6 +25,8 @@
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <zlib.h>
|
|
||||||
+#include <sys/types.h>
|
|
||||||
+#include <regex.h>
|
|
||||||
#include "kerncompat.h"
|
|
||||||
#include "ctree.h"
|
|
||||||
#include "disk-io.h"
|
|
||||||
@@ -451,7 +453,8 @@ set_size:
|
|
||||||
}
|
|
||||||
|
|
||||||
static int search_dir(struct btrfs_root *root, struct btrfs_key *key,
|
|
||||||
- const char *output_rootdir, const char *dir)
|
|
||||||
+ const char *output_rootdir, const char *dir,
|
|
||||||
+ const regex_t *mreg)
|
|
||||||
{
|
|
||||||
struct btrfs_path *path;
|
|
||||||
struct extent_buffer *leaf;
|
|
||||||
@@ -558,6 +561,9 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key,
|
|
||||||
/* full path from root of btrfs being restored */
|
|
||||||
snprintf(fs_name, 4096, "%s/%s", dir, filename);
|
|
||||||
|
|
||||||
+ if (REG_NOMATCH == regexec(mreg, fs_name, 0, NULL, 0))
|
|
||||||
+ goto next;
|
|
||||||
+
|
|
||||||
/* full path from system root */
|
|
||||||
snprintf(path_name, 4096, "%s%s", output_rootdir, fs_name);
|
|
||||||
|
|
||||||
@@ -669,7 +675,7 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key,
|
|
||||||
}
|
|
||||||
loops = 0;
|
|
||||||
ret = search_dir(search_root, &location,
|
|
||||||
- output_rootdir, dir);
|
|
||||||
+ output_rootdir, dir, mreg);
|
|
||||||
free(dir);
|
|
||||||
if (ret) {
|
|
||||||
if (ignore_errors)
|
|
||||||
@@ -690,8 +696,8 @@ next:
|
|
||||||
|
|
||||||
static void usage()
|
|
||||||
{
|
|
||||||
- fprintf(stderr, "Usage: restore [-svio] [-t disk offset] <device> "
|
|
||||||
- "<directory>\n");
|
|
||||||
+ fprintf(stderr, "Usage: restore [-svioc] [-t disk offset] "
|
|
||||||
+ "[-m regex] <device> <directory>\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_mirror)
|
|
||||||
@@ -784,8 +790,12 @@ int main(int argc, char **argv)
|
|
||||||
int opt;
|
|
||||||
int super_mirror = 0;
|
|
||||||
int find_dir = 0;
|
|
||||||
+ const char *match_regstr = NULL;
|
|
||||||
+ int match_cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
|
|
||||||
+ regex_t match_reg, *mreg = NULL;
|
|
||||||
+ char reg_err[256];
|
|
||||||
|
|
||||||
- while ((opt = getopt(argc, argv, "sviot:u:df:r:")) != -1) {
|
|
||||||
+ while ((opt = getopt(argc, argv, "sviot:u:df:r:cm:")) != -1) {
|
|
||||||
switch (opt) {
|
|
||||||
case 's':
|
|
||||||
get_snaps = 1;
|
|
||||||
@@ -836,6 +846,12 @@ int main(int argc, char **argv)
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
+ case 'c':
|
|
||||||
+ match_cflags |= REG_ICASE;
|
|
||||||
+ break;
|
|
||||||
+ case 'm':
|
|
||||||
+ match_regstr = optarg;
|
|
||||||
+ break;
|
|
||||||
default:
|
|
||||||
usage();
|
|
||||||
exit(1);
|
|
||||||
@@ -906,9 +922,21 @@ int main(int argc, char **argv)
|
|
||||||
key.objectid = BTRFS_FIRST_FREE_OBJECTID;
|
|
||||||
}
|
|
||||||
|
|
||||||
- ret = search_dir(root, &key, dir_name, "");
|
|
||||||
+ if (match_regstr) {
|
|
||||||
+ ret = regcomp(&match_reg, match_regstr, match_cflags);
|
|
||||||
+ if (ret) {
|
|
||||||
+ regerror(ret, &match_reg, reg_err, sizeof(reg_err));
|
|
||||||
+ fprintf(stderr, "Regex compile failed: %s\n", reg_err);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ mreg = &match_reg;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ret = search_dir(root, &key, dir_name, "", mreg);
|
|
||||||
|
|
||||||
out:
|
|
||||||
+ if (mreg)
|
|
||||||
+ regfree(mreg);
|
|
||||||
close_ctree(root);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
|||||||
From e8919ef79253ace49de01ba228290e4e0cafbfb7 Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Marcin <djmarcin@google.com>
|
|
||||||
Date: Mon, 21 Nov 2011 20:51:15 -0600
|
|
||||||
Subject: [PATCH 24/35] btrfs-progs: In find-root, dump bytenr for every slot.
|
|
||||||
|
|
||||||
Signed-off-by: David Marcin <djmarcin@google.com>
|
|
||||||
---
|
|
||||||
find-root.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
|
|
||||||
1 files changed, 59 insertions(+), 1 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/find-root.c b/find-root.c
|
|
||||||
index 2899632..bd44e1f 100644
|
|
||||||
--- a/find-root.c
|
|
||||||
+++ b/find-root.c
|
|
||||||
@@ -258,8 +258,63 @@ out:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int dump_root_bytenr(struct btrfs_root *root, u64 bytenr, u64 gen)
|
|
||||||
+{
|
|
||||||
+ struct btrfs_root *tmp = malloc(sizeof(struct btrfs_root));
|
|
||||||
+ struct btrfs_path *path;
|
|
||||||
+ struct btrfs_key key;
|
|
||||||
+ struct btrfs_root_item ri;
|
|
||||||
+ struct extent_buffer *leaf;
|
|
||||||
+ struct btrfs_disk_key disk_key;
|
|
||||||
+ struct btrfs_key found_key;
|
|
||||||
+ int slot;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ if (!tmp)
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+
|
|
||||||
+ __setup_root(4096, 4096, 4096, 4096, tmp,
|
|
||||||
+ root->fs_info, BTRFS_ROOT_TREE_OBJECTID);
|
|
||||||
+
|
|
||||||
+ tmp->node = read_tree_block(root, bytenr, 4096, gen);
|
|
||||||
+
|
|
||||||
+ key.objectid = 0;
|
|
||||||
+ key.type = BTRFS_ROOT_ITEM_KEY;
|
|
||||||
+ key.offset = -1;
|
|
||||||
+
|
|
||||||
+ path = btrfs_alloc_path();
|
|
||||||
+
|
|
||||||
+ /* Walk the slots of this root looking for BTRFS_ROOT_ITEM_KEYs. */
|
|
||||||
+ ret = btrfs_search_slot(NULL, tmp, &key, path, 0, 0);
|
|
||||||
+ BUG_ON(ret < 0);
|
|
||||||
+ while (1) {
|
|
||||||
+ leaf = path->nodes[0];
|
|
||||||
+ slot = path->slots[0];
|
|
||||||
+ if (slot >= btrfs_header_nritems(leaf)) {
|
|
||||||
+ ret = btrfs_next_leaf(tmp, path);
|
|
||||||
+ if (ret != 0)
|
|
||||||
+ break;
|
|
||||||
+ leaf = path->nodes[0];
|
|
||||||
+ slot = path->slots[0];
|
|
||||||
+ }
|
|
||||||
+ btrfs_item_key(leaf, &disk_key, path->slots[0]);
|
|
||||||
+ btrfs_disk_key_to_cpu(&found_key, &disk_key);
|
|
||||||
+ if (btrfs_key_type(&found_key) == BTRFS_ROOT_ITEM_KEY) {
|
|
||||||
+ unsigned long offset;
|
|
||||||
+
|
|
||||||
+ 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));
|
|
||||||
+ }
|
|
||||||
+ path->slots[0]++;
|
|
||||||
+ }
|
|
||||||
+ btrfs_free_path(path);
|
|
||||||
+ free_extent_buffer(leaf);
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int search_iobuf(struct btrfs_root *root, void *iobuf,
|
|
||||||
- size_t iobuf_size, off_t offset)
|
|
||||||
+ size_t iobuf_size, off_t offset)
|
|
||||||
{
|
|
||||||
u64 gen = btrfs_super_generation(&root->fs_info->super_copy);
|
|
||||||
u64 objectid = search_objectid;
|
|
||||||
@@ -290,6 +345,9 @@ static int search_iobuf(struct btrfs_root *root, void *iobuf,
|
|
||||||
h_byte);
|
|
||||||
goto next;
|
|
||||||
}
|
|
||||||
+ /* Found some kind of root and it's fairly valid. */
|
|
||||||
+ if (dump_root_bytenr(root, h_byte, h_gen))
|
|
||||||
+ break;
|
|
||||||
if (h_gen != gen) {
|
|
||||||
fprintf(stderr, "Well block %Lu seems great, "
|
|
||||||
"but generation doesn't match, "
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,161 +0,0 @@
|
|||||||
From db874f1e8924e86bbdee6600b0e5b3e6d11f9238 Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Marcin <djmarcin@google.com>
|
|
||||||
Date: Tue, 22 Nov 2011 10:08:00 -0800
|
|
||||||
Subject: [PATCH 25/35] btrfs-progs: Add utility to dump all superblocks found
|
|
||||||
on a device.
|
|
||||||
|
|
||||||
Signed-off-by: David Marcin <djmarcin@google.com>
|
|
||||||
---
|
|
||||||
.gitignore | 4 ++
|
|
||||||
Makefile | 9 ++++-
|
|
||||||
btrfs-dump-super.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
3 files changed, 98 insertions(+), 2 deletions(-)
|
|
||||||
create mode 100644 btrfs-dump-super.c
|
|
||||||
|
|
||||||
Index: btrfs-progs-v0.19-117-g6da41f2/.gitignore
|
|
||||||
===================================================================
|
|
||||||
--- btrfs-progs-v0.19-117-g6da41f2.orig/.gitignore
|
|
||||||
+++ btrfs-progs-v0.19-117-g6da41f2/.gitignore
|
|
||||||
@@ -3,12 +3,16 @@
|
|
||||||
version.h
|
|
||||||
man/*.gz
|
|
||||||
btrfs
|
|
||||||
+btrfs-corrupt-block
|
|
||||||
btrfs-debug-tree
|
|
||||||
+btrfs-dump-super
|
|
||||||
btrfs-map-logical
|
|
||||||
+btrfs-select-super
|
|
||||||
btrfs-show
|
|
||||||
btrfs-vol
|
|
||||||
btrfsck
|
|
||||||
btrfsctl
|
|
||||||
+calc-size
|
|
||||||
find-root
|
|
||||||
mkfs.btrfs
|
|
||||||
repair
|
|
||||||
Index: btrfs-progs-v0.19-117-g6da41f2/Makefile
|
|
||||||
===================================================================
|
|
||||||
--- btrfs-progs-v0.19-117-g6da41f2.orig/Makefile
|
|
||||||
+++ btrfs-progs-v0.19-117-g6da41f2/Makefile
|
|
||||||
@@ -17,7 +17,8 @@ LIBS=-luuid
|
|
||||||
RESTORE_LIBS=-lz
|
|
||||||
|
|
||||||
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 restore find-root calc-size btrfs-corrupt-block \
|
|
||||||
+ btrfs-dump-super
|
|
||||||
|
|
||||||
btrfs_man_page_source = btrfs.c btrfs_cmds.c scrub.c
|
|
||||||
|
|
||||||
@@ -76,6 +77,9 @@ btrfs-zero-log: $(objects) btrfs-zero-lo
|
|
||||||
btrfs-select-super: $(objects) btrfs-select-super.o
|
|
||||||
$(CC) $(CFLAGS) -o btrfs-select-super $(objects) btrfs-select-super.o $(LDFLAGS) $(LIBS)
|
|
||||||
|
|
||||||
+btrfs-dump-super: $(objects) btrfs-dump-super.o
|
|
||||||
+ $(CC) $(CFLAGS) -o btrfs-dump-super $(objects) btrfs-dump-super.o $(LDFLAGS) $(LIBS)
|
|
||||||
+
|
|
||||||
btrfstune: $(objects) btrfstune.o
|
|
||||||
$(CC) $(CFLAGS) -o btrfstune $(objects) btrfstune.o $(LDFLAGS) $(LIBS)
|
|
||||||
|
|
||||||
@@ -128,7 +132,8 @@ install-man:
|
|
||||||
clean :
|
|
||||||
rm -f man/btrfs.8.in
|
|
||||||
rm -f $(progs) cscope.out *.o .*.d btrfs-convert btrfs-image btrfs-select-super \
|
|
||||||
- btrfs-zero-log btrfstune dir-test ioctl-test quick-test version.h
|
|
||||||
+ btrfs-dump-super btrfs-zero-log btrfstune dir-test ioctl-test quick-test \
|
|
||||||
+ version.h
|
|
||||||
rm -f helpmsg.c
|
|
||||||
cd man; make clean
|
|
||||||
|
|
||||||
Index: btrfs-progs-v0.19-117-g6da41f2/btrfs-dump-super.c
|
|
||||||
===================================================================
|
|
||||||
--- /dev/null
|
|
||||||
+++ btrfs-progs-v0.19-117-g6da41f2/btrfs-dump-super.c
|
|
||||||
@@ -0,0 +1,87 @@
|
|
||||||
+/*
|
|
||||||
+ * Copyright (C) 2011 Google. All rights reserved.
|
|
||||||
+ *
|
|
||||||
+ * This program is free software; you can redistribute it and/or
|
|
||||||
+ * modify it under the terms of the GNU General Public
|
|
||||||
+ * License v2 as published by the Free Software Foundation.
|
|
||||||
+ *
|
|
||||||
+ * This program is distributed in the hope that it will be useful,
|
|
||||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
+ * General Public License for more details.
|
|
||||||
+ *
|
|
||||||
+ * You should have received a copy of the GNU General Public
|
|
||||||
+ * License along with this program; if not, write to the
|
|
||||||
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
+ * Boston, MA 021110-1307, USA.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#define _XOPEN_SOURCE 500
|
|
||||||
+#define _GNU_SOURCE 1
|
|
||||||
+#include <stdio.h>
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+#include <unistd.h>
|
|
||||||
+#include <fcntl.h>
|
|
||||||
+#include <sys/stat.h>
|
|
||||||
+#include "kerncompat.h"
|
|
||||||
+#include "ctree.h"
|
|
||||||
+#include "disk-io.h"
|
|
||||||
+#include "version.h"
|
|
||||||
+
|
|
||||||
+static void print_usage(void)
|
|
||||||
+{
|
|
||||||
+ fprintf(stderr, "usage: btrfs-dump-super dev\n");
|
|
||||||
+ fprintf(stderr, "%s\n", BTRFS_BUILD_VERSION);
|
|
||||||
+ exit(1);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int read_block(const char* filename, u64 bytenr, struct btrfs_super_block* sb) {
|
|
||||||
+ int fd = open(filename, O_RDONLY, 0600);
|
|
||||||
+ int block_size = sizeof(struct btrfs_super_block);
|
|
||||||
+ int bytes_read = 0;
|
|
||||||
+
|
|
||||||
+ if (fd < 0) {
|
|
||||||
+ fprintf(stderr, "Could not open %s\n", filename);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ bytes_read = pread(fd, sb, block_size, bytenr);
|
|
||||||
+ if (bytes_read < block_size) {
|
|
||||||
+ fprintf(stderr, "Only read %d bytes of %d.\n", bytes_read, block_size);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ close(fd);
|
|
||||||
+ return bytes_read;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int main(int ac, char **av)
|
|
||||||
+{
|
|
||||||
+ int i;
|
|
||||||
+
|
|
||||||
+ if (ac != 2)
|
|
||||||
+ print_usage();
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
|
|
||||||
+ u64 bytenr = btrfs_sb_offset(i);
|
|
||||||
+ int fd;
|
|
||||||
+ struct btrfs_super_block sb;
|
|
||||||
+ int block_size = sizeof(struct btrfs_super_block);
|
|
||||||
+ char filename[1024];
|
|
||||||
+ int bytes_read = read_block(av[optind], bytenr, &sb);
|
|
||||||
+ if (bytes_read < block_size)
|
|
||||||
+ continue;
|
|
||||||
+
|
|
||||||
+ sprintf(filename, "/tmp/block.%s.%llu",
|
|
||||||
+ strrchr(av[optind], '/') + 1, bytenr);
|
|
||||||
+ fd = open(filename, O_CREAT|O_WRONLY, 0644);
|
|
||||||
+ if (block_size != pwrite(fd, &sb, block_size, 0)) {
|
|
||||||
+ fprintf(stderr, "Failed to dump superblock %d", i);
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ fprintf(stderr, "Dumped superblock %s:%d, gen %llu to %s.\n",
|
|
||||||
+ av[optind], i, sb.generation, filename);
|
|
||||||
+ close(fd);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
@ -1,179 +0,0 @@
|
|||||||
From 6330d8d3b70c0ad35ce8048ccf69b3e96718ed53 Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Marcin <djmarcin@google.com>
|
|
||||||
Date: Mon, 21 Nov 2011 20:31:01 -0600
|
|
||||||
Subject: [PATCH 26/35] btrfs-progs: Add the ability to use the earliest super
|
|
||||||
found when opening the ctree.
|
|
||||||
|
|
||||||
Signed-off-by: David Marcin <djmarcin@google.com>
|
|
||||||
---
|
|
||||||
convert.c | 6 +++---
|
|
||||||
disk-io.c | 21 ++++++++++++++-------
|
|
||||||
disk-io.h | 2 +-
|
|
||||||
volumes.c | 9 ++++++++-
|
|
||||||
volumes.h | 6 +++++-
|
|
||||||
5 files changed, 31 insertions(+), 13 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/convert.c b/convert.c
|
|
||||||
index 291dc27..c036f46 100644
|
|
||||||
--- a/convert.c
|
|
||||||
+++ b/convert.c
|
|
||||||
@@ -2386,7 +2386,7 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr)
|
|
||||||
fprintf(stderr, "unable to update system chunk\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
- root = open_ctree_fd(fd, devname, super_bytenr, O_RDWR);
|
|
||||||
+ root = open_ctree_fd(fd, devname, super_bytenr, O_RDWR, 0);
|
|
||||||
if (!root) {
|
|
||||||
fprintf(stderr, "unable to open ctree\n");
|
|
||||||
goto fail;
|
|
||||||
@@ -2447,7 +2447,7 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr)
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
- root = open_ctree_fd(fd, devname, 0, O_RDWR);
|
|
||||||
+ root = open_ctree_fd(fd, devname, 0, O_RDWR, 0);
|
|
||||||
if (!root) {
|
|
||||||
fprintf(stderr, "unable to open ctree\n");
|
|
||||||
goto fail;
|
|
||||||
@@ -2546,7 +2546,7 @@ int do_rollback(const char *devname, int force)
|
|
||||||
fprintf(stderr, "unable to open %s\n", devname);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
- root = open_ctree_fd(fd, devname, 0, O_RDWR);
|
|
||||||
+ root = open_ctree_fd(fd, devname, 0, O_RDWR, 0);
|
|
||||||
if (!root) {
|
|
||||||
fprintf(stderr, "unable to open ctree\n");
|
|
||||||
goto fail;
|
|
||||||
diff --git a/disk-io.c b/disk-io.c
|
|
||||||
index 408b2d5..a161f15 100644
|
|
||||||
--- a/disk-io.c
|
|
||||||
+++ b/disk-io.c
|
|
||||||
@@ -580,7 +580,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
|
|
||||||
return fs_info->dev_root;
|
|
||||||
if (location->objectid == BTRFS_CSUM_TREE_OBJECTID)
|
|
||||||
return fs_info->csum_root;
|
|
||||||
-
|
|
||||||
+
|
|
||||||
BUG_ON(location->objectid == BTRFS_TREE_RELOC_OBJECTID ||
|
|
||||||
location->offset != (u64)-1);
|
|
||||||
|
|
||||||
@@ -602,7 +602,8 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct btrfs_root *__open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
|
|
||||||
- u64 root_tree_bytenr, int writes)
|
|
||||||
+ u64 root_tree_bytenr, int writes,
|
|
||||||
+ int use_earliest_bdev)
|
|
||||||
{
|
|
||||||
u32 sectorsize;
|
|
||||||
u32 nodesize;
|
|
||||||
@@ -677,8 +678,14 @@ struct btrfs_root *__open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
|
|
||||||
|
|
||||||
fs_info->super_bytenr = sb_bytenr;
|
|
||||||
disk_super = &fs_info->super_copy;
|
|
||||||
- ret = btrfs_read_dev_super(fs_devices->latest_bdev,
|
|
||||||
- disk_super, sb_bytenr);
|
|
||||||
+ if (use_earliest_bdev) {
|
|
||||||
+ ret = btrfs_read_dev_super(fs_devices->earliest_bdev,
|
|
||||||
+ disk_super, sb_bytenr);
|
|
||||||
+ } else {
|
|
||||||
+ ret = btrfs_read_dev_super(fs_devices->latest_bdev,
|
|
||||||
+ disk_super, sb_bytenr);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (ret) {
|
|
||||||
printk("No valid btrfs found\n");
|
|
||||||
goto out_devices;
|
|
||||||
@@ -847,7 +854,7 @@ 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);
|
|
||||||
+ root = __open_ctree_fd(fp, filename, sb_bytenr, 0, writes, 0);
|
|
||||||
close(fp);
|
|
||||||
|
|
||||||
return root;
|
|
||||||
@@ -871,9 +878,9 @@ struct btrfs_root *open_ctree_recovery(const char *filename, u64 sb_bytenr,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
|
|
||||||
- int writes)
|
|
||||||
+ int writes, int use_earliest_bdev)
|
|
||||||
{
|
|
||||||
- return __open_ctree_fd(fp, path, sb_bytenr, 0, writes);
|
|
||||||
+ return __open_ctree_fd(fp, path, sb_bytenr, 0, writes, use_earliest_bdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr)
|
|
||||||
diff --git a/disk-io.h b/disk-io.h
|
|
||||||
index 2048fcf..8fdcd91 100644
|
|
||||||
--- a/disk-io.h
|
|
||||||
+++ b/disk-io.h
|
|
||||||
@@ -45,7 +45,7 @@ int clean_tree_block(struct btrfs_trans_handle *trans,
|
|
||||||
struct btrfs_root *root, struct extent_buffer *buf);
|
|
||||||
struct btrfs_root *open_ctree(const char *filename, u64 sb_bytenr, int writes);
|
|
||||||
struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
|
|
||||||
- int writes);
|
|
||||||
+ int writes, int use_earliest_bdev);
|
|
||||||
struct btrfs_root *open_ctree_recovery(const char *filename, u64 sb_bytenr,
|
|
||||||
u64 root_tree_bytenr);
|
|
||||||
int close_ctree(struct btrfs_root *root);
|
|
||||||
diff --git a/volumes.c b/volumes.c
|
|
||||||
index 03bfb8c..cde20ad 100644
|
|
||||||
--- a/volumes.c
|
|
||||||
+++ b/volumes.c
|
|
||||||
@@ -99,6 +99,8 @@ static int device_list_add(const char *path,
|
|
||||||
memcpy(fs_devices->fsid, disk_super->fsid, BTRFS_FSID_SIZE);
|
|
||||||
fs_devices->latest_devid = devid;
|
|
||||||
fs_devices->latest_trans = found_transid;
|
|
||||||
+ fs_devices->earliest_devid = devid;
|
|
||||||
+ fs_devices->earliest_trans = found_transid;
|
|
||||||
fs_devices->lowest_devid = (u64)-1;
|
|
||||||
device = NULL;
|
|
||||||
} else {
|
|
||||||
@@ -133,8 +135,11 @@ static int device_list_add(const char *path,
|
|
||||||
if (found_transid > fs_devices->latest_trans) {
|
|
||||||
fs_devices->latest_devid = devid;
|
|
||||||
fs_devices->latest_trans = found_transid;
|
|
||||||
+ } else if (found_transid < fs_devices->earliest_trans) {
|
|
||||||
+ fs_devices->earliest_devid = devid;
|
|
||||||
+ fs_devices->earliest_trans = found_transid;
|
|
||||||
}
|
|
||||||
- if (fs_devices->lowest_devid > devid) {
|
|
||||||
+ if (devid < fs_devices->lowest_devid) {
|
|
||||||
fs_devices->lowest_devid = devid;
|
|
||||||
}
|
|
||||||
*fs_devices_ret = fs_devices;
|
|
||||||
@@ -183,6 +188,8 @@ int btrfs_open_devices(struct btrfs_fs_devices *fs_devices, int flags)
|
|
||||||
|
|
||||||
if (device->devid == fs_devices->latest_devid)
|
|
||||||
fs_devices->latest_bdev = fd;
|
|
||||||
+ if (device->devid == fs_devices->earliest_devid)
|
|
||||||
+ fs_devices->earliest_bdev = fd;
|
|
||||||
if (device->devid == fs_devices->lowest_devid)
|
|
||||||
fs_devices->lowest_bdev = fd;
|
|
||||||
device->fd = fd;
|
|
||||||
diff --git a/volumes.h b/volumes.h
|
|
||||||
index 7104d36..08c53e4 100644
|
|
||||||
--- a/volumes.h
|
|
||||||
+++ b/volumes.h
|
|
||||||
@@ -64,11 +64,15 @@ struct btrfs_device {
|
|
||||||
struct btrfs_fs_devices {
|
|
||||||
u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */
|
|
||||||
|
|
||||||
- /* the device with this id has the most recent coyp of the super */
|
|
||||||
+ /* the device with this id has the most recent copy of the super */
|
|
||||||
u64 latest_devid;
|
|
||||||
u64 latest_trans;
|
|
||||||
+ /* the device with this id has the least recent copy of the super */
|
|
||||||
+ u64 earliest_devid;
|
|
||||||
+ u64 earliest_trans;
|
|
||||||
u64 lowest_devid;
|
|
||||||
int latest_bdev;
|
|
||||||
+ int earliest_bdev;
|
|
||||||
int lowest_bdev;
|
|
||||||
struct list_head devices;
|
|
||||||
struct list_head list;
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,111 +0,0 @@
|
|||||||
From a780325614c0d89c9c0ea6779ada5af512b6e319 Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Marcin <djmarcin@google.com>
|
|
||||||
Date: Tue, 22 Nov 2011 10:09:35 -0800
|
|
||||||
Subject: [PATCH 27/35] btrfs-progs: Use oldest super for btrfs-select-super.
|
|
||||||
Add required confirmation to btrfs-select-super.
|
|
||||||
|
|
||||||
Signed-off-by: David Marcin <djmarcin@google.com>
|
|
||||||
---
|
|
||||||
btrfs-select-super.c | 38 ++++++++++++++++++++++++++++++--------
|
|
||||||
disk-io.c | 2 +-
|
|
||||||
2 files changed, 31 insertions(+), 9 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfs-select-super.c b/btrfs-select-super.c
|
|
||||||
index 51eb9c9..4d27f1b 100644
|
|
||||||
--- a/btrfs-select-super.c
|
|
||||||
+++ b/btrfs-select-super.c
|
|
||||||
@@ -34,7 +34,9 @@
|
|
||||||
|
|
||||||
static void print_usage(void)
|
|
||||||
{
|
|
||||||
- fprintf(stderr, "usage: btrfs-select-super -s number dev\n");
|
|
||||||
+ fprintf(stderr, "usage: btrfs-select-super [-c] [-e] -s number dev\n");
|
|
||||||
+ fprintf(stderr, " -c Commit changes to disk [IRREVERSIBLE]\n");
|
|
||||||
+ fprintf(stderr, " -e Use the earliest super found, may help recover transid verify problems\n");
|
|
||||||
fprintf(stderr, "%s\n", BTRFS_BUILD_VERSION);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
@@ -45,10 +47,13 @@ int main(int ac, char **av)
|
|
||||||
int ret;
|
|
||||||
int num;
|
|
||||||
u64 bytenr = 0;
|
|
||||||
+ int commit = 0;
|
|
||||||
+ int use_lowest_bdev = 0;
|
|
||||||
+ int fp;
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
int c;
|
|
||||||
- c = getopt(ac, av, "s:");
|
|
||||||
+ c = getopt(ac, av, "s:ce");
|
|
||||||
if (c < 0)
|
|
||||||
break;
|
|
||||||
switch(c) {
|
|
||||||
@@ -58,6 +63,12 @@ int main(int ac, char **av)
|
|
||||||
printf("using SB copy %d, bytenr %llu\n", num,
|
|
||||||
(unsigned long long)bytenr);
|
|
||||||
break;
|
|
||||||
+ case 'c':
|
|
||||||
+ commit = 1;
|
|
||||||
+ break;
|
|
||||||
+ case 'e':
|
|
||||||
+ use_earliest_bdev = 1;
|
|
||||||
+ break;
|
|
||||||
default:
|
|
||||||
print_usage();
|
|
||||||
}
|
|
||||||
@@ -74,22 +85,33 @@ int main(int ac, char **av)
|
|
||||||
|
|
||||||
radix_tree_init();
|
|
||||||
|
|
||||||
- if((ret = check_mounted(av[optind])) < 0) {
|
|
||||||
+ if ((ret = check_mounted(av[optind])) < 0) {
|
|
||||||
fprintf(stderr, "Could not check mount status: %s\n", strerror(-ret));
|
|
||||||
return ret;
|
|
||||||
- } else if(ret) {
|
|
||||||
+ } else if (ret) {
|
|
||||||
fprintf(stderr, "%s is currently mounted. Aborting.\n", av[optind]);
|
|
||||||
return -EBUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
- root = open_ctree(av[optind], bytenr, 1);
|
|
||||||
+ fp = open(av[optind], O_CREAT|O_RDRW, 0600);
|
|
||||||
+ if (fp < 0) {
|
|
||||||
+ fprintf(stderr, "Could not open %s\n", av[optind]);
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+ root = open_ctree_fd(fp, av[optind], bytenr, 1, use_earliest_bdev);
|
|
||||||
|
|
||||||
if (root == NULL)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
- /* make the super writing code think we've read the first super */
|
|
||||||
- root->fs_info->super_bytenr = BTRFS_SUPER_INFO_OFFSET;
|
|
||||||
- ret = write_all_supers(root);
|
|
||||||
+ fprintf(stderr, "Found superblock with generation %llu.\n", root->fs_info->super_copy.generation);
|
|
||||||
+
|
|
||||||
+ if (commit) {
|
|
||||||
+ fprintf(stderr, "Committing...\n");
|
|
||||||
+
|
|
||||||
+ /* make the super writing code think we've read the first super */
|
|
||||||
+ root->fs_info->super_bytenr = BTRFS_SUPER_INFO_OFFSET;
|
|
||||||
+ ret = write_all_supers(root);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/* we don't close the ctree or anything, because we don't want a real
|
|
||||||
* transaction commit. We just want the super copy we pulled off the
|
|
||||||
diff --git a/disk-io.c b/disk-io.c
|
|
||||||
index a161f15..9585057 100644
|
|
||||||
--- a/disk-io.c
|
|
||||||
+++ b/disk-io.c
|
|
||||||
@@ -871,7 +871,7 @@ struct btrfs_root *open_ctree_recovery(const char *filename, u64 sb_bytenr,
|
|
||||||
fprintf (stderr, "Could not open %s\n", filename);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
- root = __open_ctree_fd(fp, filename, sb_bytenr, root_tree_bytenr, 0);
|
|
||||||
+ root = __open_ctree_fd(fp, filename, sb_bytenr, root_tree_bytenr, 0, 0);
|
|
||||||
close(fp);
|
|
||||||
|
|
||||||
return root;
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,191 +0,0 @@
|
|||||||
From 2fe46117d3cde3737a1600195883e63ab4c59a8d Mon Sep 17 00:00:00 2001
|
|
||||||
From: Josef Bacik <josef@redhat.com>
|
|
||||||
Date: Fri, 2 Dec 2011 10:07:43 -0500
|
|
||||||
Subject: [PATCH 28/35] btrfs-progs: add lzo compression support to restore
|
|
||||||
|
|
||||||
This patch simply adds support to decompress lzo compressed extents in restore.
|
|
||||||
|
|
||||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
|
||||||
---
|
|
||||||
Makefile | 2 +-
|
|
||||||
restore.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
|
|
||||||
2 files changed, 84 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/Makefile b/Makefile
|
|
||||||
index 548f88c..64de4e6 100644
|
|
||||||
--- a/Makefile
|
|
||||||
+++ b/Makefile
|
|
||||||
@@ -14,7 +14,7 @@ INSTALL = install
|
|
||||||
prefix ?= /usr/local
|
|
||||||
bindir = $(prefix)/bin
|
|
||||||
LIBS=-luuid
|
|
||||||
-RESTORE_LIBS=-lz
|
|
||||||
+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 \
|
|
||||||
diff --git a/restore.c b/restore.c
|
|
||||||
index e65746a..6433378 100644
|
|
||||||
--- a/restore.c
|
|
||||||
+++ b/restore.c
|
|
||||||
@@ -27,6 +27,8 @@
|
|
||||||
#include <zlib.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <regex.h>
|
|
||||||
+#include <lzo/lzoconf.h>
|
|
||||||
+#include <lzo/lzo1x.h>
|
|
||||||
#include "kerncompat.h"
|
|
||||||
#include "ctree.h"
|
|
||||||
#include "disk-io.h"
|
|
||||||
@@ -44,8 +46,12 @@ static int verbose = 0;
|
|
||||||
static int ignore_errors = 0;
|
|
||||||
static int overwrite = 0;
|
|
||||||
|
|
||||||
-static int decompress(char *inbuf, char *outbuf, u64 compress_len,
|
|
||||||
- u64 decompress_len)
|
|
||||||
+#define LZO_LEN 4
|
|
||||||
+#define PAGE_CACHE_SIZE 4096
|
|
||||||
+#define lzo1x_worst_compress(x) ((x) + ((x) / 16) + 64 + 3)
|
|
||||||
+
|
|
||||||
+static int decompress_zlib(char *inbuf, char *outbuf, u64 compress_len,
|
|
||||||
+ u64 decompress_len)
|
|
||||||
{
|
|
||||||
z_stream strm;
|
|
||||||
int ret;
|
|
||||||
@@ -71,6 +77,73 @@ static int decompress(char *inbuf, char *outbuf, u64 compress_len,
|
|
||||||
(void)inflateEnd(&strm);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
+static inline size_t read_compress_length(unsigned char *buf)
|
|
||||||
+{
|
|
||||||
+ __le32 dlen;
|
|
||||||
+ memcpy(&dlen, buf, LZO_LEN);
|
|
||||||
+ return le32_to_cpu(dlen);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int decompress_lzo(unsigned char *inbuf, char *outbuf, u64 compress_len,
|
|
||||||
+ u64 *decompress_len)
|
|
||||||
+{
|
|
||||||
+ size_t new_len;
|
|
||||||
+ size_t in_len;
|
|
||||||
+ size_t out_len = 0;
|
|
||||||
+ size_t tot_len;
|
|
||||||
+ size_t tot_in;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ ret = lzo_init();
|
|
||||||
+ if (ret != LZO_E_OK) {
|
|
||||||
+ fprintf(stderr, "lzo init returned %d\n", ret);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ tot_len = read_compress_length(inbuf);
|
|
||||||
+ inbuf += LZO_LEN;
|
|
||||||
+ tot_in = LZO_LEN;
|
|
||||||
+
|
|
||||||
+ while (tot_in < tot_len) {
|
|
||||||
+ in_len = read_compress_length(inbuf);
|
|
||||||
+ inbuf += LZO_LEN;
|
|
||||||
+ tot_in += LZO_LEN;
|
|
||||||
+
|
|
||||||
+ new_len = lzo1x_worst_compress(PAGE_CACHE_SIZE);
|
|
||||||
+ ret = lzo1x_decompress_safe((const unsigned char *)inbuf, in_len,
|
|
||||||
+ (unsigned char *)outbuf, &new_len, NULL);
|
|
||||||
+ if (ret != LZO_E_OK) {
|
|
||||||
+ fprintf(stderr, "failed to inflate: %d\n", ret);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ out_len += new_len;
|
|
||||||
+ outbuf += new_len;
|
|
||||||
+ inbuf += in_len;
|
|
||||||
+ tot_in += in_len;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ *decompress_len = out_len;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int decompress(char *inbuf, char *outbuf, u64 compress_len,
|
|
||||||
+ u64 *decompress_len, int compress)
|
|
||||||
+{
|
|
||||||
+ switch (compress) {
|
|
||||||
+ case BTRFS_COMPRESS_ZLIB:
|
|
||||||
+ return decompress_zlib(inbuf, outbuf, compress_len,
|
|
||||||
+ *decompress_len);
|
|
||||||
+ case BTRFS_COMPRESS_LZO:
|
|
||||||
+ return decompress_lzo((unsigned char *)inbuf, outbuf, compress_len,
|
|
||||||
+ decompress_len);
|
|
||||||
+ default:
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ fprintf(stderr, "invalid compression type: %d\n", compress);
|
|
||||||
+ return -1;
|
|
||||||
+}
|
|
||||||
|
|
||||||
int next_leaf(struct btrfs_root *root, struct btrfs_path *path)
|
|
||||||
{
|
|
||||||
@@ -133,11 +206,11 @@ static int copy_one_inline(int fd, struct btrfs_path *path, u64 pos)
|
|
||||||
struct btrfs_file_extent_item *fi;
|
|
||||||
char buf[4096];
|
|
||||||
char *outbuf;
|
|
||||||
+ u64 ram_size;
|
|
||||||
ssize_t done;
|
|
||||||
unsigned long ptr;
|
|
||||||
int ret;
|
|
||||||
int len;
|
|
||||||
- int ram_size;
|
|
||||||
int compress;
|
|
||||||
|
|
||||||
fi = btrfs_item_ptr(leaf, path->slots[0],
|
|
||||||
@@ -165,7 +238,7 @@ static int copy_one_inline(int fd, struct btrfs_path *path, u64 pos)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
- ret = decompress(buf, outbuf, len, ram_size);
|
|
||||||
+ ret = decompress(buf, outbuf, len, &ram_size, compress);
|
|
||||||
if (ret) {
|
|
||||||
free(outbuf);
|
|
||||||
return ret;
|
|
||||||
@@ -174,7 +247,7 @@ static int copy_one_inline(int fd, struct btrfs_path *path, u64 pos)
|
|
||||||
done = pwrite(fd, outbuf, ram_size, pos);
|
|
||||||
free(outbuf);
|
|
||||||
if (done < len) {
|
|
||||||
- fprintf(stderr, "Short compressed inline write, wanted %d, "
|
|
||||||
+ fprintf(stderr, "Short compressed inline write, wanted %Lu, "
|
|
||||||
"did %zd: %d\n", ram_size, done, errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
@@ -196,6 +269,7 @@ static int copy_one_extent(struct btrfs_root *root, int fd,
|
|
||||||
u64 length;
|
|
||||||
u64 size_left;
|
|
||||||
u64 dev_bytenr;
|
|
||||||
+ u64 offset;
|
|
||||||
u64 count = 0;
|
|
||||||
int compress;
|
|
||||||
int ret;
|
|
||||||
@@ -207,8 +281,11 @@ static int copy_one_extent(struct btrfs_root *root, int fd,
|
|
||||||
bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
|
|
||||||
disk_size = btrfs_file_extent_disk_num_bytes(leaf, fi);
|
|
||||||
ram_size = btrfs_file_extent_ram_bytes(leaf, fi);
|
|
||||||
+ offset = btrfs_file_extent_offset(leaf, fi);
|
|
||||||
size_left = disk_size;
|
|
||||||
|
|
||||||
+ if (offset)
|
|
||||||
+ printf("offset is %Lu\n", offset);
|
|
||||||
/* we found a hole */
|
|
||||||
if (disk_size == 0)
|
|
||||||
return 0;
|
|
||||||
@@ -282,7 +359,7 @@ again:
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
- ret = decompress(inbuf, outbuf, disk_size, ram_size);
|
|
||||||
+ ret = decompress(inbuf, outbuf, disk_size, &ram_size, compress);
|
|
||||||
if (ret) {
|
|
||||||
num_copies = btrfs_num_copies(&root->fs_info->mapping_tree,
|
|
||||||
bytenr, length);
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
|||||||
From 1b8b3c3579ee127b174a850213df7ad81edd5710 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Josef Bacik <josef@redhat.com>
|
|
||||||
Date: Fri, 2 Dec 2011 12:52:15 -0500
|
|
||||||
Subject: [PATCH 29/35] btrfs-progs: fix regexec to only work if we actually
|
|
||||||
have a regexec
|
|
||||||
|
|
||||||
We were unconditionally executing our regular expression, even though we may not
|
|
||||||
have one, so check to make sure mreg is not null before calling regexec.
|
|
||||||
Thanks,
|
|
||||||
|
|
||||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
|
||||||
---
|
|
||||||
restore.c | 2 +-
|
|
||||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/restore.c b/restore.c
|
|
||||||
index 6433378..a4ccb18 100644
|
|
||||||
--- a/restore.c
|
|
||||||
+++ b/restore.c
|
|
||||||
@@ -638,7 +638,7 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key,
|
|
||||||
/* full path from root of btrfs being restored */
|
|
||||||
snprintf(fs_name, 4096, "%s/%s", dir, filename);
|
|
||||||
|
|
||||||
- if (REG_NOMATCH == regexec(mreg, fs_name, 0, NULL, 0))
|
|
||||||
+ if (mreg && REG_NOMATCH == regexec(mreg, fs_name, 0, NULL, 0))
|
|
||||||
goto next;
|
|
||||||
|
|
||||||
/* full path from system root */
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
From 3ceceda914e19a3f7982c5050e6ffb23522071f2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Marcin <djmarcin@google.com>
|
|
||||||
Date: Tue, 6 Dec 2011 12:14:54 -0800
|
|
||||||
Subject: [PATCH 30/35] btrfs-progs: Fix compilation errors with
|
|
||||||
btrfs-select-super.c introduced by refactoring.
|
|
||||||
|
|
||||||
Signed-off-by: David Marcin <djmarcin@google.com>
|
|
||||||
---
|
|
||||||
btrfs-select-super.c | 4 ++--
|
|
||||||
1 files changed, 2 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfs-select-super.c b/btrfs-select-super.c
|
|
||||||
index 4d27f1b..079986a 100644
|
|
||||||
--- a/btrfs-select-super.c
|
|
||||||
+++ b/btrfs-select-super.c
|
|
||||||
@@ -48,7 +48,7 @@ int main(int ac, char **av)
|
|
||||||
int num;
|
|
||||||
u64 bytenr = 0;
|
|
||||||
int commit = 0;
|
|
||||||
- int use_lowest_bdev = 0;
|
|
||||||
+ int use_earliest_bdev = 0;
|
|
||||||
int fp;
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
@@ -93,7 +93,7 @@ int main(int ac, char **av)
|
|
||||||
return -EBUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
- fp = open(av[optind], O_CREAT|O_RDRW, 0600);
|
|
||||||
+ fp = open(av[optind], O_CREAT|O_RDWR, 0600);
|
|
||||||
if (fp < 0) {
|
|
||||||
fprintf(stderr, "Could not open %s\n", av[optind]);
|
|
||||||
return 1;
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,443 +0,0 @@
|
|||||||
From fb0cfed5d3500e76ce30c6a9803ee1720bf1b4a5 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Josef Bacik <josef@redhat.com>
|
|
||||||
Date: Wed, 7 Dec 2011 14:13:35 -0500
|
|
||||||
Subject: [PATCH 31/35] Btrfs-progs: fix restore to fall back to the broken
|
|
||||||
open_ctree
|
|
||||||
|
|
||||||
We don't need most of the roots when doing restore, like the extent tree. So if
|
|
||||||
the recovery open_ctree fails because it's trying to open one of these useless
|
|
||||||
roots just fall back to open_ctree_broken. This will just open the chunk root
|
|
||||||
which is the bare minimum of what we need to operate. Then from there we can
|
|
||||||
setup the tree_root and the fs_root, and if either of those are gone we can't
|
|
||||||
restore anyway. Thanks,
|
|
||||||
|
|
||||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
|
||||||
---
|
|
||||||
disk-io.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
disk-io.h | 1 +
|
|
||||||
find-root.c | 166 -----------------------------------------------------------
|
|
||||||
restore.c | 48 +++++++++++++++++-
|
|
||||||
4 files changed, 198 insertions(+), 167 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/disk-io.c b/disk-io.c
|
|
||||||
index 9585057..8a8071c 100644
|
|
||||||
--- a/disk-io.c
|
|
||||||
+++ b/disk-io.c
|
|
||||||
@@ -883,6 +883,156 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
|
|
||||||
return __open_ctree_fd(fp, path, sb_bytenr, 0, writes, use_earliest_bdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
+struct btrfs_root *open_ctree_broken(int fd, const char *device)
|
|
||||||
+{
|
|
||||||
+ u32 sectorsize;
|
|
||||||
+ u32 nodesize;
|
|
||||||
+ u32 leafsize;
|
|
||||||
+ u32 blocksize;
|
|
||||||
+ u32 stripesize;
|
|
||||||
+ u64 generation;
|
|
||||||
+ struct btrfs_root *tree_root = malloc(sizeof(struct btrfs_root));
|
|
||||||
+ struct btrfs_root *extent_root = malloc(sizeof(struct btrfs_root));
|
|
||||||
+ struct btrfs_root *chunk_root = malloc(sizeof(struct btrfs_root));
|
|
||||||
+ struct btrfs_root *dev_root = malloc(sizeof(struct btrfs_root));
|
|
||||||
+ struct btrfs_root *csum_root = malloc(sizeof(struct btrfs_root));
|
|
||||||
+ struct btrfs_fs_info *fs_info = malloc(sizeof(*fs_info));
|
|
||||||
+ int ret;
|
|
||||||
+ struct btrfs_super_block *disk_super;
|
|
||||||
+ struct btrfs_fs_devices *fs_devices = NULL;
|
|
||||||
+ u64 total_devs;
|
|
||||||
+ u64 features;
|
|
||||||
+
|
|
||||||
+ ret = btrfs_scan_one_device(fd, device, &fs_devices,
|
|
||||||
+ &total_devs, BTRFS_SUPER_INFO_OFFSET);
|
|
||||||
+
|
|
||||||
+ if (ret) {
|
|
||||||
+ fprintf(stderr, "No valid Btrfs found on %s\n", device);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (total_devs != 1) {
|
|
||||||
+ ret = btrfs_scan_for_fsid(fs_devices, total_devs, 1);
|
|
||||||
+ if (ret)
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ memset(fs_info, 0, sizeof(*fs_info));
|
|
||||||
+ fs_info->tree_root = tree_root;
|
|
||||||
+ fs_info->extent_root = extent_root;
|
|
||||||
+ fs_info->chunk_root = chunk_root;
|
|
||||||
+ fs_info->dev_root = dev_root;
|
|
||||||
+ fs_info->csum_root = csum_root;
|
|
||||||
+
|
|
||||||
+ fs_info->readonly = 1;
|
|
||||||
+
|
|
||||||
+ extent_io_tree_init(&fs_info->extent_cache);
|
|
||||||
+ extent_io_tree_init(&fs_info->free_space_cache);
|
|
||||||
+ extent_io_tree_init(&fs_info->block_group_cache);
|
|
||||||
+ extent_io_tree_init(&fs_info->pinned_extents);
|
|
||||||
+ extent_io_tree_init(&fs_info->pending_del);
|
|
||||||
+ extent_io_tree_init(&fs_info->extent_ins);
|
|
||||||
+ cache_tree_init(&fs_info->fs_root_cache);
|
|
||||||
+
|
|
||||||
+ cache_tree_init(&fs_info->mapping_tree.cache_tree);
|
|
||||||
+
|
|
||||||
+ mutex_init(&fs_info->fs_mutex);
|
|
||||||
+ fs_info->fs_devices = fs_devices;
|
|
||||||
+ INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots);
|
|
||||||
+ INIT_LIST_HEAD(&fs_info->space_info);
|
|
||||||
+
|
|
||||||
+ __setup_root(4096, 4096, 4096, 4096, tree_root,
|
|
||||||
+ fs_info, BTRFS_ROOT_TREE_OBJECTID);
|
|
||||||
+
|
|
||||||
+ ret = btrfs_open_devices(fs_devices, O_RDONLY);
|
|
||||||
+ if (ret)
|
|
||||||
+ goto out_cleanup;
|
|
||||||
+
|
|
||||||
+ fs_info->super_bytenr = BTRFS_SUPER_INFO_OFFSET;
|
|
||||||
+ disk_super = &fs_info->super_copy;
|
|
||||||
+ ret = btrfs_read_dev_super(fs_devices->latest_bdev,
|
|
||||||
+ disk_super, BTRFS_SUPER_INFO_OFFSET);
|
|
||||||
+ if (ret) {
|
|
||||||
+ printk("No valid btrfs found\n");
|
|
||||||
+ goto out_devices;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ memcpy(fs_info->fsid, &disk_super->fsid, BTRFS_FSID_SIZE);
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ features = btrfs_super_incompat_flags(disk_super) &
|
|
||||||
+ ~BTRFS_FEATURE_INCOMPAT_SUPP;
|
|
||||||
+ if (features) {
|
|
||||||
+ printk("couldn't open because of unsupported "
|
|
||||||
+ "option features (%Lx).\n", features);
|
|
||||||
+ goto out_devices;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ features = btrfs_super_incompat_flags(disk_super);
|
|
||||||
+ if (!(features & BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF)) {
|
|
||||||
+ features |= BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF;
|
|
||||||
+ btrfs_set_super_incompat_flags(disk_super, features);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ nodesize = btrfs_super_nodesize(disk_super);
|
|
||||||
+ leafsize = btrfs_super_leafsize(disk_super);
|
|
||||||
+ sectorsize = btrfs_super_sectorsize(disk_super);
|
|
||||||
+ stripesize = btrfs_super_stripesize(disk_super);
|
|
||||||
+ tree_root->nodesize = nodesize;
|
|
||||||
+ tree_root->leafsize = leafsize;
|
|
||||||
+ tree_root->sectorsize = sectorsize;
|
|
||||||
+ tree_root->stripesize = stripesize;
|
|
||||||
+
|
|
||||||
+ ret = btrfs_read_sys_array(tree_root);
|
|
||||||
+ if (ret)
|
|
||||||
+ goto out_devices;
|
|
||||||
+ blocksize = btrfs_level_size(tree_root,
|
|
||||||
+ btrfs_super_chunk_root_level(disk_super));
|
|
||||||
+ generation = btrfs_super_chunk_root_generation(disk_super);
|
|
||||||
+
|
|
||||||
+ __setup_root(nodesize, leafsize, sectorsize, stripesize,
|
|
||||||
+ chunk_root, fs_info, BTRFS_CHUNK_TREE_OBJECTID);
|
|
||||||
+
|
|
||||||
+ chunk_root->node = read_tree_block(chunk_root,
|
|
||||||
+ btrfs_super_chunk_root(disk_super),
|
|
||||||
+ blocksize, generation);
|
|
||||||
+ if (!chunk_root->node) {
|
|
||||||
+ printk("Couldn't read chunk root\n");
|
|
||||||
+ goto out_devices;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ read_extent_buffer(chunk_root->node, fs_info->chunk_tree_uuid,
|
|
||||||
+ (unsigned long)btrfs_header_chunk_tree_uuid(chunk_root->node),
|
|
||||||
+ BTRFS_UUID_SIZE);
|
|
||||||
+
|
|
||||||
+ if (!(btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_METADUMP)) {
|
|
||||||
+ ret = btrfs_read_chunk_tree(chunk_root);
|
|
||||||
+ if (ret)
|
|
||||||
+ goto out_chunk;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return fs_info->chunk_root;
|
|
||||||
+out_chunk:
|
|
||||||
+ free_extent_buffer(fs_info->chunk_root->node);
|
|
||||||
+out_devices:
|
|
||||||
+ close_all_devices(fs_info);
|
|
||||||
+out_cleanup:
|
|
||||||
+ extent_io_tree_cleanup(&fs_info->extent_cache);
|
|
||||||
+ extent_io_tree_cleanup(&fs_info->free_space_cache);
|
|
||||||
+ extent_io_tree_cleanup(&fs_info->block_group_cache);
|
|
||||||
+ extent_io_tree_cleanup(&fs_info->pinned_extents);
|
|
||||||
+ extent_io_tree_cleanup(&fs_info->pending_del);
|
|
||||||
+ extent_io_tree_cleanup(&fs_info->extent_ins);
|
|
||||||
+out:
|
|
||||||
+ free(tree_root);
|
|
||||||
+ free(extent_root);
|
|
||||||
+ free(chunk_root);
|
|
||||||
+ free(dev_root);
|
|
||||||
+ free(csum_root);
|
|
||||||
+ free(fs_info);
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr)
|
|
||||||
{
|
|
||||||
u8 fsid[BTRFS_FSID_SIZE];
|
|
||||||
diff --git a/disk-io.h b/disk-io.h
|
|
||||||
index 8fdcd91..2b1fcd5 100644
|
|
||||||
--- a/disk-io.h
|
|
||||||
+++ b/disk-io.h
|
|
||||||
@@ -48,6 +48,7 @@ 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_root *open_ctree_broken(int fd, const char *device);
|
|
||||||
int close_ctree(struct btrfs_root *root);
|
|
||||||
int write_all_supers(struct btrfs_root *root);
|
|
||||||
int write_ctree_super(struct btrfs_trans_handle *trans,
|
|
||||||
diff --git a/find-root.c b/find-root.c
|
|
||||||
index bd44e1f..e0bc069 100644
|
|
||||||
--- a/find-root.c
|
|
||||||
+++ b/find-root.c
|
|
||||||
@@ -92,172 +92,6 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int close_all_devices(struct btrfs_fs_info *fs_info)
|
|
||||||
-{
|
|
||||||
- struct list_head *list;
|
|
||||||
- struct list_head *next;
|
|
||||||
- struct btrfs_device *device;
|
|
||||||
-
|
|
||||||
- return 0;
|
|
||||||
-
|
|
||||||
- list = &fs_info->fs_devices->devices;
|
|
||||||
- list_for_each(next, list) {
|
|
||||||
- device = list_entry(next, struct btrfs_device, dev_list);
|
|
||||||
- close(device->fd);
|
|
||||||
- }
|
|
||||||
- return 0;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static struct btrfs_root *open_ctree_broken(int fd, const char *device)
|
|
||||||
-{
|
|
||||||
- u32 sectorsize;
|
|
||||||
- u32 nodesize;
|
|
||||||
- u32 leafsize;
|
|
||||||
- u32 blocksize;
|
|
||||||
- u32 stripesize;
|
|
||||||
- u64 generation;
|
|
||||||
- struct btrfs_root *tree_root = malloc(sizeof(struct btrfs_root));
|
|
||||||
- struct btrfs_root *extent_root = malloc(sizeof(struct btrfs_root));
|
|
||||||
- struct btrfs_root *chunk_root = malloc(sizeof(struct btrfs_root));
|
|
||||||
- struct btrfs_root *dev_root = malloc(sizeof(struct btrfs_root));
|
|
||||||
- struct btrfs_root *csum_root = malloc(sizeof(struct btrfs_root));
|
|
||||||
- struct btrfs_fs_info *fs_info = malloc(sizeof(*fs_info));
|
|
||||||
- int ret;
|
|
||||||
- struct btrfs_super_block *disk_super;
|
|
||||||
- struct btrfs_fs_devices *fs_devices = NULL;
|
|
||||||
- u64 total_devs;
|
|
||||||
- u64 features;
|
|
||||||
-
|
|
||||||
- ret = btrfs_scan_one_device(fd, device, &fs_devices,
|
|
||||||
- &total_devs, BTRFS_SUPER_INFO_OFFSET);
|
|
||||||
-
|
|
||||||
- if (ret) {
|
|
||||||
- fprintf(stderr, "No valid Btrfs found on %s\n", device);
|
|
||||||
- goto out;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- if (total_devs != 1) {
|
|
||||||
- ret = btrfs_scan_for_fsid(fs_devices, total_devs, 1);
|
|
||||||
- if (ret)
|
|
||||||
- goto out;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- memset(fs_info, 0, sizeof(*fs_info));
|
|
||||||
- fs_info->tree_root = tree_root;
|
|
||||||
- fs_info->extent_root = extent_root;
|
|
||||||
- fs_info->chunk_root = chunk_root;
|
|
||||||
- fs_info->dev_root = dev_root;
|
|
||||||
- fs_info->csum_root = csum_root;
|
|
||||||
-
|
|
||||||
- fs_info->readonly = 1;
|
|
||||||
-
|
|
||||||
- extent_io_tree_init(&fs_info->extent_cache);
|
|
||||||
- extent_io_tree_init(&fs_info->free_space_cache);
|
|
||||||
- extent_io_tree_init(&fs_info->block_group_cache);
|
|
||||||
- extent_io_tree_init(&fs_info->pinned_extents);
|
|
||||||
- extent_io_tree_init(&fs_info->pending_del);
|
|
||||||
- extent_io_tree_init(&fs_info->extent_ins);
|
|
||||||
- cache_tree_init(&fs_info->fs_root_cache);
|
|
||||||
-
|
|
||||||
- cache_tree_init(&fs_info->mapping_tree.cache_tree);
|
|
||||||
-
|
|
||||||
- mutex_init(&fs_info->fs_mutex);
|
|
||||||
- fs_info->fs_devices = fs_devices;
|
|
||||||
- INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots);
|
|
||||||
- INIT_LIST_HEAD(&fs_info->space_info);
|
|
||||||
-
|
|
||||||
- __setup_root(4096, 4096, 4096, 4096, tree_root,
|
|
||||||
- fs_info, BTRFS_ROOT_TREE_OBJECTID);
|
|
||||||
-
|
|
||||||
- ret = btrfs_open_devices(fs_devices, O_RDONLY);
|
|
||||||
- if (ret)
|
|
||||||
- goto out_cleanup;
|
|
||||||
-
|
|
||||||
- fs_info->super_bytenr = BTRFS_SUPER_INFO_OFFSET;
|
|
||||||
- disk_super = &fs_info->super_copy;
|
|
||||||
- ret = btrfs_read_dev_super(fs_devices->latest_bdev,
|
|
||||||
- disk_super, BTRFS_SUPER_INFO_OFFSET);
|
|
||||||
- if (ret) {
|
|
||||||
- printk("No valid btrfs found\n");
|
|
||||||
- goto out_devices;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- memcpy(fs_info->fsid, &disk_super->fsid, BTRFS_FSID_SIZE);
|
|
||||||
-
|
|
||||||
-
|
|
||||||
- features = btrfs_super_incompat_flags(disk_super) &
|
|
||||||
- ~BTRFS_FEATURE_INCOMPAT_SUPP;
|
|
||||||
- if (features) {
|
|
||||||
- printk("couldn't open because of unsupported "
|
|
||||||
- "option features (%Lx).\n", features);
|
|
||||||
- goto out_devices;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- features = btrfs_super_incompat_flags(disk_super);
|
|
||||||
- if (!(features & BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF)) {
|
|
||||||
- features |= BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF;
|
|
||||||
- btrfs_set_super_incompat_flags(disk_super, features);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- nodesize = btrfs_super_nodesize(disk_super);
|
|
||||||
- leafsize = btrfs_super_leafsize(disk_super);
|
|
||||||
- sectorsize = btrfs_super_sectorsize(disk_super);
|
|
||||||
- stripesize = btrfs_super_stripesize(disk_super);
|
|
||||||
- tree_root->nodesize = nodesize;
|
|
||||||
- tree_root->leafsize = leafsize;
|
|
||||||
- tree_root->sectorsize = sectorsize;
|
|
||||||
- tree_root->stripesize = stripesize;
|
|
||||||
-
|
|
||||||
- ret = btrfs_read_sys_array(tree_root);
|
|
||||||
- if (ret)
|
|
||||||
- goto out_devices;
|
|
||||||
- blocksize = btrfs_level_size(tree_root,
|
|
||||||
- btrfs_super_chunk_root_level(disk_super));
|
|
||||||
- generation = btrfs_super_chunk_root_generation(disk_super);
|
|
||||||
-
|
|
||||||
- __setup_root(nodesize, leafsize, sectorsize, stripesize,
|
|
||||||
- chunk_root, fs_info, BTRFS_CHUNK_TREE_OBJECTID);
|
|
||||||
-
|
|
||||||
- chunk_root->node = read_tree_block(chunk_root,
|
|
||||||
- btrfs_super_chunk_root(disk_super),
|
|
||||||
- blocksize, generation);
|
|
||||||
- if (!chunk_root->node) {
|
|
||||||
- printk("Couldn't read chunk root\n");
|
|
||||||
- goto out_devices;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- read_extent_buffer(chunk_root->node, fs_info->chunk_tree_uuid,
|
|
||||||
- (unsigned long)btrfs_header_chunk_tree_uuid(chunk_root->node),
|
|
||||||
- BTRFS_UUID_SIZE);
|
|
||||||
-
|
|
||||||
- if (!(btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_METADUMP)) {
|
|
||||||
- ret = btrfs_read_chunk_tree(chunk_root);
|
|
||||||
- if (ret)
|
|
||||||
- goto out_chunk;
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- return fs_info->chunk_root;
|
|
||||||
-out_chunk:
|
|
||||||
- free_extent_buffer(fs_info->chunk_root->node);
|
|
||||||
-out_devices:
|
|
||||||
- close_all_devices(fs_info);
|
|
||||||
-out_cleanup:
|
|
||||||
- extent_io_tree_cleanup(&fs_info->extent_cache);
|
|
||||||
- extent_io_tree_cleanup(&fs_info->free_space_cache);
|
|
||||||
- extent_io_tree_cleanup(&fs_info->block_group_cache);
|
|
||||||
- extent_io_tree_cleanup(&fs_info->pinned_extents);
|
|
||||||
- extent_io_tree_cleanup(&fs_info->pending_del);
|
|
||||||
- extent_io_tree_cleanup(&fs_info->extent_ins);
|
|
||||||
-out:
|
|
||||||
- free(tree_root);
|
|
||||||
- free(extent_root);
|
|
||||||
- free(chunk_root);
|
|
||||||
- free(dev_root);
|
|
||||||
- free(csum_root);
|
|
||||||
- free(fs_info);
|
|
||||||
- return NULL;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
static int dump_root_bytenr(struct btrfs_root *root, u64 bytenr, u64 gen)
|
|
||||||
{
|
|
||||||
struct btrfs_root *tmp = malloc(sizeof(struct btrfs_root));
|
|
||||||
diff --git a/restore.c b/restore.c
|
|
||||||
index a4ccb18..90d54e4 100644
|
|
||||||
--- a/restore.c
|
|
||||||
+++ b/restore.c
|
|
||||||
@@ -779,9 +779,13 @@ static void usage()
|
|
||||||
|
|
||||||
static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_mirror)
|
|
||||||
{
|
|
||||||
+ struct btrfs_key key;
|
|
||||||
struct btrfs_root *root;
|
|
||||||
u64 bytenr;
|
|
||||||
+ u64 generation;
|
|
||||||
+ u32 blocksize;
|
|
||||||
int i;
|
|
||||||
+ int dev_fd;
|
|
||||||
|
|
||||||
for (i = super_mirror; i < BTRFS_SUPER_MIRROR_MAX; i++) {
|
|
||||||
bytenr = btrfs_sb_offset(i);
|
|
||||||
@@ -791,7 +795,49 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_
|
|
||||||
fprintf(stderr, "Could not open root, trying backup super\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
- return NULL;
|
|
||||||
+ fprintf(stderr, "Ok couldn't open the root the normal way, trying "
|
|
||||||
+ "the broken way\n");
|
|
||||||
+
|
|
||||||
+ dev_fd = open(dev, O_RDONLY);
|
|
||||||
+ if (dev_fd < 0) {
|
|
||||||
+ fprintf(stderr, "Failed to open device %s\n", dev);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ root = open_ctree_broken(dev_fd, dev);
|
|
||||||
+ close(dev_fd);
|
|
||||||
+ if (!root) {
|
|
||||||
+ fprintf(stderr, "Broken ctree open failed\n");
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+ if (!root_location)
|
|
||||||
+ bytenr = 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,
|
|
||||||
+ blocksize,
|
|
||||||
+ generation);
|
|
||||||
+ if (!root->fs_info->tree_root->node) {
|
|
||||||
+ fprintf(stderr, "Couldn't read tree node\n");
|
|
||||||
+ close_ctree(root);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ key.objectid = BTRFS_FS_TREE_OBJECTID;
|
|
||||||
+ key.type = BTRFS_ROOT_ITEM_KEY;
|
|
||||||
+ key.offset = (u64)-1;
|
|
||||||
+
|
|
||||||
+ root->fs_info->fs_root = btrfs_read_fs_root(root->fs_info, &key);
|
|
||||||
+ if (!root->fs_info->fs_root) {
|
|
||||||
+ fprintf(stderr, "Couldn't read fs_root\n");
|
|
||||||
+ close_ctree(root);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return root->fs_info->fs_root;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int find_first_dir(struct btrfs_root *root, u64 *objectid)
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
From 412d4f1fe3a14c7e61efbd0ad4280323de71606a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Josef Bacik <josef@redhat.com>
|
|
||||||
Date: Wed, 7 Dec 2011 15:54:13 -0500
|
|
||||||
Subject: [PATCH 32/35] Btrfs-progs: don't bug out if we can't find the last
|
|
||||||
root
|
|
||||||
|
|
||||||
Return an error instead of BUG()'ing out.
|
|
||||||
|
|
||||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
|
||||||
---
|
|
||||||
root-tree.c | 5 +++++
|
|
||||||
1 files changed, 5 insertions(+), 0 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/root-tree.c b/root-tree.c
|
|
||||||
index 782472c..7a6ae0a 100644
|
|
||||||
--- a/root-tree.c
|
|
||||||
+++ b/root-tree.c
|
|
||||||
@@ -43,6 +43,11 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
|
|
||||||
|
|
||||||
BUG_ON(ret == 0);
|
|
||||||
l = path->nodes[0];
|
|
||||||
+ if (path->slots[0] == 0) {
|
|
||||||
+ ret = -ENOENT;
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
BUG_ON(path->slots[0] == 0);
|
|
||||||
slot = path->slots[0] - 1;
|
|
||||||
btrfs_item_key_to_cpu(l, &found_key, slot);
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
|||||||
From df8b44a2980ace8b2e7483b96a661907e20b8a4c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Josef Bacik <josef@redhat.com>
|
|
||||||
Date: Wed, 7 Dec 2011 16:11:23 -0500
|
|
||||||
Subject: [PATCH 33/35] Btrfs-progs: make find_and_setup_root return an error
|
|
||||||
|
|
||||||
Don't BUG(), return an error so the recovery program can work its mojo.
|
|
||||||
|
|
||||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
|
||||||
---
|
|
||||||
disk-io.c | 6 ++++--
|
|
||||||
1 files changed, 4 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/disk-io.c b/disk-io.c
|
|
||||||
index 8a8071c..b0b9502 100644
|
|
||||||
--- a/disk-io.c
|
|
||||||
+++ b/disk-io.c
|
|
||||||
@@ -438,13 +438,15 @@ static int find_and_setup_root(struct btrfs_root *tree_root,
|
|
||||||
root, fs_info, objectid);
|
|
||||||
ret = btrfs_find_last_root(tree_root, objectid,
|
|
||||||
&root->root_item, &root->root_key);
|
|
||||||
- BUG_ON(ret);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
|
|
||||||
blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
|
|
||||||
generation = btrfs_root_generation(&root->root_item);
|
|
||||||
root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
|
|
||||||
blocksize, generation);
|
|
||||||
- BUG_ON(!root->node);
|
|
||||||
+ if (!root->node)
|
|
||||||
+ return -ENOENT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
|||||||
From 4686f96637316b509cb16c657b73b40a329be6db Mon Sep 17 00:00:00 2001
|
|
||||||
From: Josef Bacik <josef@redhat.com>
|
|
||||||
Date: Thu, 8 Dec 2011 17:24:54 -0500
|
|
||||||
Subject: [PATCH 34/35] Btrfs-progs: check return value properly
|
|
||||||
|
|
||||||
We were checking for a null root coming back from btrfs_read_fs_root but thats
|
|
||||||
not right since it returns a ERR_PTR. Thanks,
|
|
||||||
|
|
||||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
|
||||||
---
|
|
||||||
restore.c | 4 ++--
|
|
||||||
1 files changed, 2 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/restore.c b/restore.c
|
|
||||||
index 90d54e4..398c49a 100644
|
|
||||||
--- a/restore.c
|
|
||||||
+++ b/restore.c
|
|
||||||
@@ -831,8 +831,8 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_
|
|
||||||
key.offset = (u64)-1;
|
|
||||||
|
|
||||||
root->fs_info->fs_root = btrfs_read_fs_root(root->fs_info, &key);
|
|
||||||
- if (!root->fs_info->fs_root) {
|
|
||||||
- fprintf(stderr, "Couldn't read fs_root\n");
|
|
||||||
+ if (IS_ERR(root->fs_info->fs_root)) {
|
|
||||||
+ fprintf(stderr, "Couldn't read fs_root: %d\n", PTR_ERR(root));
|
|
||||||
close_ctree(root);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,180 +0,0 @@
|
|||||||
From 9bb7aa76e43f4942f5fa398bf00778067859f66c Mon Sep 17 00:00:00 2001
|
|
||||||
From: Josef Bacik <josef@redhat.com>
|
|
||||||
Date: Fri, 9 Dec 2011 14:09:18 -0500
|
|
||||||
Subject: [PATCH 35/35] Btrfs-progs: give restore a list roots option
|
|
||||||
|
|
||||||
Since restore has the ability to open really really screwed up file systems, add
|
|
||||||
a list roots option to it so we can still get the contents of the tree root on a
|
|
||||||
horribly broken fs. Thanks,
|
|
||||||
|
|
||||||
Signed-off-by: Josef Bacik <josef@redhat.com>
|
|
||||||
---
|
|
||||||
restore.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
|
|
||||||
1 files changed, 88 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/restore.c b/restore.c
|
|
||||||
index 398c49a..95daef2 100644
|
|
||||||
--- a/restore.c
|
|
||||||
+++ b/restore.c
|
|
||||||
@@ -773,11 +773,71 @@ next:
|
|
||||||
|
|
||||||
static void usage()
|
|
||||||
{
|
|
||||||
- fprintf(stderr, "Usage: restore [-svioc] [-t disk offset] "
|
|
||||||
+ fprintf(stderr, "Usage: restore [-sviocl] [-t disk offset] "
|
|
||||||
"[-m regex] <device> <directory>\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
-static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_mirror)
|
|
||||||
+static int do_list_roots(struct btrfs_root *root)
|
|
||||||
+{
|
|
||||||
+ struct btrfs_key key;
|
|
||||||
+ struct btrfs_key found_key;
|
|
||||||
+ struct btrfs_disk_key disk_key;
|
|
||||||
+ struct btrfs_path *path;
|
|
||||||
+ struct extent_buffer *leaf;
|
|
||||||
+ struct btrfs_root_item ri;
|
|
||||||
+ unsigned long offset;
|
|
||||||
+ int slot;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ root = root->fs_info->tree_root;
|
|
||||||
+ path = btrfs_alloc_path();
|
|
||||||
+ if (!path) {
|
|
||||||
+ fprintf(stderr, "Failed to alloc path\n");
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ key.offset = 0;
|
|
||||||
+ key.objectid = 0;
|
|
||||||
+ key.type = BTRFS_ROOT_ITEM_KEY;
|
|
||||||
+
|
|
||||||
+ ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ fprintf(stderr, "Failed to do search %d\n", ret);
|
|
||||||
+ btrfs_free_path(path);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ while (1) {
|
|
||||||
+ leaf = path->nodes[0];
|
|
||||||
+ slot = path->slots[0];
|
|
||||||
+ if (slot >= btrfs_header_nritems(leaf)) {
|
|
||||||
+ ret = btrfs_next_leaf(root, path);
|
|
||||||
+ if (ret)
|
|
||||||
+ break;
|
|
||||||
+ leaf = path->nodes[0];
|
|
||||||
+ slot = path->slots[0];
|
|
||||||
+ }
|
|
||||||
+ btrfs_item_key(leaf, &disk_key, slot);
|
|
||||||
+ btrfs_disk_key_to_cpu(&found_key, &disk_key);
|
|
||||||
+ if (btrfs_key_type(&found_key) != BTRFS_ROOT_ITEM_KEY) {
|
|
||||||
+ path->slots[0]++;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ offset = btrfs_item_ptr_offset(leaf, slot);
|
|
||||||
+ read_extent_buffer(leaf, &ri, offset, sizeof(ri));
|
|
||||||
+ printf(" tree ");
|
|
||||||
+ btrfs_print_key(&disk_key);
|
|
||||||
+ printf(" %Lu level %d\n", btrfs_root_bytenr(&ri),
|
|
||||||
+ btrfs_root_level(&ri));
|
|
||||||
+ path->slots[0]++;
|
|
||||||
+ }
|
|
||||||
+ btrfs_free_path(path);
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_mirror, int list_roots)
|
|
||||||
{
|
|
||||||
struct btrfs_key key;
|
|
||||||
struct btrfs_root *root;
|
|
||||||
@@ -791,7 +851,7 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_
|
|
||||||
bytenr = btrfs_sb_offset(i);
|
|
||||||
root = open_ctree_recovery(dev, bytenr, root_location);
|
|
||||||
if (root)
|
|
||||||
- return root;
|
|
||||||
+ goto out;
|
|
||||||
fprintf(stderr, "Could not open root, trying backup super\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -826,16 +886,27 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ if (list_roots)
|
|
||||||
+ goto out;
|
|
||||||
+
|
|
||||||
key.objectid = BTRFS_FS_TREE_OBJECTID;
|
|
||||||
key.type = BTRFS_ROOT_ITEM_KEY;
|
|
||||||
key.offset = (u64)-1;
|
|
||||||
|
|
||||||
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: %d\n", PTR_ERR(root));
|
|
||||||
+ fprintf(stderr, "Couldn't read fs_root: %ld\n", PTR_ERR(root));
|
|
||||||
close_ctree(root);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
+out:
|
|
||||||
+ if (list_roots) {
|
|
||||||
+ int ret = do_list_roots(root);
|
|
||||||
+ if (ret) {
|
|
||||||
+ root = NULL;
|
|
||||||
+ close_ctree(root);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
|
|
||||||
return root->fs_info->fs_root;
|
|
||||||
}
|
|
||||||
@@ -917,8 +988,9 @@ int main(int argc, char **argv)
|
|
||||||
int match_cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
|
|
||||||
regex_t match_reg, *mreg = NULL;
|
|
||||||
char reg_err[256];
|
|
||||||
+ int list_roots = 0;
|
|
||||||
|
|
||||||
- while ((opt = getopt(argc, argv, "sviot:u:df:r:cm:")) != -1) {
|
|
||||||
+ while ((opt = getopt(argc, argv, "sviot:u:df:r:cm:l")) != -1) {
|
|
||||||
switch (opt) {
|
|
||||||
case 's':
|
|
||||||
get_snaps = 1;
|
|
||||||
@@ -975,13 +1047,19 @@ int main(int argc, char **argv)
|
|
||||||
case 'm':
|
|
||||||
match_regstr = optarg;
|
|
||||||
break;
|
|
||||||
+ case 'l':
|
|
||||||
+ list_roots = 1;
|
|
||||||
+ break;
|
|
||||||
default:
|
|
||||||
usage();
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (optind + 1 >= argc) {
|
|
||||||
+ if (!list_roots && optind + 1 >= argc) {
|
|
||||||
+ usage();
|
|
||||||
+ exit(1);
|
|
||||||
+ } else if (list_roots && optind >= argc) {
|
|
||||||
usage();
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
@@ -995,10 +1073,13 @@ int main(int argc, char **argv)
|
|
||||||
return -EBUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
- root = open_fs(argv[optind], tree_location, super_mirror);
|
|
||||||
+ root = open_fs(argv[optind], tree_location, 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);
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
From 243a10fc066200621fbdee91eb28a53f5cc91d81 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Tsutomu Itoh <t-itoh@jp.fujitsu.com>
|
|
||||||
Date: Tue, 1 Nov 2011 12:20:42 +0900
|
|
||||||
Subject: [PATCH 135/138] Btrfs-progs: fix compiler warning of extent-tree.c
|
|
||||||
|
|
||||||
In recovery-beta, following compiler warning was displayed.
|
|
||||||
|
|
||||||
gcc -Wp,-MMD,./.extent-tree.o.d,-MT,extent-tree.o -Wall -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2 -g -O0 -c extent-tree.c
|
|
||||||
extent-tree.c: In function 'lookup_inline_extent_backref':
|
|
||||||
extent-tree.c:1071: warning: format '%u' expects type 'unsigned int', but argument 3 has type 'long unsigned int'
|
|
||||||
|
|
||||||
Signed-off-by: Tsutomu Itoh <t-itoh@jp.fujitsu.com>
|
|
||||||
---
|
|
||||||
extent-tree.c | 2 +-
|
|
||||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/extent-tree.c b/extent-tree.c
|
|
||||||
index 5bed3c2..5144d57 100644
|
|
||||||
--- a/extent-tree.c
|
|
||||||
+++ b/extent-tree.c
|
|
||||||
@@ -1068,7 +1068,7 @@ static int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
|
|
||||||
#endif
|
|
||||||
if (item_size < sizeof(*ei)) {
|
|
||||||
printf("Size is %u, needs to be %u, slot %d\n", item_size,
|
|
||||||
- sizeof(*ei), path->slots[0]);
|
|
||||||
+ (u32)sizeof(*ei), path->slots[0]);
|
|
||||||
btrfs_print_leaf(root, leaf);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,130 +0,0 @@
|
|||||||
From 6b74bd1ecd84d86cad6aaa1fd643de6f3f3c40b8 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ilya Dryomov <idryomov@gmail.com>
|
|
||||||
Date: Tue, 1 Nov 2011 23:27:39 +0200
|
|
||||||
Subject: [PATCH 136/138] Btrfs-progs: change the way mkfs picks raid profiles
|
|
||||||
|
|
||||||
Currently mkfs in response to
|
|
||||||
|
|
||||||
mkfs.btrfs -d raid10 dev1 dev2
|
|
||||||
|
|
||||||
instead of telling "you can't do that" creates a SINGLE on two devices,
|
|
||||||
and only rebalance can transform it to raid0. Generally, it never warns
|
|
||||||
users about decisions it makes and it's not at all obvious which profile
|
|
||||||
it picks when.
|
|
||||||
|
|
||||||
Fix this by checking the number of effective devices and reporting back
|
|
||||||
if the specified profile is impossible to create. Do not create FS in
|
|
||||||
case invalid profile was given.
|
|
||||||
|
|
||||||
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
|
|
||||||
---
|
|
||||||
mkfs.c | 46 +++++++++++++++++++++++++++++++++++-----------
|
|
||||||
1 files changed, 35 insertions(+), 11 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/mkfs.c b/mkfs.c
|
|
||||||
index be236d0..d39c5a7 100644
|
|
||||||
--- a/mkfs.c
|
|
||||||
+++ b/mkfs.c
|
|
||||||
@@ -228,12 +228,26 @@ static int create_one_raid_group(struct btrfs_trans_handle *trans,
|
|
||||||
|
|
||||||
static int create_raid_groups(struct btrfs_trans_handle *trans,
|
|
||||||
struct btrfs_root *root, u64 data_profile,
|
|
||||||
- u64 metadata_profile, int mixed)
|
|
||||||
+ int data_profile_opt, u64 metadata_profile,
|
|
||||||
+ int metadata_profile_opt, int mixed)
|
|
||||||
{
|
|
||||||
u64 num_devices = btrfs_super_num_devices(&root->fs_info->super_copy);
|
|
||||||
u64 allowed;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
+ /*
|
|
||||||
+ * Set default profiles according to number of added devices.
|
|
||||||
+ * For mixed groups defaults are single/single.
|
|
||||||
+ */
|
|
||||||
+ if (!metadata_profile_opt && !mixed) {
|
|
||||||
+ metadata_profile = (num_devices > 1) ?
|
|
||||||
+ BTRFS_BLOCK_GROUP_RAID1 : BTRFS_BLOCK_GROUP_DUP;
|
|
||||||
+ }
|
|
||||||
+ if (!data_profile_opt && !mixed) {
|
|
||||||
+ data_profile = (num_devices > 1) ?
|
|
||||||
+ BTRFS_BLOCK_GROUP_RAID0 : 0; /* raid0 or single */
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (num_devices == 1)
|
|
||||||
allowed = BTRFS_BLOCK_GROUP_DUP;
|
|
||||||
else if (num_devices >= 4) {
|
|
||||||
@@ -242,6 +256,19 @@ static int create_raid_groups(struct btrfs_trans_handle *trans,
|
|
||||||
} else
|
|
||||||
allowed = BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1;
|
|
||||||
|
|
||||||
+ if (metadata_profile & ~allowed) {
|
|
||||||
+ fprintf(stderr, "unable to create FS with metadata "
|
|
||||||
+ "profile %llu (%llu devices)\n", metadata_profile,
|
|
||||||
+ num_devices);
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
+ if (data_profile & ~allowed) {
|
|
||||||
+ fprintf(stderr, "unable to create FS with data "
|
|
||||||
+ "profile %llu (%llu devices)\n", data_profile,
|
|
||||||
+ num_devices);
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (allowed & metadata_profile) {
|
|
||||||
u64 meta_flags = BTRFS_BLOCK_GROUP_METADATA;
|
|
||||||
|
|
||||||
@@ -326,15 +353,16 @@ static u64 parse_profile(char *s)
|
|
||||||
if (strcmp(s, "raid0") == 0) {
|
|
||||||
return BTRFS_BLOCK_GROUP_RAID0;
|
|
||||||
} else if (strcmp(s, "raid1") == 0) {
|
|
||||||
- return BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_DUP;
|
|
||||||
+ return BTRFS_BLOCK_GROUP_RAID1;
|
|
||||||
} else if (strcmp(s, "raid10") == 0) {
|
|
||||||
- return BTRFS_BLOCK_GROUP_RAID10 | BTRFS_BLOCK_GROUP_DUP;
|
|
||||||
+ return BTRFS_BLOCK_GROUP_RAID10;
|
|
||||||
} else if (strcmp(s, "single") == 0) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Unknown option %s\n", s);
|
|
||||||
print_usage();
|
|
||||||
}
|
|
||||||
+ /* not reached */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1172,8 +1200,8 @@ int main(int ac, char **av)
|
|
||||||
u64 dev_block_count = 0;
|
|
||||||
u64 blocks[7];
|
|
||||||
u64 alloc_start = 0;
|
|
||||||
- u64 metadata_profile = BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_DUP;
|
|
||||||
- u64 data_profile = BTRFS_BLOCK_GROUP_RAID0;
|
|
||||||
+ u64 metadata_profile = 0;
|
|
||||||
+ u64 data_profile = 0;
|
|
||||||
u32 leafsize = getpagesize();
|
|
||||||
u32 sectorsize = 4096;
|
|
||||||
u32 nodesize = leafsize;
|
|
||||||
@@ -1311,11 +1339,6 @@ int main(int ac, char **av)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mixed) {
|
|
||||||
- if (!metadata_profile_opt)
|
|
||||||
- metadata_profile = 0;
|
|
||||||
- if (!data_profile_opt)
|
|
||||||
- data_profile = 0;
|
|
||||||
-
|
|
||||||
if (metadata_profile != data_profile) {
|
|
||||||
fprintf(stderr, "With mixed block groups data and metadata "
|
|
||||||
"profiles must be the same\n");
|
|
||||||
@@ -1400,7 +1423,8 @@ int main(int ac, char **av)
|
|
||||||
raid_groups:
|
|
||||||
if (!source_dir_set) {
|
|
||||||
ret = create_raid_groups(trans, root, data_profile,
|
|
||||||
- metadata_profile, mixed);
|
|
||||||
+ data_profile_opt, metadata_profile,
|
|
||||||
+ metadata_profile_opt, mixed);
|
|
||||||
BUG_ON(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
|||||||
From 670b953e28c25f835b713a22b03b9b0f86d8e025 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ilya Dryomov <idryomov@gmail.com>
|
|
||||||
Date: Tue, 1 Nov 2011 23:47:22 +0200
|
|
||||||
Subject: [PATCH 137/138] Btrfs-progs: fail gracefully on error from
|
|
||||||
open_ctree()
|
|
||||||
|
|
||||||
Error checking block got moved mistakenly exposing us to a potential
|
|
||||||
segmentation fault.
|
|
||||||
|
|
||||||
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
|
|
||||||
---
|
|
||||||
mkfs.c | 9 +++++----
|
|
||||||
1 files changed, 5 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/mkfs.c b/mkfs.c
|
|
||||||
index d39c5a7..d4d13af 100644
|
|
||||||
--- a/mkfs.c
|
|
||||||
+++ b/mkfs.c
|
|
||||||
@@ -1359,7 +1359,12 @@ int main(int ac, char **av)
|
|
||||||
fprintf(stderr, "error during mkfs %d\n", ret);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
+
|
|
||||||
root = open_ctree(file, 0, O_RDWR);
|
|
||||||
+ if (!root) {
|
|
||||||
+ fprintf(stderr, "ctree init failed\n");
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
root->fs_info->alloc_start = alloc_start;
|
|
||||||
|
|
||||||
ret = make_root_dir(root, mixed);
|
|
||||||
@@ -1374,10 +1379,6 @@ int main(int ac, char **av)
|
|
||||||
goto raid_groups;
|
|
||||||
|
|
||||||
btrfs_register_one_device(file);
|
|
||||||
- if (!root) {
|
|
||||||
- fprintf(stderr, "ctree init failed\n");
|
|
||||||
- return -1;
|
|
||||||
- }
|
|
||||||
|
|
||||||
zero_end = 1;
|
|
||||||
while(ac-- > 0) {
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
From d439a663a5ba789f7542163317264a6b4dbbe3f2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Arne Jansen <sensille@gmx.net>
|
|
||||||
Date: Tue, 29 Nov 2011 08:40:28 +0100
|
|
||||||
Subject: [PATCH 138/138] Btrfs-progs: bugfix for scrubbing single devices
|
|
||||||
|
|
||||||
Scrub can be invoked to scrub only a single device of a (mounted) filesystem.
|
|
||||||
The code determines whether the given path is a mountpoint of a filesystem
|
|
||||||
by issueing a btrfs-specific ioctl to it. Only in case of EINVAL it assumed
|
|
||||||
it may be a device, all other errnos just caused it fail, but some devices
|
|
||||||
(correctly) return ENOTTY. This patch adds this to the error check.
|
|
||||||
|
|
||||||
Signed-off-by: Arne Jansen <sensille@gmx.net>
|
|
||||||
---
|
|
||||||
scrub.c | 2 +-
|
|
||||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/scrub.c b/scrub.c
|
|
||||||
index 66761c5..5b0bf16 100644
|
|
||||||
--- a/scrub.c
|
|
||||||
+++ b/scrub.c
|
|
||||||
@@ -987,7 +987,7 @@ static int scrub_fs_info(int fd, char *path,
|
|
||||||
memset(fi_args, 0, sizeof(*fi_args));
|
|
||||||
|
|
||||||
ret = ioctl(fd, BTRFS_IOC_FS_INFO, fi_args);
|
|
||||||
- if (ret && errno == EINVAL) {
|
|
||||||
+ if (ret && (errno == EINVAL || errno == ENOTTY)) {
|
|
||||||
/* path is no mounted btrfs. try if it's a device */
|
|
||||||
ret = check_mounted_where(fd, path, mp, sizeof(mp),
|
|
||||||
&fs_devices_mnt);
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,170 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
|||||||
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(-)
|
|
||||||
|
|
||||||
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
|
|
||||||
@@ -2374,7 +2374,7 @@ int do_convert(const char *devname, int
|
|
||||||
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");
|
|
||||||
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
|
|
||||||
@@ -1290,6 +1290,10 @@ int main(int ac, char **av)
|
|
||||||
ret = btrfs_prepare_device(fd, file, zero_end, &dev_block_count, &mixed);
|
|
||||||
if (block_count == 0)
|
|
||||||
block_count = dev_block_count;
|
|
||||||
+ else if (block_count > dev_block_count) {
|
|
||||||
+ fprintf(stderr, "%s is smaller than requested size\n", file);
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
} else {
|
|
||||||
ac = 0;
|
|
||||||
file = av[optind++];
|
|
||||||
@@ -1302,8 +1306,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 +1335,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) {
|
|
||||||
Index: btrfs-progs-v0.19-118-gfdb6c04/utils.c
|
|
||||||
===================================================================
|
|
||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/utils.c
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/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 *devic
|
|
||||||
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);
|
|
||||||
Index: btrfs-progs-v0.19-118-gfdb6c04/utils.h
|
|
||||||
===================================================================
|
|
||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/utils.h
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/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,47 +0,0 @@
|
|||||||
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,17 +5,17 @@ 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 \-T\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\-T\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
|
|
@ -1,32 +0,0 @@
|
|||||||
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\-T\fP ]
|
|
||||||
[ \fB\-h\fP ]
|
|
||||||
[ \fB\-V\fP ] \fI device\fP [ \fI device ...\fP ]
|
|
||||||
@@ -63,6 +64,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\-T\fR, \fB\-\-nodiscard \fR
|
|
||||||
Do not perform whole device TRIM operation by default.
|
|
||||||
.TP
|
|
@ -1,409 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,194 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,892 +0,0 @@
|
|||||||
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);
|
|
||||||
}
|
|
@ -1,277 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,393 +0,0 @@
|
|||||||
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;
|
|
||||||
+}
|
|
@ -1,26 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,179 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,209 +0,0 @@
|
|||||||
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;
|
|
@ -1,974 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,285 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
|||||||
From 08121cd091aa7b555dcb09077296deec8b1c4d72 Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Sterba <dsterba@suse.cz>
|
|
||||||
Date: Tue, 13 Mar 2012 18:10:09 +0100
|
|
||||||
Subject: [PATCH 1/8] btrfs-progs: adjust size of filesystem if blockdevice is
|
|
||||||
larger
|
|
||||||
|
|
||||||
Signed-off-by: David Sterba <dsterba@suse.cz>
|
|
||||||
---
|
|
||||||
utils.c | 3 +++
|
|
||||||
1 files changed, 3 insertions(+), 0 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/utils.c b/utils.c
|
|
||||||
index 0beaf80..f885307 100644
|
|
||||||
--- a/utils.c
|
|
||||||
+++ b/utils.c
|
|
||||||
@@ -273,6 +273,9 @@ int make_btrfs(int fd, const char *device, const char *label,
|
|
||||||
btrfs_set_item_offset(buf, btrfs_item_nr(buf, nritems), itemoff);
|
|
||||||
btrfs_set_item_size(buf, btrfs_item_nr(buf, nritems), item_size);
|
|
||||||
|
|
||||||
+ if (num_bytes < dev_num_bytes)
|
|
||||||
+ dev_num_bytes = num_bytes;
|
|
||||||
+
|
|
||||||
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);
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
|||||||
From 04ed6645aa91d023c06c1db361a2a22f4615eea0 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ilya Dryomov <idryomov@gmail.com>
|
|
||||||
Date: Mon, 12 Mar 2012 19:17:39 +0200
|
|
||||||
Subject: [PATCH 2/8] Btrfs-progs: nuke redundant zeroing in
|
|
||||||
__list_subvol_search()
|
|
||||||
|
|
||||||
There's no need to zero out things twice.
|
|
||||||
|
|
||||||
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
|
|
||||||
---
|
|
||||||
btrfs-list.c | 4 ----
|
|
||||||
1 files changed, 0 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfs-list.c b/btrfs-list.c
|
|
||||||
index 5f4a9be..44a73de 100644
|
|
||||||
--- a/btrfs-list.c
|
|
||||||
+++ b/btrfs-list.c
|
|
||||||
@@ -569,10 +569,6 @@ static int __list_subvol_search(int fd, struct root_lookup *root_lookup)
|
|
||||||
root_lookup_init(root_lookup);
|
|
||||||
memset(&args, 0, sizeof(args));
|
|
||||||
|
|
||||||
- root_lookup_init(root_lookup);
|
|
||||||
-
|
|
||||||
- memset(&args, 0, sizeof(args));
|
|
||||||
-
|
|
||||||
/* search in the tree of tree roots */
|
|
||||||
sk->tree_id = 1;
|
|
||||||
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
|||||||
From 039e2ae2add77881b332667ef5c8e218cd208198 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ilya Dryomov <idryomov@gmail.com>
|
|
||||||
Date: Mon, 12 Mar 2012 19:17:39 +0200
|
|
||||||
Subject: [PATCH 3/8] Btrfs-progs: refactor resolve_root() function a bit
|
|
||||||
|
|
||||||
Don't pass a pointer to root_id to resolve_root(). It's always the same as
|
|
||||||
ri->root_id, passing a pointer hints that root_id can somehow change which is
|
|
||||||
not true.
|
|
||||||
|
|
||||||
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
|
|
||||||
---
|
|
||||||
btrfs-list.c | 21 ++++++++++-----------
|
|
||||||
1 files changed, 10 insertions(+), 11 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfs-list.c b/btrfs-list.c
|
|
||||||
index 44a73de..cc1dc66 100644
|
|
||||||
--- a/btrfs-list.c
|
|
||||||
+++ b/btrfs-list.c
|
|
||||||
@@ -200,7 +200,7 @@ static int add_root(struct root_lookup *root_lookup,
|
|
||||||
* in by lookup_ino_path
|
|
||||||
*/
|
|
||||||
static int resolve_root(struct root_lookup *rl, struct root_info *ri,
|
|
||||||
- u64 *root_id, u64 *parent_id, u64 *top_id, char **path)
|
|
||||||
+ u64 *parent_id, u64 *top_id, char **path)
|
|
||||||
{
|
|
||||||
char *full_path = NULL;
|
|
||||||
int len = 0;
|
|
||||||
@@ -254,7 +254,6 @@ static int resolve_root(struct root_lookup *rl, struct root_info *ri,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- *root_id = ri->root_id;
|
|
||||||
*path = full_path;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
@@ -692,23 +691,23 @@ int list_subvols(int fd, int print_parent)
|
|
||||||
n = rb_last(&root_lookup.root);
|
|
||||||
while (n) {
|
|
||||||
struct root_info *entry;
|
|
||||||
- u64 root_id;
|
|
||||||
u64 level;
|
|
||||||
u64 parent_id;
|
|
||||||
char *path;
|
|
||||||
+
|
|
||||||
entry = rb_entry(n, struct root_info, rb_node);
|
|
||||||
- resolve_root(&root_lookup, entry, &root_id, &parent_id,
|
|
||||||
- &level, &path);
|
|
||||||
+ resolve_root(&root_lookup, entry, &parent_id, &level, &path);
|
|
||||||
if (print_parent) {
|
|
||||||
printf("ID %llu parent %llu top level %llu path %s\n",
|
|
||||||
- (unsigned long long)root_id,
|
|
||||||
+ (unsigned long long)entry->root_id,
|
|
||||||
(unsigned long long)parent_id,
|
|
||||||
(unsigned long long)level, path);
|
|
||||||
} else {
|
|
||||||
printf("ID %llu top level %llu path %s\n",
|
|
||||||
- (unsigned long long)root_id,
|
|
||||||
+ (unsigned long long)entry->root_id,
|
|
||||||
(unsigned long long)level, path);
|
|
||||||
}
|
|
||||||
+
|
|
||||||
free(path);
|
|
||||||
n = rb_prev(n);
|
|
||||||
}
|
|
||||||
@@ -914,17 +913,17 @@ char *path_for_root(int fd, u64 root)
|
|
||||||
n = rb_last(&root_lookup.root);
|
|
||||||
while (n) {
|
|
||||||
struct root_info *entry;
|
|
||||||
- u64 root_id;
|
|
||||||
u64 parent_id;
|
|
||||||
u64 level;
|
|
||||||
char *path;
|
|
||||||
+
|
|
||||||
entry = rb_entry(n, struct root_info, rb_node);
|
|
||||||
- resolve_root(&root_lookup, entry, &root_id, &parent_id, &level,
|
|
||||||
- &path);
|
|
||||||
- if (root_id == root)
|
|
||||||
+ resolve_root(&root_lookup, entry, &parent_id, &level, &path);
|
|
||||||
+ if (entry->root_id == root)
|
|
||||||
ret_path = path;
|
|
||||||
else
|
|
||||||
free(path);
|
|
||||||
+
|
|
||||||
n = rb_prev(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,142 +0,0 @@
|
|||||||
From ab67e5db559701b71a20e39948c5a531b7469362 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ilya Dryomov <idryomov@gmail.com>
|
|
||||||
Date: Mon, 12 Mar 2012 19:17:39 +0200
|
|
||||||
Subject: [PATCH 4/8] Btrfs-progs: bring 'subvol get-default' back in
|
|
||||||
|
|
||||||
Commit bab2c565 accidentally broke 'subvol get-default' command by
|
|
||||||
removing almost all of the underlying code. Bring it back with some
|
|
||||||
fixes and improvements.
|
|
||||||
|
|
||||||
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
|
|
||||||
---
|
|
||||||
btrfs-list.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
|
|
||||||
ctree.h | 2 +
|
|
||||||
2 files changed, 82 insertions(+), 1 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfs-list.c b/btrfs-list.c
|
|
||||||
index cc1dc66..00c428b 100644
|
|
||||||
--- a/btrfs-list.c
|
|
||||||
+++ b/btrfs-list.c
|
|
||||||
@@ -552,6 +552,60 @@ build:
|
|
||||||
return full;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int get_default_subvolid(int fd, u64 *default_id)
|
|
||||||
+{
|
|
||||||
+ struct btrfs_ioctl_search_args args;
|
|
||||||
+ struct btrfs_ioctl_search_key *sk = &args.key;
|
|
||||||
+ struct btrfs_ioctl_search_header *sh;
|
|
||||||
+ u64 found = 0;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ memset(&args, 0, sizeof(args));
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * search for a dir item with a name 'default' in the tree of
|
|
||||||
+ * tree roots, it should point us to a default root
|
|
||||||
+ */
|
|
||||||
+ sk->tree_id = 1;
|
|
||||||
+
|
|
||||||
+ /* don't worry about ancient format and request only one item */
|
|
||||||
+ sk->nr_items = 1;
|
|
||||||
+
|
|
||||||
+ sk->max_objectid = BTRFS_ROOT_TREE_DIR_OBJECTID;
|
|
||||||
+ sk->min_objectid = BTRFS_ROOT_TREE_DIR_OBJECTID;
|
|
||||||
+ sk->max_type = BTRFS_DIR_ITEM_KEY;
|
|
||||||
+ sk->min_type = BTRFS_DIR_ITEM_KEY;
|
|
||||||
+ sk->max_offset = (u64)-1;
|
|
||||||
+ sk->max_transid = (u64)-1;
|
|
||||||
+
|
|
||||||
+ ret = ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args);
|
|
||||||
+ if (ret < 0)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ /* the ioctl returns the number of items it found in nr_items */
|
|
||||||
+ if (sk->nr_items == 0)
|
|
||||||
+ goto out;
|
|
||||||
+
|
|
||||||
+ sh = (struct btrfs_ioctl_search_header *)args.buf;
|
|
||||||
+
|
|
||||||
+ if (sh->type == BTRFS_DIR_ITEM_KEY) {
|
|
||||||
+ struct btrfs_dir_item *di;
|
|
||||||
+ int name_len;
|
|
||||||
+ char *name;
|
|
||||||
+
|
|
||||||
+ di = (struct btrfs_dir_item *)(sh + 1);
|
|
||||||
+ name_len = btrfs_stack_dir_name_len(di);
|
|
||||||
+ name = (char *)(di + 1);
|
|
||||||
+
|
|
||||||
+ if (!strncmp("default", name, name_len))
|
|
||||||
+ found = btrfs_disk_key_objectid(&di->location);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+out:
|
|
||||||
+ *default_id = found;
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int __list_subvol_search(int fd, struct root_lookup *root_lookup)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
@@ -663,12 +717,32 @@ static int __list_subvol_fill_paths(int fd, struct root_lookup *root_lookup)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-int list_subvols(int fd, int print_parent)
|
|
||||||
+int list_subvols(int fd, int print_parent, int get_default)
|
|
||||||
{
|
|
||||||
struct root_lookup root_lookup;
|
|
||||||
struct rb_node *n;
|
|
||||||
+ u64 default_id;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
+ if (get_default) {
|
|
||||||
+ ret = get_default_subvolid(fd, &default_id);
|
|
||||||
+ if (ret) {
|
|
||||||
+ fprintf(stderr, "ERROR: can't perform the search - %s\n",
|
|
||||||
+ strerror(errno));
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+ if (default_id == 0) {
|
|
||||||
+ fprintf(stderr, "ERROR: 'default' dir item not found\n");
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* no need to resolve roots if FS_TREE is default */
|
|
||||||
+ if (default_id == BTRFS_FS_TREE_OBJECTID) {
|
|
||||||
+ printf("ID 5 (FS_TREE)\n");
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
ret = __list_subvol_search(fd, &root_lookup);
|
|
||||||
if (ret) {
|
|
||||||
fprintf(stderr, "ERROR: can't perform the search - %s\n",
|
|
||||||
@@ -696,6 +770,11 @@ int list_subvols(int fd, int print_parent)
|
|
||||||
char *path;
|
|
||||||
|
|
||||||
entry = rb_entry(n, struct root_info, rb_node);
|
|
||||||
+ if (get_default && entry->root_id != default_id) {
|
|
||||||
+ n = rb_prev(n);
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
resolve_root(&root_lookup, entry, &parent_id, &level, &path);
|
|
||||||
if (print_parent) {
|
|
||||||
printf("ID %llu parent %llu top level %llu path %s\n",
|
|
||||||
diff --git a/ctree.h b/ctree.h
|
|
||||||
index 5309059..141ec59 100644
|
|
||||||
--- a/ctree.h
|
|
||||||
+++ b/ctree.h
|
|
||||||
@@ -1416,6 +1416,8 @@ BTRFS_SETGET_FUNCS(dir_type, struct btrfs_dir_item, type, 8);
|
|
||||||
BTRFS_SETGET_FUNCS(dir_name_len, struct btrfs_dir_item, name_len, 16);
|
|
||||||
BTRFS_SETGET_FUNCS(dir_transid, struct btrfs_dir_item, transid, 64);
|
|
||||||
|
|
||||||
+BTRFS_SETGET_STACK_FUNCS(stack_dir_name_len, struct btrfs_dir_item, name_len, 16);
|
|
||||||
+
|
|
||||||
static inline void btrfs_dir_item_key(struct extent_buffer *eb,
|
|
||||||
struct btrfs_dir_item *item,
|
|
||||||
struct btrfs_disk_key *key)
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,185 +0,0 @@
|
|||||||
From 55b993c8889135f51ce66b26caf54e3e17b03e34 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ilya Dryomov <idryomov@gmail.com>
|
|
||||||
Date: Tue, 13 Mar 2012 18:36:56 +0200
|
|
||||||
Subject: [PATCH 5/8] Btrfs-progs: make print-tree.c aware of free space cache
|
|
||||||
|
|
||||||
This adds proper formatting for free space and inode cache items in
|
|
||||||
btrfs-debug-tree output.
|
|
||||||
|
|
||||||
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
|
|
||||||
---
|
|
||||||
ctree.h | 29 +++++++++++++++++++++++++++++
|
|
||||||
print-tree.c | 52 +++++++++++++++++++++++++++++++++++++++++++---------
|
|
||||||
2 files changed, 72 insertions(+), 9 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/ctree.h b/ctree.h
|
|
||||||
index 141ec59..147c3cb 100644
|
|
||||||
--- a/ctree.h
|
|
||||||
+++ b/ctree.h
|
|
||||||
@@ -256,6 +256,13 @@ struct btrfs_chunk {
|
|
||||||
/* additional stripes go here */
|
|
||||||
} __attribute__ ((__packed__));
|
|
||||||
|
|
||||||
+struct btrfs_free_space_header {
|
|
||||||
+ struct btrfs_disk_key location;
|
|
||||||
+ __le64 generation;
|
|
||||||
+ __le64 num_entries;
|
|
||||||
+ __le64 num_bitmaps;
|
|
||||||
+} __attribute__ ((__packed__));
|
|
||||||
+
|
|
||||||
static inline unsigned long btrfs_chunk_item_size(int num_stripes)
|
|
||||||
{
|
|
||||||
BUG_ON(num_stripes == 0);
|
|
||||||
@@ -1432,6 +1439,28 @@ static inline void btrfs_set_dir_item_key(struct extent_buffer *eb,
|
|
||||||
write_eb_member(eb, item, struct btrfs_dir_item, location, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
+/* struct btrfs_free_space_header */
|
|
||||||
+BTRFS_SETGET_FUNCS(free_space_entries, struct btrfs_free_space_header,
|
|
||||||
+ num_entries, 64);
|
|
||||||
+BTRFS_SETGET_FUNCS(free_space_bitmaps, struct btrfs_free_space_header,
|
|
||||||
+ num_bitmaps, 64);
|
|
||||||
+BTRFS_SETGET_FUNCS(free_space_generation, struct btrfs_free_space_header,
|
|
||||||
+ generation, 64);
|
|
||||||
+
|
|
||||||
+static inline void btrfs_free_space_key(struct extent_buffer *eb,
|
|
||||||
+ struct btrfs_free_space_header *h,
|
|
||||||
+ struct btrfs_disk_key *key)
|
|
||||||
+{
|
|
||||||
+ read_eb_member(eb, h, struct btrfs_free_space_header, location, key);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void btrfs_set_free_space_key(struct extent_buffer *eb,
|
|
||||||
+ struct btrfs_free_space_header *h,
|
|
||||||
+ struct btrfs_disk_key *key)
|
|
||||||
+{
|
|
||||||
+ write_eb_member(eb, h, struct btrfs_free_space_header, location, key);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/* struct btrfs_disk_key */
|
|
||||||
BTRFS_SETGET_STACK_FUNCS(disk_key_objectid, struct btrfs_disk_key,
|
|
||||||
objectid, 64);
|
|
||||||
diff --git a/print-tree.c b/print-tree.c
|
|
||||||
index fc134c0..face47a 100644
|
|
||||||
--- a/print-tree.c
|
|
||||||
+++ b/print-tree.c
|
|
||||||
@@ -94,6 +94,7 @@ static void print_chunk(struct extent_buffer *eb, struct btrfs_chunk *chunk)
|
|
||||||
(unsigned long long)btrfs_stripe_offset_nr(eb, chunk, i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+
|
|
||||||
static void print_dev_item(struct extent_buffer *eb,
|
|
||||||
struct btrfs_dev_item *dev_item)
|
|
||||||
{
|
|
||||||
@@ -276,8 +277,29 @@ static void print_root_ref(struct extent_buffer *leaf, int slot, char *tag)
|
|
||||||
namelen, namebuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void print_key_type(u8 type)
|
|
||||||
+static void print_free_space_header(struct extent_buffer *leaf, int slot)
|
|
||||||
{
|
|
||||||
+ struct btrfs_free_space_header *header;
|
|
||||||
+ struct btrfs_disk_key location;
|
|
||||||
+
|
|
||||||
+ header = btrfs_item_ptr(leaf, slot, struct btrfs_free_space_header);
|
|
||||||
+ btrfs_free_space_key(leaf, header, &location);
|
|
||||||
+ printf("\t\tlocation ");
|
|
||||||
+ btrfs_print_key(&location);
|
|
||||||
+ printf("\n");
|
|
||||||
+ printf("\t\tcache generation %llu entries %llu bitmaps %llu\n",
|
|
||||||
+ (unsigned long long)btrfs_free_space_generation(leaf, header),
|
|
||||||
+ (unsigned long long)btrfs_free_space_entries(leaf, header),
|
|
||||||
+ (unsigned long long)btrfs_free_space_bitmaps(leaf, header));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void print_key_type(u64 objectid, u8 type)
|
|
||||||
+{
|
|
||||||
+ if (type == 0 && objectid == BTRFS_FREE_SPACE_OBJECTID) {
|
|
||||||
+ printf("UNTYPED");
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
switch (type) {
|
|
||||||
case BTRFS_INODE_ITEM_KEY:
|
|
||||||
printf("INODE_ITEM");
|
|
||||||
@@ -362,10 +384,10 @@ static void print_key_type(u8 type)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void print_objectid(unsigned long long objectid, u8 type)
|
|
||||||
+static void print_objectid(u64 objectid, u8 type)
|
|
||||||
{
|
|
||||||
if (type == BTRFS_DEV_EXTENT_KEY) {
|
|
||||||
- printf("%llu", objectid); /* device id */
|
|
||||||
+ printf("%llu", (unsigned long long)objectid); /* device id */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -415,6 +437,12 @@ static void print_objectid(unsigned long long objectid, u8 type)
|
|
||||||
case BTRFS_EXTENT_CSUM_OBJECTID:
|
|
||||||
printf("EXTENT_CSUM");
|
|
||||||
break;
|
|
||||||
+ case BTRFS_FREE_SPACE_OBJECTID:
|
|
||||||
+ printf("FREE_SPACE");
|
|
||||||
+ break;
|
|
||||||
+ case BTRFS_FREE_INO_OBJECTID:
|
|
||||||
+ printf("FREE_INO");
|
|
||||||
+ break;
|
|
||||||
case BTRFS_MULTIPLE_OBJECTIDS:
|
|
||||||
printf("MULTIPLE");
|
|
||||||
break;
|
|
||||||
@@ -425,19 +453,19 @@ static void print_objectid(unsigned long long objectid, u8 type)
|
|
||||||
}
|
|
||||||
/* fall-thru */
|
|
||||||
default:
|
|
||||||
- printf("%llu", objectid);
|
|
||||||
+ printf("%llu", (unsigned long long)objectid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void btrfs_print_key(struct btrfs_disk_key *disk_key)
|
|
||||||
{
|
|
||||||
- u8 type;
|
|
||||||
+ u64 objectid = btrfs_disk_key_objectid(disk_key);
|
|
||||||
+ u8 type = btrfs_disk_key_type(disk_key);
|
|
||||||
+
|
|
||||||
printf("key (");
|
|
||||||
- type = btrfs_disk_key_type(disk_key);
|
|
||||||
- print_objectid((unsigned long long)btrfs_disk_key_objectid(disk_key),
|
|
||||||
- type);
|
|
||||||
+ print_objectid(objectid, type);
|
|
||||||
printf(" ");
|
|
||||||
- print_key_type(type);
|
|
||||||
+ print_key_type(objectid, type);
|
|
||||||
printf(" %llu)", (unsigned long long)btrfs_disk_key_offset(disk_key));
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -460,6 +488,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
|
|
||||||
struct btrfs_block_group_item bg_item;
|
|
||||||
struct btrfs_dir_log_item *dlog;
|
|
||||||
u32 nr = btrfs_header_nritems(l);
|
|
||||||
+ u64 objectid;
|
|
||||||
u32 type;
|
|
||||||
|
|
||||||
printf("leaf %llu items %d free space %d generation %llu owner %llu\n",
|
|
||||||
@@ -472,12 +501,17 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
|
|
||||||
for (i = 0 ; i < nr ; i++) {
|
|
||||||
item = btrfs_item_nr(l, i);
|
|
||||||
btrfs_item_key(l, &disk_key, i);
|
|
||||||
+ objectid = btrfs_disk_key_objectid(&disk_key);
|
|
||||||
type = btrfs_disk_key_type(&disk_key);
|
|
||||||
printf("\titem %d ", i);
|
|
||||||
btrfs_print_key(&disk_key);
|
|
||||||
printf(" itemoff %d itemsize %d\n",
|
|
||||||
btrfs_item_offset(l, item),
|
|
||||||
btrfs_item_size(l, item));
|
|
||||||
+
|
|
||||||
+ if (type == 0 && objectid == BTRFS_FREE_SPACE_OBJECTID)
|
|
||||||
+ print_free_space_header(l, i);
|
|
||||||
+
|
|
||||||
switch (type) {
|
|
||||||
case BTRFS_INODE_ITEM_KEY:
|
|
||||||
ii = btrfs_item_ptr(l, i, struct btrfs_inode_item);
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
|||||||
From c64c11e0a2918e6319be9337a756979e1f398730 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Ilya Dryomov <idryomov@gmail.com>
|
|
||||||
Date: Tue, 13 Mar 2012 22:15:07 +0200
|
|
||||||
Subject: [PATCH 6/8] Btrfs-progs: allow dup for data chunks in mixed mode
|
|
||||||
|
|
||||||
Before commit a46e7ff2 was merged it was possible to create dup for
|
|
||||||
data+metadata chunks (mixed mode) by giving -m raid1 -d raid1 -M to
|
|
||||||
mkfs. a46e7ff2 purposefully disabled behind the scenes profile
|
|
||||||
upgrading/downgrading, so give users a chance to pick dup explicitly and
|
|
||||||
bail if dup for data is requested in normal mode.
|
|
||||||
|
|
||||||
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
|
|
||||||
---
|
|
||||||
mkfs.c | 16 ++++++++++++----
|
|
||||||
1 files changed, 12 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/mkfs.c b/mkfs.c
|
|
||||||
index acdb646..cf571c4 100644
|
|
||||||
--- a/mkfs.c
|
|
||||||
+++ b/mkfs.c
|
|
||||||
@@ -258,17 +258,23 @@ static int create_raid_groups(struct btrfs_trans_handle *trans,
|
|
||||||
|
|
||||||
if (metadata_profile & ~allowed) {
|
|
||||||
fprintf(stderr, "unable to create FS with metadata "
|
|
||||||
- "profile %llu (%llu devices)\n", metadata_profile,
|
|
||||||
+ "profile %llu (have %llu devices)\n", metadata_profile,
|
|
||||||
num_devices);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (data_profile & ~allowed) {
|
|
||||||
fprintf(stderr, "unable to create FS with data "
|
|
||||||
- "profile %llu (%llu devices)\n", data_profile,
|
|
||||||
+ "profile %llu (have %llu devices)\n", data_profile,
|
|
||||||
num_devices);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* allow dup'ed data chunks only in mixed mode */
|
|
||||||
+ if (!mixed && (data_profile & BTRFS_BLOCK_GROUP_DUP)) {
|
|
||||||
+ fprintf(stderr, "dup for data is allowed only in mixed mode\n");
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (allowed & metadata_profile) {
|
|
||||||
u64 meta_flags = BTRFS_BLOCK_GROUP_METADATA;
|
|
||||||
|
|
||||||
@@ -329,7 +335,7 @@ static void print_usage(void)
|
|
||||||
fprintf(stderr, "options:\n");
|
|
||||||
fprintf(stderr, "\t -A --alloc-start the offset to start the FS\n");
|
|
||||||
fprintf(stderr, "\t -b --byte-count total number of bytes in the FS\n");
|
|
||||||
- fprintf(stderr, "\t -d --data data profile, raid0, raid1, raid10 or single\n");
|
|
||||||
+ fprintf(stderr, "\t -d --data data profile, raid0, raid1, raid10, dup or single\n");
|
|
||||||
fprintf(stderr, "\t -f --force don't check if a device is already mounted\n");
|
|
||||||
fprintf(stderr, "\t -l --leafsize size of btree leaves\n");
|
|
||||||
fprintf(stderr, "\t -L --label set a label\n");
|
|
||||||
@@ -357,10 +363,12 @@ static u64 parse_profile(char *s)
|
|
||||||
return BTRFS_BLOCK_GROUP_RAID1;
|
|
||||||
} else if (strcmp(s, "raid10") == 0) {
|
|
||||||
return BTRFS_BLOCK_GROUP_RAID10;
|
|
||||||
+ } else if (strcmp(s, "dup") == 0) {
|
|
||||||
+ return BTRFS_BLOCK_GROUP_DUP;
|
|
||||||
} else if (strcmp(s, "single") == 0) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
- fprintf(stderr, "Unknown option %s\n", s);
|
|
||||||
+ fprintf(stderr, "Unknown profile %s\n", s);
|
|
||||||
print_usage();
|
|
||||||
}
|
|
||||||
/* not reached */
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
|||||||
From b6f17f9e5c87b93cd887088121551839d2f24b35 Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Sterba <dsterba@suse.cz>
|
|
||||||
Date: Mon, 26 Mar 2012 14:50:02 +0200
|
|
||||||
Subject: [PATCH 7/8] btrfs-progs: mkfs: rename -T to -K
|
|
||||||
|
|
||||||
Fixup to "mkfs: allow not to trim a device", to match mkfs.xfs option
|
|
||||||
name.
|
|
||||||
|
|
||||||
Signed-off-by: David Sterba <dsterba@suse.cz>
|
|
||||||
---
|
|
||||||
man/mkfs.btrfs.8.in | 4 ++--
|
|
||||||
mkfs.c | 8 ++++----
|
|
||||||
2 files changed, 6 insertions(+), 6 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/man/mkfs.btrfs.8.in b/man/mkfs.btrfs.8.in
|
|
||||||
index 307d1fb..71f061d 100644
|
|
||||||
--- a/man/mkfs.btrfs.8.in
|
|
||||||
+++ b/man/mkfs.btrfs.8.in
|
|
||||||
@@ -14,7 +14,7 @@ mkfs.btrfs \- create an btrfs filesystem
|
|
||||||
[ \fB\-n\fP\fI nodesize\fP ]
|
|
||||||
[ \fB\-s\fP\fI sectorsize\fP ]
|
|
||||||
[ \fB\-r\fP\fI rootdir\fP ]
|
|
||||||
-[ \fB\-T\fP ]
|
|
||||||
+[ \fB\-K\fP ]
|
|
||||||
[ \fB\-h\fP ]
|
|
||||||
[ \fB\-V\fP ] \fI device\fP [ \fI device ...\fP ]
|
|
||||||
.SH DESCRIPTION
|
|
||||||
@@ -67,7 +67,7 @@ Specify the sectorsize, the minimum block allocation.
|
|
||||||
\fB\-r\fR, \fB\-\-rootdir \fIrootdir\fR
|
|
||||||
Specify a directory to copy into the newly created fs.
|
|
||||||
.TP
|
|
||||||
-\fB\-T\fR, \fB\-\-nodiscard \fR
|
|
||||||
+\fB\-K\fR, \fB\-\-nodiscard \fR
|
|
||||||
Do not perform whole device TRIM operation by default.
|
|
||||||
.TP
|
|
||||||
\fB\-V\fR, \fB\-\-version\fR
|
|
||||||
diff --git a/mkfs.c b/mkfs.c
|
|
||||||
index cf571c4..d17f71c 100644
|
|
||||||
--- a/mkfs.c
|
|
||||||
+++ b/mkfs.c
|
|
||||||
@@ -344,7 +344,7 @@ static void print_usage(void)
|
|
||||||
fprintf(stderr, "\t -n --nodesize size of btree nodes\n");
|
|
||||||
fprintf(stderr, "\t -s --sectorsize min block allocation\n");
|
|
||||||
fprintf(stderr, "\t -r --rootdir the source directory\n");
|
|
||||||
- fprintf(stderr, "\t -T --nodiscard do not perform whole device TRIM\n");
|
|
||||||
+ fprintf(stderr, "\t -K --nodiscard do not perform whole device TRIM\n");
|
|
||||||
fprintf(stderr, "%s\n", BTRFS_BUILD_VERSION);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
@@ -407,7 +407,7 @@ static struct option long_options[] = {
|
|
||||||
{ "version", 0, NULL, 'V' },
|
|
||||||
{ "rootdir", 1, NULL, 'r' },
|
|
||||||
{ "force", 0, NULL, 'f' },
|
|
||||||
- { "nodiscard", 0, NULL, 'T' },
|
|
||||||
+ { "nodiscard", 0, NULL, 'K' },
|
|
||||||
{ 0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1236,7 +1236,7 @@ int main(int ac, char **av)
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
int c;
|
|
||||||
- c = getopt_long(ac, av, "A:b:l:n:s:m:d:L:r:VMfT", long_options,
|
|
||||||
+ c = getopt_long(ac, av, "A:b:l:n:s:m:d:L:r:VMfK", long_options,
|
|
||||||
&option_index);
|
|
||||||
if (c < 0)
|
|
||||||
break;
|
|
||||||
@@ -1285,7 +1285,7 @@ int main(int ac, char **av)
|
|
||||||
case 'f':
|
|
||||||
force=1;
|
|
||||||
break;
|
|
||||||
- case 'T':
|
|
||||||
+ case 'K':
|
|
||||||
nodiscard=1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,152 +0,0 @@
|
|||||||
From 251cef9c8992b79d9d80515387cb0c26ab3b154d Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Sterba <dsterba@suse.cz>
|
|
||||||
Date: Tue, 31 Jan 2012 15:32:28 +0100
|
|
||||||
Subject: [PATCH] btrfs-progs: mkfs: allow not to trim a device
|
|
||||||
|
|
||||||
Signed-off-by: David Sterba <dsterba@suse.cz>
|
|
||||||
---
|
|
||||||
man/mkfs.btrfs.8.in | 4 ++++
|
|
||||||
mkfs.c | 15 +++++++++++----
|
|
||||||
utils.c | 18 +++++++++++++-----
|
|
||||||
utils.h | 2 ++
|
|
||||||
4 files changed, 30 insertions(+), 9 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 \-T\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\-T\fR, \fB\-\-nodiscard \fR
|
|
||||||
+Do not perform whole device TRIM operation by default.
|
|
||||||
+.TP
|
|
||||||
\fB\-V\fR, \fB\-\-version\fR
|
|
||||||
Print the \fBmkfs.btrfs\fP version and exit.
|
|
||||||
.SH AVAILABILITY
|
|
||||||
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
|
|
||||||
@@ -311,6 +311,7 @@ static void print_usage(void)
|
|
||||||
fprintf(stderr, "\t -n --nodesize size of btree nodes\n");
|
|
||||||
fprintf(stderr, "\t -s --sectorsize min block allocation\n");
|
|
||||||
fprintf(stderr, "\t -r --rootdir the source directory\n");
|
|
||||||
+ fprintf(stderr, "\t -T --nodiscard do not perform whole device TRIM\n");
|
|
||||||
fprintf(stderr, "%s\n", BTRFS_BUILD_VERSION);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
@@ -370,6 +371,7 @@ static struct option long_options[] = {
|
|
||||||
{ "version", 0, NULL, 'V' },
|
|
||||||
{ "rootdir", 1, NULL, 'r' },
|
|
||||||
{ "force", 0, NULL, 'f' },
|
|
||||||
+ { "nodiscard", 0, NULL, 'T' },
|
|
||||||
{ 0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -1186,6 +1188,7 @@ int main(int ac, char **av)
|
|
||||||
int mixed = 0;
|
|
||||||
int data_profile_opt = 0;
|
|
||||||
int metadata_profile_opt = 0;
|
|
||||||
+ int nodiscard = 0;
|
|
||||||
|
|
||||||
char *source_dir = NULL;
|
|
||||||
int source_dir_set = 0;
|
|
||||||
@@ -1197,7 +1200,7 @@ int main(int ac, char **av)
|
|
||||||
|
|
||||||
while(1) {
|
|
||||||
int c;
|
|
||||||
- c = getopt_long(ac, av, "A:b:l:n:s:m:d:L:r:VMf", long_options,
|
|
||||||
+ c = getopt_long(ac, av, "A:b:l:n:s:m:d:L:r:VMfT", long_options,
|
|
||||||
&option_index);
|
|
||||||
if (c < 0)
|
|
||||||
break;
|
|
||||||
@@ -1246,6 +1249,9 @@ int main(int ac, char **av)
|
|
||||||
case 'f':
|
|
||||||
force=1;
|
|
||||||
break;
|
|
||||||
+ case 'T':
|
|
||||||
+ nodiscard=1;
|
|
||||||
+ break;
|
|
||||||
default:
|
|
||||||
print_usage();
|
|
||||||
}
|
|
||||||
@@ -1287,7 +1293,8 @@ int main(int ac, char **av)
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
first_file = file;
|
|
||||||
- ret = btrfs_prepare_device(fd, file, zero_end, &dev_block_count, &mixed);
|
|
||||||
+ ret = __btrfs_prepare_device(fd, file, zero_end,
|
|
||||||
+ &dev_block_count, &mixed, nodiscard);
|
|
||||||
if (block_count == 0)
|
|
||||||
block_count = dev_block_count;
|
|
||||||
else if (block_count > dev_block_count) {
|
|
||||||
@@ -1392,8 +1399,8 @@ int main(int ac, char **av)
|
|
||||||
close(fd);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
- ret = btrfs_prepare_device(fd, file, zero_end,
|
|
||||||
- &dev_block_count, &mixed);
|
|
||||||
+ ret = __btrfs_prepare_device(fd, file, zero_end,
|
|
||||||
+ &dev_block_count, &mixed, nodiscard);
|
|
||||||
mixed = old_mixed;
|
|
||||||
BUG_ON(ret);
|
|
||||||
|
|
||||||
Index: btrfs-progs-v0.19-118-gfdb6c04/utils.c
|
|
||||||
===================================================================
|
|
||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/utils.c
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/utils.c
|
|
||||||
@@ -539,6 +539,12 @@ int btrfs_add_to_fsid(struct btrfs_trans
|
|
||||||
int btrfs_prepare_device(int fd, char *file, int zero_end, u64 *block_count_ret,
|
|
||||||
int *mixed)
|
|
||||||
{
|
|
||||||
+ /* discard by default when called from 'device add' */
|
|
||||||
+ return __btrfs_prepare_device(fd, file, zero_end, block_count_ret, mixed, 0);
|
|
||||||
+}
|
|
||||||
+int __btrfs_prepare_device(int fd, char *file, int zero_end, u64 *block_count_ret,
|
|
||||||
+ int *mixed, int nodiscard)
|
|
||||||
+{
|
|
||||||
u64 block_count;
|
|
||||||
u64 bytenr;
|
|
||||||
struct stat st;
|
|
||||||
@@ -562,11 +568,13 @@ int btrfs_prepare_device(int fd, char *f
|
|
||||||
*mixed = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
- /*
|
|
||||||
- * We intentionally ignore errors from the discard ioctl. It is
|
|
||||||
- * not necessary for the mkfs functionality but just an optimization.
|
|
||||||
- */
|
|
||||||
- discard_blocks(fd, 0, block_count);
|
|
||||||
+ if (!nodiscard) {
|
|
||||||
+ /*
|
|
||||||
+ * We intentionally ignore errors from the discard ioctl. It is
|
|
||||||
+ * not necessary for the mkfs functionality but just an optimization.
|
|
||||||
+ */
|
|
||||||
+ discard_blocks(fd, 0, block_count);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
ret = zero_dev_start(fd);
|
|
||||||
if (ret) {
|
|
||||||
Index: btrfs-progs-v0.19-118-gfdb6c04/utils.h
|
|
||||||
===================================================================
|
|
||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/utils.h
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/utils.h
|
|
||||||
@@ -28,6 +28,8 @@ int btrfs_make_root_dir(struct btrfs_tra
|
|
||||||
struct btrfs_root *root, u64 objectid);
|
|
||||||
int btrfs_prepare_device(int fd, char *file, int zero_end,
|
|
||||||
u64 *block_count_ret, int *mixed);
|
|
||||||
+int __btrfs_prepare_device(int fd, char *file, int zero_end,
|
|
||||||
+ u64 *block_count_ret, int *mixed, int nodiscard);
|
|
||||||
int btrfs_add_to_fsid(struct btrfs_trans_handle *trans,
|
|
||||||
struct btrfs_root *root, int fd, char *path,
|
|
||||||
u64 block_count, u32 io_width, u32 io_align,
|
|
@ -1,107 +0,0 @@
|
|||||||
From 9e2b399e046af8a0ec96662b7b849fb7327384cc Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Sterba <dsterba@suse.cz>
|
|
||||||
Date: Tue, 31 Jan 2012 14:40:22 +0100
|
|
||||||
Subject: [PATCH] btrfs-progs: convert: set label or copy from origin
|
|
||||||
|
|
||||||
Signed-off-by: David Sterba <dsterba@suse.cz>
|
|
||||||
---
|
|
||||||
convert.c | 46 ++++++++++++++++++++++++++++++++++++++--------
|
|
||||||
1 files changed, 38 insertions(+), 8 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/convert.c b/convert.c
|
|
||||||
index 13f3ece..3e74108 100644
|
|
||||||
--- a/convert.c
|
|
||||||
+++ b/convert.c
|
|
||||||
@@ -2332,7 +2332,8 @@ err:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
-int do_convert(const char *devname, int datacsum, int packing, int noxattr)
|
|
||||||
+int do_convert(const char *devname, int datacsum, int packing, int noxattr,
|
|
||||||
+ int copylabel, const char *fslabel)
|
|
||||||
{
|
|
||||||
int i, fd, ret;
|
|
||||||
u32 blocksize;
|
|
||||||
@@ -2424,6 +2425,17 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr)
|
|
||||||
fprintf(stderr, "error during create_ext2_image %d\n", ret);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
+ memset(root->fs_info->super_copy.label, 0, BTRFS_LABEL_SIZE);
|
|
||||||
+ if (copylabel == 1) {
|
|
||||||
+ strncpy(root->fs_info->super_copy.label,
|
|
||||||
+ ext2_fs->super->s_volume_name, 16);
|
|
||||||
+ fprintf(stderr, "copy label '%s'\n",
|
|
||||||
+ root->fs_info->super_copy.label);
|
|
||||||
+ } else if (copylabel == -1) {
|
|
||||||
+ strncpy(root->fs_info->super_copy.label, fslabel, BTRFS_LABEL_SIZE);
|
|
||||||
+ fprintf(stderr, "set label to '%s'\n", fslabel);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
printf("cleaning up system chunk.\n");
|
|
||||||
ret = cleanup_sys_chunk(root, ext2_root);
|
|
||||||
if (ret) {
|
|
||||||
@@ -2812,11 +2824,13 @@ fail:
|
|
||||||
|
|
||||||
static void print_usage(void)
|
|
||||||
{
|
|
||||||
- printf("usage: btrfs-convert [-d] [-i] [-n] [-r] device\n");
|
|
||||||
- printf("\t-d disable data checksum\n");
|
|
||||||
- printf("\t-i ignore xattrs and ACLs\n");
|
|
||||||
- printf("\t-n disable packing of small files\n");
|
|
||||||
- printf("\t-r roll back to ext2fs\n");
|
|
||||||
+ printf("usage: btrfs-convert [-d] [-i] [-n] [-r] [-l label] [-L] device\n");
|
|
||||||
+ printf("\t-d disable data checksum\n");
|
|
||||||
+ printf("\t-i ignore xattrs and ACLs\n");
|
|
||||||
+ printf("\t-n disable packing of small files\n");
|
|
||||||
+ printf("\t-r roll back to ext2fs\n");
|
|
||||||
+ printf("\t-l LABEL set filesystem label\n");
|
|
||||||
+ printf("\t-L use label from converted fs\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
@@ -2826,9 +2840,12 @@ int main(int argc, char *argv[])
|
|
||||||
int noxattr = 0;
|
|
||||||
int datacsum = 1;
|
|
||||||
int rollback = 0;
|
|
||||||
+ int copylabel = 0;
|
|
||||||
char *file;
|
|
||||||
+ char *fslabel = NULL;
|
|
||||||
+
|
|
||||||
while(1) {
|
|
||||||
- int c = getopt(argc, argv, "dinr");
|
|
||||||
+ int c = getopt(argc, argv, "dinrl:L");
|
|
||||||
if (c < 0)
|
|
||||||
break;
|
|
||||||
switch(c) {
|
|
||||||
@@ -2844,6 +2861,19 @@ int main(int argc, char *argv[])
|
|
||||||
case 'r':
|
|
||||||
rollback = 1;
|
|
||||||
break;
|
|
||||||
+ case 'l':
|
|
||||||
+ copylabel = -1;
|
|
||||||
+ fslabel = strdup(optarg);
|
|
||||||
+ if (strlen(fslabel) > BTRFS_LABEL_SIZE) {
|
|
||||||
+ fprintf(stderr,
|
|
||||||
+ "warning: label too long, trimmed to %d bytes\n",
|
|
||||||
+ BTRFS_LABEL_SIZE);
|
|
||||||
+ fslabel[BTRFS_LABEL_SIZE]=0;
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+ case 'L':
|
|
||||||
+ copylabel = 1;
|
|
||||||
+ break;
|
|
||||||
default:
|
|
||||||
print_usage();
|
|
||||||
return 1;
|
|
||||||
@@ -2864,7 +2894,7 @@ int main(int argc, char *argv[])
|
|
||||||
if (rollback) {
|
|
||||||
ret = do_rollback(file, 0);
|
|
||||||
} else {
|
|
||||||
- ret = do_convert(file, datacsum, packing, noxattr);
|
|
||||||
+ ret = do_convert(file, datacsum, packing, noxattr, copylabel, fslabel);
|
|
||||||
}
|
|
||||||
if (ret)
|
|
||||||
return 1;
|
|
||||||
--
|
|
||||||
1.7.9
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
|||||||
From 273488299effe9a9182fffc1a7cd9639b68a0da4 Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Sterba <dsterba@suse.cz>
|
|
||||||
Date: Fri, 17 Feb 2012 11:44:03 +0100
|
|
||||||
Subject: [PATCH] btrfs-progs: mkfs: disallow uneven data/metadata blocksize
|
|
||||||
for mixed
|
|
||||||
|
|
||||||
With support for bigger metadata blocks, we must avoid different
|
|
||||||
block size for mixed block groups, this causes corruption
|
|
||||||
(xfstests/083).
|
|
||||||
|
|
||||||
Signed-off-by: David Sterba <dsterba@suse.cz>
|
|
||||||
---
|
|
||||||
mkfs.c | 13 +++++++++++++
|
|
||||||
1 files changed, 13 insertions(+), 0 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/mkfs.c b/mkfs.c
|
|
||||||
index e3ced19..e02efcc 100644
|
|
||||||
--- a/mkfs.c
|
|
||||||
+++ b/mkfs.c
|
|
||||||
@@ -1313,6 +1313,19 @@ int main(int ac, char **av)
|
|
||||||
"profiles must be the same\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ if (leafsize != nodesize) {
|
|
||||||
+ fprintf(stderr, "With mixed block groups node and leaf "
|
|
||||||
+ "block sizes must be the same\n");
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (sectorsize != nodesize) {
|
|
||||||
+ fprintf(stderr, "With mixed block groups data and metadata "
|
|
||||||
+ "block sizes must be the same\n");
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
}
|
|
||||||
|
|
||||||
blocks[0] = BTRFS_SUPER_INFO_OFFSET;
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
From 68b5d415ff9515863c2080aebfe8d069b00a47fc Mon Sep 17 00:00:00 2001
|
|
||||||
From: Goffredo Baroncelli <kreijack@inwind.it>
|
|
||||||
Date: Mon, 26 Mar 2012 17:41:33 +0200
|
|
||||||
Subject: [PATCH 01/10] btrfs-progs: get-default man page
|
|
||||||
|
|
||||||
Added the man page info for the "btrfs subvolume get-default" command
|
|
||||||
|
|
||||||
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
|
|
||||||
---
|
|
||||||
btrfs_cmds.c | 10 ++++++++++
|
|
||||||
1 files changed, 10 insertions(+), 0 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
|
|
||||||
index 558d40e..26a0700 100644
|
|
||||||
--- a/btrfs_cmds.c
|
|
||||||
+++ b/btrfs_cmds.c
|
|
||||||
@@ -1761,6 +1761,16 @@ int do_change_label(int nargs, char **argv)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
+/**** man: btrfs subvolume get-default
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bsubvolume get-default\b\I <path>\i
|
|
||||||
+ *
|
|
||||||
+ * Query which subvolume of the filesystem <path> will be mounted
|
|
||||||
+ * as default.
|
|
||||||
+ *
|
|
||||||
+ * Get the \Idefault\i subvolume of the filesystem \I<path>\i.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_get_default_subvol(int nargs, char **argv)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
|||||||
From e38f0663be83e68f682919ca4e2d60cf6683b643 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Goffredo Baroncelli <kreijack@inwind.it>
|
|
||||||
Date: Mon, 26 Mar 2012 17:43:26 +0200
|
|
||||||
Subject: [PATCH 02/10] btrfs-progs: Correct xstrip() function
|
|
||||||
|
|
||||||
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
|
|
||||||
---
|
|
||||||
helpextract.c | 9 +++++----
|
|
||||||
1 files changed, 5 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/helpextract.c b/helpextract.c
|
|
||||||
index 9489ea0..a729074 100644
|
|
||||||
--- a/helpextract.c
|
|
||||||
+++ b/helpextract.c
|
|
||||||
@@ -38,20 +38,21 @@ static char *xstrip(char *s){
|
|
||||||
|
|
||||||
char *last=NULL;
|
|
||||||
char *first;
|
|
||||||
+ char prev;
|
|
||||||
|
|
||||||
while(*s && isspace(*s) ) s++;
|
|
||||||
|
|
||||||
first=s;
|
|
||||||
-
|
|
||||||
+ prev=*s;
|
|
||||||
while(*s){
|
|
||||||
- if(isspace(*s)) last=s;
|
|
||||||
+ if(!isspace(prev) && isspace(*s)) last=s;
|
|
||||||
+ prev=*s;
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(last) *last=0;
|
|
||||||
return first;
|
|
||||||
|
|
||||||
-
|
|
||||||
}
|
|
||||||
|
|
||||||
static void addtuple(char *key, char *cmdline, char *short_help,
|
|
||||||
@@ -184,7 +185,7 @@ static int search_in_file(char *nf){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-/* remove all the escape sequence excepet \\ */
|
|
||||||
+/* remove all the escape sequence except \\ */
|
|
||||||
static char * my_escape(char *src, char *filters[] ){
|
|
||||||
|
|
||||||
static char buffer[LINEBUF*5];
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
|||||||
From a8d78caea3bd1983181806f5110288f23c776005 Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Sterba <dsterba@suse.cz>
|
|
||||||
Date: Mon, 26 Mar 2012 18:00:58 +0200
|
|
||||||
Subject: [PATCH 03/10] btrfs-progs: document devid parameter for resize
|
|
||||||
|
|
||||||
Based on patch from Goffredo Baroncelli.
|
|
||||||
|
|
||||||
Signed-off-by: David Sterba <dsterba@suse.cz>
|
|
||||||
---
|
|
||||||
btrfs_cmds.c | 15 +++++++++------
|
|
||||||
1 files changed, 9 insertions(+), 6 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
|
|
||||||
index 26a0700..0a741f0 100644
|
|
||||||
--- a/btrfs_cmds.c
|
|
||||||
+++ b/btrfs_cmds.c
|
|
||||||
@@ -804,10 +804,9 @@ int do_scan(int argc, char **argv)
|
|
||||||
|
|
||||||
/**** man: btrfs filesystem resize
|
|
||||||
*
|
|
||||||
- * \Bbtrfs\b \Bfilesystem resize\b\I [+/\-]<size>[gkm]|max <path>\i
|
|
||||||
+ * \Bbtrfs\b \Bfilesystem resize\b\I [<devid>:][+/\-]<size>[gkm]|max <path>\i
|
|
||||||
*
|
|
||||||
- * Resize the file system. If 'max' is passed, the filesystem
|
|
||||||
- * will occupe all available space on the device.
|
|
||||||
+ * Resize the file system.
|
|
||||||
*
|
|
||||||
* Resize a filesystem identified by \I<path>\i.
|
|
||||||
* The \I<size>\i parameter specifies the new size of the filesystem.
|
|
||||||
@@ -818,13 +817,17 @@ int do_scan(int argc, char **argv)
|
|
||||||
* the units designators: 'K', 'M', or 'G', kilobytes, megabytes, or gigabytes,
|
|
||||||
* respectively.
|
|
||||||
*
|
|
||||||
- * If 'max' is passed, the filesystem will occupy all available space on the
|
|
||||||
+ * If 'max' is specified, the filesystem will occupy all available space on the
|
|
||||||
* volume(s).
|
|
||||||
*
|
|
||||||
- * The \Bresize\b command \Bdoes not\b manipulate the size of underlying
|
|
||||||
- * partition. If you wish to enlarge/reduce a filesystem, you must make sure
|
|
||||||
+ * The \Bresize\b command \Bdoes not\b manipulate the size of the underlying
|
|
||||||
+ * partition. If you wish to enlarge/reduce a filesystem, you have to make sure
|
|
||||||
* you can expand the partition before enlarging the filesystem and shrink the
|
|
||||||
* partition after reducing the size of the filesystem.
|
|
||||||
+ *
|
|
||||||
+ * When the filesystem consists of multiple devices, it is possible to specify
|
|
||||||
+ * which one should be resized via the <devid> parameter. To know the <devid>
|
|
||||||
+ * of a device use the command \fBbtrfs filesystem show\fR.
|
|
||||||
****/
|
|
||||||
|
|
||||||
int do_resize(int argc, char **argv)
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
|||||||
From ffa4e18f557d39e5d4b2357a40e073607e0c98a0 Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Sterba <dsterba@suse.cz>
|
|
||||||
Date: Mon, 26 Mar 2012 18:14:20 +0200
|
|
||||||
Subject: [PATCH 04/10] btrfs-progs: document csize in manpage
|
|
||||||
|
|
||||||
Signed-off-by: David Sterba <dsterba@suse.cz>
|
|
||||||
---
|
|
||||||
btrfs_cmds.c | 17 +++++++++++++++++
|
|
||||||
1 files changed, 17 insertions(+), 0 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
|
|
||||||
index 0a741f0..17c3f8e 100644
|
|
||||||
--- a/btrfs_cmds.c
|
|
||||||
+++ b/btrfs_cmds.c
|
|
||||||
@@ -2090,6 +2090,23 @@ out:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+/**** man: btrfs filesystem csize
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bfilesystem csize [-s \Istart\i\B] [-e \Iend\i\B] <file>
|
|
||||||
+ *
|
|
||||||
+ * Read regular and compressed size of extents in the range \I[start,end)\i.
|
|
||||||
+ *
|
|
||||||
+ * Read regular and compressed size of extents in the range \I[start,end)\i.
|
|
||||||
+ *
|
|
||||||
+ * \B-s\b\I start\i
|
|
||||||
+ * range start inclusive, accepts K/M/G modifiers
|
|
||||||
+ * \B-e\b\I end\i
|
|
||||||
+ * range end exclusive, accepts K/M/G modifiers
|
|
||||||
+ *
|
|
||||||
+ * No range specified will read the whole file, no end of range reads up to
|
|
||||||
+ * the end of file.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_compr_size(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,126 +0,0 @@
|
|||||||
From ba5f32986c342795eb910e8d77b5a5756af049ce Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Sterba <dsterba@suse.cz>
|
|
||||||
Date: Mon, 26 Mar 2012 19:25:41 +0200
|
|
||||||
Subject: [PATCH 05/10] btrfs-progs: document balance in manpage
|
|
||||||
|
|
||||||
Signed-off-by: David Sterba <dsterba@suse.cz>
|
|
||||||
---
|
|
||||||
btrfs_cmds.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
|
|
||||||
1 files changed, 71 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
|
|
||||||
index 17c3f8e..a7231d0 100644
|
|
||||||
--- a/btrfs_cmds.c
|
|
||||||
+++ b/btrfs_cmds.c
|
|
||||||
@@ -1350,9 +1350,38 @@ static struct option balance_longopts[] = {
|
|
||||||
{ 0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
-/*
|
|
||||||
- * [-d [filters]] [-m [filters]] [-s [filters]] [-vf]
|
|
||||||
- */
|
|
||||||
+/**** man: btrfs filesystem balance start
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bfilesystem balance start\b \B[-d [filters]] [-m [filters]] [-s [filters]] [-vf]\b \I<path>\i
|
|
||||||
+ *
|
|
||||||
+ * Balance chunks accross the devices on filesystem under \Ipath\i. Control
|
|
||||||
+ * operation by subcommands.
|
|
||||||
+ *
|
|
||||||
+ * \B-d\b apply filters on data block groups
|
|
||||||
+ *
|
|
||||||
+ * \B-m\b apply filters on metadata block groups
|
|
||||||
+ *
|
|
||||||
+ * \B-s\b apply filters on system block groups
|
|
||||||
+ *
|
|
||||||
+ * \B-f\b force operation on system block groups
|
|
||||||
+ *
|
|
||||||
+ * \B-v\b verbose, dupms filters at the end of operation
|
|
||||||
+ *
|
|
||||||
+ * \Ifilters\i may be a comma separated list of the following items, see section \BBALANCE FILTERS\b for more.
|
|
||||||
+ *
|
|
||||||
+ * \Bprofile\b=raid0|raid1|raid10|single|dup specify profiles, multiple allowed, note to escape the '|' from shell
|
|
||||||
+ *
|
|
||||||
+ * \Busage\b=<nnn> process only block groups with usage above \Innn\i percent
|
|
||||||
+ *
|
|
||||||
+ * \Bdevid\b=<devid> process only block groups on device \Idevid\i
|
|
||||||
+ *
|
|
||||||
+ * \Bconvert\b=raid0|raid1|radi10|single|dup convert raid profile to the specified one (only one profile allowed)
|
|
||||||
+ *
|
|
||||||
+ * \Bvrange\b=[start]..[end] virtual block address space subset filter
|
|
||||||
+ *
|
|
||||||
+ * \Bdrange\b=[start]..[end] devid subset filter, it's tied to devid filter: we say balance out range [start..end) on a particular devid.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_balance(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
@@ -1496,6 +1525,16 @@ int do_balance(int argc, char **argv)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+/**** man: btrfs filesystem balance pause
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bfilesystem balance pause\b \I<path>\i
|
|
||||||
+ *
|
|
||||||
+ * Pause balance operation at the first possible occasion.
|
|
||||||
+ *
|
|
||||||
+ * Pause balance operation at the first possible occasion. This may block for a
|
|
||||||
+ * few minutes if the balance is in the middle of processing.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_balance_pause(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
@@ -1522,6 +1561,16 @@ int do_balance_pause(int argc, char **argv)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+/**** man: btrfs filesystem balance cancel
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bfilesystem balance cancel\b \I<path>\i
|
|
||||||
+ *
|
|
||||||
+ * Cancel balance operation at the first possible occasion.
|
|
||||||
+ *
|
|
||||||
+ * Cancel balance operation at the first possible occasion. This may block for
|
|
||||||
+ * a few minutes if the balance is in the middle of processing.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_balance_cancel(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
@@ -1548,6 +1597,15 @@ int do_balance_cancel(int argc, char **argv)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+/**** man: btrfs filesystem balance resume
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bfilesystem balance resume\b \I<path>\i
|
|
||||||
+ *
|
|
||||||
+ * Resume balance operation.
|
|
||||||
+ *
|
|
||||||
+ * Resume balance operation and continue from the last position.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_balance_resume(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
@@ -1601,6 +1659,16 @@ static struct option balance_progress_longopts[] = {
|
|
||||||
{ 0, 0, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
+/**** man: btrfs filesystem balance status
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bfilesystem balance status\b [-v] \I<path>\i
|
|
||||||
+ *
|
|
||||||
+ * Show status of running or paused balance operation.
|
|
||||||
+ *
|
|
||||||
+ * Show status of running or paused balance operation.
|
|
||||||
+ *
|
|
||||||
+ * \B-v\b verbose
|
|
||||||
+ ****/
|
|
||||||
int do_balance_progress(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
|||||||
From 05b288e9a3ced5f077156726622904081f41388f Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Sterba <dsterba@suse.cz>
|
|
||||||
Date: Mon, 26 Mar 2012 23:35:14 +0200
|
|
||||||
Subject: [PATCH 06/10] btrfs-progs: manpage:fix markup in device scan
|
|
||||||
|
|
||||||
Signed-off-by: David Sterba <dsterba@suse.cz>
|
|
||||||
---
|
|
||||||
btrfs_cmds.c | 2 +-
|
|
||||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
|
|
||||||
index a7231d0..c2fd09e 100644
|
|
||||||
--- a/btrfs_cmds.c
|
|
||||||
+++ b/btrfs_cmds.c
|
|
||||||
@@ -827,7 +827,7 @@ int do_scan(int argc, char **argv)
|
|
||||||
*
|
|
||||||
* When the filesystem consists of multiple devices, it is possible to specify
|
|
||||||
* which one should be resized via the <devid> parameter. To know the <devid>
|
|
||||||
- * of a device use the command \fBbtrfs filesystem show\fR.
|
|
||||||
+ * of a device use the command \Bbtrfs filesystem show\b.
|
|
||||||
****/
|
|
||||||
|
|
||||||
int do_resize(int argc, char **argv)
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
|||||||
From 13a29ecb84a41af67c1d96c2c5f2848738a2f570 Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Sterba <dsterba@suse.cz>
|
|
||||||
Date: Tue, 27 Mar 2012 00:02:35 +0200
|
|
||||||
Subject: [PATCH 07/10] btrfs-progs: document fi df
|
|
||||||
|
|
||||||
Signed-off-by: David Sterba <dsterba@suse.cz>
|
|
||||||
---
|
|
||||||
btrfs_cmds.c | 31 +++++++++++++++++++++++++++++++
|
|
||||||
1 files changed, 31 insertions(+), 0 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
|
|
||||||
index c2fd09e..f7310ee 100644
|
|
||||||
--- a/btrfs_cmds.c
|
|
||||||
+++ b/btrfs_cmds.c
|
|
||||||
@@ -1871,6 +1871,37 @@ int do_get_default_subvol(int nargs, char **argv)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+/**** man: btrfs filesystem df
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Bfilesystem df\b\I <path>\i
|
|
||||||
+ *
|
|
||||||
+ * Print allocated and used data for all block group types.
|
|
||||||
+ *
|
|
||||||
+ * Print allocated and used data for all block group types.
|
|
||||||
+ *
|
|
||||||
+ * Example of filesystem created with default mkfs options:
|
|
||||||
+ *
|
|
||||||
+ * Data, RAID0: total=4.00GiB, used=0.00
|
|
||||||
+ * Data: total=8.00MiB, used=0.00
|
|
||||||
+ * System, RAID1: total=8.00MiB, used=4.00KiB
|
|
||||||
+ * System: total=4.00MiB, used=0.00
|
|
||||||
+ * Metadata, RAID1: total=1.00GiB, used=24.00KiB
|
|
||||||
+ * Metadata: total=8.00MiB, used=0.00
|
|
||||||
+ *
|
|
||||||
+ * Example of filesystem created with \Isingle\i profiles for data and metadata:
|
|
||||||
+ *
|
|
||||||
+ * Data: total=38.99GiB, used=58.89MiB
|
|
||||||
+ * System: total=4.00MiB, used=12.00KiB
|
|
||||||
+ * Metadata: total=1.01GiB, used=2.86MiB
|
|
||||||
+ *
|
|
||||||
+ * \Itotal\i allocated space
|
|
||||||
+ * \t
|
|
||||||
+ * \Iused\i actually used data
|
|
||||||
+ *
|
|
||||||
+ * This information gives better idea of allocated space than the 'df' utility,
|
|
||||||
+ * though it does not actually answer the question of how much free space there is.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_df_filesystem(int nargs, char **argv)
|
|
||||||
{
|
|
||||||
struct btrfs_ioctl_space_args *sargs;
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
|||||||
From 9219cfd9e5cb86a2123b3159056ad53b6efd578e Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Sterba <dsterba@suse.cz>
|
|
||||||
Date: Tue, 27 Mar 2012 00:15:39 +0200
|
|
||||||
Subject: [PATCH 08/10] btrfs-progs: document inspect-internal commands
|
|
||||||
|
|
||||||
Signed-off-by: David Sterba <dsterba@suse.cz>
|
|
||||||
---
|
|
||||||
btrfs_cmds.c | 23 +++++++++++++++++++++++
|
|
||||||
1 files changed, 23 insertions(+), 0 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
|
|
||||||
index f7310ee..cb6df70 100644
|
|
||||||
--- a/btrfs_cmds.c
|
|
||||||
+++ b/btrfs_cmds.c
|
|
||||||
@@ -2047,6 +2047,17 @@ out:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+/**** man: btrfs inspect-internal inode-resolve
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Binspect-internal inode-resolve\b \B[-v]\b\I <inode> <path>\i
|
|
||||||
+ *
|
|
||||||
+ * Resolve given inode number to path name.
|
|
||||||
+ *
|
|
||||||
+ * Resolve given inode number to path name. This operation does not need to
|
|
||||||
+ * traverse the whole filesystem, but effectively uses internal
|
|
||||||
+ * structures.
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_ino_to_path(int nargs, char **argv)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
@@ -2081,6 +2092,18 @@ int do_ino_to_path(int nargs, char **argv)
|
|
||||||
argv[optind+1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
+/**** man: btrfs inspect-internal logical-resolve
|
|
||||||
+ *
|
|
||||||
+ * \Bbtrfs\b \Binspect-internal logical-resolve\b \B[-v] [-P]\b\I <logical> <path>\i
|
|
||||||
+ *
|
|
||||||
+ * Resolve given logical block number to path name or inode number.
|
|
||||||
+ *
|
|
||||||
+ * Resolve given logical block number to path name or inode number. Can be used
|
|
||||||
+ * in connection with scrub reports.
|
|
||||||
+ *
|
|
||||||
+ * \I-P\i print paths instead of inode numbers
|
|
||||||
+ ****/
|
|
||||||
+
|
|
||||||
int do_logical_to_ino(int nargs, char **argv)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
|||||||
From e2a577cb8f553a1cc74f949b0a798aa5f07d6302 Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Sterba <dsterba@suse.cz>
|
|
||||||
Date: Tue, 27 Mar 2012 00:51:11 +0200
|
|
||||||
Subject: [PATCH 10/10] btrfs-progs: tweak order of devices in fi show
|
|
||||||
|
|
||||||
Devids are printed in descending order, change it to ascending.
|
|
||||||
|
|
||||||
Signed-off-by: David Sterba <dsterba@suse.cz>
|
|
||||||
---
|
|
||||||
btrfs_cmds.c | 2 +-
|
|
||||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
|
|
||||||
index cb6df70..82fb61f 100644
|
|
||||||
--- a/btrfs_cmds.c
|
|
||||||
+++ b/btrfs_cmds.c
|
|
||||||
@@ -901,7 +901,7 @@ static void print_one_uuid(struct btrfs_fs_devices *fs_devices)
|
|
||||||
|
|
||||||
free(super_bytes_used);
|
|
||||||
|
|
||||||
- list_for_each(cur, &fs_devices->devices) {
|
|
||||||
+ list_for_each_prev(cur, &fs_devices->devices) {
|
|
||||||
char *total_bytes;
|
|
||||||
char *bytes_used;
|
|
||||||
device = list_entry(cur, struct btrfs_device, dev_list);
|
|
||||||
--
|
|
||||||
1.7.6.233.gd79bc
|
|
||||||
|
|
20
80-btrfs.rules
Normal file
20
80-btrfs.rules
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
SUBSYSTEM!="block", GOTO="btrfs_end"
|
||||||
|
ACTION!="add|change", GOTO="btrfs_end"
|
||||||
|
|
||||||
|
ENV{ID_FS_TYPE}=="LVM2_member|LVM1_member", GOTO="btrfs_end"
|
||||||
|
ENV{ID_FS_TYPE}=="linux_raid_member", GOTO="btrfs_end"
|
||||||
|
|
||||||
|
ENV{ID_FS_TYPE}=="btrfs", GOTO="btrfs_do_scan"
|
||||||
|
ENV{DM_UUID}=="LVM-?*", GOTO="btrfs_do_scan"
|
||||||
|
ENV{DM_UUID}=="LUKS-CRYPT1-?*", GOTO="btrfs_do_scan"
|
||||||
|
ENV{DM_UUID}=="LUKS-PLAIN-?*", GOTO="btrfs_do_scan"
|
||||||
|
ENV{DM_UUID}=="LUKS-VERITY-?*", GOTO="btrfs_do_scan"
|
||||||
|
ENV{DM_UUID}=="LUKS-LOOPAES-?*", GOTO="btrfs_do_scan"
|
||||||
|
ENV{MD_UUID}=="?*", GOTO="btrfs_do_scan"
|
||||||
|
GOTO="btrfs_end"
|
||||||
|
|
||||||
|
LABEL="btrfs_do_scan"
|
||||||
|
RUN+="/sbin/modprobe btrfs"
|
||||||
|
RUN+="/usr/sbin/btrfs device scan $env{DEVNAME}"
|
||||||
|
|
||||||
|
LABEL="btrfs_end"
|
@ -1,28 +0,0 @@
|
|||||||
commit a2fe2e1b978f724f53d025461e65adb4e030d043
|
|
||||||
Author: Dirk Mueller <dmueller@suse.de>
|
|
||||||
Date: Thu Dec 16 20:40:34 2010 +0100
|
|
||||||
|
|
||||||
[PATCH] Plug Memory leak in find_and_setup_log_root()
|
|
||||||
|
|
||||||
The error path forgets to free a previously allocated
|
|
||||||
memory structure.
|
|
||||||
|
|
||||||
Index: btrfs-progs-v0.19-116-g13eced9/disk-io.c
|
|
||||||
===================================================================
|
|
||||||
--- btrfs-progs-v0.19-116-g13eced9.orig/disk-io.c
|
|
||||||
+++ btrfs-progs-v0.19-116-g13eced9/disk-io.c
|
|
||||||
@@ -454,11 +454,13 @@ static int find_and_setup_log_root(struc
|
|
||||||
{
|
|
||||||
u32 blocksize;
|
|
||||||
u64 blocknr = btrfs_super_log_root(disk_super);
|
|
||||||
- struct btrfs_root *log_root = malloc(sizeof(struct btrfs_root));
|
|
||||||
+ struct btrfs_root *log_root;
|
|
||||||
|
|
||||||
if (blocknr == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
+ log_root = malloc(sizeof(struct btrfs_root));
|
|
||||||
+
|
|
||||||
blocksize = btrfs_level_size(tree_root,
|
|
||||||
btrfs_super_log_root_level(disk_super));
|
|
||||||
|
|
@ -1,11 +1,22 @@
|
|||||||
#!/bin/bash -e
|
#!/bin/bash -e
|
||||||
#%stage: filesystem
|
#%stage: filesystem
|
||||||
#%if: -x /usr/sbin/btrfs
|
#%depends: dm dmraid lvm2 udev md luks
|
||||||
#%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 /sbin/btrfs-debug-tree
|
#%programs: btrfs
|
||||||
|
#%programs: btrfs-convert
|
||||||
|
#%programs: btrfs-debug-tree
|
||||||
|
#%programs: btrfs-dump-super
|
||||||
|
#%programs: btrfs-find-root
|
||||||
|
#%programs: btrfs-image
|
||||||
|
#%programs: btrfs-select-super
|
||||||
|
#%programs: btrfs-zero-log
|
||||||
|
#%programs: btrfsck
|
||||||
|
#%programs: btrfstune
|
||||||
|
# for fsck(8): listed twice so that a copy really ends up in /sbin
|
||||||
|
#%programs: /sbin/fsck.btrfs
|
||||||
|
#%programs: fsck.btrfs
|
||||||
|
#%programs: mkfs.btrfs
|
||||||
#%modules: btrfs
|
#%modules: btrfs
|
||||||
|
|
||||||
modprobe btrfs
|
modprobe btrfs
|
||||||
|
|
||||||
if [ -x /usr/sbin/btrfs ]; then
|
btrfs dev scan >& /dev/null
|
||||||
/usr/sbin/btrfs dev scan >& /dev/null
|
|
||||||
fi
|
|
||||||
|
@ -1,43 +1,19 @@
|
|||||||
From 2c19dc5e7bd5fe9a2838ec852128f64a5be54c4c Mon Sep 17 00:00:00 2001
|
From 3c7ae0fc5139c195100eb931bc6e1148ac1f11f5 Mon Sep 17 00:00:00 2001
|
||||||
From: David Sterba <dsterba@suse.cz>
|
From: David Sterba <dsterba@suse.cz>
|
||||||
Date: Mon, 26 Mar 2012 15:39:08 +0200
|
Date: Mon, 26 Mar 2012 15:39:08 +0200
|
||||||
Subject: [PATCH 09/10] btrfs-progs: add man page for btrfs-convert
|
Subject: [PATCH 37/46] btrfs-progs: add man page for btrfs-convert
|
||||||
|
|
||||||
Signed-off-by: David Sterba <dsterba@suse.cz>
|
Signed-off-by: David Sterba <dsterba@suse.cz>
|
||||||
---
|
---
|
||||||
man/Makefile | 5 +++-
|
man/Makefile | 2 +-
|
||||||
man/btrfs-convert.8.in | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
|
man/btrfs-convert.8.in | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
2 files changed, 64 insertions(+), 1 deletions(-)
|
2 files changed, 61 insertions(+), 1 deletion(-)
|
||||||
create mode 100644 man/btrfs-convert.8.in
|
create mode 100644 man/btrfs-convert.8.in
|
||||||
|
|
||||||
diff --git a/man/Makefile b/man/Makefile
|
Index: btrfs-progs-v0.20-rc1-335-gf00dd83/man/btrfs-convert.8.in
|
||||||
index 4a90b75..f28eec7 100644
|
===================================================================
|
||||||
--- a/man/Makefile
|
|
||||||
+++ b/man/Makefile
|
|
||||||
@@ -7,7 +7,7 @@ mandir = $(prefix)/man
|
|
||||||
man8dir = $(mandir)/man8
|
|
||||||
|
|
||||||
MANPAGES = mkfs.btrfs.8.gz btrfsctl.8.gz btrfsck.8.gz btrfs-image.8.gz \
|
|
||||||
- btrfs-show.8.gz btrfs.8.gz
|
|
||||||
+ btrfs-show.8.gz btrfs.8.gz btrfs-convert.8.gz
|
|
||||||
|
|
||||||
all: $(MANPAGES)
|
|
||||||
|
|
||||||
@@ -29,6 +29,9 @@ btrfs-image.8.gz: btrfs-image.8.in
|
|
||||||
btrfs-show.8.gz: btrfs-show.8.in
|
|
||||||
$(GZIP) -n -c btrfs-show.8.in > btrfs-show.8.gz
|
|
||||||
|
|
||||||
+btrfs-convert.8.gz: btrfs-convert.8.in
|
|
||||||
+ $(GZIP) -n -c btrfs-convert.8.in > btrfs-convert.8.gz
|
|
||||||
+
|
|
||||||
clean :
|
|
||||||
rm -f $(MANPAGES)
|
|
||||||
|
|
||||||
diff --git a/man/btrfs-convert.8.in b/man/btrfs-convert.8.in
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..4057419
|
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/man/btrfs-convert.8.in
|
+++ btrfs-progs-v0.20-rc1-335-gf00dd83/man/btrfs-convert.8.in
|
||||||
@@ -0,0 +1,60 @@
|
@@ -0,0 +1,60 @@
|
||||||
+.TH BTRFS-CONVERT 8
|
+.TH BTRFS-CONVERT 8
|
||||||
+.SH NAME
|
+.SH NAME
|
||||||
@ -99,6 +75,16 @@ index 0000000..4057419
|
|||||||
+is part of btrfs-progs.
|
+is part of btrfs-progs.
|
||||||
+.SH SEE ALSO
|
+.SH SEE ALSO
|
||||||
+.BR mkfs.btrfs (8)
|
+.BR mkfs.btrfs (8)
|
||||||
--
|
Index: btrfs-progs-v0.20-rc1-335-gf00dd83/man/Makefile
|
||||||
1.7.6.233.gd79bc
|
===================================================================
|
||||||
|
--- btrfs-progs-v0.20-rc1-335-gf00dd83.orig/man/Makefile
|
||||||
|
+++ btrfs-progs-v0.20-rc1-335-gf00dd83/man/Makefile
|
||||||
|
@@ -11,7 +11,7 @@ man8dir = $(mandir)/man8
|
||||||
|
# list only those we use
|
||||||
|
.SUFFIXES: .in .gz
|
||||||
|
|
||||||
|
-MANPAGES = mkfs.btrfs.8.gz btrfsck.8.gz btrfs-image.8.gz btrfs.8.gz
|
||||||
|
+MANPAGES = mkfs.btrfs.8.gz btrfsck.8.gz btrfs-image.8.gz btrfs.8.gz btrfs-convert.8.gz
|
||||||
|
INFILES = ${MANPAGES:.in=.gz}
|
||||||
|
|
||||||
|
all: $(MANPAGES)
|
@ -1,248 +0,0 @@
|
|||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/btrfs-image.c
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/btrfs-image.c
|
|
||||||
@@ -491,6 +491,11 @@ static int create_metadump(const char *i
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
root = open_ctree(input, 0, 0);
|
|
||||||
+ if (!root) {
|
|
||||||
+ fprintf(stderr, "Open ctree failed\n");
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
BUG_ON(root->nodesize != root->leafsize);
|
|
||||||
|
|
||||||
ret = metadump_init(&metadump, root, out, num_threads,
|
|
||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/btrfs-select-super.c
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/btrfs-select-super.c
|
|
||||||
@@ -100,8 +100,10 @@ int main(int ac, char **av)
|
|
||||||
}
|
|
||||||
root = open_ctree_fd(fp, av[optind], bytenr, 1, use_earliest_bdev);
|
|
||||||
|
|
||||||
- if (root == NULL)
|
|
||||||
+ if (!root) {
|
|
||||||
+ fprintf(stderr, "Open ctree failed\n");
|
|
||||||
return 1;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
fprintf(stderr, "Found superblock with generation %llu.\n", root->fs_info->super_copy.generation);
|
|
||||||
|
|
||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/btrfslabel.c
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/btrfslabel.c
|
|
||||||
@@ -46,7 +46,7 @@
|
|
||||||
#define GET_LABEL 3
|
|
||||||
#define SET_LABEL 4
|
|
||||||
|
|
||||||
-static void change_label_unmounted(char *dev, char *nLabel)
|
|
||||||
+static int change_label_unmounted(char *dev, char *nLabel)
|
|
||||||
{
|
|
||||||
struct btrfs_root *root;
|
|
||||||
struct btrfs_trans_handle *trans;
|
|
||||||
@@ -55,6 +55,10 @@ static void change_label_unmounted(char
|
|
||||||
* and as read-write.
|
|
||||||
*/
|
|
||||||
root = open_ctree(dev, 0, 1);
|
|
||||||
+ if (!root) {
|
|
||||||
+ fprintf(stderr, "Open ctree failed\n");
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
trans = btrfs_start_transaction(root, 1);
|
|
||||||
strncpy(root->fs_info->super_copy.label, nLabel, BTRFS_LABEL_SIZE);
|
|
||||||
@@ -62,9 +66,10 @@ static void change_label_unmounted(char
|
|
||||||
|
|
||||||
/* Now we close it since we are done. */
|
|
||||||
close_ctree(root);
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void get_label_unmounted(char *dev)
|
|
||||||
+static int get_label_unmounted(char *dev)
|
|
||||||
{
|
|
||||||
struct btrfs_root *root;
|
|
||||||
|
|
||||||
@@ -72,11 +77,16 @@ static void get_label_unmounted(char *de
|
|
||||||
* and as read-only.
|
|
||||||
*/
|
|
||||||
root = open_ctree(dev, 0, 0);
|
|
||||||
+ if (!root) {
|
|
||||||
+ fprintf(stderr, "Open ctree failed\n");
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
fprintf(stdout, "%s\n", root->fs_info->super_copy.label);
|
|
||||||
|
|
||||||
/* Now we close it since we are done. */
|
|
||||||
close_ctree(root);
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_label(char *btrfs_dev)
|
|
||||||
@@ -95,8 +105,7 @@ int get_label(char *btrfs_dev)
|
|
||||||
fprintf(stderr, "FATAL: the filesystem has to be unmounted\n");
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
- get_label_unmounted(btrfs_dev);
|
|
||||||
- return 0;
|
|
||||||
+ return get_label_unmounted(btrfs_dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -116,6 +125,5 @@ int set_label(char *btrfs_dev, char *nLa
|
|
||||||
fprintf(stderr, "FATAL: the filesystem has to be unmounted\n");
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
- change_label_unmounted(btrfs_dev, nLabel);
|
|
||||||
- return 0;
|
|
||||||
+ return change_label_unmounted(btrfs_dev, nLabel);
|
|
||||||
}
|
|
||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/btrfstune.c
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/btrfstune.c
|
|
||||||
@@ -108,6 +108,11 @@ int main(int argc, char *argv[])
|
|
||||||
|
|
||||||
root = open_ctree(device, 0, 1);
|
|
||||||
|
|
||||||
+ if (!root) {
|
|
||||||
+ fprintf(stderr, "Open ctree failed\n");
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (seeding_flag) {
|
|
||||||
ret = update_seeding_flag(root, seeding_value);
|
|
||||||
if (!ret)
|
|
||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/dir-test.c
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/dir-test.c
|
|
||||||
@@ -436,6 +436,12 @@ int main(int ac, char **av)
|
|
||||||
radix_tree_init();
|
|
||||||
|
|
||||||
root = open_ctree(av[ac-1], &super, 0);
|
|
||||||
+
|
|
||||||
+ if (!root) {
|
|
||||||
+ fprintf(stderr, "Open ctree failed\n");
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
trans = btrfs_start_transaction(root, 1);
|
|
||||||
|
|
||||||
dir_oid = btrfs_super_root_dir(&super);
|
|
||||||
@@ -479,6 +485,11 @@ int main(int ac, char **av)
|
|
||||||
btrfs_header_nritems(&root->node->node.header));
|
|
||||||
close_ctree(root, &super);
|
|
||||||
root = open_ctree("dbfile", &super, 0);
|
|
||||||
+
|
|
||||||
+ if (!root) {
|
|
||||||
+ fprintf(stderr, "Open ctree failed\n");
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
while(count--) {
|
|
||||||
ret = ops[op](trans, root, &radix);
|
|
||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/find-root.c
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/find-root.c
|
|
||||||
@@ -351,8 +351,11 @@ int main(int argc, char **argv)
|
|
||||||
|
|
||||||
root = open_ctree_broken(dev_fd, argv[optind]);
|
|
||||||
close(dev_fd);
|
|
||||||
- if (!root)
|
|
||||||
+
|
|
||||||
+ if (!root) {
|
|
||||||
+ fprintf(stderr, "Open ctree failed\n");
|
|
||||||
exit(1);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
csum_size = btrfs_super_csum_size(&root->fs_info->super_copy);
|
|
||||||
ret = find_root(root);
|
|
||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/mkfs.c
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/mkfs.c
|
|
||||||
@@ -1362,8 +1362,9 @@ int main(int ac, char **av)
|
|
||||||
|
|
||||||
root = open_ctree(file, 0, O_RDWR);
|
|
||||||
if (!root) {
|
|
||||||
- fprintf(stderr, "ctree init failed\n");
|
|
||||||
- return -1;
|
|
||||||
+ fprintf(stderr, "Open ctree failed\n");
|
|
||||||
+ close (fd);
|
|
||||||
+ exit(1);
|
|
||||||
}
|
|
||||||
root->fs_info->alloc_start = alloc_start;
|
|
||||||
|
|
||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/quick-test.c
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/quick-test.c
|
|
||||||
@@ -52,6 +52,10 @@ int main(int ac, char **av) {
|
|
||||||
radix_tree_init();
|
|
||||||
|
|
||||||
root = open_ctree(av[1], BTRFS_SUPER_INFO_OFFSET, O_RDWR);
|
|
||||||
+ if (!root) {
|
|
||||||
+ fprintf(stderr, "Open ctree failed\n");
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
trans = btrfs_start_transaction(root, 1);
|
|
||||||
srand(55);
|
|
||||||
btrfs_set_key_type(&ins, BTRFS_STRING_ITEM_KEY);
|
|
||||||
@@ -75,6 +79,10 @@ int main(int ac, char **av) {
|
|
||||||
close_ctree(root);
|
|
||||||
exit(1);
|
|
||||||
root = open_ctree(av[1], BTRFS_SUPER_INFO_OFFSET, O_RDWR);
|
|
||||||
+ if (!root) {
|
|
||||||
+ fprintf(stderr, "Open ctree failed\n");
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
printf("starting search\n");
|
|
||||||
srand(55);
|
|
||||||
for (i = 0; i < run_size; i++) {
|
|
||||||
@@ -94,6 +102,10 @@ int main(int ac, char **av) {
|
|
||||||
close_ctree(root);
|
|
||||||
|
|
||||||
root = open_ctree(av[1], BTRFS_SUPER_INFO_OFFSET, O_RDWR);
|
|
||||||
+ if (!root) {
|
|
||||||
+ fprintf(stderr, "Open ctree failed\n");
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
printf("node %p level %d total ptrs %d free spc %lu\n", root->node,
|
|
||||||
btrfs_header_level(root->node),
|
|
||||||
btrfs_header_nritems(root->node),
|
|
||||||
@@ -122,6 +134,10 @@ int main(int ac, char **av) {
|
|
||||||
close_ctree(root);
|
|
||||||
|
|
||||||
root = open_ctree(av[1], BTRFS_SUPER_INFO_OFFSET, O_RDWR);
|
|
||||||
+ if (!root) {
|
|
||||||
+ fprintf(stderr, "Open ctree failed\n");
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
trans = btrfs_start_transaction(root, 1);
|
|
||||||
srand(128);
|
|
||||||
for (i = 0; i < run_size; i++) {
|
|
||||||
@@ -138,6 +154,10 @@ int main(int ac, char **av) {
|
|
||||||
close_ctree(root);
|
|
||||||
|
|
||||||
root = open_ctree(av[1], BTRFS_SUPER_INFO_OFFSET, O_RDWR);
|
|
||||||
+ if (!root) {
|
|
||||||
+ fprintf(stderr, "Open ctree failed\n");
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
srand(128);
|
|
||||||
printf("starting search2\n");
|
|
||||||
for (i = 0; i < run_size; i++) {
|
|
||||||
--- btrfs-progs-v0.19-118-gfdb6c04.orig/random-test.c
|
|
||||||
+++ btrfs-progs-v0.19-118-gfdb6c04/random-test.c
|
|
||||||
@@ -356,6 +356,10 @@ int main(int ac, char **av)
|
|
||||||
struct btrfs_trans_handle *trans;
|
|
||||||
radix_tree_init();
|
|
||||||
root = open_ctree("dbfile", &super);
|
|
||||||
+ if (!root) {
|
|
||||||
+ fprintf(stderr, "Open ctree failed\n");
|
|
||||||
+ exit(1);
|
|
||||||
+ }
|
|
||||||
fill_radix(root, &radix);
|
|
||||||
|
|
||||||
signal(SIGTERM, sigstopper);
|
|
||||||
@@ -398,6 +402,10 @@ int main(int ac, char **av)
|
|
||||||
btrfs_header_nritems(&root->node->node.header));
|
|
||||||
close_ctree(root, &super);
|
|
||||||
root = open_ctree("dbfile", &super);
|
|
||||||
+ if (!root) {
|
|
||||||
+ fprintf(stderr, "Open ctree failed\n");
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
while(count--) {
|
|
||||||
ret = ops[op](trans, root, &radix);
|
|
@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:7c7d0bb613659bd63e4894bfb481a85cbadb695f7b9418c97921274ac8344021
|
|
||||||
size 162236
|
|
3
btrfs-progs-v0.20-rc1-335-gf00dd83.tar.bz2
Normal file
3
btrfs-progs-v0.20-rc1-335-gf00dd83.tar.bz2
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:08e8eafbcc4cdd65eabdfc24e1165e1cb835a63a37f0e0f88af1e48c37d54826
|
||||||
|
size 234916
|
@ -1,47 +0,0 @@
|
|||||||
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>.",
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user