aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-04-22 13:26:46 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:02 -0400
commite1c4b7451e22f5b0a9fbccfa560ee7b80c35b8cd (patch)
tree4e9d3f9d0a8084ad6282965fa190200de3a91d7d /fs
parent409c6118d39cb2d8666bee3d61a1a9ae5bbd4f5d (diff)
Fix btrfs_get_extent and get_block corner cases, and disable O_DIRECT reads
The generic O_DIRECT code assumes all the bios have the same bdev, which isn't true for multi-device btrfs. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/extent_io.c1
-rw-r--r--fs/btrfs/inode.c32
-rw-r--r--fs/btrfs/volumes.c2
3 files changed, 23 insertions, 12 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 81f8b4fd069b..6e4bf029c6d4 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -1694,6 +1694,7 @@ extent_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs,
1694 } 1694 }
1695 1695
1696 if (bio) { 1696 if (bio) {
1697 bio->bi_size = 0;
1697 bio->bi_bdev = bdev; 1698 bio->bi_bdev = bdev;
1698 bio->bi_sector = first_sector; 1699 bio->bi_sector = first_sector;
1699 } 1700 }
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index e875c7c8a647..abfe86df02d2 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -494,6 +494,7 @@ int btrfs_readpage_io_failed_hook(struct bio *failed_bio,
494 bio->bi_end_io = failed_bio->bi_end_io; 494 bio->bi_end_io = failed_bio->bi_end_io;
495 bio->bi_sector = failrec->logical >> 9; 495 bio->bi_sector = failrec->logical >> 9;
496 bio->bi_bdev = failed_bio->bi_bdev; 496 bio->bi_bdev = failed_bio->bi_bdev;
497 bio->bi_size = 0;
497 bio_add_page(bio, page, failrec->len, start - page_offset(page)); 498 bio_add_page(bio, page, failrec->len, start - page_offset(page));
498 btrfs_submit_bio_hook(inode, READ, bio, failrec->last_mirror); 499 btrfs_submit_bio_hook(inode, READ, bio, failrec->last_mirror);
499 return 0; 500 return 0;
@@ -2187,12 +2188,9 @@ again:
2187 spin_unlock(&em_tree->lock); 2188 spin_unlock(&em_tree->lock);
2188 2189
2189 if (em) { 2190 if (em) {
2190 if (em->start > start) { 2191 if (em->start > start || em->start + em->len <= start)
2191 printk("get_extent lookup [%Lu %Lu] em [%Lu %Lu]\n", 2192 free_extent_map(em);
2192 start, len, em->start, em->len); 2193 else if (em->block_start == EXTENT_MAP_INLINE && page)
2193 WARN_ON(1);
2194 }
2195 if (em->block_start == EXTENT_MAP_INLINE && page)
2196 free_extent_map(em); 2194 free_extent_map(em);
2197 else 2195 else
2198 goto out; 2196 goto out;
@@ -2340,7 +2338,6 @@ insert:
2340 err = 0; 2338 err = 0;
2341 spin_lock(&em_tree->lock); 2339 spin_lock(&em_tree->lock);
2342 ret = add_extent_mapping(em_tree, em); 2340 ret = add_extent_mapping(em_tree, em);
2343
2344 /* it is possible that someone inserted the extent into the tree 2341 /* it is possible that someone inserted the extent into the tree
2345 * while we had the lock dropped. It is also possible that 2342 * while we had the lock dropped. It is also possible that
2346 * an overlapping map exists in the tree 2343 * an overlapping map exists in the tree
@@ -2348,6 +2345,11 @@ insert:
2348 if (ret == -EEXIST) { 2345 if (ret == -EEXIST) {
2349 struct extent_map *existing; 2346 struct extent_map *existing;
2350 existing = lookup_extent_mapping(em_tree, start, len); 2347 existing = lookup_extent_mapping(em_tree, start, len);
2348 if (existing && (existing->start > start ||
2349 existing->start + existing->len <= start)) {
2350 free_extent_map(existing);
2351 existing = NULL;
2352 }
2351 if (!existing) { 2353 if (!existing) {
2352 existing = lookup_extent_mapping(em_tree, em->start, 2354 existing = lookup_extent_mapping(em_tree, em->start,
2353 em->len); 2355 em->len);
@@ -2388,6 +2390,7 @@ out:
2388 return em; 2390 return em;
2389} 2391}
2390 2392
2393#if 0 /* waiting for O_DIRECT reads */
2391static int btrfs_get_block(struct inode *inode, sector_t iblock, 2394static int btrfs_get_block(struct inode *inode, sector_t iblock,
2392 struct buffer_head *bh_result, int create) 2395 struct buffer_head *bh_result, int create)
2393{ 2396{
@@ -2405,22 +2408,24 @@ static int btrfs_get_block(struct inode *inode, sector_t iblock,
2405 if (!em || IS_ERR(em)) 2408 if (!em || IS_ERR(em))
2406 goto out; 2409 goto out;
2407 2410
2408 if (em->start > start || em->start + em->len <= start) 2411 if (em->start > start || em->start + em->len <= start) {
2409 goto out; 2412 goto out;
2413 }
2410 2414
2411 if (em->block_start == EXTENT_MAP_INLINE) { 2415 if (em->block_start == EXTENT_MAP_INLINE) {
2412 ret = -EINVAL; 2416 ret = -EINVAL;
2413 goto out; 2417 goto out;
2414 } 2418 }
2415 2419
2420 len = em->start + em->len - start;
2421 len = min_t(u64, len, INT_LIMIT(typeof(bh_result->b_size)));
2422
2416 if (em->block_start == EXTENT_MAP_HOLE || 2423 if (em->block_start == EXTENT_MAP_HOLE ||
2417 em->block_start == EXTENT_MAP_DELALLOC) { 2424 em->block_start == EXTENT_MAP_DELALLOC) {
2425 bh_result->b_size = len;
2418 goto out; 2426 goto out;
2419 } 2427 }
2420 2428
2421 len = em->start + em->len - start;
2422 len = min_t(u64, len, INT_LIMIT(typeof(bh_result->b_size)));
2423
2424 logical = start - em->start; 2429 logical = start - em->start;
2425 logical = em->block_start + logical; 2430 logical = em->block_start + logical;
2426 2431
@@ -2430,6 +2435,7 @@ static int btrfs_get_block(struct inode *inode, sector_t iblock,
2430 BUG_ON(ret); 2435 BUG_ON(ret);
2431 bh_result->b_blocknr = multi->stripes[0].physical >> inode->i_blkbits; 2436 bh_result->b_blocknr = multi->stripes[0].physical >> inode->i_blkbits;
2432 bh_result->b_size = min(map_length, len); 2437 bh_result->b_size = min(map_length, len);
2438
2433 bh_result->b_bdev = multi->stripes[0].dev->bdev; 2439 bh_result->b_bdev = multi->stripes[0].dev->bdev;
2434 set_buffer_mapped(bh_result); 2440 set_buffer_mapped(bh_result);
2435 kfree(multi); 2441 kfree(multi);
@@ -2437,11 +2443,14 @@ out:
2437 free_extent_map(em); 2443 free_extent_map(em);
2438 return ret; 2444 return ret;
2439} 2445}
2446#endif
2440 2447
2441static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb, 2448static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
2442 const struct iovec *iov, loff_t offset, 2449 const struct iovec *iov, loff_t offset,
2443 unsigned long nr_segs) 2450 unsigned long nr_segs)
2444{ 2451{
2452 return -EINVAL;
2453#if 0
2445 struct file *file = iocb->ki_filp; 2454 struct file *file = iocb->ki_filp;
2446 struct inode *inode = file->f_mapping->host; 2455 struct inode *inode = file->f_mapping->host;
2447 2456
@@ -2450,6 +2459,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
2450 2459
2451 return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, 2460 return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
2452 offset, nr_segs, btrfs_get_block, NULL); 2461 offset, nr_segs, btrfs_get_block, NULL);
2462#endif
2453} 2463}
2454 2464
2455static sector_t btrfs_bmap(struct address_space *mapping, sector_t iblock) 2465static sector_t btrfs_bmap(struct address_space *mapping, sector_t iblock)
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 5619e50583e3..bccb5566fd84 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1161,7 +1161,6 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
1161 int total_devs = 1; 1161 int total_devs = 1;
1162 1162
1163 length = bio->bi_size; 1163 length = bio->bi_size;
1164
1165 map_tree = &root->fs_info->mapping_tree; 1164 map_tree = &root->fs_info->mapping_tree;
1166 map_length = length; 1165 map_length = length;
1167 1166
@@ -1192,6 +1191,7 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
1192 } 1191 }
1193 bio->bi_sector = multi->stripes[dev_nr].physical >> 9; 1192 bio->bi_sector = multi->stripes[dev_nr].physical >> 9;
1194 dev = multi->stripes[dev_nr].dev; 1193 dev = multi->stripes[dev_nr].dev;
1194
1195 bio->bi_bdev = dev->bdev; 1195 bio->bi_bdev = dev->bdev;
1196 spin_lock(&dev->io_lock); 1196 spin_lock(&dev->io_lock);
1197 dev->total_ios++; 1197 dev->total_ios++;