aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ordered-data.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-07-17 12:54:15 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:04 -0400
commitba1da2f442ec91a1534afa893f9bef7e33056ace (patch)
treebc567aa83da6d709d3762f7e0bf9a5fe4d16de11 /fs/btrfs/ordered-data.c
parentf9295749388f82c8d2f485e99c72cd7c7876a99b (diff)
Btrfs: Don't pin pages in ram until the entire ordered extent is on disk.
Checksum items are not inserted until the entire ordered extent is on disk, but individual pages might be clean and available for reclaim long before the whole extent is on disk. In order to allow those pages to be freed, we need to be able to search the list of ordered extents to find the checksum that is going to be inserted in the tree. This way if the page needs to be read back in before the checksums are in the btree, we'll be able to verify the checksum on the page. This commit adds the ability to search the pending ordered extents for a given offset in the file, and changes btrfs_releasepage to allow ordered pages to be freed. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ordered-data.c')
-rw-r--r--fs/btrfs/ordered-data.c48
1 files changed, 46 insertions, 2 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
index d86a953ae51d..b739e3abebb9 100644
--- a/fs/btrfs/ordered-data.c
+++ b/fs/btrfs/ordered-data.c
@@ -245,8 +245,18 @@ out:
245 245
246int btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry) 246int btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry)
247{ 247{
248 if (atomic_dec_and_test(&entry->refs)) 248 struct list_head *cur;
249 struct btrfs_ordered_sum *sum;
250
251 if (atomic_dec_and_test(&entry->refs)) {
252 while(!list_empty(&entry->list)) {
253 cur = entry->list.next;
254 sum = list_entry(cur, struct btrfs_ordered_sum, list);
255 list_del(&sum->list);
256 kfree(sum);
257 }
249 kfree(entry); 258 kfree(entry);
259 }
250 return 0; 260 return 0;
251} 261}
252 262
@@ -444,8 +454,9 @@ int btrfs_ordered_update_i_size(struct inode *inode,
444 * if we find an ordered extent then we can't update disk i_size 454 * if we find an ordered extent then we can't update disk i_size
445 * yet 455 * yet
446 */ 456 */
457 node = &ordered->rb_node;
447 while(1) { 458 while(1) {
448 node = rb_prev(&ordered->rb_node); 459 node = rb_prev(node);
449 if (!node) 460 if (!node)
450 break; 461 break;
451 test = rb_entry(node, struct btrfs_ordered_extent, rb_node); 462 test = rb_entry(node, struct btrfs_ordered_extent, rb_node);
@@ -495,3 +506,36 @@ out:
495 mutex_unlock(&tree->mutex); 506 mutex_unlock(&tree->mutex);
496 return 0; 507 return 0;
497} 508}
509
510int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u32 *sum)
511{
512 struct btrfs_ordered_sum *ordered_sum;
513 struct btrfs_sector_sum *sector_sums;
514 struct btrfs_ordered_extent *ordered;
515 struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree;
516 struct list_head *cur;
517 int ret = 1;
518 int index;
519
520 ordered = btrfs_lookup_ordered_extent(inode, offset);
521 if (!ordered)
522 return 1;
523
524 mutex_lock(&tree->mutex);
525 list_for_each_prev(cur, &ordered->list) {
526 ordered_sum = list_entry(cur, struct btrfs_ordered_sum, list);
527 if (offset >= ordered_sum->file_offset &&
528 offset < ordered_sum->file_offset + ordered_sum->len) {
529 index = (offset - ordered_sum->file_offset) /
530 BTRFS_I(inode)->root->sectorsize;;
531 sector_sums = &ordered_sum->sums;
532 *sum = sector_sums[index].sum;
533 ret = 0;
534 goto out;
535 }
536 }
537out:
538 mutex_unlock(&tree->mutex);
539 return ret;
540}
541