Re: md linear personality oops on boot with 2.6.10-rc1-mm4 and 2.6.10-rc1-mm5

From: Neil Brown
Date: Sat Nov 13 2004 - 02:26:17 EST


On Friday November 12, thunder7@xxxxxxxxx wrote:
>
> In 2.6.9-mm1, this works.
> In 2.6.10-rc1-mm4 and 2.6.10-rc1-mm5, I get an oops during boot:
>
> linear_run+0x20b
>

Thanks. Looks like an unsigned variable going negative:-(
I made the mistake of only testing it with a linear array with all
components the same size.

Please verify that this patch fixes it.

Thanks,
NeilBrown


###Comments for ChangeSet
Fix problem with unsigned variable going "negative" in linear.c

We replace 'size' by 'start'.
'start' means exactly the same as 'curr_offset - size', and
the equivalence of the new code can be tested based on this.
The difference is that 'start' will never be negative and so can
fit in a 'sector_t' while 'size' could be negative.

Also make curr_offset sector_t, as it should have been.

Signed-off-by: Neil Brown <neilb@xxxxxxxxxxxxxxx>

### Diffstat output
./drivers/md/linear.c | 21 +++++++++++----------
1 files changed, 11 insertions(+), 10 deletions(-)

diff ./drivers/md/linear.c~current~ ./drivers/md/linear.c
--- ./drivers/md/linear.c~current~ 2004-11-13 17:34:23.000000000 +1100
+++ ./drivers/md/linear.c 2004-11-13 18:18:17.000000000 +1100
@@ -117,8 +117,8 @@ static int linear_run (mddev_t *mddev)
struct linear_hash *table;
mdk_rdev_t *rdev;
int i, nb_zone, cnt;
- sector_t size;
- unsigned int curr_offset;
+ sector_t start;
+ sector_t curr_offset;
struct list_head *tmp;

conf = kmalloc (sizeof (*conf) + mddev->raid_disks*sizeof(dev_info_t),
@@ -193,23 +193,24 @@ static int linear_run (mddev_t *mddev)
* Here we generate the linear hash table
*/
table = conf->hash_table;
- size = 0;
+ start = 0;
curr_offset = 0;
for (i = 0; i < cnt; i++) {
dev_info_t *disk = conf->disks + i;

+ if (start > curr_offset)
+ table[-1].dev1 = disk;
+
disk->offset = curr_offset;
curr_offset += disk->size;

- if (size < 0) {
- table[-1].dev1 = disk;
- }
- size += disk->size;
-
- while (size>0) {
+ /* 'curr_offset' is the end of this disk
+ * 'start' is the start of table
+ */
+ while (start < curr_offset) {
table->dev0 = disk;
table->dev1 = NULL;
- size -= conf->smallest->size;
+ start += conf->smallest->size;
table++;
}
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/