diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-02-20 12:07:25 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:00 -0400 |
commit | 6e92f5e651a34f24ab31ebdf3f113c7d23a36000 (patch) | |
tree | 57695b87c3a86c418cb4ba65de53ca809e7b5e60 /fs/btrfs/file-item.c | |
parent | 065631f6dccea07bfad48d8981369f6d9cfd6e2b (diff) |
Btrfs: While doing checksums on bios, cache the extent_buffer mapping
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/file-item.c')
-rw-r--r-- | fs/btrfs/file-item.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 3f0e71b0e5d9..ee25e50e7c04 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -156,6 +156,11 @@ int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, | |||
156 | int bio_index = 0; | 156 | int bio_index = 0; |
157 | struct bio_vec *bvec = bio->bi_io_vec; | 157 | struct bio_vec *bvec = bio->bi_io_vec; |
158 | char *data; | 158 | char *data; |
159 | char *eb_map; | ||
160 | char *eb_token; | ||
161 | unsigned long map_len; | ||
162 | unsigned long map_start; | ||
163 | |||
159 | 164 | ||
160 | path = btrfs_alloc_path(); | 165 | path = btrfs_alloc_path(); |
161 | BUG_ON(!path); | 166 | BUG_ON(!path); |
@@ -272,6 +277,7 @@ found: | |||
272 | item_end = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item); | 277 | item_end = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item); |
273 | item_end = (struct btrfs_csum_item *)((unsigned char *)item_end + | 278 | item_end = (struct btrfs_csum_item *)((unsigned char *)item_end + |
274 | btrfs_item_size_nr(leaf, path->slots[0])); | 279 | btrfs_item_size_nr(leaf, path->slots[0])); |
280 | eb_token = NULL; | ||
275 | next_bvec: | 281 | next_bvec: |
276 | data = kmap_atomic(bvec->bv_page, KM_IRQ0); | 282 | data = kmap_atomic(bvec->bv_page, KM_IRQ0); |
277 | csum_result = ~(u32)0; | 283 | csum_result = ~(u32)0; |
@@ -283,15 +289,39 @@ next_bvec: | |||
283 | printk("csum result is 0 for inode %lu offset %Lu\n", inode->i_ino, offset); | 289 | printk("csum result is 0 for inode %lu offset %Lu\n", inode->i_ino, offset); |
284 | } | 290 | } |
285 | 291 | ||
286 | write_extent_buffer(leaf, &csum_result, (unsigned long)item, | 292 | if (!eb_token || |
287 | BTRFS_CRC32_SIZE); | 293 | (unsigned long)item + BTRFS_CRC32_SIZE >= map_start + map_len) { |
294 | int err; | ||
295 | |||
296 | if (eb_token) | ||
297 | unmap_extent_buffer(leaf, eb_token, KM_IRQ1); | ||
298 | eb_token = NULL; | ||
299 | err = map_private_extent_buffer(leaf, (unsigned long)item, | ||
300 | BTRFS_CRC32_SIZE, | ||
301 | &eb_token, &eb_map, | ||
302 | &map_start, &map_len, KM_IRQ1); | ||
303 | if (err) | ||
304 | eb_token = NULL; | ||
305 | } | ||
306 | if (eb_token) { | ||
307 | memcpy(eb_token + ((unsigned long)item & (PAGE_CACHE_SIZE - 1)), | ||
308 | &csum_result, BTRFS_CRC32_SIZE); | ||
309 | } else { | ||
310 | write_extent_buffer(leaf, &csum_result, (unsigned long)item, | ||
311 | BTRFS_CRC32_SIZE); | ||
312 | } | ||
288 | bio_index++; | 313 | bio_index++; |
289 | bvec++; | 314 | bvec++; |
290 | if (bio_index < bio->bi_vcnt) { | 315 | if (bio_index < bio->bi_vcnt) { |
291 | item = (struct btrfs_csum_item *)((char *)item + BTRFS_CRC32_SIZE); | 316 | item = (struct btrfs_csum_item *)((char *)item + |
317 | BTRFS_CRC32_SIZE); | ||
292 | if (item < item_end) | 318 | if (item < item_end) |
293 | goto next_bvec; | 319 | goto next_bvec; |
294 | } | 320 | } |
321 | if (eb_token) { | ||
322 | unmap_extent_buffer(leaf, eb_token, KM_IRQ1); | ||
323 | eb_token = NULL; | ||
324 | } | ||
295 | btrfs_mark_buffer_dirty(path->nodes[0]); | 325 | btrfs_mark_buffer_dirty(path->nodes[0]); |
296 | if (bio_index < bio->bi_vcnt) { | 326 | if (bio_index < bio->bi_vcnt) { |
297 | btrfs_release_path(root, path); | 327 | btrfs_release_path(root, path); |