#include #include #include #include static wait_queue_head_t read_wq; static struct timer_list ptimer; static void *copy_to; static unsigned long max_copy; void timer_function( unsigned long p ) { struct kiocb *iocb = (struct kiocb *)p; if( !kiocbIsCancelled( iocb ) ) { kick_iocb(iocb); } else { printk("iocb is cancelled ...\n"); } return; } static int driver_cancel( struct kiocb *iocb, struct io_event *event ) { printk("driver_cancel ...\n"); del_timer( &ptimer ); kiocbSetCancelled( iocb ); aio_complete( iocb, -1, 0 ); return 0; } static long driver_retry( struct kiocb *iocb ) { printk("driver_retry ...\n"); if( copy_to ) copy_to_user(copy_to, "Hello World",(max_copy>12)?12:max_copy); aio_put_req(iocb); return (max_copy>12)?12:max_copy; } static ssize_t driver_aioread(struct kiocb *iocb, char __user *buf, size_t count, loff_t offset) { printk( "driver_aioread(%p,%p,%d)\n", iocb, buf, count ); copy_to = (void *)buf; max_copy = count; iocb->ki_cancel = driver_cancel; iocb->ki_retry = driver_retry; ptimer.function = timer_function; ptimer.data = (unsigned long)iocb; ptimer.expires = jiffies + (2*HZ); add_timer( &ptimer ); return -EIOCBQUEUED; } static struct file_operations fops = { .owner=THIS_MODULE, .aio_read=driver_aioread, }; static int __init async_init(void) { if(register_chrdev(240, "async_test", &fops) == 0) { init_waitqueue_head( &read_wq ); init_timer( &ptimer ); return 0; }; return -EIO; } static void __exit async_exit(void) { del_timer_sync( &ptimer ); unregister_chrdev(240,"async_test"); } module_init( async_init ); module_exit( async_exit ); MODULE_LICENSE("GPL");