- btrfs-progs-fix-open_ctree_usage_segfaults.patch: fix

segfaults from bnc#710486 due to unchecked usage of return
  value of open_ctree()
  [fixed compilation warnings]

- pull upstream, replace existing patches, spec update
- update 'restore' utility
  - lzo support
  - tools may now take earlies superblock when opening the fs
  - other fixes
- pull integration-20111030 branch
  - mkfs: force mkfs if desired
  - other fixes
- add btrfs-dump-super to mkinitrd
- other fixes
  - skip non-existent devices or without media
  - documentation updates
  - scrubbing single device
  - graceful error handling when opening fs fails

- updated mkinitrd script to scan devices before mount (bnc#727383)

OBS-URL: https://build.opensuse.org/package/show/filesystems/btrfsprogs?expand=0&rev=115
This commit is contained in:
David Sterba 2011-12-14 23:25:51 +00:00 committed by Git OBS Bridge
parent 2f977a5763
commit db07609875
51 changed files with 9288 additions and 153 deletions

View File

@ -0,0 +1,37 @@
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

View File

@ -0,0 +1,108 @@
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

View File

@ -0,0 +1,35 @@
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

View File

@ -0,0 +1,42 @@
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

275
0105-Regression-tests.patch Normal file
View File

@ -0,0 +1,275 @@
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

View File

@ -0,0 +1,84 @@
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

View File

@ -0,0 +1,474 @@
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

View File

@ -0,0 +1,202 @@
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

View File

@ -0,0 +1,458 @@
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

View File

@ -0,0 +1,710 @@
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

View File

@ -0,0 +1,78 @@
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

View File

@ -0,0 +1,53 @@
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

View File

@ -0,0 +1,750 @@
From 192484f121dbbffd004303a760ef8b4dbd470ce2 Mon Sep 17 00:00:00 2001
From: Ilya Dryomov <idryomov@gmail.com>
Date: Tue, 23 Aug 2011 23:08:16 +0300
Subject: [PATCH 14/35] Btrfs-progs: add restriper commands
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
---
btrfs.c | 21 +++
btrfs_cmds.c | 505 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
btrfs_cmds.h | 5 +
ctree.h | 9 +
ioctl.h | 46 +++++-
print-tree.c | 3 +
volumes.h | 42 +++++
7 files changed, 628 insertions(+), 3 deletions(-)
diff --git a/btrfs.c b/btrfs.c
index 66b0d80..52af8f7 100644
--- a/btrfs.c
+++ b/btrfs.c
@@ -329,6 +329,27 @@ static struct Command commands[] = {
"Show status of running or finished scrub.",
NULL
},
+ { do_restripe, -1,
+ "filesystem restripe start", "[-d [filters]] [-m [filters]] "
+ "[-s [filters]] [-vf] <path>\n"
+ "Start restriper."
+ },
+ { do_restripe_cancel, 1,
+ "filesystem restripe cancel", "<path>\n"
+ "Cancel restriper."
+ },
+ { do_restripe_pause, 1,
+ "filesystem restripe pause", "<path>\n"
+ "Pause restriper."
+ },
+ { do_restripe_resume, 1,
+ "filesystem restripe resume", "<path>\n"
+ "Resume interrupted restripe operation."
+ },
+ { do_restripe_progress, -1,
+ "filesystem restripe status", "[-v] <path>\n"
+ "Show status of running or paused restripe operation."
+ },
{ do_scan, 999,
"device scan", "[<device>...]\n"
"Scan all device for or the passed device for a btrfs\n"
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
index 1bfc669..e4c5592 100644
--- a/btrfs_cmds.c
+++ b/btrfs_cmds.c
@@ -1094,14 +1094,515 @@ int do_balance(int argc, char **argv)
e = errno;
close(fdmnt);
if(ret<0){
- fprintf(stderr, "ERROR: error during balancing '%s' - %s\n",
- path, strerror(e));
+ if (e == ECANCELED) {
+ fprintf(stderr, "restripe interrupted by user\n");
+ } else {
+ fprintf(stderr, "ERROR: error during restriping '%s' "
+ "- %s\n", path, strerror(e));
+ return 19;
+ }
+ }
+ return 0;
+}
+
+static int parse_one_profile(char *profile, u64 *flags)
+{
+ if (!strcmp(profile, "raid0")) {
+ *flags |= BTRFS_BLOCK_GROUP_RAID0;
+ } else if (!strcmp(profile, "raid1")) {
+ *flags |= BTRFS_BLOCK_GROUP_RAID1;
+ } else if (!strcmp(profile, "raid10")) {
+ *flags |= BTRFS_BLOCK_GROUP_RAID10;
+ } else if (!strcmp(profile, "dup")) {
+ *flags |= BTRFS_BLOCK_GROUP_DUP;
+ } else if (!strcmp(profile, "single")) {
+ *flags |= BTRFS_AVAIL_ALLOC_BIT_SINGLE;
+ } else {
+ fprintf(stderr, "Unknown profile '%s'\n", profile);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int parse_profiles(char *profiles, u64 *flags)
+{
+ char *this_char;
+ char *save_ptr;
+
+ for (this_char = strtok_r(profiles, "|", &save_ptr);
+ this_char != NULL;
+ this_char = strtok_r(NULL, "|", &save_ptr)) {
+ if (parse_one_profile(this_char, flags))
+ return 1;
+ }
+
+ return 0;
+}
+
+static int parse_range(char *range, u64 *start, u64 *end)
+{
+ char *dots;
+
+ dots = strstr(range, "..");
+ if (dots) {
+ const char *rest = dots + 2;
+ int skipped = 0;
+
+ *dots = 0;
+
+ if (!*rest) {
+ *end = (u64)-1;
+ skipped++;
+ } else {
+ *end = strtoull(rest, (char **)NULL, 10);
+ }
+ if (dots == range) {
+ *start = 0;
+ skipped++;
+ } else {
+ *start = strtoull(range, (char **)NULL, 10);
+ }
+
+ if (skipped <= 1)
+ return 0;
+ }
+
+ return 1;
+}
+
+static int parse_filters(char *filters, struct btrfs_restripe_args *rargs)
+{
+ char *this_char;
+ char *value;
+ char *save_ptr;
+
+ if (!filters)
+ return 0;
+
+ for (this_char = strtok_r(filters, ",", &save_ptr);
+ this_char != NULL;
+ this_char = strtok_r(NULL, ",", &save_ptr)) {
+ if ((value = strchr(this_char, '=')) != NULL)
+ *value++ = 0;
+ if (!strcmp(this_char, "profiles")) {
+ if (!value || !*value) {
+ fprintf(stderr, "the profiles filter requires "
+ "an argument\n");
+ return 1;
+ }
+ if (parse_profiles(value, &rargs->profiles)) {
+ fprintf(stderr, "Invalid profiles argument\n");
+ return 1;
+ }
+ rargs->flags |= BTRFS_RESTRIPE_ARGS_PROFILES;
+ } else if (!strcmp(this_char, "usage")) {
+ if (!value || !*value) {
+ fprintf(stderr, "the usage filter requires "
+ "an argument\n");
+ return 1;
+ }
+ rargs->usage = strtoull(value, (char **)NULL, 10);
+ if (rargs->usage < 1 || rargs->usage > 100) {
+ fprintf(stderr, "Invalid usage argument: %s\n",
+ value);
+ return 1;
+ }
+ rargs->flags |= BTRFS_RESTRIPE_ARGS_USAGE;
+ } else if (!strcmp(this_char, "devid")) {
+ if (!value || !*value) {
+ fprintf(stderr, "the devid filter requires "
+ "an argument\n");
+ return 1;
+ }
+ rargs->devid = strtoull(value, (char **)NULL, 10);
+ if (rargs->devid == 0) {
+ fprintf(stderr, "Invalid devid argument: %s\n",
+ value);
+ return 1;
+ }
+ rargs->flags |= BTRFS_RESTRIPE_ARGS_DEVID;
+ } else if (!strcmp(this_char, "drange")) {
+ if (!value || !*value) {
+ fprintf(stderr, "the drange filter requires "
+ "an argument\n");
+ return 1;
+ }
+ if (parse_range(value, &rargs->pstart, &rargs->pend)) {
+ fprintf(stderr, "Invalid drange argument\n");
+ return 1;
+ }
+ rargs->flags |= BTRFS_RESTRIPE_ARGS_DRANGE;
+ } else if (!strcmp(this_char, "vrange")) {
+ if (!value || !*value) {
+ fprintf(stderr, "the vrange filter requires "
+ "an argument\n");
+ return 1;
+ }
+ if (parse_range(value, &rargs->vstart, &rargs->vend)) {
+ fprintf(stderr, "Invalid vrange argument\n");
+ return 1;
+ }
+ rargs->flags |= BTRFS_RESTRIPE_ARGS_VRANGE;
+ } else if (!strcmp(this_char, "convert")) {
+ if (!value || !*value) {
+ fprintf(stderr, "the convert option requires "
+ "an argument\n");
+ return 1;
+ }
+ if (parse_one_profile(value, &rargs->target)) {
+ fprintf(stderr, "Invalid convert argument\n");
+ return 1;
+ }
+ rargs->flags |= BTRFS_RESTRIPE_ARGS_CONVERT;
+ } else if (!strcmp(this_char, "soft")) {
+ rargs->flags |= BTRFS_RESTRIPE_ARGS_SOFT;
+ } else {
+ fprintf(stderr, "Unrecognized restripe option '%s'\n",
+ this_char);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void dump_ioctl_restripe_args(struct btrfs_ioctl_restripe_args *args);
+
+static struct option restripe_longopts[] = {
+ { "data", 2, NULL, 'd'},
+ { "metadata", 2, NULL, 'm' },
+ { "system", 2, NULL, 's' },
+ { "force", 0, NULL, 'f' },
+ { "verbose", 0, NULL, 'v' },
+ { 0, 0, 0, 0}
+};
+/*
+ * [-d [filters]] [-m [filters]] [-s [filters]] [-vf]
+ */
+int do_restripe(int ac, char **av)
+{
+ int fd;
+ char *path;
+ struct btrfs_ioctl_restripe_args args;
+ struct btrfs_restripe_args *ptrs[] = { &args.data, &args.sys,
+ &args.meta, NULL };
+ int force = 0;
+ int verbose = 0;
+ int nofilters = 1;
+ int i;
+ int longindex;
+ int ret;
+ int e;
+
+ memset(&args, 0, sizeof(args));
+
+ while (1) {
+ int opt = getopt_long(ac, av, "d::s::m::fv", restripe_longopts,
+ &longindex);
+ if (opt < 0)
+ break;
+
+ switch (opt) {
+ case 'd':
+ nofilters = 0;
+ args.flags |= BTRFS_RESTRIPE_DATA;
+
+ if (parse_filters(optarg, &args.data))
+ return 1;
+ break;
+ case 's':
+ nofilters = 0;
+ args.flags |= BTRFS_RESTRIPE_SYSTEM;
+
+ if (parse_filters(optarg, &args.sys))
+ return 1;
+ break;
+ case 'm':
+ nofilters = 0;
+ args.flags |= BTRFS_RESTRIPE_METADATA;
+
+ if (parse_filters(optarg, &args.meta))
+ return 1;
+ break;
+ case 'f':
+ force = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ fprintf(stderr, "Invalid arguments for restripe\n");
+ return 1;
+ }
+ }
+
+ if (ac - optind != 1) {
+ fprintf(stderr, "Invalid arguments for restripe\n");
+ return 1;
+ }
+
+ if (nofilters) {
+ /* relocate everything - no filters */
+ args.flags |= BTRFS_RESTRIPE_TYPE_MASK;
+ }
+
+ /* drange makes sense only when devid is set */
+ for (i = 0; ptrs[i]; i++) {
+ if ((ptrs[i]->flags & BTRFS_RESTRIPE_ARGS_DRANGE) &&
+ !(ptrs[i]->flags & BTRFS_RESTRIPE_ARGS_DEVID)) {
+ fprintf(stderr, "drange filter can be used only if "
+ "devid filter is used\n");
+ return 1;
+ }
+ }
+
+ /* soft makes sense only when convert for corresponding type is set */
+ for (i = 0; ptrs[i]; i++) {
+ if ((ptrs[i]->flags & BTRFS_RESTRIPE_ARGS_SOFT) &&
+ !(ptrs[i]->flags & BTRFS_RESTRIPE_ARGS_CONVERT)) {
+ fprintf(stderr, "'soft' option can be used only if "
+ "changing profiles\n");
+ return 1;
+ }
+ }
+
+ path = av[optind];
+ fd = open_file_or_dir(path);
+ if (fd < 0) {
+ fprintf(stderr, "ERROR: can't access to '%s'\n", path);
+ return 12;
+ }
+
+ if (force)
+ args.flags |= BTRFS_RESTRIPE_FORCE;
+ if (verbose)
+ dump_ioctl_restripe_args(&args);
+
+ ret = ioctl(fd, BTRFS_IOC_RESTRIPE, &args);
+ e = errno;
+ close(fd);
+
+ if (ret < 0) {
+ if (e == ECANCELED) {
+ fprintf(stderr, "restripe interrupted by user\n");
+ } else {
+ fprintf(stderr, "ERROR: error during restriping '%s' "
+ "- %s\n", path, strerror(e));
+ return 19;
+ }
+ }
+
+ return 0;
+}
+
+int do_restripe_cancel(int ac, char **av)
+{
+ int fd;
+ char *path = av[1];
+ int ret;
+ int e;
+
+ fd = open_file_or_dir(path);
+ if (fd < 0) {
+ fprintf(stderr, "ERROR: can't access to '%s'\n", path);
+ return 12;
+ }
+
+ ret = ioctl(fd, BTRFS_IOC_RESTRIPE_CTL, BTRFS_RESTRIPE_CTL_CANCEL);
+ e = errno;
+ close(fd);
+
+ if (ret < 0) {
+ fprintf(stderr, "ERROR: restripe cancel on '%s' failed - %s\n",
+ path, (e == ENOTCONN) ? "Not in progress" : strerror(e));
+ return 19;
+ }
+
+ return 0;
+}
+
+int do_restripe_pause(int ac, char **av)
+{
+ int fd;
+ char *path = av[1];
+ int ret;
+ int e;
+
+ fd = open_file_or_dir(path);
+ if (fd < 0) {
+ fprintf(stderr, "ERROR: can't access to '%s'\n", path);
+ return 12;
+ }
+
+ ret = ioctl(fd, BTRFS_IOC_RESTRIPE_CTL, BTRFS_RESTRIPE_CTL_PAUSE);
+ e = errno;
+ close(fd);
+
+ if (ret < 0) {
+ fprintf(stderr, "ERROR: restripe pause on '%s' failed - %s\n",
+ path, (e == ENOTCONN) ? "Not running" : strerror(e));
+ return 19;
+ }
+
+ return 0;
+}
+
+int do_restripe_resume(int ac, char **av)
+{
+ int fd;
+ char *path = av[1];
+ int ret;
+ int e;
+
+ fd = open_file_or_dir(path);
+ if (fd < 0) {
+ fprintf(stderr, "ERROR: can't access to '%s'\n", path);
+ return 12;
+ }
+
+ ret = ioctl(fd, BTRFS_IOC_RESTRIPE_CTL, BTRFS_RESTRIPE_CTL_RESUME);
+ e = errno;
+ close(fd);
+
+ if (ret < 0) {
+ if (e == ECANCELED) {
+ fprintf(stderr, "restripe interrupted by user\n");
+ } else if (e == ENOTCONN || e == EINPROGRESS) {
+ fprintf(stderr, "ERROR: restripe resume on '%s' "
+ "failed - %s\n", path,
+ (e == ENOTCONN) ? "Not in progress" :
+ "Already running");
+ return 19;
+ } else {
+ fprintf(stderr, "ERROR: error during restriping '%s' "
+ "- %s\n", path, strerror(e));
+ return 19;
+ }
+ }
+
+ return 0;
+}
+
+static struct option restripe_progress_longopts[] = {
+ { "verbose", 0, NULL, 'v' },
+ { 0, 0, 0, 0}
+};
+
+int do_restripe_progress(int ac, char **av)
+{
+ int fd;
+ char *path;
+ struct btrfs_ioctl_restripe_args args;
+ int verbose = 0;
+ int longindex;
+ int ret;
+ int e;
+
+ while (1) {
+ int opt = getopt_long(ac, av, "v", restripe_progress_longopts,
+ &longindex);
+ if (opt < 0)
+ break;
+
+ switch (opt) {
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ fprintf(stderr, "Invalid arguments for restripe "
+ "status\n");
+ return 1;
+ }
+ }
+
+ if (ac - optind != 1) {
+ fprintf(stderr, "Invalid arguments for restripe status\n");
+ return 1;
+ }
+
+ path = av[optind];
+ fd = open_file_or_dir(path);
+ if (fd < 0) {
+ fprintf(stderr, "ERROR: can't access to '%s'\n", path);
+ return 12;
+ }
+
+ ret = ioctl(fd, BTRFS_IOC_RESTRIPE_PROGRESS, &args);
+ e = errno;
+ close(fd);
+
+ if (ret < 0) {
+ fprintf(stderr, "ERROR: restripe status on '%s' failed - %s\n",
+ path, (e == ENOTCONN) ? "Not in progress" : strerror(e));
return 19;
}
+
+ if (args.state & BTRFS_RESTRIPE_ST_RUNNING) {
+ printf("Restripe on '%s' is running", path);
+ if (args.state & BTRFS_RESTRIPE_ST_CANCEL_REQ)
+ printf(", cancel requested\n");
+ else if (args.state & BTRFS_RESTRIPE_ST_PAUSE_REQ)
+ printf(", pause requested\n");
+ else
+ printf("\n");
+ } else {
+ printf("Restripe on '%s' is paused\n", path);
+ }
+
+ printf("%llu out of about %llu chunks restriped (%llu considered), "
+ "%3.f%% left\n", args.stat.completed, args.stat.expected,
+ args.stat.considered,
+ 100 * (1 - (float)args.stat.completed/args.stat.expected));
+
+ if (verbose)
+ dump_ioctl_restripe_args(&args);
+
return 0;
}
+static void dump_restripe_args(struct btrfs_restripe_args *args)
+{
+ if (args->flags & BTRFS_RESTRIPE_ARGS_CONVERT) {
+ printf("converting, target=%llu, soft is %s", args->target,
+ (args->flags & BTRFS_RESTRIPE_ARGS_SOFT) ? "on" : "off");
+ } else {
+ printf("balancing");
+ }
+
+ if (args->flags & BTRFS_RESTRIPE_ARGS_PROFILES)
+ printf(", profiles=%llu", args->profiles);
+ if (args->flags & BTRFS_RESTRIPE_ARGS_USAGE)
+ printf(", usage=%llu", args->usage);
+ if (args->flags & BTRFS_RESTRIPE_ARGS_DEVID)
+ printf(", devid=%llu", args->devid);
+ if (args->flags & BTRFS_RESTRIPE_ARGS_DRANGE)
+ printf(", drange=%llu..%llu", args->pstart, args->pend);
+ if (args->flags & BTRFS_RESTRIPE_ARGS_VRANGE)
+ printf(", vrange=%llu..%llu", args->vstart, args->vend);
+
+ printf("\n");
+}
+
+static void dump_ioctl_restripe_args(struct btrfs_ioctl_restripe_args *args)
+{
+ printf("Dumping filters: flags 0x%llx, state 0x%llx, force is %s\n",
+ args->flags, args->state,
+ (args->flags & BTRFS_RESTRIPE_FORCE) ? "on" : "off");
+ if (args->flags & BTRFS_RESTRIPE_DATA) {
+ printf(" DATA (flags 0x%llx): ", args->data.flags);
+ dump_restripe_args(&args->data);
+ }
+ if (args->flags & BTRFS_RESTRIPE_METADATA) {
+ printf(" METADATA (flags 0x%llx): ", args->meta.flags);
+ dump_restripe_args(&args->meta);
+ }
+ if (args->flags & BTRFS_RESTRIPE_SYSTEM) {
+ printf(" SYSTEM (flags 0x%llx): ", args->sys.flags);
+ dump_restripe_args(&args->sys);
+ }
+}
/**** man: btrfs device delete
diff --git a/btrfs_cmds.h b/btrfs_cmds.h
index 81182b1..2cd0ac1 100644
--- a/btrfs_cmds.h
+++ b/btrfs_cmds.h
@@ -27,6 +27,11 @@ int do_scrub_start(int nargs, char **argv);
int do_scrub_status(int argc, char **argv);
int do_scrub_resume(int argc, char **argv);
int do_scrub_cancel(int nargs, char **argv);
+int do_restripe(int ac, char **av);
+int do_restripe_cancel(int ac, char **av);
+int do_restripe_pause(int ac, char **av);
+int do_restripe_resume(int ac, char **av);
+int do_restripe_progress(int ac, char **av);
int do_remove_volume(int nargs, char **args);
int do_scan(int nargs, char **argv);
int do_resize(int nargs, char **argv);
diff --git a/ctree.h b/ctree.h
index 54748c8..58ea3d3 100644
--- a/ctree.h
+++ b/ctree.h
@@ -61,6 +61,9 @@ struct btrfs_trans_handle;
#define BTRFS_CSUM_TREE_OBJECTID 7ULL
+/* for storing restripe params in the root tree */
+#define BTRFS_RESTRIPE_OBJECTID -4ULL
+
/* oprhan objectid for tracking unlinked/truncated files */
#define BTRFS_ORPHAN_OBJECTID -5ULL
@@ -705,6 +708,12 @@ struct btrfs_csum_item {
#define BTRFS_BLOCK_GROUP_DUP (1 << 5)
#define BTRFS_BLOCK_GROUP_RAID10 (1 << 6)
+/*
+ * to avoid troubles..
+ */
+#define BTRFS_AVAIL_ALLOC_BIT_SINGLE (1 << 7)
+#define BTRFS_BLOCK_GROUP_RESERVED (1 << 7)
+
struct btrfs_block_group_item {
__le64 used;
__le64 chunk_objectid;
diff --git a/ioctl.h b/ioctl.h
index 1ae7537..af8b18b 100644
--- a/ioctl.h
+++ b/ioctl.h
@@ -91,6 +91,45 @@ struct btrfs_ioctl_fs_info_args {
__u64 reserved[124]; /* pad to 1k */
};
+#define BTRFS_RESTRIPE_CTL_CANCEL 1
+#define BTRFS_RESTRIPE_CTL_PAUSE 2
+#define BTRFS_RESTRIPE_CTL_RESUME 3
+
+struct btrfs_restripe_args {
+ __u64 profiles;
+ __u64 usage;
+ __u64 devid;
+ __u64 pstart;
+ __u64 pend;
+ __u64 vstart;
+ __u64 vend;
+
+ __u64 target;
+
+ __u64 flags;
+
+ __u64 unused[8];
+} __attribute__ ((__packed__));
+
+struct btrfs_restripe_progress {
+ __u64 expected;
+ __u64 considered;
+ __u64 completed;
+};
+
+struct btrfs_ioctl_restripe_args {
+ __u64 flags;
+ __u64 state;
+
+ struct btrfs_restripe_args data;
+ struct btrfs_restripe_args sys;
+ struct btrfs_restripe_args meta;
+
+ struct btrfs_restripe_progress stat;
+
+ __u64 unused[72]; /* pad to 1k */
+};
+
struct btrfs_ioctl_search_key {
/* which root are we searching. 0 is the tree of tree roots */
__u64 tree_id;
@@ -272,10 +311,15 @@ struct btrfs_ioctl_logical_ino_args {
#define BTRFS_IOC_DEV_INFO _IOWR(BTRFS_IOCTL_MAGIC, 30, \
struct btrfs_ioctl_dev_info_args)
#define BTRFS_IOC_FS_INFO _IOR(BTRFS_IOCTL_MAGIC, 31, \
- struct btrfs_ioctl_fs_info_args)
+ struct btrfs_ioctl_fs_info_args)
#define BTRFS_IOC_INO_PATHS _IOWR(BTRFS_IOCTL_MAGIC, 35, \
struct btrfs_ioctl_ino_path_args)
#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
struct btrfs_ioctl_ino_path_args)
+#define BTRFS_IOC_RESTRIPE _IOW(BTRFS_IOCTL_MAGIC, 32, \
+ struct btrfs_ioctl_restripe_args)
+#define BTRFS_IOC_RESTRIPE_CTL _IOW(BTRFS_IOCTL_MAGIC, 33, int)
+#define BTRFS_IOC_RESTRIPE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 34, \
+ struct btrfs_ioctl_restripe_args)
#endif
diff --git a/print-tree.c b/print-tree.c
index 6039699..49f98af 100644
--- a/print-tree.c
+++ b/print-tree.c
@@ -391,6 +391,9 @@ static void print_objectid(unsigned long long objectid, u8 type)
case BTRFS_CSUM_TREE_OBJECTID:
printf("CSUM_TREE");
break;
+ case BTRFS_RESTRIPE_OBJECTID:
+ printf("RESTRIPE");
+ break;
case BTRFS_ORPHAN_OBJECTID:
printf("ORPHAN");
break;
diff --git a/volumes.h b/volumes.h
index 7104d36..6929aca 100644
--- a/volumes.h
+++ b/volumes.h
@@ -91,6 +91,48 @@ struct btrfs_multi_bio {
#define btrfs_multi_bio_size(n) (sizeof(struct btrfs_multi_bio) + \
(sizeof(struct btrfs_bio_stripe) * (n)))
+/*
+ * Restriper's general "type" filter. Shares bits with chunk type for
+ * simplicity, RESTRIPE prefix is used to avoid confusion.
+ */
+#define BTRFS_RESTRIPE_DATA (1ULL << 0)
+#define BTRFS_RESTRIPE_SYSTEM (1ULL << 1)
+#define BTRFS_RESTRIPE_METADATA (1ULL << 2)
+
+#define BTRFS_RESTRIPE_TYPE_MASK (BTRFS_RESTRIPE_DATA | \
+ BTRFS_RESTRIPE_SYSTEM | \
+ BTRFS_RESTRIPE_METADATA)
+
+#define BTRFS_RESTRIPE_FORCE (1ULL << 3)
+
+/*
+ * Restripe filters
+ */
+#define BTRFS_RESTRIPE_ARGS_PROFILES (1ULL << 0)
+#define BTRFS_RESTRIPE_ARGS_USAGE (1ULL << 1)
+#define BTRFS_RESTRIPE_ARGS_DEVID (1ULL << 2)
+#define BTRFS_RESTRIPE_ARGS_DRANGE (1ULL << 3)
+#define BTRFS_RESTRIPE_ARGS_VRANGE (1ULL << 4)
+
+/*
+ * Profile changing flags. When SOFT is set we won't relocate chunk if
+ * it already has the target profile (even though it may be
+ * half-filled).
+ */
+#define BTRFS_RESTRIPE_ARGS_CONVERT (1ULL << 8)
+#define BTRFS_RESTRIPE_ARGS_SOFT (1ULL << 9)
+
+/*
+ * Restripe state bits
+ */
+#define RESTRIPE_RUNNING 0
+#define RESTRIPE_CANCEL_REQ 1
+#define RESTRIPE_PAUSE_REQ 2
+
+#define BTRFS_RESTRIPE_ST_RUNNING (1ULL << RESTRIPE_RUNNING)
+#define BTRFS_RESTRIPE_ST_CANCEL_REQ (1ULL << RESTRIPE_CANCEL_REQ)
+#define BTRFS_RESTRIPE_ST_PAUSE_REQ (1ULL << RESTRIPE_PAUSE_REQ)
+
int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
struct btrfs_device *device,
u64 chunk_tree, u64 chunk_objectid,
--
1.7.6.233.gd79bc

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,85 @@
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

View File

@ -0,0 +1,95 @@
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

View File

@ -0,0 +1,134 @@
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

View File

@ -0,0 +1,40 @@
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

View File

@ -0,0 +1,54 @@
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

View File

@ -0,0 +1,55 @@
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

View File

@ -0,0 +1,84 @@
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

View File

@ -0,0 +1,130 @@
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

View File

@ -0,0 +1,92 @@
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

View File

@ -0,0 +1,161 @@
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;
+}

View File

@ -0,0 +1,179 @@
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

View File

@ -0,0 +1,111 @@
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

View File

@ -0,0 +1,191 @@
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

View File

@ -0,0 +1,31 @@
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

View File

@ -0,0 +1,36 @@
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

View File

@ -0,0 +1,443 @@
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

View File

@ -0,0 +1,32 @@
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

View File

@ -0,0 +1,37 @@
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

View File

@ -0,0 +1,31 @@
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

View File

@ -0,0 +1,180 @@
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

View File

@ -0,0 +1,32 @@
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

View File

@ -0,0 +1,130 @@
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

View File

@ -0,0 +1,45 @@
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

View File

@ -0,0 +1,32 @@
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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,750 @@
From 927d075e63d7c21038c53eae1e1b1edbdb01cdcf Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba@suse.cz>
Date: Wed, 14 Dec 2011 18:46:02 +0100
Subject: [PATCH] Revert "Btrfs-progs: add restriper commands"
This reverts commit 192484f121dbbffd004303a760ef8b4dbd470ce2.
---
btrfs.c | 21 ---
btrfs_cmds.c | 505 +---------------------------------------------------------
btrfs_cmds.h | 5 -
ctree.h | 9 -
ioctl.h | 46 +-----
print-tree.c | 3 -
volumes.h | 42 -----
7 files changed, 3 insertions(+), 628 deletions(-)
diff --git a/btrfs.c b/btrfs.c
index 52af8f7..66b0d80 100644
--- a/btrfs.c
+++ b/btrfs.c
@@ -329,27 +329,6 @@ static struct Command commands[] = {
"Show status of running or finished scrub.",
NULL
},
- { do_restripe, -1,
- "filesystem restripe start", "[-d [filters]] [-m [filters]] "
- "[-s [filters]] [-vf] <path>\n"
- "Start restriper."
- },
- { do_restripe_cancel, 1,
- "filesystem restripe cancel", "<path>\n"
- "Cancel restriper."
- },
- { do_restripe_pause, 1,
- "filesystem restripe pause", "<path>\n"
- "Pause restriper."
- },
- { do_restripe_resume, 1,
- "filesystem restripe resume", "<path>\n"
- "Resume interrupted restripe operation."
- },
- { do_restripe_progress, -1,
- "filesystem restripe status", "[-v] <path>\n"
- "Show status of running or paused restripe operation."
- },
{ do_scan, 999,
"device scan", "[<device>...]\n"
"Scan all device for or the passed device for a btrfs\n"
diff --git a/btrfs_cmds.c b/btrfs_cmds.c
index e4c5592..1bfc669 100644
--- a/btrfs_cmds.c
+++ b/btrfs_cmds.c
@@ -1094,515 +1094,14 @@ int do_balance(int argc, char **argv)
e = errno;
close(fdmnt);
if(ret<0){
- if (e == ECANCELED) {
- fprintf(stderr, "restripe interrupted by user\n");
- } else {
- fprintf(stderr, "ERROR: error during restriping '%s' "
- "- %s\n", path, strerror(e));
- return 19;
- }
- }
- return 0;
-}
-
-static int parse_one_profile(char *profile, u64 *flags)
-{
- if (!strcmp(profile, "raid0")) {
- *flags |= BTRFS_BLOCK_GROUP_RAID0;
- } else if (!strcmp(profile, "raid1")) {
- *flags |= BTRFS_BLOCK_GROUP_RAID1;
- } else if (!strcmp(profile, "raid10")) {
- *flags |= BTRFS_BLOCK_GROUP_RAID10;
- } else if (!strcmp(profile, "dup")) {
- *flags |= BTRFS_BLOCK_GROUP_DUP;
- } else if (!strcmp(profile, "single")) {
- *flags |= BTRFS_AVAIL_ALLOC_BIT_SINGLE;
- } else {
- fprintf(stderr, "Unknown profile '%s'\n", profile);
- return 1;
- }
-
- return 0;
-}
-
-static int parse_profiles(char *profiles, u64 *flags)
-{
- char *this_char;
- char *save_ptr;
-
- for (this_char = strtok_r(profiles, "|", &save_ptr);
- this_char != NULL;
- this_char = strtok_r(NULL, "|", &save_ptr)) {
- if (parse_one_profile(this_char, flags))
- return 1;
- }
-
- return 0;
-}
-
-static int parse_range(char *range, u64 *start, u64 *end)
-{
- char *dots;
-
- dots = strstr(range, "..");
- if (dots) {
- const char *rest = dots + 2;
- int skipped = 0;
-
- *dots = 0;
-
- if (!*rest) {
- *end = (u64)-1;
- skipped++;
- } else {
- *end = strtoull(rest, (char **)NULL, 10);
- }
- if (dots == range) {
- *start = 0;
- skipped++;
- } else {
- *start = strtoull(range, (char **)NULL, 10);
- }
-
- if (skipped <= 1)
- return 0;
- }
-
- return 1;
-}
-
-static int parse_filters(char *filters, struct btrfs_restripe_args *rargs)
-{
- char *this_char;
- char *value;
- char *save_ptr;
-
- if (!filters)
- return 0;
-
- for (this_char = strtok_r(filters, ",", &save_ptr);
- this_char != NULL;
- this_char = strtok_r(NULL, ",", &save_ptr)) {
- if ((value = strchr(this_char, '=')) != NULL)
- *value++ = 0;
- if (!strcmp(this_char, "profiles")) {
- if (!value || !*value) {
- fprintf(stderr, "the profiles filter requires "
- "an argument\n");
- return 1;
- }
- if (parse_profiles(value, &rargs->profiles)) {
- fprintf(stderr, "Invalid profiles argument\n");
- return 1;
- }
- rargs->flags |= BTRFS_RESTRIPE_ARGS_PROFILES;
- } else if (!strcmp(this_char, "usage")) {
- if (!value || !*value) {
- fprintf(stderr, "the usage filter requires "
- "an argument\n");
- return 1;
- }
- rargs->usage = strtoull(value, (char **)NULL, 10);
- if (rargs->usage < 1 || rargs->usage > 100) {
- fprintf(stderr, "Invalid usage argument: %s\n",
- value);
- return 1;
- }
- rargs->flags |= BTRFS_RESTRIPE_ARGS_USAGE;
- } else if (!strcmp(this_char, "devid")) {
- if (!value || !*value) {
- fprintf(stderr, "the devid filter requires "
- "an argument\n");
- return 1;
- }
- rargs->devid = strtoull(value, (char **)NULL, 10);
- if (rargs->devid == 0) {
- fprintf(stderr, "Invalid devid argument: %s\n",
- value);
- return 1;
- }
- rargs->flags |= BTRFS_RESTRIPE_ARGS_DEVID;
- } else if (!strcmp(this_char, "drange")) {
- if (!value || !*value) {
- fprintf(stderr, "the drange filter requires "
- "an argument\n");
- return 1;
- }
- if (parse_range(value, &rargs->pstart, &rargs->pend)) {
- fprintf(stderr, "Invalid drange argument\n");
- return 1;
- }
- rargs->flags |= BTRFS_RESTRIPE_ARGS_DRANGE;
- } else if (!strcmp(this_char, "vrange")) {
- if (!value || !*value) {
- fprintf(stderr, "the vrange filter requires "
- "an argument\n");
- return 1;
- }
- if (parse_range(value, &rargs->vstart, &rargs->vend)) {
- fprintf(stderr, "Invalid vrange argument\n");
- return 1;
- }
- rargs->flags |= BTRFS_RESTRIPE_ARGS_VRANGE;
- } else if (!strcmp(this_char, "convert")) {
- if (!value || !*value) {
- fprintf(stderr, "the convert option requires "
- "an argument\n");
- return 1;
- }
- if (parse_one_profile(value, &rargs->target)) {
- fprintf(stderr, "Invalid convert argument\n");
- return 1;
- }
- rargs->flags |= BTRFS_RESTRIPE_ARGS_CONVERT;
- } else if (!strcmp(this_char, "soft")) {
- rargs->flags |= BTRFS_RESTRIPE_ARGS_SOFT;
- } else {
- fprintf(stderr, "Unrecognized restripe option '%s'\n",
- this_char);
- return 1;
- }
- }
-
- return 0;
-}
-
-static void dump_ioctl_restripe_args(struct btrfs_ioctl_restripe_args *args);
-
-static struct option restripe_longopts[] = {
- { "data", 2, NULL, 'd'},
- { "metadata", 2, NULL, 'm' },
- { "system", 2, NULL, 's' },
- { "force", 0, NULL, 'f' },
- { "verbose", 0, NULL, 'v' },
- { 0, 0, 0, 0}
-};
-
-/*
- * [-d [filters]] [-m [filters]] [-s [filters]] [-vf]
- */
-int do_restripe(int ac, char **av)
-{
- int fd;
- char *path;
- struct btrfs_ioctl_restripe_args args;
- struct btrfs_restripe_args *ptrs[] = { &args.data, &args.sys,
- &args.meta, NULL };
- int force = 0;
- int verbose = 0;
- int nofilters = 1;
- int i;
- int longindex;
- int ret;
- int e;
-
- memset(&args, 0, sizeof(args));
-
- while (1) {
- int opt = getopt_long(ac, av, "d::s::m::fv", restripe_longopts,
- &longindex);
- if (opt < 0)
- break;
-
- switch (opt) {
- case 'd':
- nofilters = 0;
- args.flags |= BTRFS_RESTRIPE_DATA;
-
- if (parse_filters(optarg, &args.data))
- return 1;
- break;
- case 's':
- nofilters = 0;
- args.flags |= BTRFS_RESTRIPE_SYSTEM;
-
- if (parse_filters(optarg, &args.sys))
- return 1;
- break;
- case 'm':
- nofilters = 0;
- args.flags |= BTRFS_RESTRIPE_METADATA;
-
- if (parse_filters(optarg, &args.meta))
- return 1;
- break;
- case 'f':
- force = 1;
- break;
- case 'v':
- verbose = 1;
- break;
- default:
- fprintf(stderr, "Invalid arguments for restripe\n");
- return 1;
- }
- }
-
- if (ac - optind != 1) {
- fprintf(stderr, "Invalid arguments for restripe\n");
- return 1;
- }
-
- if (nofilters) {
- /* relocate everything - no filters */
- args.flags |= BTRFS_RESTRIPE_TYPE_MASK;
- }
-
- /* drange makes sense only when devid is set */
- for (i = 0; ptrs[i]; i++) {
- if ((ptrs[i]->flags & BTRFS_RESTRIPE_ARGS_DRANGE) &&
- !(ptrs[i]->flags & BTRFS_RESTRIPE_ARGS_DEVID)) {
- fprintf(stderr, "drange filter can be used only if "
- "devid filter is used\n");
- return 1;
- }
- }
-
- /* soft makes sense only when convert for corresponding type is set */
- for (i = 0; ptrs[i]; i++) {
- if ((ptrs[i]->flags & BTRFS_RESTRIPE_ARGS_SOFT) &&
- !(ptrs[i]->flags & BTRFS_RESTRIPE_ARGS_CONVERT)) {
- fprintf(stderr, "'soft' option can be used only if "
- "changing profiles\n");
- return 1;
- }
- }
-
- path = av[optind];
- fd = open_file_or_dir(path);
- if (fd < 0) {
- fprintf(stderr, "ERROR: can't access to '%s'\n", path);
- return 12;
- }
-
- if (force)
- args.flags |= BTRFS_RESTRIPE_FORCE;
- if (verbose)
- dump_ioctl_restripe_args(&args);
-
- ret = ioctl(fd, BTRFS_IOC_RESTRIPE, &args);
- e = errno;
- close(fd);
-
- if (ret < 0) {
- if (e == ECANCELED) {
- fprintf(stderr, "restripe interrupted by user\n");
- } else {
- fprintf(stderr, "ERROR: error during restriping '%s' "
- "- %s\n", path, strerror(e));
- return 19;
- }
- }
-
- return 0;
-}
-
-int do_restripe_cancel(int ac, char **av)
-{
- int fd;
- char *path = av[1];
- int ret;
- int e;
-
- fd = open_file_or_dir(path);
- if (fd < 0) {
- fprintf(stderr, "ERROR: can't access to '%s'\n", path);
- return 12;
- }
-
- ret = ioctl(fd, BTRFS_IOC_RESTRIPE_CTL, BTRFS_RESTRIPE_CTL_CANCEL);
- e = errno;
- close(fd);
-
- if (ret < 0) {
- fprintf(stderr, "ERROR: restripe cancel on '%s' failed - %s\n",
- path, (e == ENOTCONN) ? "Not in progress" : strerror(e));
- return 19;
- }
-
- return 0;
-}
-
-int do_restripe_pause(int ac, char **av)
-{
- int fd;
- char *path = av[1];
- int ret;
- int e;
-
- fd = open_file_or_dir(path);
- if (fd < 0) {
- fprintf(stderr, "ERROR: can't access to '%s'\n", path);
- return 12;
- }
-
- ret = ioctl(fd, BTRFS_IOC_RESTRIPE_CTL, BTRFS_RESTRIPE_CTL_PAUSE);
- e = errno;
- close(fd);
-
- if (ret < 0) {
- fprintf(stderr, "ERROR: restripe pause on '%s' failed - %s\n",
- path, (e == ENOTCONN) ? "Not running" : strerror(e));
- return 19;
- }
-
- return 0;
-}
-
-int do_restripe_resume(int ac, char **av)
-{
- int fd;
- char *path = av[1];
- int ret;
- int e;
-
- fd = open_file_or_dir(path);
- if (fd < 0) {
- fprintf(stderr, "ERROR: can't access to '%s'\n", path);
- return 12;
- }
-
- ret = ioctl(fd, BTRFS_IOC_RESTRIPE_CTL, BTRFS_RESTRIPE_CTL_RESUME);
- e = errno;
- close(fd);
-
- if (ret < 0) {
- if (e == ECANCELED) {
- fprintf(stderr, "restripe interrupted by user\n");
- } else if (e == ENOTCONN || e == EINPROGRESS) {
- fprintf(stderr, "ERROR: restripe resume on '%s' "
- "failed - %s\n", path,
- (e == ENOTCONN) ? "Not in progress" :
- "Already running");
- return 19;
- } else {
- fprintf(stderr, "ERROR: error during restriping '%s' "
- "- %s\n", path, strerror(e));
- return 19;
- }
- }
-
- return 0;
-}
-
-static struct option restripe_progress_longopts[] = {
- { "verbose", 0, NULL, 'v' },
- { 0, 0, 0, 0}
-};
-
-int do_restripe_progress(int ac, char **av)
-{
- int fd;
- char *path;
- struct btrfs_ioctl_restripe_args args;
- int verbose = 0;
- int longindex;
- int ret;
- int e;
-
- while (1) {
- int opt = getopt_long(ac, av, "v", restripe_progress_longopts,
- &longindex);
- if (opt < 0)
- break;
-
- switch (opt) {
- case 'v':
- verbose = 1;
- break;
- default:
- fprintf(stderr, "Invalid arguments for restripe "
- "status\n");
- return 1;
- }
- }
-
- if (ac - optind != 1) {
- fprintf(stderr, "Invalid arguments for restripe status\n");
- return 1;
- }
-
- path = av[optind];
- fd = open_file_or_dir(path);
- if (fd < 0) {
- fprintf(stderr, "ERROR: can't access to '%s'\n", path);
- return 12;
- }
-
- ret = ioctl(fd, BTRFS_IOC_RESTRIPE_PROGRESS, &args);
- e = errno;
- close(fd);
+ fprintf(stderr, "ERROR: error during balancing '%s' - %s\n",
+ path, strerror(e));
- if (ret < 0) {
- fprintf(stderr, "ERROR: restripe status on '%s' failed - %s\n",
- path, (e == ENOTCONN) ? "Not in progress" : strerror(e));
return 19;
}
-
- if (args.state & BTRFS_RESTRIPE_ST_RUNNING) {
- printf("Restripe on '%s' is running", path);
- if (args.state & BTRFS_RESTRIPE_ST_CANCEL_REQ)
- printf(", cancel requested\n");
- else if (args.state & BTRFS_RESTRIPE_ST_PAUSE_REQ)
- printf(", pause requested\n");
- else
- printf("\n");
- } else {
- printf("Restripe on '%s' is paused\n", path);
- }
-
- printf("%llu out of about %llu chunks restriped (%llu considered), "
- "%3.f%% left\n", args.stat.completed, args.stat.expected,
- args.stat.considered,
- 100 * (1 - (float)args.stat.completed/args.stat.expected));
-
- if (verbose)
- dump_ioctl_restripe_args(&args);
-
return 0;
}
-static void dump_restripe_args(struct btrfs_restripe_args *args)
-{
- if (args->flags & BTRFS_RESTRIPE_ARGS_CONVERT) {
- printf("converting, target=%llu, soft is %s", args->target,
- (args->flags & BTRFS_RESTRIPE_ARGS_SOFT) ? "on" : "off");
- } else {
- printf("balancing");
- }
-
- if (args->flags & BTRFS_RESTRIPE_ARGS_PROFILES)
- printf(", profiles=%llu", args->profiles);
- if (args->flags & BTRFS_RESTRIPE_ARGS_USAGE)
- printf(", usage=%llu", args->usage);
- if (args->flags & BTRFS_RESTRIPE_ARGS_DEVID)
- printf(", devid=%llu", args->devid);
- if (args->flags & BTRFS_RESTRIPE_ARGS_DRANGE)
- printf(", drange=%llu..%llu", args->pstart, args->pend);
- if (args->flags & BTRFS_RESTRIPE_ARGS_VRANGE)
- printf(", vrange=%llu..%llu", args->vstart, args->vend);
-
- printf("\n");
-}
-
-static void dump_ioctl_restripe_args(struct btrfs_ioctl_restripe_args *args)
-{
- printf("Dumping filters: flags 0x%llx, state 0x%llx, force is %s\n",
- args->flags, args->state,
- (args->flags & BTRFS_RESTRIPE_FORCE) ? "on" : "off");
- if (args->flags & BTRFS_RESTRIPE_DATA) {
- printf(" DATA (flags 0x%llx): ", args->data.flags);
- dump_restripe_args(&args->data);
- }
- if (args->flags & BTRFS_RESTRIPE_METADATA) {
- printf(" METADATA (flags 0x%llx): ", args->meta.flags);
- dump_restripe_args(&args->meta);
- }
- if (args->flags & BTRFS_RESTRIPE_SYSTEM) {
- printf(" SYSTEM (flags 0x%llx): ", args->sys.flags);
- dump_restripe_args(&args->sys);
- }
-}
/**** man: btrfs device delete
diff --git a/btrfs_cmds.h b/btrfs_cmds.h
index 2cd0ac1..81182b1 100644
--- a/btrfs_cmds.h
+++ b/btrfs_cmds.h
@@ -27,11 +27,6 @@ int do_scrub_start(int nargs, char **argv);
int do_scrub_status(int argc, char **argv);
int do_scrub_resume(int argc, char **argv);
int do_scrub_cancel(int nargs, char **argv);
-int do_restripe(int ac, char **av);
-int do_restripe_cancel(int ac, char **av);
-int do_restripe_pause(int ac, char **av);
-int do_restripe_resume(int ac, char **av);
-int do_restripe_progress(int ac, char **av);
int do_remove_volume(int nargs, char **args);
int do_scan(int nargs, char **argv);
int do_resize(int nargs, char **argv);
diff --git a/ctree.h b/ctree.h
index 58ea3d3..54748c8 100644
--- a/ctree.h
+++ b/ctree.h
@@ -61,9 +61,6 @@ struct btrfs_trans_handle;
#define BTRFS_CSUM_TREE_OBJECTID 7ULL
-/* for storing restripe params in the root tree */
-#define BTRFS_RESTRIPE_OBJECTID -4ULL
-
/* oprhan objectid for tracking unlinked/truncated files */
#define BTRFS_ORPHAN_OBJECTID -5ULL
@@ -708,12 +705,6 @@ struct btrfs_csum_item {
#define BTRFS_BLOCK_GROUP_DUP (1 << 5)
#define BTRFS_BLOCK_GROUP_RAID10 (1 << 6)
-/*
- * to avoid troubles..
- */
-#define BTRFS_AVAIL_ALLOC_BIT_SINGLE (1 << 7)
-#define BTRFS_BLOCK_GROUP_RESERVED (1 << 7)
-
struct btrfs_block_group_item {
__le64 used;
__le64 chunk_objectid;
diff --git a/ioctl.h b/ioctl.h
index af8b18b..1ae7537 100644
--- a/ioctl.h
+++ b/ioctl.h
@@ -91,45 +91,6 @@ struct btrfs_ioctl_fs_info_args {
__u64 reserved[124]; /* pad to 1k */
};
-#define BTRFS_RESTRIPE_CTL_CANCEL 1
-#define BTRFS_RESTRIPE_CTL_PAUSE 2
-#define BTRFS_RESTRIPE_CTL_RESUME 3
-
-struct btrfs_restripe_args {
- __u64 profiles;
- __u64 usage;
- __u64 devid;
- __u64 pstart;
- __u64 pend;
- __u64 vstart;
- __u64 vend;
-
- __u64 target;
-
- __u64 flags;
-
- __u64 unused[8];
-} __attribute__ ((__packed__));
-
-struct btrfs_restripe_progress {
- __u64 expected;
- __u64 considered;
- __u64 completed;
-};
-
-struct btrfs_ioctl_restripe_args {
- __u64 flags;
- __u64 state;
-
- struct btrfs_restripe_args data;
- struct btrfs_restripe_args sys;
- struct btrfs_restripe_args meta;
-
- struct btrfs_restripe_progress stat;
-
- __u64 unused[72]; /* pad to 1k */
-};
-
struct btrfs_ioctl_search_key {
/* which root are we searching. 0 is the tree of tree roots */
__u64 tree_id;
@@ -311,15 +272,10 @@ struct btrfs_ioctl_logical_ino_args {
#define BTRFS_IOC_DEV_INFO _IOWR(BTRFS_IOCTL_MAGIC, 30, \
struct btrfs_ioctl_dev_info_args)
#define BTRFS_IOC_FS_INFO _IOR(BTRFS_IOCTL_MAGIC, 31, \
- struct btrfs_ioctl_fs_info_args)
+ struct btrfs_ioctl_fs_info_args)
#define BTRFS_IOC_INO_PATHS _IOWR(BTRFS_IOCTL_MAGIC, 35, \
struct btrfs_ioctl_ino_path_args)
#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
struct btrfs_ioctl_ino_path_args)
-#define BTRFS_IOC_RESTRIPE _IOW(BTRFS_IOCTL_MAGIC, 32, \
- struct btrfs_ioctl_restripe_args)
-#define BTRFS_IOC_RESTRIPE_CTL _IOW(BTRFS_IOCTL_MAGIC, 33, int)
-#define BTRFS_IOC_RESTRIPE_PROGRESS _IOR(BTRFS_IOCTL_MAGIC, 34, \
- struct btrfs_ioctl_restripe_args)
#endif
diff --git a/print-tree.c b/print-tree.c
index 49f98af..6039699 100644
--- a/print-tree.c
+++ b/print-tree.c
@@ -391,9 +391,6 @@ static void print_objectid(unsigned long long objectid, u8 type)
case BTRFS_CSUM_TREE_OBJECTID:
printf("CSUM_TREE");
break;
- case BTRFS_RESTRIPE_OBJECTID:
- printf("RESTRIPE");
- break;
case BTRFS_ORPHAN_OBJECTID:
printf("ORPHAN");
break;
diff --git a/volumes.h b/volumes.h
index 5845c1d..08c53e4 100644
--- a/volumes.h
+++ b/volumes.h
@@ -95,48 +95,6 @@ struct btrfs_multi_bio {
#define btrfs_multi_bio_size(n) (sizeof(struct btrfs_multi_bio) + \
(sizeof(struct btrfs_bio_stripe) * (n)))
-/*
- * Restriper's general "type" filter. Shares bits with chunk type for
- * simplicity, RESTRIPE prefix is used to avoid confusion.
- */
-#define BTRFS_RESTRIPE_DATA (1ULL << 0)
-#define BTRFS_RESTRIPE_SYSTEM (1ULL << 1)
-#define BTRFS_RESTRIPE_METADATA (1ULL << 2)
-
-#define BTRFS_RESTRIPE_TYPE_MASK (BTRFS_RESTRIPE_DATA | \
- BTRFS_RESTRIPE_SYSTEM | \
- BTRFS_RESTRIPE_METADATA)
-
-#define BTRFS_RESTRIPE_FORCE (1ULL << 3)
-
-/*
- * Restripe filters
- */
-#define BTRFS_RESTRIPE_ARGS_PROFILES (1ULL << 0)
-#define BTRFS_RESTRIPE_ARGS_USAGE (1ULL << 1)
-#define BTRFS_RESTRIPE_ARGS_DEVID (1ULL << 2)
-#define BTRFS_RESTRIPE_ARGS_DRANGE (1ULL << 3)
-#define BTRFS_RESTRIPE_ARGS_VRANGE (1ULL << 4)
-
-/*
- * Profile changing flags. When SOFT is set we won't relocate chunk if
- * it already has the target profile (even though it may be
- * half-filled).
- */
-#define BTRFS_RESTRIPE_ARGS_CONVERT (1ULL << 8)
-#define BTRFS_RESTRIPE_ARGS_SOFT (1ULL << 9)
-
-/*
- * Restripe state bits
- */
-#define RESTRIPE_RUNNING 0
-#define RESTRIPE_CANCEL_REQ 1
-#define RESTRIPE_PAUSE_REQ 2
-
-#define BTRFS_RESTRIPE_ST_RUNNING (1ULL << RESTRIPE_RUNNING)
-#define BTRFS_RESTRIPE_ST_CANCEL_REQ (1ULL << RESTRIPE_CANCEL_REQ)
-#define BTRFS_RESTRIPE_ST_PAUSE_REQ (1ULL << RESTRIPE_PAUSE_REQ)
-
int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
struct btrfs_device *device,
u64 chunk_tree, u64 chunk_objectid,
--
1.7.6.233.gd79bc

View File

@ -7,11 +7,11 @@ Date: Thu Dec 16 20:40:34 2010 +0100
The error path forgets to free a previously allocated
memory structure.
diff --git a/disk-io.c b/disk-io.c
index a6e1000..2b5e1d5 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -423,11 +423,13 @@ static int find_and_setup_log_root(struct btrfs_root *tree_root,
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);

View File

@ -1,4 +1,10 @@
#!/bin/bash
#%stage: filesystem
#!/bin/bash -e
#%stage: block
#%if: "$rootfstype" = "btrfs"
#%programs: /sbin/btrfs /sbin/btrfs-zero-log /sbin/btrfs-convert /sbin/btrfs-select-super /sbin/btrfs-image /sbin/btrfstune /sbin/btrfs-restore /sbin/btrfs-find-root /sbin/btrfsck /sbin/mkfs.btrfs
#%programs: /sbin/btrfs /sbin/btrfs-zero-log /sbin/btrfs-convert /sbin/btrfs-select-super /sbin/btrfs-image /sbin/btrfstune /sbin/btrfs-restore /sbin/btrfs-find-root /sbin/btrfsck /sbin/mkfs.btrfs /sbin/btrfs-dump-super
modprobe btrfs
if [ -x /sbin/btrfs ]; then
/sbin/btrfs dev scan >& /dev/null
fi

View File

@ -0,0 +1,248 @@
--- 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);

View File

@ -1,22 +0,0 @@
diff --git a/Makefile b/Makefile
index 96e2002..7a5e2c1 100644
--- a/Makefile
+++ b/Makefile
@@ -37,7 +37,7 @@ version:
bash version.sh
btrfs: $(objects) btrfs.o btrfs_cmds.o scrub.o
- $(CC) -lpthread $(CFLAGS) -o btrfs btrfs.o btrfs_cmds.o scrub.o \
+ $(CC) -pthread $(CFLAGS) -o btrfs btrfs.o btrfs_cmds.o scrub.o \
$(objects) $(LDFLAGS) $(LIBS)
calc-size: $(objects) calc-size.o
@@ -83,7 +83,7 @@ btrfs-corrupt-block: $(objects) btrfs-corrupt-block.o
$(CC) $(CFLAGS) -o btrfs-corrupt-block $(objects) btrfs-corrupt-block.o $(LDFLAGS) $(LIBS)
btrfs-image: $(objects) btrfs-image.o
- $(CC) $(CFLAGS) -o btrfs-image $(objects) btrfs-image.o -lpthread -lz $(LDFLAGS) $(LIBS)
+ $(CC) $(CFLAGS) -o btrfs-image $(objects) btrfs-image.o -pthread -lz $(LDFLAGS) $(LIBS)
dir-test: $(objects) dir-test.o
$(CC) $(CFLAGS) -o dir-test $(objects) dir-test.o $(LDFLAGS) $(LIBS)

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:00bf3761187270d3ba2da8d3eb17989ed4e64b12e024850a2f537ee9b84bdbfd
size 162346

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7c7d0bb613659bd63e4894bfb481a85cbadb695f7b9418c97921274ac8344021
size 162236

