Hi! I am writing a very trivial module. It uses submit_bio to write a page to a device and then read it back. It works but submit_bio returns -5 error code when reading. Neverthless the data is correctly read! The uptodate bit of bi_flags also does not get set! I am using k 2.26.29 on UML x86_64. Any help? TIA /* * ptm_bio01.c * Using bio: * Write a page to device. * Read back that data. */ #include <linux/module.h> /* Needed by all modules */ #include <linux/kernel.h> /* Needed for KERN_INFO */ #include <linux/init.h> /* Needed for the macros */ #include <linux/blkdev.h> #define MY_BLOCK_SIZE PAGE_SIZE #define MODEFLAGS FMODE_READ|FMODE_WRITE /* Ex. FMODE_READ (inlude/linux/fs.h) for opening read-only */ #define DEV "/dev/loop2" MODULE_LICENSE("Dual BSD/GPL"); static struct bio *bio; static struct page *page; static struct block_device *bdev; static void end_bio_write_sync(struct bio *bio, int err) { printk(KERN_INFO "Entering end_bio_write_sync ...\n"); end_page_writeback(page); bio_put(bio); if (err) printk(KERN_INFO "end_bio_write_sync: Error n. %d\n",err); printk(KERN_INFO "Exiting end_bio_write_sync ...\n"); } static void end_bio_read_sync(struct bio *bio, int err) { int i; short *page_data=page_address(page); printk(KERN_INFO "Entering end_bio_read_sync ...\n"); /* *(int *)(bio->bi_private)=err; */ for (i=0;i<PAGE_SIZE/sizeof(*page_data);++i,page_data++) { if (*page_data!=i) { printk(KERN_INFO "Page data read does not match!!!\n"); break; } } if (i==PAGE_SIZE/sizeof(*page_data)) printk(KERN_INFO "Page data read OK!\n"); bio_put(bio); SetPageUptodate(page); unlock_page(page); if (err) printk(KERN_INFO "end_bio_read_sync: Error n. %d\n",err); printk(KERN_INFO "Exiting end_bio_read_sync ...\n"); } /* static int __init ptm_bio01_init(void) */ /* I removed "__init" because initialization is all this module does */ static int ptm_bio01_init(void) { int err=0; int flags=MODEFLAGS; short *page_data; int secsperpage=PAGE_SIZE/MY_BLOCK_SIZE; int i; printk(KERN_INFO "Writing a page - %d sectors\n",secsperpage); /* Get a block device */ /* I used THIS_MODULE. Usually put the fstype here. Everything it needs is a unique pointer of a owner */ bdev = open_bdev_exclusive(DEV, flags, THIS_MODULE); if (IS_ERR(bdev)) { err=PTR_ERR(bdev); printk(KERN_INFO "Could not open_bdev_exclusive\n"); goto fail1; } /* Alloc and fill a page */ page=alloc_page(GFP_NOFS); if (!page) { err=-ENOMEM; printk(KERN_INFO "Could not alloc_page\n"); goto fail2; } lock_page(page); page_data=page_address(page); if (!page_data) { err=-1; printk(KERN_INFO "Could not get the address of the page!!! Use kmap(?)\n"); goto fail3; } for (i=0;i<PAGE_SIZE/sizeof(*page_data);++i,page_data++) *page_data=i; /* Alloc the bio for n. sects per page sectors */ bio=bio_alloc(GFP_NOIO, secsperpage); if (!bio) { err=-ENOMEM; printk(KERN_INFO "Could not allocate a bio W\n"); goto fail3; } bio->bi_sector=1; /* Device address in 512 bytes sectors. 1 -> 512 bytes from beginning of disk. */ bio->bi_bdev=bdev; for (i=0;i<secsperpage;++i) { bio->bi_io_vec[i].bv_page=page; bio->bi_io_vec[i].bv_len=MY_BLOCK_SIZE; bio->bi_io_vec[i].bv_offset=i*MY_BLOCK_SIZE; } bio->bi_vcnt=secsperpage; /* how many bio_vec's */ bio->bi_idx=0; /* current index into bvl_vec */ bio->bi_size=PAGE_SIZE; /* residual I/O count */ bio->bi_end_io=end_bio_write_sync; /* bio->bi_private=&err; */ bio_get(bio); TestSetPageWriteback(page); unlock_page(page); submit_bio(WRITE, bio); if (bio_flagged(bio, BIO_EOPNOTSUPP)) { err=-EOPNOTSUPP; printk(KERN_INFO "Could not submit_bio W\n"); goto fail4; } wait_on_page_writeback(page); #if 1 bio_put(bio); bio=bio_alloc(GFP_KERNEL, secsperpage); if (!bio) { err=-ENOMEM; printk(KERN_INFO "Could not allocate a bio R\n"); goto fail3; } /* Read the page */ bio->bi_sector=1; /* Device address in 512 bytes sectors. 1 -> 512 bytes from beginning of disk. DDDD: Why 512 bytes? */ bio->bi_bdev=bdev; for (i=0;i<secsperpage;++i) { bio->bi_io_vec[i].bv_page=page; bio->bi_io_vec[i].bv_len=MY_BLOCK_SIZE; bio->bi_io_vec[i].bv_offset=i*MY_BLOCK_SIZE; } bio->bi_vcnt=secsperpage; /* how many bio_vec's */ bio->bi_idx=0; /* current index into bvl_vec */ bio->bi_size=PAGE_SIZE; /* residual I/O count */ #endif bio->bi_end_io=end_bio_read_sync; /* bio->bi_private=&err; */ bio->bi_rw=0; clear_bit(BIO_UPTODATE,&bio->bi_flags); bio_get(bio); lock_page(page); /* Clear the page */ page_data=page_address(page); if (!page_data) { unlock_page(page); err=-1; printk(KERN_INFO "Could not get the address of the page!!! Use kmap(?)\n"); goto fail4; } memset(page_data,0,PAGE_SIZE); ClearPageUptodate(page); /* go and read */ submit_bio(READ, bio); if (bio_flagged(bio, BIO_EOPNOTSUPP)) { err=-EOPNOTSUPP; printk(KERN_INFO "Could not submit_bio R\n"); goto fail4; } lock_page(page); page_data=page_address(page); if (!page_data) { err=-1; printk(KERN_INFO "Could not get the address of the page!!! Use kmap(?)\n"); goto fail4; } for (i=0;i<PAGE_SIZE/sizeof(*page_data);++i,page_data++) { if (*page_data!=i) { printk(KERN_INFO "Page data read does not match!!!\n"); break; } } if (i==PAGE_SIZE/sizeof(*page_data)) printk(KERN_INFO "Page data read OK!\n"); unlock_page(page); printk(KERN_INFO "Ending init!\n"); return 0; fail4: bio_put(bio); fail3: __free_page(page); page=NULL; fail2: close_bdev_exclusive(bdev,flags); bdev=NULL; fail1: if (err) printk(KERN_INFO "Error n. %d\n",err); return err; } static void __exit ptm_bio01_exit(void) { int flags=MODEFLAGS; /* Must be the same as in init */ if (atomic_read(&bio->bi_cnt)) { bio_put(bio); } if (page && atomic_read(&page->_count)) { __free_page(page); } if (bdev) close_bdev_exclusive(bdev,flags); printk(KERN_INFO "Going out ...\n"); } module_init(ptm_bio01_init); module_exit(ptm_bio01_exit); -- To unsubscribe from this list: send an email with "unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx Please read the FAQ at http://kernelnewbies.org/FAQ