From: Dan A. <da...@gm...> - 2004-02-15 22:20:39
|
On Sat, Feb 14, 2004 at 08:07:32PM -0600, Richard Goodwin wrote: > On one of my systems I'm having some problems adding a new cobd device. I > tried using Sean's 4gb image, mounted via the xml, used fdisk to put a > partition on it, but then mke2fs (or ext3) bombs out with "Invalid argument > zeroing block 536846320 at end of filesystem". fdisk, cfdisk, and sfdisk all > report that the partitions I create are screwy, like -19349 blocks or > something. > > I tried creating a 3gb image by copy /b the Debian 1gb image, but the same > problem happens (different block sizes of course). sfdisk -g (get geometry) > says the kernel can't determine the geometry. > > I've done this fine on my work system but doesn't appear to be working on > the home system. I actually already have a cobd0, cobd1, and cobd2, so this > makes cobd3. Has anyone else run into this? This patch on top of the 0.5.3/linux/patch should address the problem. It turns out that cobd was passing wrong information about the device's size to userspace. Userspace gets the size of the disk in hardsects and that can only fit into an unsigned long. The previous calculation was overflowing. Tested this with a newly created 3gb image, and it seems to be okay. diff -u linux/drivers/block/cobd.c linux/drivers/block/cobd.c --- linux/drivers/block/cobd.c 2004-02-14 01:54:01.000000000 +0200 +++ linux/drivers/block/cobd.c 2004-02-16 00:04:44.000000000 +0200 @@ -39,7 +39,7 @@ unsigned int cmd, unsigned long arg) { int err; - long size; + unsigned long size; int dev; dev = MINOR(inode->i_rdev); @@ -55,8 +55,8 @@ if (err) return -EFAULT; - size = (cobd_sizes[dev] * 1024) / cobd_hardsects[dev]; - if (copy_to_user((long *) arg, &size, sizeof (long))) + size = (cobd_sizes[dev]) * (1024 / cobd_hardsects[dev]); + if (copy_to_user((unsigned long *) arg, &size, sizeof (unsigned long))) return -EFAULT; return 0; @@ -139,7 +139,7 @@ co_request->type = CO_BLOCK_READ; else co_request->type = CO_BLOCK_WRITE; - co_request->offset = req->sector * PBD_BLOCK_SIZE; + co_request->offset = ((unsigned long long)req->sector) * PBD_BLOCK_SIZE; co_request->size = req->current_nr_sectors * PBD_BLOCK_SIZE; co_request->address = req->buffer; co_request->rc = 0; @@ -211,6 +211,7 @@ co_block_request_t *request; unsigned long flags; unsigned long long size = 0; + long rc = 0; local_irq_save(flags); co_passage_page->operation = CO_OPERATION_DEVICE; @@ -219,10 +220,17 @@ request = (co_block_request_t *)&co_passage_page->params[2]; request->type = CO_BLOCK_STAT; co_switch(); + rc = request->rc; size = request->disk_size; local_irq_restore(flags); - cobd_sizes[i] = size / 1024; + if (!rc) { + /* Request successed */ + cobd_sizes[i] = size / 1024; + } else { + cobd_sizes[i] = 0; + } + cobd_blksizes[i] = PAGE_SIZE; cobd_hardsects[i] = PBD_BLOCK_SIZE; } -- Dan Aloni da...@gm... |