diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-06-25 16:01:31 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:04 -0400 |
commit | 1b1e2135dc1e4efbcf25ac9ac9979316d4e1193e (patch) | |
tree | 2af53ed5d4c368bbefd9de94f0adc2902a785468 | |
parent | 079899c2384023cd8efcd3806680b4f1d2abbd54 (diff) |
Btrfs: Add a per-inode csum mutex to avoid races creating csum items
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/btrfs_inode.h | 1 | ||||
-rw-r--r-- | fs/btrfs/file.c | 6 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 6 | ||||
-rw-r--r-- | fs/btrfs/ordered-data.c | 5 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 2 | ||||
-rw-r--r-- | fs/btrfs/tree-defrag.c | 7 |
6 files changed, 21 insertions, 6 deletions
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index 5ba83894c8b7..40b4e0c9cd09 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h | |||
@@ -30,6 +30,7 @@ struct btrfs_inode { | |||
30 | struct extent_map_tree extent_tree; | 30 | struct extent_map_tree extent_tree; |
31 | struct extent_io_tree io_tree; | 31 | struct extent_io_tree io_tree; |
32 | struct extent_io_tree io_failure_tree; | 32 | struct extent_io_tree io_failure_tree; |
33 | struct mutex csum_mutex; | ||
33 | struct inode vfs_inode; | 34 | struct inode vfs_inode; |
34 | atomic_t ordered_writeback; | 35 | atomic_t ordered_writeback; |
35 | 36 | ||
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index ece221cba90c..8037792f8789 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -267,13 +267,13 @@ static int noinline dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
267 | 267 | ||
268 | /* FIXME...EIEIO, ENOSPC and more */ | 268 | /* FIXME...EIEIO, ENOSPC and more */ |
269 | /* insert any holes we need to create */ | 269 | /* insert any holes we need to create */ |
270 | if (isize < end_pos) { | 270 | if (isize < start_pos) { |
271 | u64 last_pos_in_file; | 271 | u64 last_pos_in_file; |
272 | u64 hole_size; | 272 | u64 hole_size; |
273 | u64 mask = root->sectorsize - 1; | 273 | u64 mask = root->sectorsize - 1; |
274 | last_pos_in_file = (isize + mask) & ~mask; | 274 | last_pos_in_file = (isize + mask) & ~mask; |
275 | hole_size = (end_pos - last_pos_in_file + mask) & ~mask; | 275 | hole_size = (start_pos - last_pos_in_file + mask) & ~mask; |
276 | if (last_pos_in_file < end_pos) { | 276 | if (last_pos_in_file < start_pos) { |
277 | err = btrfs_drop_extents(trans, root, inode, | 277 | err = btrfs_drop_extents(trans, root, inode, |
278 | last_pos_in_file, | 278 | last_pos_in_file, |
279 | last_pos_in_file + hole_size, | 279 | last_pos_in_file + hole_size, |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index bbba3350d023..d39433dfb2c7 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -351,7 +351,9 @@ int __btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
351 | trans = btrfs_start_transaction(root, 1); | 351 | trans = btrfs_start_transaction(root, 1); |
352 | 352 | ||
353 | btrfs_set_trans_block_group(trans, inode); | 353 | btrfs_set_trans_block_group(trans, inode); |
354 | mutex_lock(&BTRFS_I(inode)->csum_mutex); | ||
354 | btrfs_csum_file_blocks(trans, root, inode, bio, sums); | 355 | btrfs_csum_file_blocks(trans, root, inode, bio, sums); |
356 | mutex_unlock(&BTRFS_I(inode)->csum_mutex); | ||
355 | 357 | ||
356 | ret = btrfs_end_transaction(trans, root); | 358 | ret = btrfs_end_transaction(trans, root); |
357 | BUG_ON(ret); | 359 | BUG_ON(ret); |
@@ -1400,6 +1402,7 @@ static int btrfs_init_locked_inode(struct inode *inode, void *p) | |||
1400 | inode->i_mapping, GFP_NOFS); | 1402 | inode->i_mapping, GFP_NOFS); |
1401 | extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree, | 1403 | extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree, |
1402 | inode->i_mapping, GFP_NOFS); | 1404 | inode->i_mapping, GFP_NOFS); |
1405 | mutex_init(&BTRFS_I(inode)->csum_mutex); | ||
1403 | atomic_set(&BTRFS_I(inode)->ordered_writeback, 0); | 1406 | atomic_set(&BTRFS_I(inode)->ordered_writeback, 0); |
1404 | return 0; | 1407 | return 0; |
1405 | } | 1408 | } |
@@ -1701,6 +1704,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
1701 | inode->i_mapping, GFP_NOFS); | 1704 | inode->i_mapping, GFP_NOFS); |
1702 | extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree, | 1705 | extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree, |
1703 | inode->i_mapping, GFP_NOFS); | 1706 | inode->i_mapping, GFP_NOFS); |
1707 | mutex_init(&BTRFS_I(inode)->csum_mutex); | ||
1704 | atomic_set(&BTRFS_I(inode)->ordered_writeback, 0); | 1708 | atomic_set(&BTRFS_I(inode)->ordered_writeback, 0); |
1705 | BTRFS_I(inode)->delalloc_bytes = 0; | 1709 | BTRFS_I(inode)->delalloc_bytes = 0; |
1706 | BTRFS_I(inode)->root = root; | 1710 | BTRFS_I(inode)->root = root; |
@@ -1924,6 +1928,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
1924 | inode->i_mapping, GFP_NOFS); | 1928 | inode->i_mapping, GFP_NOFS); |
1925 | extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree, | 1929 | extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree, |
1926 | inode->i_mapping, GFP_NOFS); | 1930 | inode->i_mapping, GFP_NOFS); |
1931 | mutex_init(&BTRFS_I(inode)->csum_mutex); | ||
1927 | BTRFS_I(inode)->delalloc_bytes = 0; | 1932 | BTRFS_I(inode)->delalloc_bytes = 0; |
1928 | atomic_set(&BTRFS_I(inode)->ordered_writeback, 0); | 1933 | atomic_set(&BTRFS_I(inode)->ordered_writeback, 0); |
1929 | BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; | 1934 | BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; |
@@ -2862,6 +2867,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
2862 | inode->i_mapping, GFP_NOFS); | 2867 | inode->i_mapping, GFP_NOFS); |
2863 | extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree, | 2868 | extent_io_tree_init(&BTRFS_I(inode)->io_failure_tree, |
2864 | inode->i_mapping, GFP_NOFS); | 2869 | inode->i_mapping, GFP_NOFS); |
2870 | mutex_init(&BTRFS_I(inode)->csum_mutex); | ||
2865 | BTRFS_I(inode)->delalloc_bytes = 0; | 2871 | BTRFS_I(inode)->delalloc_bytes = 0; |
2866 | atomic_set(&BTRFS_I(inode)->ordered_writeback, 0); | 2872 | atomic_set(&BTRFS_I(inode)->ordered_writeback, 0); |
2867 | BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; | 2873 | BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; |
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 5e4c0d95ce43..254da8225664 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -152,12 +152,13 @@ int btrfs_add_ordered_inode(struct inode *inode) | |||
152 | inode->i_ino, &entry->rb_node); | 152 | inode->i_ino, &entry->rb_node); |
153 | 153 | ||
154 | BTRFS_I(inode)->ordered_trans = transid; | 154 | BTRFS_I(inode)->ordered_trans = transid; |
155 | if (!node) | ||
156 | igrab(inode); | ||
155 | 157 | ||
156 | write_unlock(&tree->lock); | 158 | write_unlock(&tree->lock); |
159 | |||
157 | if (node) | 160 | if (node) |
158 | kfree(entry); | 161 | kfree(entry); |
159 | else | ||
160 | igrab(inode); | ||
161 | return 0; | 162 | return 0; |
162 | } | 163 | } |
163 | 164 | ||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 0c53ff775b92..8e909cb97c6d 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -477,7 +477,7 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root, | |||
477 | if (err) | 477 | if (err) |
478 | ret = err; | 478 | ret = err; |
479 | nr = trans->blocks_used; | 479 | nr = trans->blocks_used; |
480 | ret = btrfs_end_transaction(trans, tree_root); | 480 | ret = btrfs_end_transaction_throttle(trans, tree_root); |
481 | BUG_ON(ret); | 481 | BUG_ON(ret); |
482 | 482 | ||
483 | mutex_unlock(&root->fs_info->drop_mutex); | 483 | mutex_unlock(&root->fs_info->drop_mutex); |
diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c index 1677e4edaf6f..b17693f61fbc 100644 --- a/fs/btrfs/tree-defrag.c +++ b/fs/btrfs/tree-defrag.c | |||
@@ -38,8 +38,15 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | |||
38 | u64 last_ret = 0; | 38 | u64 last_ret = 0; |
39 | 39 | ||
40 | if (root->fs_info->extent_root == root) { | 40 | if (root->fs_info->extent_root == root) { |
41 | /* | ||
42 | * there's recursion here right now in the tree locking, | ||
43 | * we can't defrag the extent root without deadlock | ||
44 | */ | ||
45 | goto out; | ||
46 | #if 0 | ||
41 | mutex_lock(&root->fs_info->alloc_mutex); | 47 | mutex_lock(&root->fs_info->alloc_mutex); |
42 | is_extent = 1; | 48 | is_extent = 1; |
49 | #endif | ||
43 | } | 50 | } |
44 | 51 | ||
45 | if (root->ref_cows == 0 && !is_extent) | 52 | if (root->ref_cows == 0 && !is_extent) |