1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
| #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/blkdev.h> #include <linux/genhd.h> #include <linux/hdreg.h> #include <linux/vmalloc.h> #include <linux/bio.h>
#define RAMDISK_SECTOR_SIZE 512 #define RAMDISK_SIZE (1024 * 1024 * 10) // 10MB
static int major_num = 0; static struct request_queue *queue; static struct gendisk *disk; static unsigned char *ramdisk_data;
#if 0 static void ramdisk_transfer(struct request *req) { struct bio_vec bvec; struct req_iterator iter; sector_t pos = blk_rq_pos(req); unsigned int num_sectors = blk_rq_sectors(req); unsigned int offset = pos * RAMDISK_SECTOR_SIZE; ///< unsigned int nbytes = num_sectors * RAMDISK_SECTOR_SIZE;
rq_for_each_segment(bvec, req, iter) { void *buffer = page_address(bvec.bv_page) + bvec.bv_offset; if (rq_data_dir(req) == READ) { memcpy(buffer, ramdisk_data + offset, bvec.bv_len); } else { memcpy(ramdisk_data + offset, buffer, bvec.bv_len); } offset += bvec.bv_len; } } #endif
static blk_qc_t ramdisk_make_request(struct request_queue *q, struct bio *bio) { bio_endio(bio); return BLK_QC_T_NONE; }
static int ramdisk_open(struct block_device *bdev, fmode_t mode) { printk("open ramdisk ..."); return 0; }
static void ramdisk_release(struct gendisk *gd, fmode_t mode) { printk("close ramdisk ..."); }
static struct block_device_operations fops = { .owner = THIS_MODULE, .open = ramdisk_open, .release = ramdisk_release, };
static int __init ramdisk_init(void) { ramdisk_data = vmalloc(RAMDISK_SIZE); if (!ramdisk_data) { return -ENOMEM; }
major_num = register_blkdev(0, "ramdisk"); if (major_num <= 0) { vfree(ramdisk_data); return -EBUSY; }
queue = blk_alloc_queue(GFP_KERNEL); if (!queue) { unregister_blkdev(major_num, "ramdisk"); vfree(ramdisk_data); return -ENOMEM; }
blk_queue_make_request(queue, ramdisk_make_request); disk = alloc_disk(1); if (!disk) { blk_cleanup_queue(queue); unregister_blkdev(major_num, "ramdisk"); vfree(ramdisk_data); return -ENOMEM; }
strcpy(disk->disk_name, "ramdisk0"); disk->major = major_num; disk->first_minor = 0; disk->fops = &fops; disk->queue = queue; set_capacity(disk, RAMDISK_SIZE / RAMDISK_SECTOR_SIZE); add_disk(disk);
return 0; }
static void __exit ramdisk_exit(void) { del_gendisk(disk); put_disk(disk); blk_cleanup_queue(queue); unregister_blkdev(major_num, "ramdisk"); vfree(ramdisk_data); }
module_init(ramdisk_init); module_exit(ramdisk_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("lpyuan"); MODULE_DESCRIPTION("RAM Disk Block Device Driver");
|