diff options
author | Miao Xie <miaox@cn.fujitsu.com> | 2013-04-05 03:20:56 -0400 |
---|---|---|
committer | Josef Bacik <jbacik@fusionio.com> | 2013-05-06 15:54:35 -0400 |
commit | e4100d987b2437596ebcf11809022b79507f3db1 (patch) | |
tree | 2e1b987afa41149ef621581f1eb125c027453f74 /fs/btrfs/file-item.c | |
parent | 09a2a8f96e3009273bed1833b3f210e2c68728a5 (diff) |
Btrfs: improve the performance of the csums lookup
It is very likely that there are several blocks in bio, it is very
inefficient if we get their csums one by one. This patch improves
this problem by getting the csums in batch.
According to the result of the following test, the execute time of
__btrfs_lookup_bio_sums() is down by ~28%(300us -> 217us).
# dd if=<mnt>/file of=/dev/null bs=1M count=1024
Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/file-item.c')
-rw-r--r-- | fs/btrfs/file-item.c | 49 |
1 files changed, 30 insertions, 19 deletions
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index ad3cd8614d29..18f12aab6ebf 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -177,7 +177,8 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, | |||
177 | struct inode *inode, struct bio *bio, | 177 | struct inode *inode, struct bio *bio, |
178 | u64 logical_offset, u32 *dst, int dio) | 178 | u64 logical_offset, u32 *dst, int dio) |
179 | { | 179 | { |
180 | u32 sum; | 180 | u32 sum[16]; |
181 | int len; | ||
181 | struct bio_vec *bvec = bio->bi_io_vec; | 182 | struct bio_vec *bvec = bio->bi_io_vec; |
182 | int bio_index = 0; | 183 | int bio_index = 0; |
183 | u64 offset = 0; | 184 | u64 offset = 0; |
@@ -186,7 +187,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, | |||
186 | u64 disk_bytenr; | 187 | u64 disk_bytenr; |
187 | u32 diff; | 188 | u32 diff; |
188 | u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); | 189 | u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); |
189 | int ret; | 190 | int count; |
190 | struct btrfs_path *path; | 191 | struct btrfs_path *path; |
191 | struct btrfs_csum_item *item = NULL; | 192 | struct btrfs_csum_item *item = NULL; |
192 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | 193 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; |
@@ -214,10 +215,12 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, | |||
214 | if (dio) | 215 | if (dio) |
215 | offset = logical_offset; | 216 | offset = logical_offset; |
216 | while (bio_index < bio->bi_vcnt) { | 217 | while (bio_index < bio->bi_vcnt) { |
218 | len = min_t(int, ARRAY_SIZE(sum), bio->bi_vcnt - bio_index); | ||
217 | if (!dio) | 219 | if (!dio) |
218 | offset = page_offset(bvec->bv_page) + bvec->bv_offset; | 220 | offset = page_offset(bvec->bv_page) + bvec->bv_offset; |
219 | ret = btrfs_find_ordered_sum(inode, offset, disk_bytenr, &sum); | 221 | count = btrfs_find_ordered_sum(inode, offset, disk_bytenr, sum, |
220 | if (ret == 0) | 222 | len); |
223 | if (count) | ||
221 | goto found; | 224 | goto found; |
222 | 225 | ||
223 | if (!item || disk_bytenr < item_start_offset || | 226 | if (!item || disk_bytenr < item_start_offset || |
@@ -230,10 +233,8 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, | |||
230 | item = btrfs_lookup_csum(NULL, root->fs_info->csum_root, | 233 | item = btrfs_lookup_csum(NULL, root->fs_info->csum_root, |
231 | path, disk_bytenr, 0); | 234 | path, disk_bytenr, 0); |
232 | if (IS_ERR(item)) { | 235 | if (IS_ERR(item)) { |
233 | ret = PTR_ERR(item); | 236 | count = 1; |
234 | if (ret == -ENOENT || ret == -EFBIG) | 237 | sum[0] = 0; |
235 | ret = 0; | ||
236 | sum = 0; | ||
237 | if (BTRFS_I(inode)->root->root_key.objectid == | 238 | if (BTRFS_I(inode)->root->root_key.objectid == |
238 | BTRFS_DATA_RELOC_TREE_OBJECTID) { | 239 | BTRFS_DATA_RELOC_TREE_OBJECTID) { |
239 | set_extent_bits(io_tree, offset, | 240 | set_extent_bits(io_tree, offset, |
@@ -269,19 +270,29 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, | |||
269 | diff = disk_bytenr - item_start_offset; | 270 | diff = disk_bytenr - item_start_offset; |
270 | diff = diff / root->sectorsize; | 271 | diff = diff / root->sectorsize; |
271 | diff = diff * csum_size; | 272 | diff = diff * csum_size; |
272 | 273 | count = min_t(int, len, (item_last_offset - disk_bytenr) >> | |
273 | read_extent_buffer(path->nodes[0], &sum, | 274 | inode->i_sb->s_blocksize_bits); |
275 | read_extent_buffer(path->nodes[0], sum, | ||
274 | ((unsigned long)item) + diff, | 276 | ((unsigned long)item) + diff, |
275 | csum_size); | 277 | csum_size * count); |
276 | found: | 278 | found: |
277 | if (dst) | 279 | if (dst) { |
278 | *dst++ = sum; | 280 | memcpy(dst, sum, count * csum_size); |
279 | else | 281 | dst += count; |
280 | set_state_private(io_tree, offset, sum); | 282 | } else { |
281 | disk_bytenr += bvec->bv_len; | 283 | if (dio) |
282 | offset += bvec->bv_len; | 284 | extent_cache_csums_dio(io_tree, offset, sum, |
283 | bio_index++; | 285 | count); |
284 | bvec++; | 286 | else |
287 | extent_cache_csums(io_tree, bio, bio_index, sum, | ||
288 | count); | ||
289 | } | ||
290 | while (count--) { | ||
291 | disk_bytenr += bvec->bv_len; | ||
292 | offset += bvec->bv_len; | ||
293 | bio_index++; | ||
294 | bvec++; | ||
295 | } | ||
285 | } | 296 | } |
286 | btrfs_free_path(path); | 297 | btrfs_free_path(path); |
287 | return 0; | 298 | return 0; |