struct btrfs_root *root,
                             struct btrfs_path *path, u64 objectid,
                             u64 bytenr, int mod);
-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);
 struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans,
                                          struct btrfs_root *root,
                                          struct btrfs_path *path,
 
                        (unsigned long long)bio->bi_sector);
                WARN_ON(1);
        }
+       if (tree->ops && tree->ops->submit_bio_hook)
+               tree->ops->submit_bio_hook(rw, bio);
 
        submit_bio(rw, bio);
        if (bio_flagged(bio, BIO_EOPNOTSUPP))
 
 struct extent_io_ops {
        int (*fill_delalloc)(struct inode *inode, u64 start, u64 end);
        int (*writepage_io_hook)(struct page *page, u64 start, u64 end);
+       int (*submit_bio_hook)(int rw, struct bio *bio);
        int (*readpage_io_hook)(struct page *page, u64 start, u64 end);
        int (*readpage_end_io_hook)(struct page *page, u64 start, u64 end,
                                    struct extent_state *state);
 
  * 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"
        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);
        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);
 
        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;
 }
 
  * Boston, MA 021110-1307, USA.
  */
 
+#include <linux/bio.h>
 #include <linux/buffer_head.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
        return 0;
 }
 
+int btrfs_submit_bio_hook(int rw, struct bio *bio)
+{
+       // struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
+       struct bio_vec *bvec = bio->bi_io_vec;
+       struct inode *inode = bvec->bv_page->mapping->host;
+       struct btrfs_root *root = BTRFS_I(inode)->root;
+       struct btrfs_trans_handle *trans;
+       int ret = 0;
+
+       if (rw != WRITE)
+               return 0;
+
+       if (btrfs_test_opt(root, NODATASUM) ||
+           btrfs_test_flag(inode, NODATASUM))
+               return 0;
+
+       mutex_lock(&root->fs_info->fs_mutex);
+       trans = btrfs_start_transaction(root, 1);
+       btrfs_set_trans_block_group(trans, inode);
+       btrfs_csum_file_blocks(trans, root, inode, bio);
+       ret = btrfs_end_transaction(trans, root);
+       BUG_ON(ret);
+       mutex_unlock(&root->fs_info->fs_mutex);
+       return ret;
+}
+#if 0
 int btrfs_writepage_io_hook(struct page *page, u64 start, u64 end)
 {
        struct inode *inode = page->mapping->host;
        mutex_unlock(&root->fs_info->fs_mutex);
        return ret;
 }
-
+#endif
 int btrfs_readpage_io_hook(struct page *page, u64 start, u64 end)
 {
        int ret = 0;
 
 static struct extent_io_ops btrfs_extent_io_ops = {
        .fill_delalloc = run_delalloc_range,
-       .writepage_io_hook = btrfs_writepage_io_hook,
+       // .writepage_io_hook = btrfs_writepage_io_hook,
+       .submit_bio_hook = btrfs_submit_bio_hook,
        .readpage_io_hook = btrfs_readpage_io_hook,
        .readpage_end_io_hook = btrfs_readpage_end_io_hook,
        .set_bit_hook = btrfs_set_bit_hook,