aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-12-16 13:51:01 -0500
committerChris Mason <chris.mason@oracle.com>2008-12-16 13:51:01 -0500
commitdcbdd4dcb9793b00b46ab023e9330922c8c7c54c (patch)
treeca599e975c92de75c98283756f80b2aa7a1879bb
parent75eff68ea6959efd999b125fc3dcf73931a3b30b (diff)
Btrfs: delete checksum items before marking blocks free
Btrfs maintains a cache of blocks available for allocation in ram. The code that frees extents was marking the extents free and then deleting the checksum items. This meant it was possible the extent would be reallocated before the checksum item was actually deleted, leading to races and other problems as the checksums were updated for the newly allocated extent. The fix is to delete the checksum before marking the extent free. Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/extent-tree.c6
-rw-r--r--fs/btrfs/file-item.c4
2 files changed, 7 insertions, 3 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index fbd6a8f28b52..9ef2a2be2686 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2477,15 +2477,15 @@ static int __free_extent(struct btrfs_trans_handle *trans,
2477 num_to_del); 2477 num_to_del);
2478 BUG_ON(ret); 2478 BUG_ON(ret);
2479 btrfs_release_path(extent_root, path); 2479 btrfs_release_path(extent_root, path);
2480 ret = update_block_group(trans, root, bytenr, num_bytes, 0,
2481 mark_free);
2482 BUG_ON(ret);
2483 2480
2484 if (owner_objectid >= BTRFS_FIRST_FREE_OBJECTID) { 2481 if (owner_objectid >= BTRFS_FIRST_FREE_OBJECTID) {
2485 ret = btrfs_del_csums(trans, root, bytenr, num_bytes); 2482 ret = btrfs_del_csums(trans, root, bytenr, num_bytes);
2486 BUG_ON(ret); 2483 BUG_ON(ret);
2487 } 2484 }
2488 2485
2486 ret = update_block_group(trans, root, bytenr, num_bytes, 0,
2487 mark_free);
2488 BUG_ON(ret);
2489#ifdef BIO_RW_DISCARD 2489#ifdef BIO_RW_DISCARD
2490 /* Tell the block device(s) that the sectors can be discarded */ 2490 /* Tell the block device(s) that the sectors can be discarded */
2491 ret = btrfs_map_block(&root->fs_info->mapping_tree, READ, 2491 ret = btrfs_map_block(&root->fs_info->mapping_tree, READ,
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index df0447632dbd..7acadf3b742a 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -537,6 +537,8 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans,
537 if (key.offset >= bytenr && csum_end <= end_byte) { 537 if (key.offset >= bytenr && csum_end <= end_byte) {
538 ret = btrfs_del_item(trans, root, path); 538 ret = btrfs_del_item(trans, root, path);
539 BUG_ON(ret); 539 BUG_ON(ret);
540 if (key.offset == bytenr)
541 break;
540 } else if (key.offset < bytenr && csum_end > end_byte) { 542 } else if (key.offset < bytenr && csum_end > end_byte) {
541 unsigned long offset; 543 unsigned long offset;
542 unsigned long shift_len; 544 unsigned long shift_len;
@@ -583,6 +585,8 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans,
583 ret = truncate_one_csum(trans, root, path, 585 ret = truncate_one_csum(trans, root, path,
584 &key, bytenr, len); 586 &key, bytenr, len);
585 BUG_ON(ret); 587 BUG_ON(ret);
588 if (key.offset < bytenr)
589 break;
586 } 590 }
587 btrfs_release_path(root, path); 591 btrfs_release_path(root, path);
588 } 592 }