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

📄 ubd_kern.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
 * happen on CPU 0. */int intr_count = 0;/* call ubd_finish if you need to serialize */static void __ubd_finish(struct request *req, int error){	int nsect;	if(error){		end_request(req, 0);		return;	}	nsect = req->current_nr_sectors;	req->sector += nsect;	req->buffer += nsect << 9;	req->errors = 0;	req->nr_sectors -= nsect;	req->current_nr_sectors = 0;	end_request(req, 1);}static inline void ubd_finish(struct request *req, int error){ 	spin_lock(&ubd_io_lock);	__ubd_finish(req, error);	spin_unlock(&ubd_io_lock);}/* Called without ubd_io_lock held */static void ubd_handler(void){	struct io_thread_req req;	struct request *rq = elv_next_request(ubd_queue);	int n;	do_ubd = NULL;	intr_count++;	n = os_read_file(thread_fd, &req, sizeof(req));	if(n != sizeof(req)){		printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "		       "err = %d\n", os_getpid(), -n);		spin_lock(&ubd_io_lock);		end_request(rq, 0);		spin_unlock(&ubd_io_lock);		return;	}        	ubd_finish(rq, req.error);	reactivate_fd(thread_fd, UBD_IRQ);		do_ubd_request(ubd_queue);}static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused){	ubd_handler();	return(IRQ_HANDLED);}/* Only changed by ubd_init, which is an initcall. */static int io_pid = -1;void kill_io_thread(void){	if(io_pid != -1) 		os_kill_process(io_pid, 1);}__uml_exitcall(kill_io_thread);static int ubd_file_size(struct ubd *dev, __u64 *size_out){	char *file;	file = dev->cow.file ? dev->cow.file : dev->file;	return(os_file_size(file, size_out));}static void ubd_close(struct ubd *dev){	os_close_file(dev->fd);	if(dev->cow.file == NULL)		return;	os_close_file(dev->cow.fd);	vfree(dev->cow.bitmap);	dev->cow.bitmap = NULL;}static int ubd_open_dev(struct ubd *dev){	struct openflags flags;	char **back_ptr;	int err, create_cow, *create_ptr;	dev->openflags = dev->boot_openflags;	create_cow = 0;	create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL;	back_ptr = dev->no_cow ? NULL : &dev->cow.file;	dev->fd = open_ubd_file(dev->file, &dev->openflags, back_ptr,				&dev->cow.bitmap_offset, &dev->cow.bitmap_len, 				&dev->cow.data_offset, create_ptr);	if((dev->fd == -ENOENT) && create_cow){		dev->fd = create_cow_file(dev->file, dev->cow.file, 					  dev->openflags, 1 << 9, PAGE_SIZE,					  &dev->cow.bitmap_offset, 					  &dev->cow.bitmap_len,					  &dev->cow.data_offset);		if(dev->fd >= 0){			printk(KERN_INFO "Creating \"%s\" as COW file for "			       "\"%s\"\n", dev->file, dev->cow.file);		}	}	if(dev->fd < 0){		printk("Failed to open '%s', errno = %d\n", dev->file,		       -dev->fd);		return(dev->fd);	}	if(dev->cow.file != NULL){		err = -ENOMEM;		dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len);		if(dev->cow.bitmap == NULL){			printk(KERN_ERR "Failed to vmalloc COW bitmap\n");			goto error;		}		flush_tlb_kernel_vm();		err = read_cow_bitmap(dev->fd, dev->cow.bitmap, 				      dev->cow.bitmap_offset, 				      dev->cow.bitmap_len);		if(err < 0)			goto error;		flags = dev->openflags;		flags.w = 0;		err = open_ubd_file(dev->cow.file, &flags, NULL, NULL, NULL, 				    NULL, NULL);		if(err < 0) goto error;		dev->cow.fd = err;	}	return(0); error:	os_close_file(dev->fd);	return(err);}static int ubd_new_disk(int major, u64 size, int unit,			struct gendisk **disk_out)			{	struct gendisk *disk;	char from[sizeof("ubd/nnnnn\0")], to[sizeof("discnnnnn/disc\0")];	int err;	disk = alloc_disk(1 << UBD_SHIFT);	if(disk == NULL)		return(-ENOMEM);	disk->major = major;	disk->first_minor = unit << UBD_SHIFT;	disk->fops = &ubd_blops;	set_capacity(disk, size / 512);	if(major == MAJOR_NR){		sprintf(disk->disk_name, "ubd%c", 'a' + unit);		sprintf(disk->devfs_name, "ubd/disc%d", unit);		sprintf(from, "ubd/%d", unit);		sprintf(to, "disc%d/disc", unit);		err = devfs_mk_symlink(from, to);		if(err)			printk("ubd_new_disk failed to make link from %s to "			       "%s, error = %d\n", from, to, err);	}	else {		sprintf(disk->disk_name, "ubd_fake%d", unit);		sprintf(disk->devfs_name, "ubd_fake/disc%d", unit);	}	/* sysfs register (not for ide fake devices) */	if (major == MAJOR_NR) {		ubd_dev[unit].pdev.id   = unit;		ubd_dev[unit].pdev.name = DRIVER_NAME;		platform_device_register(&ubd_dev[unit].pdev);		disk->driverfs_dev = &ubd_dev[unit].pdev.dev;	}	disk->private_data = &ubd_dev[unit];	disk->queue = ubd_queue;	add_disk(disk);	*disk_out = disk;	return 0;}#define ROUND_BLOCK(n) ((n + ((1 << 9) - 1)) & (-1 << 9))static int ubd_add(int n){	struct ubd *dev = &ubd_dev[n];	int err;	err = -ENODEV;	if(dev->file == NULL)		goto out;	if (ubd_open_dev(dev))		goto out;	err = ubd_file_size(dev, &dev->size);	if(err < 0)		goto out_close;	dev->size = ROUND_BLOCK(dev->size);	err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]);	if(err) 		goto out_close; 	if(fake_major != MAJOR_NR)		ubd_new_disk(fake_major, dev->size, n, 			     &fake_gendisk[n]);	/* perhaps this should also be under the "if (fake_major)" above */	/* using the fake_disk->disk_name and also the fakehd_set name */	if (fake_ide)		make_ide_entries(ubd_gendisk[n]->disk_name);	err = 0;out_close:	ubd_close(dev);out:	return err;}static int ubd_config(char *str){	int n, err;	str = uml_strdup(str);	if(str == NULL){		printk(KERN_ERR "ubd_config failed to strdup string\n");		return(1);	}	err = ubd_setup_common(str, &n);	if(err){		kfree(str);		return(-1);	}	if(n == -1) return(0); 	spin_lock(&ubd_lock);	err = ubd_add(n);	if(err)		ubd_dev[n].file = NULL; 	spin_unlock(&ubd_lock);	return(err);}static int ubd_get_config(char *name, char *str, int size, char **error_out){	struct ubd *dev;	int n, len = 0;	n = parse_unit(&name);	if((n >= MAX_DEV) || (n < 0)){		*error_out = "ubd_get_config : device number out of range";		return(-1);	}	dev = &ubd_dev[n];	spin_lock(&ubd_lock);	if(dev->file == NULL){		CONFIG_CHUNK(str, size, len, "", 1);		goto out;	}	CONFIG_CHUNK(str, size, len, dev->file, 0);	if(dev->cow.file != NULL){		CONFIG_CHUNK(str, size, len, ",", 0);		CONFIG_CHUNK(str, size, len, dev->cow.file, 1);	}	else CONFIG_CHUNK(str, size, len, "", 1); out:	spin_unlock(&ubd_lock);	return(len);}static int ubd_id(char **str, int *start_out, int *end_out){        int n;	n = parse_unit(str);        *start_out = 0;        *end_out = MAX_DEV - 1;        return n;}static int ubd_remove(int n){	struct ubd *dev;	int err = -ENODEV;	spin_lock(&ubd_lock);	if(ubd_gendisk[n] == NULL)		goto out;	dev = &ubd_dev[n];	if(dev->file == NULL)		goto out;	/* you cannot remove a open disk */	err = -EBUSY;	if(dev->count > 0)		goto out;	del_gendisk(ubd_gendisk[n]);	put_disk(ubd_gendisk[n]);	ubd_gendisk[n] = NULL;	if(fake_gendisk[n] != NULL){		del_gendisk(fake_gendisk[n]);		put_disk(fake_gendisk[n]);		fake_gendisk[n] = NULL;	}	platform_device_unregister(&dev->pdev);	*dev = ((struct ubd) DEFAULT_UBD);	err = 0;out:	spin_unlock(&ubd_lock);	return err;}static struct mc_device ubd_mc = {	.name		= "ubd",	.config		= ubd_config, 	.get_config	= ubd_get_config,	.id		= ubd_id,	.remove		= ubd_remove,};static int ubd_mc_init(void){	mconsole_register_dev(&ubd_mc);	return 0;}__initcall(ubd_mc_init);static struct platform_driver ubd_driver = {	.driver = {		.name  = DRIVER_NAME,	},};int ubd_init(void){        int i;	devfs_mk_dir("ubd");	if (register_blkdev(MAJOR_NR, "ubd"))		return -1;	ubd_queue = blk_init_queue(do_ubd_request, &ubd_io_lock);	if (!ubd_queue) {		unregister_blkdev(MAJOR_NR, "ubd");		return -1;	}			if (fake_major != MAJOR_NR) {		char name[sizeof("ubd_nnn\0")];		snprintf(name, sizeof(name), "ubd_%d", fake_major);		devfs_mk_dir(name);		if (register_blkdev(fake_major, "ubd"))			return -1;	}	platform_driver_register(&ubd_driver);	for (i = 0; i < MAX_DEV; i++) 		ubd_add(i);	return 0;}late_initcall(ubd_init);int ubd_driver_init(void){	unsigned long stack;	int err;	/* Set by CONFIG_BLK_DEV_UBD_SYNC or ubd=sync.*/	if(global_openflags.s){		printk(KERN_INFO "ubd: Synchronous mode\n");		/* Letting ubd=sync be like using ubd#s= instead of ubd#= is		 * enough. So use anyway the io thread. */	}	stack = alloc_stack(0, 0);	io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *), 				 &thread_fd);	if(io_pid < 0){		printk(KERN_ERR 		       "ubd : Failed to start I/O thread (errno = %d) - "		       "falling back to synchronous I/O\n", -io_pid);		io_pid = -1;		return(0);	}	err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, 			     SA_INTERRUPT, "ubd", ubd_dev);	if(err != 0)		printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);	return(err);}device_initcall(ubd_driver_init);static int ubd_open(struct inode *inode, struct file *filp){	struct gendisk *disk = inode->i_bdev->bd_disk;	struct ubd *dev = disk->private_data;	int err = 0;	if(dev->count == 0){		err = ubd_open_dev(dev);		if(err){			printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n",			       disk->disk_name, dev->file, -err);			goto out;		}	}	dev->count++;	set_disk_ro(disk, !dev->openflags.w);	/* This should no more be needed. And it didn't work anyway to exclude	 * read-write remounting of filesystems.*/	/*if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){	        if(--dev->count == 0) ubd_close(dev);	        err = -EROFS;	}*/ out:	return(err);}static int ubd_release(struct inode * inode, struct file * file){	struct gendisk *disk = inode->i_bdev->bd_disk;	struct ubd *dev = disk->private_data;	if(--dev->count == 0)		ubd_close(dev);	return(0);}static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,			  __u64 *cow_offset, unsigned long *bitmap,			  __u64 bitmap_offset, unsigned long *bitmap_words,			  __u64 bitmap_len){	__u64 sector = io_offset >> 9;	int i, update_bitmap = 0;	for(i = 0; i < length >> 9; i++){

⌨️ 快捷键说明

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