diff options
author | David Dillow <dillowda@ornl.gov> | 2011-01-20 17:44:22 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-20 20:02:05 -0500 |
commit | 20d9600cb407b0b55fef6ee814b60345c6f58264 (patch) | |
tree | a023082339b33c55e8def552abecd441ffe92fb5 /fs | |
parent | 82478fb7bca28e3ca2f3c55c14e690f749dd4dbb (diff) |
fs/direct-io.c: don't try to allocate more than BIO_MAX_PAGES in a bio
When using devices that support max_segments > BIO_MAX_PAGES (256), direct
IO tries to allocate a bio with more pages than allowed, which leads to an
oops in dio_bio_alloc(). Clamp the request to the supported maximum, and
change dio_bio_alloc() to reflect that bio_alloc() will always return a
bio when called with __GFP_WAIT and a valid number of vectors.
[akpm@linux-foundation.org: remove redundant BUG_ON()]
Signed-off-by: David Dillow <dillowda@ornl.gov>
Reviewed-by: Jeff Moyer <jmoyer@redhat.com>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/direct-io.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/fs/direct-io.c b/fs/direct-io.c index 85882f6ba5f7..b044705eedd4 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
@@ -325,12 +325,16 @@ void dio_end_io(struct bio *bio, int error) | |||
325 | } | 325 | } |
326 | EXPORT_SYMBOL_GPL(dio_end_io); | 326 | EXPORT_SYMBOL_GPL(dio_end_io); |
327 | 327 | ||
328 | static int | 328 | static void |
329 | dio_bio_alloc(struct dio *dio, struct block_device *bdev, | 329 | dio_bio_alloc(struct dio *dio, struct block_device *bdev, |
330 | sector_t first_sector, int nr_vecs) | 330 | sector_t first_sector, int nr_vecs) |
331 | { | 331 | { |
332 | struct bio *bio; | 332 | struct bio *bio; |
333 | 333 | ||
334 | /* | ||
335 | * bio_alloc() is guaranteed to return a bio when called with | ||
336 | * __GFP_WAIT and we request a valid number of vectors. | ||
337 | */ | ||
334 | bio = bio_alloc(GFP_KERNEL, nr_vecs); | 338 | bio = bio_alloc(GFP_KERNEL, nr_vecs); |
335 | 339 | ||
336 | bio->bi_bdev = bdev; | 340 | bio->bi_bdev = bdev; |
@@ -342,7 +346,6 @@ dio_bio_alloc(struct dio *dio, struct block_device *bdev, | |||
342 | 346 | ||
343 | dio->bio = bio; | 347 | dio->bio = bio; |
344 | dio->logical_offset_in_bio = dio->cur_page_fs_offset; | 348 | dio->logical_offset_in_bio = dio->cur_page_fs_offset; |
345 | return 0; | ||
346 | } | 349 | } |
347 | 350 | ||
348 | /* | 351 | /* |
@@ -583,8 +586,9 @@ static int dio_new_bio(struct dio *dio, sector_t start_sector) | |||
583 | goto out; | 586 | goto out; |
584 | sector = start_sector << (dio->blkbits - 9); | 587 | sector = start_sector << (dio->blkbits - 9); |
585 | nr_pages = min(dio->pages_in_io, bio_get_nr_vecs(dio->map_bh.b_bdev)); | 588 | nr_pages = min(dio->pages_in_io, bio_get_nr_vecs(dio->map_bh.b_bdev)); |
589 | nr_pages = min(nr_pages, BIO_MAX_PAGES); | ||
586 | BUG_ON(nr_pages <= 0); | 590 | BUG_ON(nr_pages <= 0); |
587 | ret = dio_bio_alloc(dio, dio->map_bh.b_bdev, sector, nr_pages); | 591 | dio_bio_alloc(dio, dio->map_bh.b_bdev, sector, nr_pages); |
588 | dio->boundary = 0; | 592 | dio->boundary = 0; |
589 | out: | 593 | out: |
590 | return ret; | 594 | return ret; |