View File

@ -1,15 +0,0 @@
--- a/btrfsck.c.new 2011-10-04 02:05:51.891833030 +0200
+++ b/btrfsck.c 2011-10-04 02:07:51.999653799 +0200
@@ -2816,10 +2816,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);

View File

@ -1,4 +1,36 @@
-------------------------------------------------------------------
Mon Dec 12 15:44:48 CET 2011 - dkukawka@suse.de
- btrfs-progs-fix-open_ctree_usage_segfaults.patch: fix
segfaults from bnc#710486 due to unchecked usage of return
value of open_ctree()
[fixed compilation warnings]
-------------------------------------------------------------------
Mon Dec 12 14:50:07 CET 2011 - dsterba@suse.cz
- pull upstream, replace existing patches, spec update
- update 'restore' utility
- lzo support
- tools may now take earlies superblock when opening the fs
- other fixes
- pull integration-20111030 branch
- mkfs: force mkfs if desired
- other fixes
- add btrfs-dump-super to mkinitrd
- other fixes
- skip non-existent devices or without media
- documentation updates
- scrubbing single device
- graceful error handling when opening fs fails
-------------------------------------------------------------------
Fri Dec 9 00:43:08 CET 2011 - dsterba@suse.cz
- updated mkinitrd script to scan devices before mount (bnc#727383)
-------------------------------------------------------------------
Wed Nov 9 14:34:56 CET 2011 - dsterba@suse.cz
- add several tools to mkinitrd if root fs is btrfs

View File

@ -21,24 +21,69 @@ Name: btrfsprogs
Url: http://btrfs.wiki.kernel.org/index.php/Main_Page
Version: 0.19
Release: 50
%define tar_version v0.19-116-g13eced9
%define tar_version v0.19-118-gfdb6c04
Summary: Utilities for the Btrfs filesystem
License: GPL v2 only
Group: System/Filesystems
Supplements: filesystem(btrfs)
# git archive --format=tar --prefix=btrfs-progs-`git describe`/ HEAD > %D/btrfs-progs-`git describe`.tar
Source: btrfs-progs-%{tar_version}.tar.bz2
Source1: boot-btrfs.sh
Patch0: memleak-fix.diff
Patch1: 0001-Plug-Memory-leak-in-find_and_setup_log_root.patch
Patch1: Plug-Memory-leak-in-find_and_setup_log_root.patch
Patch1000: local-version-override.patch
Patch57: ignore-deleted-loopmounts.diff
Patch58: btrfsck-ignore-option-a.diff
Patch59: build-extra-progs.diff
Patch60: btrfs-progs-pass-correct-build-option-for-pthreads.patch
# patches above upstream master:
# + hugo's integration
Patch100: 0100-btrfs-progs-ignore-a-option-in-mkfs.patch
Patch102: 0102-Add-the-force-option.patch
Patch103: 0103-mkfs.btrfs-man-page-document-the-force-option.patch
Patch104: 0104-Ignore-the-error-ENXIO-and-ENOMEDIUM-during-a-devs-s.patch
Patch105: 0105-Regression-tests.patch
Patch106: 0106-Fix-sub-snap-parameter-handling.patch
Patch107: 0107-Add-info-for-the-commands.patch
Patch108: 0108-Add-the-header-footer-introduction-of-the-man-page.patch
Patch109: 0109-helpextract-tool-to-extract-the-info-for-the-help-fr.patch
Patch110: 0110-Update-the-makefile-for-generating-the-man-page.patch
Patch111: 0111-Show-the-help-messages-from-the-info-in-the-comment.patch
Patch112: 0112-Update-the-makefile-for-generating-the-help-messages.patch
Patch113: 0113-Btrfs-progs-add-restriper-commands.patch
Patch114: 0114-btrfs-progs-add-qgroup-commands.patch
Patch115: 0115-btrfs-progs-fixup-is_mounted-checks.patch
# + josef's restore utility fixes
Patch116: 0116-Btrfs-progs-add-an-option-for-specifying-the-root-to.patch
Patch117: 0117-Btrfs-progs-try-other-mirrors-if-decomression-fails.patch
Patch118: 0118-Btrfs-progs-try-other-mirrors-on-read-failure.patch
Patch119: 0119-btrfs-progs-Fix-error-handling-for-failed-reads-in-r.patch
Patch120: 0120-btrfs-progs-Check-metadata-mirrors-in-find-root.patch
Patch121: 0121-restore-Split-output-directory-and-btrfs-local-path-.patch
Patch122: 0122-restore-Add-regex-matching-of-paths-and-files-to-be-.patch
Patch123: 0123-btrfs-progs-In-find-root-dump-bytenr-for-every-slot.patch
Patch124: 0124-btrfs-progs-Add-utility-to-dump-all-superblocks-foun.patch
Patch125: 0125-btrfs-progs-Add-the-ability-to-use-the-earliest-supe.patch
Patch126: 0126-btrfs-progs-Use-oldest-super-for-btrfs-select-super..patch
Patch127: 0127-btrfs-progs-add-lzo-compression-support-to-restore.patch
Patch128: 0128-btrfs-progs-fix-regexec-to-only-work-if-we-actually-.patch
Patch129: 0129-btrfs-progs-Fix-compilation-errors-with-btrfs-select.patch
Patch130: 0130-Btrfs-progs-fix-restore-to-fall-back-to-the-broken-o.patch
Patch131: 0131-Btrfs-progs-don-t-bug-out-if-we-can-t-find-the-last-.patch
Patch132: 0132-Btrfs-progs-make-find_and_setup_root-return-an-error.patch
Patch133: 0133-Btrfs-progs-check-return-value-properly.patch
Patch134: 0134-Btrfs-progs-give-restore-a-list-roots-option.patch
Patch135: 0135-Btrfs-progs-fix-compiler-warning-of-extent-tree.c.patch
Patch136: 0136-Btrfs-progs-change-the-way-mkfs-picks-raid-profiles.patch
Patch137: 0137-Btrfs-progs-fail-gracefully-on-error-from-open_ctree.patch
Patch138: 0138-Btrfs-progs-bugfix-for-scrubbing-single-devices.patch
#
Patch150: btrfs-progs-fix-open_ctree_usage_segfaults.patch
# - missing kernel features: qgroups
Patch900: 0900-Revert-btrfs-progs-add-qgroup-commands.patch
Patch901: 0901-Revert-Btrfs-progs-add-restriper-commands.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-build
BuildRequires: libacl-devel libext2fs-devel libuuid-devel zlib-devel
BuildRequires: libacl-devel libext2fs-devel libuuid-devel lzo-devel zlib-devel
# for /bin/true
Requires: coreutils
@ -50,28 +95,72 @@ Utilities needed to create and maintain btrfs file systems under Linux.
%patch0
%patch1 -p1
%patch1000 -p1
%patch57 -p1
%patch58 -p1
%patch59 -p0
%patch60 -p1
%patch100 -p1
%patch102 -p1
%patch103 -p1
%patch104 -p1
%patch105 -p1
%patch106 -p1
%patch107 -p1
%patch108 -p1
%patch109 -p1
%patch110 -p1
%patch111 -p1
%patch112 -p1
%patch113 -p1
%patch114 -p1
%patch115 -p1
%patch116 -p1
%patch117 -p1
%patch118 -p1
%patch119 -p1
%patch120 -p1
%patch121 -p1
%patch122 -p1
%patch123 -p1
%patch124 -p1
%patch125 -p1
%patch126 -p1
%patch127 -p1
%patch128 -p1
%patch129 -p1
%patch130 -p1
%patch131 -p1
%patch132 -p1
%patch133 -p1
%patch134 -p1
%patch135 -p1
%patch136 -p1
%patch137 -p1
%patch138 -p1
%patch150 -p1
%patch900 -p1
%patch901 -p1
%build
make %{?_smp_mflags} CFLAGS="%{optflags}" all convert \
btrfs-zero-log btrfs-select-super btrfs-image btrfstune \
restore find-root
mv restore btrfs-restore
mv find-root btrfs-find-root
restore find-root btrfs-dump-super
%install
make install DESTDIR=${RPM_BUILD_ROOT} prefix=%{_prefix} bindir=/sbin mandir=%{_mandir}
install -m 0755 -d ${RPM_BUILD_ROOT}/sbin
install -m 0755 -d ${RPM_BUILD_ROOT}/%{_bindir}
# remove dangerous and unwanted tools
rm ${RPM_BUILD_ROOT}/sbin/btrfs-corrupt-block
rm ${RPM_BUILD_ROOT}/sbin/calc-size
# add btrfs- prefix to generic names
mv ${RPM_BUILD_ROOT}/sbin/restore ${RPM_BUILD_ROOT}/sbin/btrfs-restore
mv ${RPM_BUILD_ROOT}/sbin/find-root ${RPM_BUILD_ROOT}/sbin/btrfs-find-root
# move some utilities out of /sbin
mv ${RPM_BUILD_ROOT}/sbin/{btrfs-show,btrfs-vol,btrfsctl} ${RPM_BUILD_ROOT}/%{_bindir}
mv ${RPM_BUILD_ROOT}/sbin/{btrfs-map-logical,btrfs-debug-tree} ${RPM_BUILD_ROOT}/%{_bindir}
# mkinitrd rescue utilities
install -m 0755 btrfs-zero-log btrfs-select-super btrfs-image btrfstune ${RPM_BUILD_ROOT}/sbin
install -m 0755 btrfs-restore btrfs-find-root ${RPM_BUILD_ROOT}/sbin
install -m 0755 btrfs-zero-log ${RPM_BUILD_ROOT}/sbin
install -m 0755 btrfs-select-super ${RPM_BUILD_ROOT}/sbin
install -m 0755 btrfs-image ${RPM_BUILD_ROOT}/sbin
install -m 0755 btrfstune ${RPM_BUILD_ROOT}/sbin
install -m 0755 btrfs-dump-super ${RPM_BUILD_ROOT}/sbin
# command line options are not compatible (bnc#599224)
# copy needed if /bin is different fs from /sbin
cp /bin/true ${RPM_BUILD_ROOT}/sbin/fsck.btrfs
@ -91,6 +180,7 @@ cp %{S:1} ${RPM_BUILD_ROOT}/lib/mkinitrd/scripts/
/sbin/btrfsck
/sbin/btrfs-restore
/sbin/btrfs-find-root
/sbin/btrfs-dump-super
/sbin/mkfs.btrfs
/lib/mkinitrd/scripts/boot-btrfs.sh
# other

View File

@ -1,12 +0,0 @@
--- Makefile.orig 2011-11-08 19:03:26.188610871 +0100
+++ Makefile 2011-11-08 19:03:52.699995062 +0100
@@ -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
+progsextra = restore find-root calc-size btrfs-corrupt-block
# make C=1 to enable sparse
ifdef C

View File

@ -1,77 +0,0 @@
Index: btrfs-progs-v0.19-116-g13eced9/utils.c
===================================================================
--- btrfs-progs-v0.19-116-g13eced9.orig/utils.c
+++ btrfs-progs-v0.19-116-g13eced9/utils.c
@@ -674,21 +674,29 @@ int is_same_blk_file(const char* a, cons
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)
return 1;
- if(stat(a, &st_buf_a) < 0 ||
- stat(b, &st_buf_b) < 0)
- {
- if (errno == ENOENT)
- return 0;
+ if(stat(a, &st_buf_a) < 0)
+ {
+ if (errno == ENOENT)
+ return 0;
+
+ return -errno;
+ }
+
+ if(stat(b, &st_buf_b) < 0)
+ {
+ if (errno == ENOENT)
+ return 0;
+
return -errno;
}
@@ -729,10 +737,12 @@ int is_same_loop_file(const char* a, con
return 0;
return ret;
} else if (ret) {
- if ((ret = resolve_loop_device(a, res_a, sizeof(res_a))) < 0)
+ if((ret = resolve_loop_device(a, res_a, sizeof(res_a))) < 0) {
+ if (errno != EPERM)
return ret;
-
- final_a = res_a;
+ } else {
+ final_a = res_a;
+ }
} else {
final_a = a;
}
@@ -743,10 +753,12 @@ int is_same_loop_file(const char* a, con
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;
}