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

📄 vdisk-multdev.c

📁 vdisk-v2 source vdisk-v2 source
💻 C
字号:
/* * vdisk-multdev.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 <linux/vmalloc.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)struct vdisk_struct{	struct gendisk *rd_disk;	struct block_device *rd_bdev;	struct request_queue *rd_queue;	unsigned char * vdisk_mem;};/* Various static variables go here.  Most are used only in the vdisk code. */#define CONFIG_BLK_DEV_VDISK_COUNT  3static struct vdisk_struct virtual_disks[CONFIG_BLK_DEV_VDISK_COUNT];static int vdisk_blkdev_IO(int rw, struct bio_vec *vec, sector_t sector, int devno){	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 = virtual_disks[devno].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;	unsigned int unit = iminor(bdev->bd_inode);	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, unit);		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;	unsigned unit = iminor(inode);	if (virtual_disks[unit].rd_bdev == NULL) {		virtual_disks[unit].rd_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;		int i;		for (i = 0; i < CONFIG_BLK_DEV_VDISK_COUNT; i++) {		virtual_disks[i].rd_disk = alloc_disk(1);		if (!virtual_disks[i].rd_disk)			goto out;		virtual_disks[i].rd_queue = blk_alloc_queue(GFP_KERNEL);		if (!virtual_disks[i].rd_queue) {			put_disk(virtual_disks[i].rd_disk);			goto out;		}		virtual_disks[i].vdisk_mem = vmalloc(VDISK_SIZE);		if (!virtual_disks[i].vdisk_mem) {			put_disk(virtual_disks[i].rd_disk);			blk_cleanup_queue(virtual_disks[i].rd_queue);			goto out;		}	}		vdisk_major = register_blkdev(VDISK_MAJOR, "vdisk");	if ( vdisk_major<0 ) {		err = -EIO;		goto out;	}	for (i = 0; i < CONFIG_BLK_DEV_VDISK_COUNT; i++) {		struct gendisk *disk;				blk_queue_make_request(virtual_disks[i].rd_queue, &vdisk_make_request);		blk_queue_hardsect_size(virtual_disks[i].rd_queue, 512);				disk = virtual_disks[i].rd_disk;		disk->major = VDISK_MAJOR;		disk->first_minor = i;		disk->fops = &vdisk_bd_op;		disk->queue = virtual_disks[i].rd_queue;		disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;		sprintf(disk->disk_name, "vdisk%d", i);		set_capacity(disk, VDISK_SIZE/SECTOR_SIZE);		add_disk(disk);	}		printk("VDISK driver initialized, vdisk_major= %d\n", vdisk_major);	return 0;out:	while (i--) {		put_disk(virtual_disks[i].rd_disk);		blk_cleanup_queue(virtual_disks[i].rd_queue);	}	return err;}static void __exit vdisk_cleanup(void){	int i;	for (i = 0; i < CONFIG_BLK_DEV_VDISK_COUNT; i++) {		struct block_device *bdev = virtual_disks[i].rd_bdev;		virtual_disks[i].rd_bdev = NULL;		if (bdev) {			invalidate_bdev(bdev);			blkdev_put(bdev);		}		del_gendisk(virtual_disks[i].rd_disk);		put_disk(virtual_disks[i].rd_disk);		blk_cleanup_queue(virtual_disks[i].rd_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 + -