aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilan Broz <mbroz@redhat.com>2008-12-03 06:55:08 -0500
committerJens Axboe <jens.axboe@oracle.com>2008-12-03 06:55:55 -0500
commit0e435ac26e3f951d83338ed3d4ab7dc0fe0055bc (patch)
tree8f208a3093de1a314a981ae47e5ef92a5909c13b
parent53a08807c01989c6847bb135d8d43f61c5dfdda5 (diff)
block: fix setting of max_segment_size and seg_boundary mask
Fix setting of max_segment_size and seg_boundary mask for stacked md/dm devices. When stacking devices (LVM over MD over SCSI) some of the request queue parameters are not set up correctly in some cases by default, namely max_segment_size and and seg_boundary mask. If you create MD device over SCSI, these attributes are zeroed. Problem become when there is over this mapping next device-mapper mapping - queue attributes are set in DM this way: request_queue max_segment_size seg_boundary_mask SCSI 65536 0xffffffff MD RAID1 0 0 LVM 65536 -1 (64bit) Unfortunately bio_add_page (resp. bio_phys_segments) calculates number of physical segments according to these parameters. During the generic_make_request() is segment cout recalculated and can increase bio->bi_phys_segments count over the allowed limit. (After bio_clone() in stack operation.) Thi is specially problem in CCISS driver, where it produce OOPS here BUG_ON(creq->nr_phys_segments > MAXSGENTRIES); (MAXSEGENTRIES is 31 by default.) Sometimes even this command is enough to cause oops: dd iflag=direct if=/dev/<vg>/<lv> of=/dev/null bs=128000 count=10 This command generates bios with 250 sectors, allocated in 32 4k-pages (last page uses only 1024 bytes). For LVM layer, it allocates bio with 31 segments (still OK for CCISS), unfortunatelly on lower layer it is recalculated to 32 segments and this violates CCISS restriction and triggers BUG_ON(). The patch tries to fix it by: * initializing attributes above in queue request constructor blk_queue_make_request() * make sure that blk_queue_stack_limits() inherits setting (DM uses its own function to set the limits because it blk_queue_stack_limits() was introduced later. It should probably switch to use generic stack limit function too.) * sets the default seg_boundary value in one place (blkdev.h) * use this mask as default in DM (instead of -1, which differs in 64bit) Bugs related to this: https://bugzilla.redhat.com/show_bug.cgi?id=471639 http://bugzilla.kernel.org/show_bug.cgi?id=8672 Signed-off-by: Milan Broz <mbroz@redhat.com> Reviewed-by: Alasdair G Kergon <agk@redhat.com> Cc: Neil Brown <neilb@suse.de> Cc: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Cc: Tejun Heo <htejun@gmail.com> Cc: Mike Miller <mike.miller@hp.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r--block/blk-core.c2
-rw-r--r--block/blk-settings.c4
-rw-r--r--drivers/md/dm-table.c2
-rw-r--r--include/linux/blkdev.h2
4 files changed, 8 insertions, 2 deletions
diff --git a/block/blk-core.c b/block/blk-core.c
index 7a779d7c69c9..c36aa98fafa3 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -592,7 +592,7 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
592 1 << QUEUE_FLAG_STACKABLE); 592 1 << QUEUE_FLAG_STACKABLE);
593 q->queue_lock = lock; 593 q->queue_lock = lock;
594 594
595 blk_queue_segment_boundary(q, 0xffffffff); 595 blk_queue_segment_boundary(q, BLK_SEG_BOUNDARY_MASK);
596 596
597 blk_queue_make_request(q, __make_request); 597 blk_queue_make_request(q, __make_request);
598 blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE); 598 blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE);
diff --git a/block/blk-settings.c b/block/blk-settings.c
index 41392fbe19ff..afa55e14e278 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -125,6 +125,9 @@ void blk_queue_make_request(struct request_queue *q, make_request_fn *mfn)
125 q->nr_requests = BLKDEV_MAX_RQ; 125 q->nr_requests = BLKDEV_MAX_RQ;
126 blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS); 126 blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
127 blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS); 127 blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
128 blk_queue_segment_boundary(q, BLK_SEG_BOUNDARY_MASK);
129 blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE);
130
128 q->make_request_fn = mfn; 131 q->make_request_fn = mfn;
129 q->backing_dev_info.ra_pages = 132 q->backing_dev_info.ra_pages =
130 (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE; 133 (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
@@ -314,6 +317,7 @@ void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)
314 /* zero is "infinity" */ 317 /* zero is "infinity" */
315 t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors); 318 t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);
316 t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors); 319 t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors);
320 t->seg_boundary_mask = min_not_zero(t->seg_boundary_mask, b->seg_boundary_mask);
317 321
318 t->max_phys_segments = min(t->max_phys_segments, b->max_phys_segments); 322 t->max_phys_segments = min(t->max_phys_segments, b->max_phys_segments);
319 t->max_hw_segments = min(t->max_hw_segments, b->max_hw_segments); 323 t->max_hw_segments = min(t->max_hw_segments, b->max_hw_segments);
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index a63161aec487..04e5fd742c2c 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -668,7 +668,7 @@ static void check_for_valid_limits(struct io_restrictions *rs)
668 if (!rs->max_segment_size) 668 if (!rs->max_segment_size)
669 rs->max_segment_size = MAX_SEGMENT_SIZE; 669 rs->max_segment_size = MAX_SEGMENT_SIZE;
670 if (!rs->seg_boundary_mask) 670 if (!rs->seg_boundary_mask)
671 rs->seg_boundary_mask = -1; 671 rs->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK;
672 if (!rs->bounce_pfn) 672 if (!rs->bounce_pfn)
673 rs->bounce_pfn = -1; 673 rs->bounce_pfn = -1;
674} 674}
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 9cc7cc5fdce1..6dcd30d806cd 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -918,6 +918,8 @@ extern void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter);
918 918
919#define MAX_SEGMENT_SIZE 65536 919#define MAX_SEGMENT_SIZE 65536
920 920
921#define BLK_SEG_BOUNDARY_MASK 0xFFFFFFFFUL
922
921#define blkdev_entry_to_request(entry) list_entry((entry), struct request, queuelist) 923#define blkdev_entry_to_request(entry) list_entry((entry), struct request, queuelist)
922 924
923static inline int queue_hardsect_size(struct request_queue *q) 925static inline int queue_hardsect_size(struct request_queue *q)