⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vdisk.c

📁 vdisk-v2 source vdisk-v2 source
💻 C
字号:
/* * vdisk.c - virtual disk driver * * Copyright 2008 (C) weiqin (qinwei1998@hotmail.com) * * This code is based in part on ramdisk driver , only for teching * * This software is distributed under the terms of the GNU General * Public License ("GPL") as published by the Free Software Foundation, * either version 2 of that License or (at your option) any later version. * */#include <linux/string.h>#include <linux/slab.h>#include <asm/atomic.h>#include <linux/bio.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/init.h>#include <linux/pagemap.h>#include <linux/blkdev.h>#include <linux/genhd.h>#include <linux/buffer_head.h>	#include <linux/backing-dev.h>#include <linux/blkpg.h>#include <linux/writeback.h>#include <asm/uaccess.h>#ifdef VDISK_DEBUG#define dprintk(fmt, args...) printk(fmt, ## args)#else#define dprintk(fmt, args...) /* not debugging: nothing */#endif#define VDISK_MAJOR  254#define VDISK_SIZE   (2*1024*1024)#define SECTOR_SIZE  (512)static unsigned char vdisk_mem[VDISK_SIZE];/* Various static variables go here.  Most are used only in the vdisk code. */static struct gendisk *vdisks;static struct block_device *vdisk_bdev;/* Protected device data */static struct request_queue *vdisk_queue;static int vdisk_blkdev_IO(int rw, struct bio_vec *vec, sector_t sector){	pgoff_t index = sector >> (PAGE_CACHE_SHIFT - 9);	unsigned int vec_offset = vec->bv_offset;	int offset = (sector << 9) & ~PAGE_CACHE_MASK;	int size = vec->bv_len;	char * accessoffset;	dprintk("start: sectors=%d, vec_offset=%d, offset=%d, size=%d\n", (int)sector, vec_offset, offset, size);		do{		int count;		char *src;		char *dst;		count = PAGE_CACHE_SIZE - offset;		if (count > size)			count = size;		size -= count;		accessoffset = vdisk_mem + ( index * PAGE_SIZE );		index++;		if (rw == READ) {			src = accessoffset + offset;			dst = kmap_atomic(vec->bv_page, KM_USER1) + vec_offset;		} else {			src = kmap_atomic(vec->bv_page, KM_USER0) + vec_offset;			dst = accessoffset + offset;		}		offset = 0;		vec_offset += count;		dprintk("rw=%d, sectors=%d, vec_offset=%d, offset=%d, size=%d\n", rw, (int)sector, vec_offset, offset, size);		memcpy(dst, src, count);		if( rw == READ ){			flush_dcache_page(vec->bv_page);			kunmap_atomic(dst, KM_USER1);		}else{			kunmap_atomic(src, KM_USER0);		}	}while( size );	return 0;}static int vdisk_make_request(struct request_queue *q, struct bio *bio){	struct block_device *bdev = bio->bi_bdev;	sector_t sector = bio->bi_sector;	unsigned long len = bio->bi_size >> 9;	int rw = bio_data_dir(bio);	struct bio_vec *bvec;	int ret = 0, i;	if (sector + len > get_capacity(bdev->bd_disk))		goto fail;	if (rw==READA)		rw=READ;	bio_for_each_segment(bvec, bio, i) {		ret |= vdisk_blkdev_IO(rw, bvec, sector);		sector += bvec->bv_len >> 9;	}	if (ret)		goto fail;	bio_endio(bio, bio->bi_size, 0);	return 0;fail:	bio_io_error(bio, bio->bi_size);	return 0;} static int vdisk_ioctl(struct inode *inode, struct file *file,			unsigned int cmd, unsigned long arg){	return 0;}static int vdisk_open(struct inode *inode, struct file *filp){	struct block_device *bdev = inode->i_bdev;	unsigned bsize;	vdisk_bdev = bdev;	bsize = bdev_hardsect_size(bdev);	bdev->bd_block_size = bsize;	return 0;}static struct block_device_operations vdisk_bd_op = {	.owner =	THIS_MODULE,	.open =		vdisk_open,	.ioctl =	vdisk_ioctl,};/* * This is the registration and initialization section of the vdisk driver */static int vdisk_major = 0;static int __init vdisk_init(void){	int err = -ENOMEM;	struct gendisk *disk;	vdisks = alloc_disk(1);	if (!vdisks)		goto out;		vdisk_queue = blk_alloc_queue(GFP_KERNEL);	if (!vdisk_queue) {		put_disk(vdisks);		goto out;	}		vdisk_major = register_blkdev(VDISK_MAJOR, "vdisk");	if ( vdisk_major<0 ) {		put_disk(vdisks);		blk_cleanup_queue(vdisk_queue);		err = -EIO;		goto out;	}		blk_queue_make_request(vdisk_queue, &vdisk_make_request);	blk_queue_hardsect_size(vdisk_queue, 512);		disk = vdisks;	disk->major = VDISK_MAJOR;	disk->first_minor = 0;	disk->fops = &vdisk_bd_op;	disk->queue = vdisk_queue;	disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;	sprintf(disk->disk_name, "vdisk");	set_capacity(disk, VDISK_SIZE/SECTOR_SIZE);	add_disk(vdisks);		memset(vdisk_mem, 0, VDISK_SIZE);	printk("VDISK driver initialized, vdisk_major= %d\n", vdisk_major);	return 0;out:	put_disk(vdisks);	blk_cleanup_queue(vdisk_queue);	return err;}static void __exit vdisk_cleanup(void){	struct block_device *bdev = vdisk_bdev;	vdisk_bdev = NULL;	if (bdev) {		invalidate_bdev(bdev);		blkdev_put(bdev);	}	del_gendisk(vdisks);	put_disk(vdisks);	blk_cleanup_queue(vdisk_queue);	unregister_blkdev(VDISK_MAJOR, "vdisk");}module_init(vdisk_init);module_exit(vdisk_cleanup);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -