summaryrefslogtreecommitdiffstats
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 d86a953ae51..b739e3abebb 100644
--- a/fs/btrfs/ordered-data.c
+++ b/fs/btrfs/ordered-data.c
@@ -245,8 +245,18 @@ out:
int btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry)
{
- if (atomic_dec_and_test(&entry->refs))
+ struct list_head *cur;
+ struct btrfs_ordered_sum *sum;
+
+ if (atomic_dec_and_test(&entry->refs)) {
+ while(!list_empty(&entry->list)) {
+ cur = entry->list.next;
+ sum = list_entry(cur, struct btrfs_ordered_sum, list);
+ list_del(&sum->list);
+ kfree(sum);
+ }
kfree(entry);
+ }
return 0;
}
@@ -444,8 +454,9 @@ int btrfs_ordered_update_i_size(struct inode *inode,
* if we find an ordered extent then we can't update disk i_size
* yet
*/
+ node = &ordered->rb_node;
while(1) {
- node = rb_prev(&ordered->rb_node);
+ node = rb_prev(node);
if (!node)
break;
test = rb_entry(node, struct btrfs_ordered_extent, rb_node);
@@ -495,3 +506,36 @@ out:
mutex_unlock(&tree->mutex);
return 0;
}
+
+int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u32 *sum)
+{
+ struct btrfs_ordered_sum *ordered_sum;
+ struct btrfs_sector_sum *sector_sums;
+ struct btrfs_ordered_extent *ordered;
+ struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree;
+ struct list_head *cur;
+ int ret = 1;
+ int index;
+
+ ordered = btrfs_lookup_ordered_extent(inode, offset);
+ if (!ordered)
+ return 1;
+
+ mutex_lock(&tree->mutex);
+ list_for_each_prev(cur, &ordered->list) {
+ ordered_sum = list_entry(cur, struct btrfs_ordered_sum, list);
+ if (offset >= ordered_sum->file_offset &&
+ offset < ordered_sum->file_offset + ordered_sum->len) {
+ index = (offset - ordered_sum->file_offset) /
+ BTRFS_I(inode)->root->sectorsize;;
+ sector_sums = &ordered_sum->sums;
+ *sum = sector_sums[index].sum;
+ ret = 0;
+ goto out;
+ }
+ }
+out:
+ mutex_unlock(&tree->mutex);
+ return ret;
+}
+