aboutsummaryrefslogtreecommitdiffstats
path: root/disk-io.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2013-05-14 14:44:22 -0400
committerChris Mason <chris.mason@fusionio.com>2013-06-19 13:52:16 -0400
commit11be10f71e1af5256f221feb9e91300b3e28bbef (patch)
treebda0d77fbae18150aa1d866e008bc71a5b36b9fd /disk-io.c
parentbd338824de665c0ccef576ccd119cfc7dace829c (diff)
downloadbtrfs-progs-11be10f71e1af5256f221feb9e91300b3e28bbef.tar.gz
btrfs-progs-11be10f71e1af5256f221feb9e91300b3e28bbef.tar.xz
btrfs-progs-11be10f71e1af5256f221feb9e91300b3e28bbef.zip
Btrfs-progs: make fsck fix certain file extent inconsistencies
The tree log bug I introduced could create inconsistent file extent entries in the file system tree and in some worst cases even create multiple extent entries for the same entry. To fix this we need to do a few things 1) Keep track of extent items that overlap and then pick the one that covers the largest area and delete the rest of the items. 2) Keep track of file extent items that land in extent items but don't match disk_bytenr/disk_num_bytes exactly. Once we find these we need to figure out who is the right ref and then fix all of the other refs to agree. Each of these cases require a complete rescan of all of the extents, so unfortunately if you hit this particular problem the fsck is going to take quite a while since it will likely rescan all the trees 2 or 3 times. With this patch the broken file system a user sent me is fixed and a broken file system that was created by my reproducer is also fixed. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com> Signed-off-by: Chris Mason <chris.mason@fusionio.com>
Diffstat (limited to 'disk-io.c')
-rw-r--r--disk-io.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/disk-io.c b/disk-io.c
index 21b410d..9ffe6e4 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -538,7 +538,10 @@ static int commit_tree_roots(struct btrfs_trans_handle *trans,
list_del_init(next);
root = list_entry(next, struct btrfs_root, dirty_list);
update_cowonly_root(trans, root);
+ free_extent_buffer(root->commit_root);
+ root->commit_root = NULL;
}
+
return 0;
}