]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.suse/md-bitmap-sub-page-chunks
Updated xen patches taken from suse.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.suse / md-bitmap-sub-page-chunks
1 From: Neil Brown <neilb@suse.de>
2 Subject: md: Allow write-intent bitmaps to have chunksize < PAGE_SIZE
3 Patch-mainline: no
4 References: 459557
5
6 md currently insists that the chunk size used for write-intent
7 bitmaps (the amount of data that corresponds to one chunk)
8 be at least one page.
9
10 The reason for this list restriction is lost in the mists of time,
11 but a review of the code (and a vague memory) suggests that the only
12 problem would be related to resync. Resync tries very hard to
13 work in multiples of a page, but also needs to sync with units
14 of a bitmap_chunk too.
15
16 This connection comes out in the bitmap_start_sync call.
17
18 So change bitmap_start_sync to always work in multiples of a page.
19 If the bitmap chunk size is less that one page, we flag multiple
20 chunks as 'syncing' and generally make them all appear to the
21 resync routines like one chunk.
22
23 All other code either already works with data ranges that could
24 span multiple chunks, or explicitly only cares about a single chunk.
25
26 This is needed because some architectures use 64K pages in SLES11
27 where they used 4K pages in SLES10. So arrays created on SLES10
28 might not work with SLES11 without this change.
29
30 Also, the default chunk size is 4K, and so newly create arrays
31 that use the default will not work.
32
33 Signed-off-by: Neil Brown <neilb@suse.de>
34
35 ---
36 drivers/md/bitmap.c | 41 ++++++++++++++++++++++++++++++++---------
37 1 file changed, 32 insertions(+), 9 deletions(-)
38
39 --- a/drivers/md/bitmap.c
40 +++ b/drivers/md/bitmap.c
41 @@ -110,13 +110,12 @@ static int bitmap_checkpage(struct bitma
42 {
43 unsigned char *mappage;
44
45 - if (page >= bitmap->pages) {
46 - printk(KERN_ALERT
47 - "%s: invalid bitmap page request: %lu (> %lu)\n",
48 - bmname(bitmap), page, bitmap->pages-1);
49 + if (page >= bitmap->pages)
50 + /* This can happen if bitmap_start_sync goes beyond
51 + * End-of-device while looking for a whole page.
52 + * It is harmless.
53 + */
54 return -EINVAL;
55 - }
56 -
57
58 if (bitmap->bp[page].hijacked) /* it's hijacked, don't try to alloc */
59 return 0;
60 @@ -571,7 +570,7 @@ static int bitmap_read_sb(struct bitmap
61 else if (le32_to_cpu(sb->version) < BITMAP_MAJOR_LO ||
62 le32_to_cpu(sb->version) > BITMAP_MAJOR_HI)
63 reason = "unrecognized superblock version";
64 - else if (chunksize < PAGE_SIZE)
65 + else if (chunksize < 512)
66 reason = "bitmap chunksize too small";
67 else if ((1 << ffz(~chunksize)) != chunksize)
68 reason = "bitmap chunksize not a power of 2";
69 @@ -1347,8 +1346,8 @@ void bitmap_endwrite(struct bitmap *bitm
70 }
71 }
72
73 -int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks,
74 - int degraded)
75 +static int __bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks,
76 + int degraded)
77 {
78 bitmap_counter_t *bmc;
79 int rv;
80 @@ -1376,6 +1375,30 @@ int bitmap_start_sync(struct bitmap *bit
81 return rv;
82 }
83
84 +int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks,
85 + int degraded)
86 +{
87 + /* bitmap_start_sync must always report on multiples of whole
88 + * pages, otherwise resync (which is very PAGE_SIZE based) will
89 + * get confused.
90 + * So call __bitmap_start_sync repeatedly (if needed) until
91 + * At least PAGE_SIZE>>9 blocks are covered.
92 + * Return the 'or' of the result.
93 + */
94 + int rv = 0;
95 + int blocks1;
96 +
97 + *blocks = 0;
98 + while (*blocks < (PAGE_SIZE>>9)) {
99 + rv |= __bitmap_start_sync(bitmap, offset,
100 + &blocks1, degraded);
101 + offset += blocks1;
102 + *blocks += blocks1;
103 + }
104 + return rv;
105 +}
106 +
107 +
108 void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted)
109 {
110 bitmap_counter_t *bmc;