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
|
||||
#%stage: filesystem
|
||||
#%if: -x /usr/sbin/btrfs
|
||||
#%programs: /sbin/btrfs /sbin/btrfs-zero-log /sbin/btrfs-convert /sbin/btrfs-select-super /sbin/btrfs-image /sbin/btrfstune /sbin/btrfs-restore /sbin/btrfs-find-root /sbin/btrfsck /sbin/mkfs.btrfs /sbin/btrfs-dump-super /sbin/btrfs-debug-tree
|
||||
#%depends: dm dmraid lvm2 udev md luks
|
||||
#%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
|
||||
|
||||
modprobe btrfs
|
||||
|
||||
if [ -x /usr/sbin/btrfs ]; then
|
||||
/usr/sbin/btrfs dev scan >& /dev/null
|
||||
fi
|
||||
btrfs dev scan >& /dev/null
|
||||
|
@ -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>
|
||||
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>
|
||||
---
|
||||
man/Makefile | 5 +++-
|
||||
man/btrfs-convert.8.in | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 64 insertions(+), 1 deletions(-)
|
||||
man/Makefile | 2 +-
|
||||
man/btrfs-convert.8.in | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 61 insertions(+), 1 deletion(-)
|
||||
create mode 100644 man/btrfs-convert.8.in
|
||||
|
||||
diff --git a/man/Makefile b/man/Makefile
|
||||
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
|
||||
Index: btrfs-progs-v0.20-rc1-335-gf00dd83/man/btrfs-convert.8.in
|
||||
===================================================================
|
||||
--- /dev/null
|
||||
+++ b/man/btrfs-convert.8.in
|
||||
+++ btrfs-progs-v0.20-rc1-335-gf00dd83/man/btrfs-convert.8.in
|
||||
@@ -0,0 +1,60 @@
|
||||
+.TH BTRFS-CONVERT 8
|
||||
+.SH NAME
|
||||
@ -99,6 +75,16 @@ index 0000000..4057419
|
||||
+is part of btrfs-progs.
|
||||
+.SH SEE ALSO
|
||||
+.BR mkfs.btrfs (8)
|
||||
--
|
||||
1.7.6.233.gd79bc
|
||||
Index: btrfs-progs-v0.20-rc1-335-gf00dd83/man/Makefile
|
||||
===================================================================
|
||||
--- 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