#include #include #include #include #include #include #include #include #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<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); #if 0 generic_unplug_device(rq); kmsg("Unplugged request queue..\n"); #endif 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"); 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);