aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file-item.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2013-04-05 03:20:56 -0400
committerJosef Bacik <jbacik@fusionio.com>2013-05-06 15:54:35 -0400
commite4100d987b2437596ebcf11809022b79507f3db1 (patch)
tree2e1b987afa41149ef621581f1eb125c027453f74 /fs/btrfs/file-item.c
parent09a2a8f96e3009273bed1833b3f210e2c68728a5 (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.c49
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);
276found: 278found:
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;