rendered paste body#include <linux/module.h>#include <linux/proc_fs.h>#include <linux/jiffies.h>#include <linux/list.h>#include <asm/uaccess.h>#include <linux/config.h>#include <linux/genhd.h>#include <linux/blkdev.h>#define kmsg(...) printk("<2>btst:" __VA_ARGS__)static int btst_end_io(struct bio *bio, unsigned int bytes_done, int err){ int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); struct page *pg = bio->bi_io_vec[0].bv_page; request_queue_t *rq = bdev_get_queue(bio->bi_bdev); kmsg("end_io: bi_flags:0x%x bytes_done:%d err:%d\n", (int) bio->bi_flags, bytes_done, err); kmsg("end_io: bio{bdev:%p bicnt:%d private:%ld flags:0x%x rw:0x%x page:%p len:%d offset:%d sector:%ld size:%d " "vcnt:%d idx:%d endio:%p\n", bio->bi_bdev, atomic_read(&bio->bi_cnt), (long) bio->bi_private, (unsigned int) bio->bi_flags, (unsigned int) bio->bi_rw, bio->bi_io_vec[0].bv_page, bio->bi_io_vec[0].bv_len, bio->bi_io_vec[0].bv_offset, (unsigned long) bio->bi_sector, bio->bi_size, bio->bi_vcnt, bio->bi_idx, bio->bi_end_io); kmsg("end_io: [*] qflags:0x%x inflight:%d\n", (int) rq->queue_flags, rq->in_flight); if (bio->bi_size) return 1; kmsg("end_io: uptodate:%d\n", uptodate); if (!uptodate) kmsg("end_io: IO page not uptodate!!\n"); //end_page_writeback(pg); /* verify this */ unlock_page(pg); kmsg("end_io: unlocked page\n"); bio_put(bio); kmsg("end_io: IO done!:)\n"); return 0;}static struct bio *btst_build_bio(struct block_device *bdev, struct page *page){ struct bio *bio;#define DFILE "/dev/sdc2"#define SECT 0#define DSTR "YYYYYYYYYYYY" //bio = bio_alloc(GFP_KERNEL, 1); bio = bio_alloc(GFP_NOIO, 1); if (bio) { kmsg("build_bio: bio:%p biocnt:%d\n", bio, atomic_read(&bio->bi_cnt)); bio->bi_bdev = bdev; bio->bi_sector = SECT; bio->bi_end_io = btst_end_io; //bio->bi_size = PAGE_SIZE; bio->bi_private = (void *) 7; // used here to store some dummy value for debugging purpose bio->bi_rw = (1<<BIO_RW_SYNC) | (1<<BIO_RW_BARRIER); if (!bio_add_page(bio, page, PAGE_SIZE, 0)) { kmsg("bio_add_page fialed!\n"); bio_put(bio); bio = NULL; } if (bio) kmsg("build_bio: bi_flags:0x%x\n", (int) bio->bi_flags);/* bio->bi_io_vec[0].bv_page = page; bio->bi_io_vec[0].bv_len = PAGE_SIZE; bio->bi_io_vec[0].bv_offset = 0; bio->bi_vcnt = 1; bio->bi_idx = 0; bio->bi_rw = WRITE; bio->bi_rw = WRITE | 0x10; bio->bi_flags = 0;*/ } return bio;}static int btst_dev_write(void){ struct file *fp; struct page *pg; struct block_device *bdev; struct bio *bio; char *ka; request_queue_t *rq; fp = filp_open(DFILE, O_RDWR|O_LARGEFILE, 0); if (IS_ERR(fp)) { kmsg("filp_open " DFILE " failed..\n"); return -1; } bdev = I_BDEV(fp->f_mapping->host); kmsg("dev_write: device: " DFILE " sector: %d DSTR: \"" DSTR "\"\n", SECT); kmsg("dev_write: file{refcnt:%d mode:0x%x\n", atomic_read(&fp->f_count), fp->f_mode); kmsg("dev_write: bdev[bdev:%p hd_struct:%p gendisk:%p backing_dev_info:%p]\n", bdev, bdev->bd_part, bdev->bd_disk, bdev->bd_inode_backing_dev_info); pg = alloc_page(GFP_NOIO | __GFP_ZERO); //pg = alloc_page(GFP_KERNEL); if (!pg) { kmsg("dev_write: get_free_page failed!\n"); return -1; } ka = pfn_to_kaddr(page_to_pfn(pg)); kmsg("dev_write: pagre_address: page:%p ka:%p\n", pg, ka); strcpy(ka, DSTR); bio = btst_build_bio(bdev, pg); if (!bio) { kmsg("dev_write: build_bio failed!\n"); __free_page(pg); return -1; } kmsg("dev_write: nrsects: %d\n", bio_sectors(bio)); rq = bdev_get_queue(bdev); kmsg("dev_write: hardsectsiz:%d\n", rq->hardsect_size); kmsg("dev_write: [1] qflags:0x%x inflight:%d\n", (int) rq->queue_flags, rq->in_flight);// set_bit(QUEUE_FLAG_ELVSWITCH, &rq->queue_flags);// kmsg("dev_write: [2] qflags:0x%x inflight:%d\n", (int) rq->queue_flags, rq->in_flight);#if 0 spin_lock_irq(rq->queue_lock); //blk_plug_device(rq); blk_stop_queue(rq); spin_unlock_irq(rq->queue_lock); kmsg("Stopped request queue..\n");#endif kmsg("dev_write: [1] unp_thresh:%d unp_delay:%ld last_mrg:%p\n", rq->unplug_thresh, rq->unplug_delay, rq->last_merge); rq->last_merge = NULL; rq->unplug_thresh = 0; rq->unplug_delay = 0; kmsg("dev_write: [2] unp_thresh:%d unp_delay:%ld last_mrg:%p\n", rq->unplug_thresh, rq->unplug_delay, rq->last_merge); lock_page(pg); //set_page_writeback(pg); kmsg("dev_write: locked page\n"); bio_get(bio); submit_bio(WRITE, bio); kmsg("dev_write: submitted bio..\n"); if (bio_flagged(bio, BIO_EOPNOTSUPP)) kmsg("dev_write: bio_flagged BIO_EOPNOTSUPP\n"); bio_put(bio); kmsg("dev_write: wait-on-page-locking..\n"); wait_on_page_locked(pg); kmsg("dev_write: [3] qflags:0x%x inflight:%d\n", (int) rq->queue_flags, rq->in_flight); __free_page(pg); kmsg("dev_write: freed page\n");#if 0 generic_unplug_device(rq); kmsg("Unplugged request queue..\n");#endif return 0;}int btst_proc_init(void){ return btst_dev_write();}void btst_proc_exit(void){ kmsg("btst_proc_exit: exiting..\n");}module_init(btst_proc_init);module_exit(btst_proc_exit);