summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file-item.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/file-item.c')
-rw-r--r--fs/btrfs/file-item.c50
1 files changed, 39 insertions, 11 deletions
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index 3ebbc058d082..3f0e71b0e5d9 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -16,6 +16,9 @@
* Boston, MA 021110-1307, USA.
*/
+#include <linux/bio.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
#include "ctree.h"
#include "disk-io.h"
#include "transaction.h"
@@ -131,28 +134,35 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
return ret;
}
-int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
- struct btrfs_root *root,
- struct inode *inode,
- u64 objectid, u64 offset,
- char *data, size_t len)
+int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root, struct inode *inode,
+ struct bio *bio)
{
+ u64 objectid = inode->i_ino;
+ u64 offset;
int ret;
struct btrfs_key file_key;
struct btrfs_key found_key;
- u64 next_offset = (u64)-1;
- int found_next = 0;
+ u64 next_offset;
+ int found_next;
struct btrfs_path *path;
struct btrfs_csum_item *item;
+ struct btrfs_csum_item *item_end;
struct extent_buffer *leaf = NULL;
u64 csum_offset;
- u32 csum_result = ~(u32)0;
+ u32 csum_result;
u32 nritems;
u32 ins_size;
+ int bio_index = 0;
+ struct bio_vec *bvec = bio->bi_io_vec;
+ char *data;
path = btrfs_alloc_path();
BUG_ON(!path);
-
+again:
+ next_offset = (u64)-1;
+ found_next = 0;
+ offset = page_offset(bvec->bv_page) + bvec->bv_offset;
file_key.objectid = objectid;
file_key.offset = offset;
btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY);
@@ -259,7 +269,15 @@ csum:
item = (struct btrfs_csum_item *)((unsigned char *)item +
csum_offset * BTRFS_CRC32_SIZE);
found:
- csum_result = btrfs_csum_data(root, data, csum_result, len);
+ item_end = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
+ item_end = (struct btrfs_csum_item *)((unsigned char *)item_end +
+ btrfs_item_size_nr(leaf, path->slots[0]));
+next_bvec:
+ data = kmap_atomic(bvec->bv_page, KM_IRQ0);
+ csum_result = ~(u32)0;
+ csum_result = btrfs_csum_data(root, data + bvec->bv_offset,
+ csum_result, bvec->bv_len);
+ kunmap_atomic(data, KM_IRQ0);
btrfs_csum_final(csum_result, (char *)&csum_result);
if (csum_result == 0) {
printk("csum result is 0 for inode %lu offset %Lu\n", inode->i_ino, offset);
@@ -267,9 +285,19 @@ found:
write_extent_buffer(leaf, &csum_result, (unsigned long)item,
BTRFS_CRC32_SIZE);
+ bio_index++;
+ bvec++;
+ if (bio_index < bio->bi_vcnt) {
+ item = (struct btrfs_csum_item *)((char *)item + BTRFS_CRC32_SIZE);
+ if (item < item_end)
+ goto next_bvec;
+ }
btrfs_mark_buffer_dirty(path->nodes[0]);
+ if (bio_index < bio->bi_vcnt) {
+ btrfs_release_path(root, path);
+ goto again;
+ }
fail:
- btrfs_release_path(root, path);
btrfs_free_path(path);
return ret;
}