Index: linux-2.6.33-source/include/linux/major.h =================================================================== --- linux-2.6.33-source.orig/include/linux/major.h +++ linux-2.6.33-source/include/linux/major.h @@ -131,6 +131,7 @@ #define VIOCD_MAJOR 113 #define ATARAID_MAJOR 114 +#define COLINUX_MAJOR 117 #define SCSI_DISK8_MAJOR 128 #define SCSI_DISK9_MAJOR 129 Index: linux-2.6.33-source/drivers/block/Kconfig =================================================================== --- linux-2.6.33-source.orig/drivers/block/Kconfig +++ linux-2.6.33-source/drivers/block/Kconfig @@ -383,6 +383,15 @@ will prevent RAM block device backing store memory from being allocated from highmem (only a problem for highmem systems). +config BLK_DEV_COBD + tristate 'Cooperative block device support' + default y + depends on COOPERATIVE + help + Virtual block device support for cooperative kernels. + + If unsure, say Y. + config CDROM_PKTCDVD tristate "Packet writing on CD/DVD media" depends on !UML Index: linux-2.6.33-source/drivers/block/Makefile =================================================================== --- linux-2.6.33-source.orig/drivers/block/Makefile +++ linux-2.6.33-source/drivers/block/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o obj-$(CONFIG_BLK_DEV_RAM) += brd.o +obj-$(CONFIG_BLK_DEV_COBD) += cobd.o obj-$(CONFIG_BLK_DEV_LOOP) += loop.o obj-$(CONFIG_BLK_DEV_XD) += xd.o obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o Index: linux-2.6.33-source/drivers/block/cobd.c =================================================================== --- linux-2.6.33-source.orig/drivers/block/cobd.c +++ linux-2.6.33-source/drivers/block/cobd.c @@ -44,7 +44,6 @@ long rc; co_passage_page_assert_valid(); - co_passage_page_acquire(&flags); co_passage_page->operation = CO_OPERATION_DEVICE; co_passage_page->params[0] = CO_DEVICE_BLOCK; @@ -70,21 +69,21 @@ return cobd_request(cobd, CO_BLOCK_GET_ALIAS, out_request); } -static int cobd_ioctl(struct inode * inode, struct file * file, +static int cobd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { return -ENOTTY; /* unknown command */ } -static int cobd_open(struct inode *inode, struct file *file) +static int cobd_open(struct block_device *bdev, fmode_t mode) { - struct cobd_device *cobd = (struct cobd_device *)(inode->i_bdev->bd_disk->private_data); + struct cobd_device *cobd = bdev->bd_disk->private_data; co_block_request_t *co_request; co_block_request_t stat_request; unsigned long flags; int result; - if (cobd->device && cobd->device != inode->i_bdev) + if (cobd->device && cobd->device != bdev) return -EBUSY; if (cobd->refcount == 0) { @@ -96,7 +95,6 @@ result = 0; co_passage_page_assert_valid(); - co_passage_page_acquire(&flags); co_passage_page->operation = CO_OPERATION_DEVICE; co_passage_page->params[0] = CO_DEVICE_BLOCK; @@ -114,22 +112,21 @@ return result; if (cobd->refcount == 1) { - set_capacity(inode->i_bdev->bd_disk, stat_request.disk_size >> hardsect_size_shift); - cobd->device = inode->i_bdev; + set_capacity(bdev->bd_disk, stat_request.disk_size >> hardsect_size_shift); + cobd->device = bdev; } return 0; } -static int cobd_release(struct inode *inode, struct file *file) +static int cobd_release(struct gendisk *disk, fmode_t mode) { - struct cobd_device *cobd = (struct cobd_device *)(inode->i_bdev->bd_disk->private_data); + struct cobd_device *cobd = disk->private_data; co_block_request_t *co_request; unsigned long flags; int ret = 0; co_passage_page_assert_valid(); - co_passage_page_acquire(&flags); co_passage_page->operation = CO_OPERATION_DEVICE; co_passage_page->params[0] = CO_DEVICE_BLOCK; @@ -151,14 +148,17 @@ /* * Handle an I/O request. */ -static int cobd_transfer(struct cobd_device *cobd, struct request *req, int *async) +static void cobd_transfer(struct request_queue *q, struct request *req) { + struct cobd_device *cobd = (struct cobd_device *)(req->rq_disk->private_data); co_block_request_t *co_request; unsigned long flags; + int async; int ret; - co_passage_page_assert_valid(); +next_segment: + co_passage_page_assert_valid(); co_passage_page_acquire(&flags); co_passage_page->operation = CO_OPERATION_DEVICE; co_passage_page->params[0] = CO_DEVICE_BLOCK; @@ -166,47 +166,43 @@ co_request = (co_block_request_t *)&co_passage_page->params[2]; co_request->type = (rq_data_dir(req) == READ) ? CO_BLOCK_READ : CO_BLOCK_WRITE; co_request->irq_request = req; - co_request->offset = ((unsigned long long)(req->sector)) << hardsect_size_shift; - co_request->size = req->current_nr_sectors << hardsect_size_shift; + co_request->offset = ((unsigned long long)blk_rq_pos(req)) << hardsect_size_shift; + co_request->size = blk_rq_cur_bytes(req); co_request->address = req->buffer; co_request->rc = 0; co_request->async = 0; co_switch_wrapper(); - *async = co_request->async; + async = co_request->async; ret = co_request->rc; - co_passage_page_release(flags); - return ret; + + /* + * OK: ret == 0 + * FAIL: ret == -1 + */ + if (ret == CO_BLOCK_REQUEST_RETCODE_OK) { + if (async) + return; /* wait for interrupt */ + + if (__blk_end_request_cur(req, 0)) + goto next_segment; + + } else { + __blk_end_request_all(req, -EIO); + } } -static void do_cobd_request(request_queue_t *q) +static void do_cobd_request(struct request_queue *q) { struct request *req; - struct cobd_device *cobd; - - while ((req = elv_next_request(q)) != NULL) { - int ret; - int async; + while ((req = blk_fetch_request(q)) != NULL) { if (!blk_fs_request(req)) { - end_request(req, 0); + __blk_end_request_all(req, -EIO); continue; } - cobd = (struct cobd_device *)(req->rq_disk->private_data); - - ret = cobd_transfer(cobd, req, &async); - /* - * OK: ret == 0 --> uptodate = 1 - * FAIL: ret == -1 --> uptodate = 0 - */ - if (ret == CO_BLOCK_REQUEST_RETCODE_OK) { - if (async) - break; /* wait for interrupt */ - end_request(req, 1); - } else { - end_request(req, 0); - } + cobd_transfer(q, req); } } @@ -231,8 +227,10 @@ BUG_ON(!req); spin_lock(&cobd_lock); - end_request(req, intr->uptodate); - do_cobd_request(req->q); + if (__blk_end_request_cur(req, intr->uptodate ? 0 : -EIO)) + cobd_transfer(req->q, req); /* next segment */ + else + do_cobd_request(req->q); spin_unlock(&cobd_lock); goto_next_message: @@ -284,7 +282,7 @@ if (!disk->queue) goto fail_malloc4; - blk_queue_hardsect_size(disk->queue, hardsect_size); + blk_queue_logical_block_size(disk->queue, hardsect_size); cobd->unit = i; disk->major = COLINUX_MAJOR; @@ -314,8 +312,7 @@ kfree(cobd_disks); fail_malloc: - if (unregister_blkdev(COLINUX_MAJOR, "cobd")) - printk(KERN_WARNING "cobd: cannot unregister blkdev\n"); + unregister_blkdev(COLINUX_MAJOR, "cobd"); fail_irq: free_irq(BLOCKDEV_IRQ, NULL); @@ -460,7 +457,7 @@ } cobd = &cobd_devs[cobd_unit]; - blk_queue_hardsect_size(disk->queue, hardsect_size); + blk_queue_logical_block_size(disk->queue, hardsect_size); disk->major = alias->major->number; disk->first_minor = alias->minor_start + index; disk->fops = &cobd_fops; @@ -514,8 +511,7 @@ put_disk(cobd_disks[i]); } - if (unregister_blkdev(COLINUX_MAJOR, "cobd")) - printk(KERN_WARNING "cobd: cannot unregister blkdev\n"); + unregister_blkdev(COLINUX_MAJOR, "cobd"); free_irq(BLOCKDEV_IRQ, NULL); kfree(cobd_disks);