diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-07-18 20:42:20 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:05 -0400 |
commit | e5a2217ef6ff088d08a27208929a6f9c635d672c (patch) | |
tree | 47dfed451e11357a5e066180eebba8db942af2b3 /fs/btrfs/inode.c | |
parent | 7f3c74fb831fa19bafe087e817c0a5ff3883f1ea (diff) |
Fix btrfs_wait_ordered_extent_range to properly wait
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 08dbe738b512..50ee4befac8e 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -128,7 +128,9 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end) | |||
128 | goto out; | 128 | goto out; |
129 | 129 | ||
130 | BUG_ON(num_bytes > btrfs_super_total_bytes(&root->fs_info->super_copy)); | 130 | BUG_ON(num_bytes > btrfs_super_total_bytes(&root->fs_info->super_copy)); |
131 | mutex_lock(&BTRFS_I(inode)->extent_mutex); | ||
131 | btrfs_drop_extent_cache(inode, start, start + num_bytes - 1); | 132 | btrfs_drop_extent_cache(inode, start, start + num_bytes - 1); |
133 | mutex_unlock(&BTRFS_I(inode)->extent_mutex); | ||
132 | 134 | ||
133 | while(num_bytes > 0) { | 135 | while(num_bytes > 0) { |
134 | cur_alloc_size = min(num_bytes, root->fs_info->max_extent); | 136 | cur_alloc_size = min(num_bytes, root->fs_info->max_extent); |
@@ -144,6 +146,7 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end) | |||
144 | em->len = ins.offset; | 146 | em->len = ins.offset; |
145 | em->block_start = ins.objectid; | 147 | em->block_start = ins.objectid; |
146 | em->bdev = root->fs_info->fs_devices->latest_bdev; | 148 | em->bdev = root->fs_info->fs_devices->latest_bdev; |
149 | mutex_lock(&BTRFS_I(inode)->extent_mutex); | ||
147 | set_bit(EXTENT_FLAG_PINNED, &em->flags); | 150 | set_bit(EXTENT_FLAG_PINNED, &em->flags); |
148 | while(1) { | 151 | while(1) { |
149 | spin_lock(&em_tree->lock); | 152 | spin_lock(&em_tree->lock); |
@@ -156,6 +159,7 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end) | |||
156 | btrfs_drop_extent_cache(inode, start, | 159 | btrfs_drop_extent_cache(inode, start, |
157 | start + ins.offset - 1); | 160 | start + ins.offset - 1); |
158 | } | 161 | } |
162 | mutex_unlock(&BTRFS_I(inode)->extent_mutex); | ||
159 | 163 | ||
160 | cur_alloc_size = ins.offset; | 164 | cur_alloc_size = ins.offset; |
161 | ret = btrfs_add_ordered_extent(inode, start, ins.objectid, | 165 | ret = btrfs_add_ordered_extent(inode, start, ins.objectid, |
@@ -487,6 +491,8 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
487 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | 491 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; |
488 | struct extent_map *em; | 492 | struct extent_map *em; |
489 | u64 alloc_hint = 0; | 493 | u64 alloc_hint = 0; |
494 | u64 clear_start; | ||
495 | u64 clear_end; | ||
490 | struct list_head list; | 496 | struct list_head list; |
491 | struct btrfs_key ins; | 497 | struct btrfs_key ins; |
492 | int ret; | 498 | int ret; |
@@ -509,12 +515,14 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
509 | ins.objectid = ordered_extent->start; | 515 | ins.objectid = ordered_extent->start; |
510 | ins.offset = ordered_extent->len; | 516 | ins.offset = ordered_extent->len; |
511 | ins.type = BTRFS_EXTENT_ITEM_KEY; | 517 | ins.type = BTRFS_EXTENT_ITEM_KEY; |
518 | |||
512 | ret = btrfs_alloc_reserved_extent(trans, root, root->root_key.objectid, | 519 | ret = btrfs_alloc_reserved_extent(trans, root, root->root_key.objectid, |
513 | trans->transid, inode->i_ino, | 520 | trans->transid, inode->i_ino, |
514 | ordered_extent->file_offset, &ins); | 521 | ordered_extent->file_offset, &ins); |
515 | BUG_ON(ret); | 522 | BUG_ON(ret); |
516 | 523 | ||
517 | mutex_lock(&BTRFS_I(inode)->extent_mutex); | 524 | mutex_lock(&BTRFS_I(inode)->extent_mutex); |
525 | |||
518 | ret = btrfs_drop_extents(trans, root, inode, | 526 | ret = btrfs_drop_extents(trans, root, inode, |
519 | ordered_extent->file_offset, | 527 | ordered_extent->file_offset, |
520 | ordered_extent->file_offset + | 528 | ordered_extent->file_offset + |
@@ -528,13 +536,19 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
528 | ordered_extent->len, 0); | 536 | ordered_extent->len, 0); |
529 | BUG_ON(ret); | 537 | BUG_ON(ret); |
530 | 538 | ||
531 | |||
532 | spin_lock(&em_tree->lock); | 539 | spin_lock(&em_tree->lock); |
533 | em = lookup_extent_mapping(em_tree, ordered_extent->file_offset, | 540 | clear_start = ordered_extent->file_offset; |
534 | ordered_extent->len); | 541 | clear_end = ordered_extent->file_offset + ordered_extent->len; |
535 | if (em) { | 542 | while(clear_start < clear_end) { |
536 | clear_bit(EXTENT_FLAG_PINNED, &em->flags); | 543 | em = lookup_extent_mapping(em_tree, clear_start, |
537 | free_extent_map(em); | 544 | clear_end - clear_start); |
545 | if (em) { | ||
546 | clear_bit(EXTENT_FLAG_PINNED, &em->flags); | ||
547 | clear_start = em->start + em->len; | ||
548 | free_extent_map(em); | ||
549 | } else { | ||
550 | break; | ||
551 | } | ||
538 | } | 552 | } |
539 | spin_unlock(&em_tree->lock); | 553 | spin_unlock(&em_tree->lock); |
540 | 554 | ||