diff options
Diffstat (limited to 'fs/btrfs/file-item.c')
-rw-r--r-- | fs/btrfs/file-item.c | 50 |
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 @@ | |||
16 | * Boston, MA 021110-1307, USA. | 16 | * Boston, MA 021110-1307, USA. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/bio.h> | ||
20 | #include <linux/pagemap.h> | ||
21 | #include <linux/highmem.h> | ||
19 | #include "ctree.h" | 22 | #include "ctree.h" |
20 | #include "disk-io.h" | 23 | #include "disk-io.h" |
21 | #include "transaction.h" | 24 | #include "transaction.h" |
@@ -131,28 +134,35 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, | |||
131 | return ret; | 134 | return ret; |
132 | } | 135 | } |
133 | 136 | ||
134 | int btrfs_csum_file_block(struct btrfs_trans_handle *trans, | 137 | int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, |
135 | struct btrfs_root *root, | 138 | struct btrfs_root *root, struct inode *inode, |
136 | struct inode *inode, | 139 | struct bio *bio) |
137 | u64 objectid, u64 offset, | ||
138 | char *data, size_t len) | ||
139 | { | 140 | { |
141 | u64 objectid = inode->i_ino; | ||
142 | u64 offset; | ||
140 | int ret; | 143 | int ret; |
141 | struct btrfs_key file_key; | 144 | struct btrfs_key file_key; |
142 | struct btrfs_key found_key; | 145 | struct btrfs_key found_key; |
143 | u64 next_offset = (u64)-1; | 146 | u64 next_offset; |
144 | int found_next = 0; | 147 | int found_next; |
145 | struct btrfs_path *path; | 148 | struct btrfs_path *path; |
146 | struct btrfs_csum_item *item; | 149 | struct btrfs_csum_item *item; |
150 | struct btrfs_csum_item *item_end; | ||
147 | struct extent_buffer *leaf = NULL; | 151 | struct extent_buffer *leaf = NULL; |
148 | u64 csum_offset; | 152 | u64 csum_offset; |
149 | u32 csum_result = ~(u32)0; | 153 | u32 csum_result; |
150 | u32 nritems; | 154 | u32 nritems; |
151 | u32 ins_size; | 155 | u32 ins_size; |
156 | int bio_index = 0; | ||
157 | struct bio_vec *bvec = bio->bi_io_vec; | ||
158 | char *data; | ||
152 | 159 | ||
153 | path = btrfs_alloc_path(); | 160 | path = btrfs_alloc_path(); |
154 | BUG_ON(!path); | 161 | BUG_ON(!path); |
155 | 162 | again: | |
163 | next_offset = (u64)-1; | ||
164 | found_next = 0; | ||
165 | offset = page_offset(bvec->bv_page) + bvec->bv_offset; | ||
156 | file_key.objectid = objectid; | 166 | file_key.objectid = objectid; |
157 | file_key.offset = offset; | 167 | file_key.offset = offset; |
158 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); | 168 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); |
@@ -259,7 +269,15 @@ csum: | |||
259 | item = (struct btrfs_csum_item *)((unsigned char *)item + | 269 | item = (struct btrfs_csum_item *)((unsigned char *)item + |
260 | csum_offset * BTRFS_CRC32_SIZE); | 270 | csum_offset * BTRFS_CRC32_SIZE); |
261 | found: | 271 | found: |
262 | csum_result = btrfs_csum_data(root, data, csum_result, len); | 272 | item_end = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item); |
273 | item_end = (struct btrfs_csum_item *)((unsigned char *)item_end + | ||
274 | btrfs_item_size_nr(leaf, path->slots[0])); | ||
275 | next_bvec: | ||
276 | data = kmap_atomic(bvec->bv_page, KM_IRQ0); | ||
277 | csum_result = ~(u32)0; | ||
278 | csum_result = btrfs_csum_data(root, data + bvec->bv_offset, | ||
279 | csum_result, bvec->bv_len); | ||
280 | kunmap_atomic(data, KM_IRQ0); | ||
263 | btrfs_csum_final(csum_result, (char *)&csum_result); | 281 | btrfs_csum_final(csum_result, (char *)&csum_result); |
264 | if (csum_result == 0) { | 282 | if (csum_result == 0) { |
265 | printk("csum result is 0 for inode %lu offset %Lu\n", inode->i_ino, offset); | 283 | printk("csum result is 0 for inode %lu offset %Lu\n", inode->i_ino, offset); |
@@ -267,9 +285,19 @@ found: | |||
267 | 285 | ||
268 | write_extent_buffer(leaf, &csum_result, (unsigned long)item, | 286 | write_extent_buffer(leaf, &csum_result, (unsigned long)item, |
269 | BTRFS_CRC32_SIZE); | 287 | BTRFS_CRC32_SIZE); |
288 | bio_index++; | ||
289 | bvec++; | ||
290 | if (bio_index < bio->bi_vcnt) { | ||
291 | item = (struct btrfs_csum_item *)((char *)item + BTRFS_CRC32_SIZE); | ||
292 | if (item < item_end) | ||
293 | goto next_bvec; | ||
294 | } | ||
270 | btrfs_mark_buffer_dirty(path->nodes[0]); | 295 | btrfs_mark_buffer_dirty(path->nodes[0]); |
296 | if (bio_index < bio->bi_vcnt) { | ||
297 | btrfs_release_path(root, path); | ||
298 | goto again; | ||
299 | } | ||
271 | fail: | 300 | fail: |
272 | btrfs_release_path(root, path); | ||
273 | btrfs_free_path(path); | 301 | btrfs_free_path(path); |
274 | return ret; | 302 | return ret; |
275 | } | 303 | } |