From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jochen Oekonomopulos Subject: block i/o problem Date: Wed, 24 Jan 2007 01:19:04 +0100 Message-ID: <1169597944.45b6a5f859516@webmail.uni-konstanz.de> References: Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7BIT Return-path: Received: from guanin.uni-konstanz.de ([134.34.240.60]:39689 "EHLO guanin.uni-konstanz.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S965605AbXAXAwM (ORCPT ); Tue, 23 Jan 2007 19:52:12 -0500 Received: from purin.rz.uni-konstanz.de (purin.rz.uni-konstanz.de [134.34.240.45]) by guanin.uni-konstanz.de (Postfix) with ESMTP id 72C9F1649 for ; Wed, 24 Jan 2007 01:19:04 +0100 (CET) To: linux-fsdevel@vger.kernel.org In-Reply-To: Sender: linux-fsdevel-owner@vger.kernel.org List-Id: linux-fsdevel.vger.kernel.org Hello, I wrote a module to change the underlying block_device of a bio structure. It works, but the first processed page is always filled with junk. All the remaining pages are processed correctly. I tried it under a 2.6.8 and a 2.6.19 kernel. Does anybody has an idea what could be wrong? Thanks and regards, Jochen --- /** * * Test module to play around with the bio structure in order to * redirect a READ from one block device to another. * * **/ #define MAJOR_NR 241 #define KERNEL_SECTOR_SIZE 512 #include #include #include #include #include #include #include /* kmalloc */ #include /* printk() */ #include /* everything */ #include /* error codes */ #include /* size_t */ #include #include #include #include #include /* udelay(int); */ #include #include MODULE_LICENSE("GPL"); /* The sector size of the block device. */ static int sect_size = 512; struct pseudo_device { char * name; spinlock_t lock; struct request_queue *queue; struct gendisk *gendisk; struct block_device *bdev; }; // the test device struct pseudo_device *pd; int register_device(struct pseudo_device *); static int pd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { return 0; } static int pd_open(struct inode *inode, struct file *file) { return 0; } static struct block_device_operations pd_ops = { .owner = THIS_MODULE, .ioctl = pd_ioctl, .open = pd_open }; static int pd_transfer_request(struct pseudo_device *pd, struct request *req) { struct bio *bio; struct bio *cloned_bio; int nsect = 0; printk(KERN_WARNING "pd: pd_transfer_request\n"); rq_for_each_bio(bio, req) { // Extend the bio. //extended = extend_bio(bio, pd_device); //bio -> bi_bdev = pd_device -> bdev; cloned_bio = bio_clone(bio, GFP_NOIO); cloned_bio -> bi_private = bio; cloned_bio -> bi_bdev = pd -> bdev; if(bio_data_dir(cloned_bio) == WRITE) { submit_bio(WRITE, cloned_bio); } else { submit_bio(READ, cloned_bio); } nsect += cloned_bio->bi_size/KERNEL_SECTOR_SIZE; } return nsect; } static void pd_full_request(request_queue_t *q) { struct request *req; int sectors_xferred; struct pseudo_device *pd = q->queuedata; printk(KERN_WARNING "pd: pd_full_request\n"); while ((req = elv_next_request(q)) != NULL) { if (! blk_fs_request(req)) { printk (KERN_NOTICE "Skip non-fs request\n"); end_request(req, 0); continue; } sectors_xferred = pd_transfer_request(pd, req); if (! end_that_request_first(req, 1, sectors_xferred)) { blkdev_dequeue_request(req); end_that_request_last(req, 0); } } } static int pd_init(void) { printk(KERN_INFO "pd: Initialize pseudo module\n"); pd = kmalloc(sizeof(struct pseudo_device), GFP_KERNEL); memset(pd, 0, sizeof(*pd)); pd -> name = "pd1"; spin_lock_init(&pd->lock); //pd->queue = blk_init_queue(pd_full_request, &pd->lock); pd -> bdev = open_bdev_excl("/dev/sdb", 00000002, NULL); pd -> gendisk = alloc_disk(1); if(!pd -> gendisk) { printk(KERN_WARNING "pd: alloc_disk failure for control device.\n"); goto abort; } pd -> gendisk -> major = MAJOR_NR; pd -> gendisk -> first_minor = 0; pd -> gendisk -> fops = &pd_ops; pd -> gendisk -> private_data = &pd; strcpy(pd->gendisk -> disk_name, pd -> name); set_capacity(pd -> gendisk, (pd->bdev->bd_disk->capacity)); spin_lock_init(&pd -> lock); if( (pd -> queue = blk_init_queue(pd_full_request, &pd -> lock)) == NULL) { printk(KERN_WARNING "pd: register: no queue\n"); goto abort; } blk_queue_hardsect_size(pd -> queue, sect_size); pd -> queue -> queuedata = pd; pd -> gendisk -> queue = pd -> queue; add_disk(pd -> gendisk); /* Create device node in /dev/ */ /** * mknod seems not to work in kernel land. * "mknod /dev/pd1 b 241 0" does the job in the console. */ return 0; abort: return -1; } static void pd_exit(void) { printk(KERN_INFO "pd: Removing pseudo module from kernel\n"); if(pd -> gendisk) { del_gendisk(pd->gendisk); put_disk(pd->gendisk); } } module_init(pd_init); module_exit(pd_exit); My Makefile looks like this: obj-m += biomod.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean And after creating the device node with "mknod /dev/pd1 b 241 0", I try to read with: "dd if=/dev/pd1 of=./output count=2000" The error occurs, regardless of the values for count (and skip).