aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2012-08-03 16:49:19 -0400
committerChris Mason <chris.mason@oracle.com>2012-08-28 16:53:30 -0400
commitc329861da40623cd838b8c9ee31a850242fd88cf (patch)
treed395b6dae57c00c25f1b890db1f39871575a7013 /fs
parent99f5944b8477914406173b47b4f261356286730b (diff)
Btrfs: don't allocate a seperate csums array for direct reads
We've been allocating a big array for csums instead of storing them in the io_tree like we do for buffered reads because previously we were locking the entire range, so we didn't have an extent state for each sector of the range. But now that we do the range locking as we map the buffers we can limit the mapping lenght to sectorsize and use the private part of the io_tree for our csums. This allows us to avoid an extra memory allocation for direct reads which could incur latency. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/file-item.c4
-rw-r--r--fs/btrfs/inode.c45
3 files changed, 19 insertions, 32 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index adb1cd7ceb9b..348196350bf0 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3192,7 +3192,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans,
3192int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, 3192int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode,
3193 struct bio *bio, u32 *dst); 3193 struct bio *bio, u32 *dst);
3194int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode, 3194int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode,
3195 struct bio *bio, u64 logical_offset, u32 *dst); 3195 struct bio *bio, u64 logical_offset);
3196int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, 3196int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
3197 struct btrfs_root *root, 3197 struct btrfs_root *root,
3198 u64 objectid, u64 pos, 3198 u64 objectid, u64 pos,
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index b45b9de0c21d..857d93cd01dc 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -272,9 +272,9 @@ int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode,
272} 272}
273 273
274int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode, 274int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode,
275 struct bio *bio, u64 offset, u32 *dst) 275 struct bio *bio, u64 offset)
276{ 276{
277 return __btrfs_lookup_bio_sums(root, inode, bio, offset, dst, 1); 277 return __btrfs_lookup_bio_sums(root, inode, bio, offset, NULL, 1);
278} 278}
279 279
280int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, 280int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 09182449cbdf..2d65c52b0944 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -5847,15 +5847,18 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
5847 int unlock_bits = EXTENT_LOCKED; 5847 int unlock_bits = EXTENT_LOCKED;
5848 int ret; 5848 int ret;
5849 5849
5850 lockstart = start;
5851 lockend = start + len - 1;
5852 if (create) { 5850 if (create) {
5853 ret = btrfs_delalloc_reserve_space(inode, len); 5851 ret = btrfs_delalloc_reserve_space(inode, len);
5854 if (ret) 5852 if (ret)
5855 return ret; 5853 return ret;
5856 unlock_bits |= EXTENT_DELALLOC | EXTENT_DIRTY; 5854 unlock_bits |= EXTENT_DELALLOC | EXTENT_DIRTY;
5855 } else {
5856 len = min_t(u64, len, root->sectorsize);
5857 } 5857 }
5858 5858
5859 lockstart = start;
5860 lockend = start + len - 1;
5861
5859 /* 5862 /*
5860 * If this errors out it's because we couldn't invalidate pagecache for 5863 * If this errors out it's because we couldn't invalidate pagecache for
5861 * this range and we need to fallback to buffered. 5864 * this range and we need to fallback to buffered.
@@ -6015,7 +6018,6 @@ struct btrfs_dio_private {
6015 u64 logical_offset; 6018 u64 logical_offset;
6016 u64 disk_bytenr; 6019 u64 disk_bytenr;
6017 u64 bytes; 6020 u64 bytes;
6018 u32 *csums;
6019 void *private; 6021 void *private;
6020 6022
6021 /* number of bios pending for this dio */ 6023 /* number of bios pending for this dio */
@@ -6035,7 +6037,6 @@ static void btrfs_endio_direct_read(struct bio *bio, int err)
6035 struct inode *inode = dip->inode; 6037 struct inode *inode = dip->inode;
6036 struct btrfs_root *root = BTRFS_I(inode)->root; 6038 struct btrfs_root *root = BTRFS_I(inode)->root;
6037 u64 start; 6039 u64 start;
6038 u32 *private = dip->csums;
6039 6040
6040 start = dip->logical_offset; 6041 start = dip->logical_offset;
6041 do { 6042 do {
@@ -6043,8 +6044,12 @@ static void btrfs_endio_direct_read(struct bio *bio, int err)
6043 struct page *page = bvec->bv_page; 6044 struct page *page = bvec->bv_page;
6044 char *kaddr; 6045 char *kaddr;
6045 u32 csum = ~(u32)0; 6046 u32 csum = ~(u32)0;
6047 u64 private = ~(u32)0;
6046 unsigned long flags; 6048 unsigned long flags;
6047 6049
6050 if (get_state_private(&BTRFS_I(inode)->io_tree,
6051 start, &private))
6052 goto failed;
6048 local_irq_save(flags); 6053 local_irq_save(flags);
6049 kaddr = kmap_atomic(page); 6054 kaddr = kmap_atomic(page);
6050 csum = btrfs_csum_data(root, kaddr + bvec->bv_offset, 6055 csum = btrfs_csum_data(root, kaddr + bvec->bv_offset,
@@ -6054,18 +6059,18 @@ static void btrfs_endio_direct_read(struct bio *bio, int err)
6054 local_irq_restore(flags); 6059 local_irq_restore(flags);
6055 6060
6056 flush_dcache_page(bvec->bv_page); 6061 flush_dcache_page(bvec->bv_page);
6057 if (csum != *private) { 6062 if (csum != private) {
6063failed:
6058 printk(KERN_ERR "btrfs csum failed ino %llu off" 6064 printk(KERN_ERR "btrfs csum failed ino %llu off"
6059 " %llu csum %u private %u\n", 6065 " %llu csum %u private %u\n",
6060 (unsigned long long)btrfs_ino(inode), 6066 (unsigned long long)btrfs_ino(inode),
6061 (unsigned long long)start, 6067 (unsigned long long)start,
6062 csum, *private); 6068 csum, (unsigned)private);
6063 err = -EIO; 6069 err = -EIO;
6064 } 6070 }
6065 } 6071 }
6066 6072
6067 start += bvec->bv_len; 6073 start += bvec->bv_len;
6068 private++;
6069 bvec++; 6074 bvec++;
6070 } while (bvec <= bvec_end); 6075 } while (bvec <= bvec_end);
6071 6076
@@ -6073,7 +6078,6 @@ static void btrfs_endio_direct_read(struct bio *bio, int err)
6073 dip->logical_offset + dip->bytes - 1); 6078 dip->logical_offset + dip->bytes - 1);
6074 bio->bi_private = dip->private; 6079 bio->bi_private = dip->private;
6075 6080
6076 kfree(dip->csums);
6077 kfree(dip); 6081 kfree(dip);
6078 6082
6079 /* If we had a csum failure make sure to clear the uptodate flag */ 6083 /* If we had a csum failure make sure to clear the uptodate flag */
@@ -6179,7 +6183,7 @@ static struct bio *btrfs_dio_bio_alloc(struct block_device *bdev,
6179 6183
6180static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, 6184static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
6181 int rw, u64 file_offset, int skip_sum, 6185 int rw, u64 file_offset, int skip_sum,
6182 u32 *csums, int async_submit) 6186 int async_submit)
6183{ 6187{
6184 int write = rw & REQ_WRITE; 6188 int write = rw & REQ_WRITE;
6185 struct btrfs_root *root = BTRFS_I(inode)->root; 6189 struct btrfs_root *root = BTRFS_I(inode)->root;
@@ -6212,8 +6216,7 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
6212 if (ret) 6216 if (ret)
6213 goto err; 6217 goto err;
6214 } else if (!skip_sum) { 6218 } else if (!skip_sum) {
6215 ret = btrfs_lookup_bio_sums_dio(root, inode, bio, 6219 ret = btrfs_lookup_bio_sums_dio(root, inode, bio, file_offset);
6216 file_offset, csums);
6217 if (ret) 6220 if (ret)
6218 goto err; 6221 goto err;
6219 } 6222 }
@@ -6239,10 +6242,8 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
6239 u64 submit_len = 0; 6242 u64 submit_len = 0;
6240 u64 map_length; 6243 u64 map_length;
6241 int nr_pages = 0; 6244 int nr_pages = 0;
6242 u32 *csums = dip->csums;
6243 int ret = 0; 6245 int ret = 0;
6244 int async_submit = 0; 6246 int async_submit = 0;
6245 int write = rw & REQ_WRITE;
6246 6247
6247 map_length = orig_bio->bi_size; 6248 map_length = orig_bio->bi_size;
6248 ret = btrfs_map_block(map_tree, READ, start_sector << 9, 6249 ret = btrfs_map_block(map_tree, READ, start_sector << 9,
@@ -6278,16 +6279,13 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
6278 atomic_inc(&dip->pending_bios); 6279 atomic_inc(&dip->pending_bios);
6279 ret = __btrfs_submit_dio_bio(bio, inode, rw, 6280 ret = __btrfs_submit_dio_bio(bio, inode, rw,
6280 file_offset, skip_sum, 6281 file_offset, skip_sum,
6281 csums, async_submit); 6282 async_submit);
6282 if (ret) { 6283 if (ret) {
6283 bio_put(bio); 6284 bio_put(bio);
6284 atomic_dec(&dip->pending_bios); 6285 atomic_dec(&dip->pending_bios);
6285 goto out_err; 6286 goto out_err;
6286 } 6287 }
6287 6288
6288 /* Write's use the ordered csums */
6289 if (!write && !skip_sum)
6290 csums = csums + nr_pages;
6291 start_sector += submit_len >> 9; 6289 start_sector += submit_len >> 9;
6292 file_offset += submit_len; 6290 file_offset += submit_len;
6293 6291
@@ -6317,7 +6315,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
6317 6315
6318submit: 6316submit:
6319 ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum, 6317 ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum,
6320 csums, async_submit); 6318 async_submit);
6321 if (!ret) 6319 if (!ret)
6322 return 0; 6320 return 0;
6323 6321
@@ -6353,17 +6351,6 @@ static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode,
6353 ret = -ENOMEM; 6351 ret = -ENOMEM;
6354 goto free_ordered; 6352 goto free_ordered;
6355 } 6353 }
6356 dip->csums = NULL;
6357
6358 /* Write's use the ordered csum stuff, so we don't need dip->csums */
6359 if (!write && !skip_sum) {
6360 dip->csums = kmalloc(sizeof(u32) * bio->bi_vcnt, GFP_NOFS);
6361 if (!dip->csums) {
6362 kfree(dip);
6363 ret = -ENOMEM;
6364 goto free_ordered;
6365 }
6366 }
6367 6354
6368 dip->private = bio->bi_private; 6355 dip->private = bio->bi_private;
6369 dip->inode = inode; 6356 dip->inode = inode;