From: Filipe David Borba Manana <fdmanana@gmail.com>
To: linux-btrfs@vger.kernel.org
Cc: Filipe David Borba Manana <fdmanana@gmail.com>
Subject: [PATCH v5] Btrfs-progs: fix restore command leaving corrupted files
Date: Thu, 11 Jul 2013 16:33:40 +0100 [thread overview]
Message-ID: <1373556820-30293-1-git-send-email-fdmanana@gmail.com> (raw)
In-Reply-To: <1373475413-23563-1-git-send-email-fdmanana@gmail.com>
When there are files that have parts shared with snapshots, the
restore command was incorrectly restoring them, as it was not
taking into account the offset and number of bytes fields from
the file extent item. Besides leaving the recovered file corrupt,
it was also inneficient as it read and wrote more data than needed
(with each extent copy overwriting portions of the one previously
written).
The following steps show how to reproduce this corruption issue:
$ mkfs.btrfs -f /dev/sdb3
$ mount /dev/sdb3 /mnt/btrfs
$ perl -e '$d = "\x41" . ("\x00" x (1024*1024+349)); open($f,">","/mnt/btrfs/foobar"); print $f $d; close($f);'
$ du -b /mnt/btrfs/foobar
1048926 /mnt/btrfs/foobar
$ md5sum /mnt/btrfs/foobar
f9f778f3a7410c40e4ed104a3a63c3c4 /mnt/btrfs/foobar
$ btrfs subvolume snapshot /mnt/btrfs /mnt/btrfs/my_snap
$ perl -e 'open($f, "+<", "/dev/btrfs/foobar"); seek($f, 4096, 0); print $f "\xff"; close($f);'
$ md5sum /mnt/btrfs/foobar
b983fcefd4622a03a78936484c40272b /mnt/btrfs/foobar
$ umount /mnt/btrfs
$ btrfs restore /dev/sdb3 /tmp/copy
$ du -b /tmp/copy/foobar
1048926 /tmp/copy/foobar
$ md5sum /tmp/copy/foobar
88db338cbc1c44dfabae083f1ce642d5 /tmp/copy/foobar
$ od -t x1 -j 8192 -N 4 /tmp/copy/foobar
0020000 41 00 00 00
0020004
$ mount /dev/sdb3 /mnt/btrfs
$ od -t x1 -j 8192 -N 4 /mnt/btrfs/foobar
0020000 00 00 00 00
0020004
$ md5sum /mnt/btrfs/foobar
b983fcefd4622a03a78936484c40272b /mnt/btrfs/foobar
Tested this change with zlib, lzo compression and file sizes larger
than 1GiB, and found no regression or other corruption issues (so far
at least).
Signed-off-by: Filipe David Borba Manana <fdmanana@gmail.com>
---
V2: updated commit message to include the C preprocessor macros
in the C program.
V3: updated commit message again to reflect the file size used in
the example in the C program macro.
V4: fixed wrong path in commit message in the perl command line.
V5: updated commit message with simpler steps to reproduce the issue.
cmds-restore.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/cmds-restore.c b/cmds-restore.c
index e48df40..9688599 100644
--- a/cmds-restore.c
+++ b/cmds-restore.c
@@ -272,6 +272,7 @@ static int copy_one_extent(struct btrfs_root *root, int fd,
u64 bytenr;
u64 ram_size;
u64 disk_size;
+ u64 num_bytes;
u64 length;
u64 size_left;
u64 dev_bytenr;
@@ -288,7 +289,9 @@ static int copy_one_extent(struct btrfs_root *root, int fd,
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;
+ num_bytes = btrfs_file_extent_num_bytes(leaf, fi);
+ size_left = num_bytes;
+ bytenr += offset;
if (offset)
printf("offset is %Lu\n", offset);
@@ -296,7 +299,7 @@ static int copy_one_extent(struct btrfs_root *root, int fd,
if (disk_size == 0)
return 0;
- inbuf = malloc(disk_size);
+ inbuf = malloc(size_left);
if (!inbuf) {
fprintf(stderr, "No memory\n");
return -1;
@@ -351,8 +354,8 @@ again:
goto again;
if (compress == BTRFS_COMPRESS_NONE) {
- while (total < ram_size) {
- done = pwrite(fd, inbuf+total, ram_size-total,
+ while (total < num_bytes) {
+ done = pwrite(fd, inbuf+total, num_bytes-total,
pos+total);
if (done < 0) {
ret = -1;
@@ -365,7 +368,7 @@ again:
goto out;
}
- ret = decompress(inbuf, outbuf, disk_size, &ram_size, compress);
+ ret = decompress(inbuf, outbuf, num_bytes, &ram_size, compress);
if (ret) {
num_copies = btrfs_num_copies(&root->fs_info->mapping_tree,
bytenr, length);
--
1.7.9.5
next prev parent reply other threads:[~2013-07-11 15:33 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-10 15:43 [PATCH] Btrfs-progs: fix restore command leaving corrupted files Filipe David Borba Manana
2013-07-10 16:11 ` [PATCH v2] " Filipe David Borba Manana
2013-07-10 16:17 ` [PATCH v3] " Filipe David Borba Manana
2013-07-10 16:56 ` [PATCH v4] " Filipe David Borba Manana
2013-07-11 15:33 ` Filipe David Borba Manana [this message]
2013-07-12 14:01 ` [PATCH v6] " Filipe David Borba Manana
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1373556820-30293-1-git-send-email-fdmanana@gmail.com \
--to=fdmanana@gmail.com \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).