You are not logged in.
This story is from ~5-6 years ago. I gave my backup drive to my girlfriend with Windows. I installed some btrfs compat layer so she could actually use it. Yeah, bad idea. The drive was corrupted... I remember I frantically tried to recover the disk as quickly as possible, throwing all kind of btrfs commands at it, without actually understanding what they do... I imagine I might have broken it even more...
So back to today, she's my wife now. And I still kind of want to recover that disk... Suffice to say I don't remember what I did back then.
I took an image of the disk, and tried my hand again, but yeah I don't get that far with the actual tools...
So I tried:
$ fsck.btrfs /mnt/seagate/corrupted-hardrive-copy/partition1
If you wish to check the consistency of a BTRFS filesystem or repair a damaged filesystem, see btrfs(8) subcommand 'check'.
$ btrfs check /mnt/seagate/corrupted-hardrive-copy/partition1
Opening filesystem to check...
No valid Btrfs found on /mnt/seagate/corrupted-hardrive-copy/partition1
ERROR: cannot open file system
$ btrfs check -s 2 --force --read only /mnt/seagate/corrupted-hardrive-copy/partition1
using SB copy 2, bytenr 274877906944
Opening filesystem to check...
No valid Btrfs found on /mnt/seagate/corrupted-hardrive-copy/partition1
ERROR: cannot open file systemSo for some reason that immediately blocks. I knew from my previous attempt from years before that using binwalk I got some files out of it. But by now, I kind of forgot what files are even on this disk so I tried to enumerate the filenames on it with this project, to evaluate if it's even still worth it: https://github.com/danobi/btrfs-walk.git
(Apply my patch for getting rid of the unaligned dereference errors in current rust:
diff --git a/src/main.rs b/src/main.rs
index a47b1d0..7fc634c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -13,7 +13,7 @@ use chunk_tree::{ChunkTreeCache, ChunkTreeKey, ChunkTreeValue};
mod tree;
/// Physical address of the first superblock
-const BTRFS_SUPERBLOCK_OFFSET: u64 = 0x10_000;
+const BTRFS_SUPERBLOCK_OFFSET: u64 = 274877906944; //0x10_000;
const BTRFS_SUPERBLOCK_MAGIC: [u8; 8] = *b"_BHRfS_M";
#[derive(Debug, StructOpt)]
@@ -169,12 +169,12 @@ fn read_chunk_tree(
superblock: &BtrfsSuperblock,
) -> Result<()> {
let header = tree::parse_btrfs_header(root).expect("failed to parse chunk root header");
- unsafe {
- println!(
- "chunk tree node level={}, bytenr={}, nritems={}",
- header.level, header.bytenr, header.nritems
- );
- }
+ println!(
+ "chunk tree node level={}, bytenr={}, nritems={}",
+ header.level,
+ { let a = header.bytenr; a },
+ { let a = header.nritems; a }
+ );
// Level 0 is leaf node, !0 is internal node
if header.level == 0 {
@@ -226,19 +226,22 @@ fn read_fs_tree_root(
) -> Result<Vec<u8>> {
let header =
tree::parse_btrfs_header(root_tree_root).expect("failed to parse root tree root header");
- unsafe {
- println!(
- "root tree root level={}, bytenr={}, nritems={}",
- header.level, header.bytenr, header.nritems
- );
- }
+ println!(
+ "root tree root level={}, bytenr={}, nritems={}",
+ header.level,
+ { let a = header.bytenr; a },
+ { let a = header.nritems; a }
+ );
+
if header.level != 0 {
bail!("Root tree root is not a leaf node");
}
let items = tree::parse_btrfs_leaf(root_tree_root)?;
+ dbg!(items.len());
for item in items.iter().rev() {
+ dbg!(item.key.objectid);
if item.key.objectid != BTRFS_FS_TREE_OBJECTID || item.key.ty != BTRFS_ROOT_ITEM_KEY {
continue;
}
@@ -256,12 +259,11 @@ fn read_fs_tree_root(
let mut node = vec![0; superblock.node_size as usize];
file.read_exact_at(&mut node, physical)?;
- unsafe {
- println!(
- "fs tree root at logical offset={}, physical offset={}, size={}",
- root_item.bytenr, physical, superblock.node_size,
- );
- }
+ println!(
+ "fs tree root at logical offset={}, physical offset={}, size={}",
+ { let a = root_item.bytenr; a },
+ physical,
+ { let a = superblock.node_size; a });
return Ok(node);
}
@@ -334,12 +336,12 @@ fn walk_fs_tree(
cache: &ChunkTreeCache,
) -> Result<()> {
let header = tree::parse_btrfs_header(node)?;
- unsafe {
- println!(
- "fs tree node level={}, bytenr={}, nritems={}",
- header.level, header.bytenr, header.nritems
- );
- }
+ println!(
+ "fs tree node level={}, bytenr={}, nritems={}",
+ header.level,
+ { let a = header.bytenr; a },
+ { let a = header.nritems; a }
+ );
// Leaf node
if header.level == 0 {
@@ -381,7 +383,9 @@ fn walk_fs_tree(
.ok_or_else(|| {
anyhow!("Failed to find inode_ref for inode={}", current_inode_nr)
})?;
- unsafe { assert_eq!(current_key.objectid, current_inode_nr) };
+ assert_eq!(
+ { let a = current_key.objectid; a },
+ current_inode_nr);
// `current_key.offset` is parent inode # of `current_inode`
if current_key.offset == current_inode_nr {)
It panics with the default superblock, but with superblock 2 it actually does seem to find stuff. The magic is there etc, etc. It prints:
warning: 2 stripes detected but only processing 1
chunk tree root at logical offset=22052864, physical offset=22052864, size=8388608
chunk tree node level=1, bytenr=22052864, nritems=5
chunk tree node level=0, bytenr=22069248, nritems=154
chunk tree node level=0, bytenr=22134784, nritems=155
chunk tree node level=0, bytenr=22151168, nritems=155
chunk tree node level=0, bytenr=22167552, nritems=154
chunk tree node level=0, bytenr=22085632, nritems=80
root tree root at logical offset=47972352, physical offset=56360960, size=1073741824
root tree root level=0, bytenr=262144, nritems=1
[src/main.rs:242:5] items.len() = 1
[src/main.rs:244:9] item.key.objectid = 0
thread 'main' panicked at src/main.rs:452:10:
failed to read fs tree root: Failed to find root tree item for fs tree root
note: run with `RUST_BACKTRACE=1` environment variable to display a backtraceStill an error, but it gets to parse a lot of stuff. So to me, it seems there's still a lot there, and I'm just not issueing the right btrfs commands?
Any input on what to try would be appreciated!
Offline
The #btrfs irc channel on libera is very active. Can you ask there?
Offline