]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.fixes/blk-set-segment-boundary-mask
Fix oinkmaster patch.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.fixes / blk-set-segment-boundary-mask
CommitLineData
2cb7cef9
BS
1Subject: block: fix setting of max_segment_size and seg_boundary mask
2From: Milan Broz <mbroz@redhat.com>
3Date: Wed Dec 3 12:55:55 2008 +0100:
4Git: 0e435ac26e3f951d83338ed3d4ab7dc0fe0055bc
5
6Fix setting of max_segment_size and seg_boundary mask for stacked md/dm
7devices.
8
9When stacking devices (LVM over MD over SCSI) some of the request queue
10parameters are not set up correctly in some cases by default, namely
11max_segment_size and and seg_boundary mask.
12
13If you create MD device over SCSI, these attributes are zeroed.
14
15Problem become when there is over this mapping next device-mapper mapping
16- queue attributes are set in DM this way:
17
18request_queue max_segment_size seg_boundary_mask
19SCSI 65536 0xffffffff
20MD RAID1 0 0
21LVM 65536 -1 (64bit)
22
23Unfortunately bio_add_page (resp. bio_phys_segments) calculates number of
24physical segments according to these parameters.
25
26During the generic_make_request() is segment cout recalculated and can
27increase bio->bi_phys_segments count over the allowed limit. (After
28bio_clone() in stack operation.)
29
30Thi is specially problem in CCISS driver, where it produce OOPS here
31
32 BUG_ON(creq->nr_phys_segments > MAXSGENTRIES);
33
34(MAXSEGENTRIES is 31 by default.)
35
36Sometimes even this command is enough to cause oops:
37
38 dd iflag=direct if=/dev/<vg>/<lv> of=/dev/null bs=128000 count=10
39
40This command generates bios with 250 sectors, allocated in 32 4k-pages
41(last page uses only 1024 bytes).
42
43For LVM layer, it allocates bio with 31 segments (still OK for CCISS),
44unfortunatelly on lower layer it is recalculated to 32 segments and this
45violates CCISS restriction and triggers BUG_ON().
46
47The patch tries to fix it by:
48
49 * initializing attributes above in queue request constructor
50 blk_queue_make_request()
51
52 * make sure that blk_queue_stack_limits() inherits setting
53
54 (DM uses its own function to set the limits because it
55 blk_queue_stack_limits() was introduced later. It should probably switch
56 to use generic stack limit function too.)
57
58 * sets the default seg_boundary value in one place (blkdev.h)
59
60 * use this mask as default in DM (instead of -1, which differs in 64bit)
61
62Bugs related to this:
63https://bugzilla.redhat.com/show_bug.cgi?id=471639
64http://bugzilla.kernel.org/show_bug.cgi?id=8672
65
66Signed-off-by: Milan Broz <mbroz@redhat.com>
67Reviewed-by: Alasdair G Kergon <agk@redhat.com>
68Cc: Neil Brown <neilb@suse.de>
69Cc: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
70Cc: Tejun Heo <htejun@gmail.com>
71Cc: Mike Miller <mike.miller@hp.com>
72Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
73Signed-off-by: Hannes Reinecke <hare@suse.de>
74
75---
76 block/blk-core.c | 2 +-
77 block/blk-settings.c | 4 ++++
78 drivers/md/dm-table.c | 2 +-
79 include/linux/blkdev.h | 2 ++
80 4 files changed, 8 insertions(+), 2 deletions(-)
81
82--- a/block/blk-core.c
83+++ b/block/blk-core.c
84@@ -596,7 +596,7 @@ blk_init_queue_node(request_fn_proc *rfn
85 1 << QUEUE_FLAG_STACKABLE);
86 q->queue_lock = lock;
87
88- blk_queue_segment_boundary(q, 0xffffffff);
89+ blk_queue_segment_boundary(q, BLK_SEG_BOUNDARY_MASK);
90
91 blk_queue_make_request(q, __make_request);
92 blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE);
93--- a/block/blk-settings.c
94+++ b/block/blk-settings.c
95@@ -125,6 +125,9 @@ void blk_queue_make_request(struct reque
96 q->nr_requests = BLKDEV_MAX_RQ;
97 blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS);
98 blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS);
99+ blk_queue_segment_boundary(q, BLK_SEG_BOUNDARY_MASK);
100+ blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE);
101+
102 q->make_request_fn = mfn;
103 q->backing_dev_info.ra_pages =
104 (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
105@@ -314,6 +317,7 @@ void blk_queue_stack_limits(struct reque
106 /* zero is "infinity" */
107 t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);
108 t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors);
109+ t->seg_boundary_mask = min_not_zero(t->seg_boundary_mask, b->seg_boundary_mask);
110
111 t->max_phys_segments = min(t->max_phys_segments, b->max_phys_segments);
112 t->max_hw_segments = min(t->max_hw_segments, b->max_hw_segments);
113--- a/drivers/md/dm-table.c
114+++ b/drivers/md/dm-table.c
115@@ -687,7 +687,7 @@ static void check_for_valid_limits(struc
116 if (!rs->max_segment_size)
117 rs->max_segment_size = MAX_SEGMENT_SIZE;
118 if (!rs->seg_boundary_mask)
119- rs->seg_boundary_mask = -1;
120+ rs->seg_boundary_mask = BLK_SEG_BOUNDARY_MASK;
121 if (!rs->bounce_pfn)
122 rs->bounce_pfn = -1;
123 }
124--- a/include/linux/blkdev.h
125+++ b/include/linux/blkdev.h
126@@ -908,6 +908,8 @@ extern void blk_set_cmd_filter_defaults(
127
128 #define MAX_SEGMENT_SIZE 65536
129
130+#define BLK_SEG_BOUNDARY_MASK 0xFFFFFFFFUL
131+
132 #define blkdev_entry_to_request(entry) list_entry((entry), struct request, queuelist)
133
134 static inline int queue_hardsect_size(struct request_queue *q)