mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 07:50:53 +07:00
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>
This commit is contained in:
parent
53a08807c0
commit
0e435ac26e
@ -592,7 +592,7 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
|
|||||||
1 << QUEUE_FLAG_STACKABLE);
|
1 << QUEUE_FLAG_STACKABLE);
|
||||||
q->queue_lock = lock;
|
q->queue_lock = lock;
|
||||||
|
|
||||||
blk_queue_segment_boundary(q, 0xffffffff);
|
blk_queue_segment_boundary(q, BLK_SEG_BOUNDARY_MASK);
|
||||||
|
|
||||||
blk_queue_make_request(q, __make_request);
|
blk_queue_make_request(q, __make_request);
|
||||||
blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE);
|
blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE);
|
||||||
|
@ -125,6 +125,9 @@ void blk_queue_make_request(struct request_queue *q, make_request_fn *mfn)
|
|||||||
q->nr_requests = BLKDEV_MAX_RQ;
|
q->nr_requests = BLKDEV_MAX_RQ;
|
||||||
blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
|
blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
|
||||||
blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
|
blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
|
||||||
|
blk_queue_segment_boundary(q, BLK_SEG_BOUNDARY_MASK);
|
||||||
|
blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE);
|
||||||
|
|
||||||
q->make_request_fn = mfn;
|
q->make_request_fn = mfn;
|
||||||
q->backing_dev_info.ra_pages =
|
q->backing_dev_info.ra_pages =
|
||||||
(VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
|
(VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
|
||||||
@ -314,6 +317,7 @@ void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)
|
|||||||
/* zero is "infinity" */
|
/* zero is "infinity" */
|
||||||
t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);
|
t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);
|
||||||
t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors);
|
t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors);
|
||||||
|
t->seg_boundary_mask = min_not_zero(t->seg_boundary_mask, b->seg_boundary_mask);
|
||||||
|
|
||||||
t->max_phys_segments = min(t->max_phys_segments, b->max_phys_segments);
|
t->max_phys_segments = min(t->max_phys_segments, b->max_phys_segments);
|
||||||
t->max_hw_segments = min(t->max_hw_segments, b->max_hw_segments);
|
t->max_hw_segments = min(t->max_hw_segments, b->max_hw_segments);
|
||||||
|
@ -668,7 +668,7 @@ static void check_for_valid_limits(struct io_restrictions *rs)
|
|||||||
if (!rs->max_segment_size)
|
if (!rs->max_segment_size)
|
||||||
rs->max_segment_size = MAX_SEGMENT_SIZE;
|
rs->max_segment_size = MAX_SEGMENT_SIZE;
|
||||||
if (!rs->seg_boundary_mask)
|
if (!rs->seg_boundary_mask)
|
||||||
rs->seg_boundary_mask = -1;
|
rs->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK;
|
||||||
if (!rs->bounce_pfn)
|
if (!rs->bounce_pfn)
|
||||||
rs->bounce_pfn = -1;
|
rs->bounce_pfn = -1;
|
||||||
}
|
}
|
||||||
|
@ -918,6 +918,8 @@ extern void blk_set_cmd_filter_defaults(struct blk_cmd_filter *filter);
|
|||||||
|
|
||||||
#define MAX_SEGMENT_SIZE 65536
|
#define MAX_SEGMENT_SIZE 65536
|
||||||
|
|
||||||
|
#define BLK_SEG_BOUNDARY_MASK 0xFFFFFFFFUL
|
||||||
|
|
||||||
#define blkdev_entry_to_request(entry) list_entry((entry), struct request, queuelist)
|
#define blkdev_entry_to_request(entry) list_entry((entry), struct request, queuelist)
|
||||||
|
|
||||||
static inline int queue_hardsect_size(struct request_queue *q)
|
static inline int queue_hardsect_size(struct request_queue *q)
|
||||||
|
Loading…
Reference in New Issue
Block a user