aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--fs/btrfs/ctree.h4
-rw-r--r--fs/btrfs/file-item.c46
-rw-r--r--fs/btrfs/inode.c11
3 files changed, 45 insertions, 16 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index ff15b8513f90..b56ae1950658 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1515,7 +1515,9 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
1515 u64 bytenr, int mod); 1515 u64 bytenr, int mod);
1516int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, 1516int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans,
1517 struct btrfs_root *root, struct inode *inode, 1517 struct btrfs_root *root, struct inode *inode,
1518 struct bio *bio); 1518 struct bio *bio, char *sums);
1519int btrfs_csum_one_bio(struct btrfs_root *root,
1520 struct bio *bio, char **sums_ret);
1519struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, 1521struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans,
1520 struct btrfs_root *root, 1522 struct btrfs_root *root,
1521 struct btrfs_path *path, 1523 struct btrfs_path *path,
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);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 457daf725d29..3e1f21c632c1 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -330,14 +330,23 @@ int __btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
330 struct btrfs_root *root = BTRFS_I(inode)->root; 330 struct btrfs_root *root = BTRFS_I(inode)->root;
331 struct btrfs_trans_handle *trans; 331 struct btrfs_trans_handle *trans;
332 int ret = 0; 332 int ret = 0;
333 char *sums = NULL;
334
335 ret = btrfs_csum_one_bio(root, bio, &sums);
336 BUG_ON(ret);
333 337
334 mutex_lock(&root->fs_info->fs_mutex); 338 mutex_lock(&root->fs_info->fs_mutex);
335 trans = btrfs_start_transaction(root, 1); 339 trans = btrfs_start_transaction(root, 1);
340
336 btrfs_set_trans_block_group(trans, inode); 341 btrfs_set_trans_block_group(trans, inode);
337 btrfs_csum_file_blocks(trans, root, inode, bio); 342 btrfs_csum_file_blocks(trans, root, inode, bio, sums);
343
338 ret = btrfs_end_transaction(trans, root); 344 ret = btrfs_end_transaction(trans, root);
339 BUG_ON(ret); 345 BUG_ON(ret);
340 mutex_unlock(&root->fs_info->fs_mutex); 346 mutex_unlock(&root->fs_info->fs_mutex);
347
348 kfree(sums);
349
341 return btrfs_map_bio(root, rw, bio, mirror_num); 350 return btrfs_map_bio(root, rw, bio, mirror_num);
342} 351}
343 352