aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file-item.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-04-16 11:15:20 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:01 -0400
commite015640f9c4fa2417dcc3bbbb3b2b61ad4059ab0 (patch)
tree2ba41617e428f60ff970abc8a862ab77980b4a20 /fs/btrfs/file-item.c
parent44b8bd7edda4f63de180d0f7325c9fb704b3806b (diff)
Btrfs: Write bio checksumming outside the FS mutex
This significantly improves streaming write performance by allowing concurrency in the data checksumming. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/file-item.c')
-rw-r--r--fs/btrfs/file-item.c46
1 files changed, 32 insertions, 14 deletions
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index 374d0245b29d..9259aece6ed1 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -134,9 +134,36 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
134 return ret; 134 return ret;
135} 135}
136 136
137int btrfs_csum_one_bio(struct btrfs_root *root,
138 struct bio *bio, char **sums_ret)
139{
140 u32 *sums;
141 char *data;
142 struct bio_vec *bvec = bio->bi_io_vec;
143 int bio_index = 0;
144
145 sums = kmalloc(bio->bi_vcnt * BTRFS_CRC32_SIZE, GFP_NOFS);
146 if (!sums)
147 return -ENOMEM;
148 *sums_ret = (char *)sums;
149
150 while(bio_index < bio->bi_vcnt) {
151 data = kmap_atomic(bvec->bv_page, KM_USER0);
152 *sums = ~(u32)0;
153 *sums = btrfs_csum_data(root, data + bvec->bv_offset,
154 *sums, bvec->bv_len);
155 kunmap_atomic(data, KM_USER0);
156 btrfs_csum_final(*sums, (char *)sums);
157 sums++;
158 bio_index++;
159 bvec++;
160 }
161 return 0;
162}
163
137int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, 164int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans,
138 struct btrfs_root *root, struct inode *inode, 165 struct btrfs_root *root, struct inode *inode,
139 struct bio *bio) 166 struct bio *bio, char *sums)
140{ 167{
141 u64 objectid = inode->i_ino; 168 u64 objectid = inode->i_ino;
142 u64 offset; 169 u64 offset;
@@ -150,12 +177,11 @@ int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans,
150 struct btrfs_csum_item *item_end; 177 struct btrfs_csum_item *item_end;
151 struct extent_buffer *leaf = NULL; 178 struct extent_buffer *leaf = NULL;
152 u64 csum_offset; 179 u64 csum_offset;
153 u32 csum_result; 180 u32 *sums32 = (u32 *)sums;
154 u32 nritems; 181 u32 nritems;
155 u32 ins_size; 182 u32 ins_size;
156 int bio_index = 0; 183 int bio_index = 0;
157 struct bio_vec *bvec = bio->bi_io_vec; 184 struct bio_vec *bvec = bio->bi_io_vec;
158 char *data;
159 char *eb_map; 185 char *eb_map;
160 char *eb_token; 186 char *eb_token;
161 unsigned long map_len; 187 unsigned long map_len;
@@ -278,15 +304,6 @@ found:
278 btrfs_item_size_nr(leaf, path->slots[0])); 304 btrfs_item_size_nr(leaf, path->slots[0]));
279 eb_token = NULL; 305 eb_token = NULL;
280next_bvec: 306next_bvec:
281 data = kmap_atomic(bvec->bv_page, KM_USER0);
282 csum_result = ~(u32)0;
283 csum_result = btrfs_csum_data(root, data + bvec->bv_offset,
284 csum_result, bvec->bv_len);
285 kunmap_atomic(data, KM_USER0);
286 btrfs_csum_final(csum_result, (char *)&csum_result);
287 if (csum_result == 0) {
288 printk("csum result is 0 for inode %lu offset %Lu\n", inode->i_ino, offset);
289 }
290 307
291 if (!eb_token || 308 if (!eb_token ||
292 (unsigned long)item + BTRFS_CRC32_SIZE >= map_start + map_len) { 309 (unsigned long)item + BTRFS_CRC32_SIZE >= map_start + map_len) {
@@ -304,13 +321,14 @@ next_bvec:
304 } 321 }
305 if (eb_token) { 322 if (eb_token) {
306 memcpy(eb_token + ((unsigned long)item & (PAGE_CACHE_SIZE - 1)), 323 memcpy(eb_token + ((unsigned long)item & (PAGE_CACHE_SIZE - 1)),
307 &csum_result, BTRFS_CRC32_SIZE); 324 sums32, BTRFS_CRC32_SIZE);
308 } else { 325 } else {
309 write_extent_buffer(leaf, &csum_result, (unsigned long)item, 326 write_extent_buffer(leaf, sums32, (unsigned long)item,
310 BTRFS_CRC32_SIZE); 327 BTRFS_CRC32_SIZE);
311 } 328 }
312 bio_index++; 329 bio_index++;
313 bvec++; 330 bvec++;
331 sums32++;
314 if (bio_index < bio->bi_vcnt) { 332 if (bio_index < bio->bi_vcnt) {
315 item = (struct btrfs_csum_item *)((char *)item + 333 item = (struct btrfs_csum_item *)((char *)item +
316 BTRFS_CRC32_SIZE); 334 BTRFS_CRC32_SIZE);