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

📄 ubd_kern.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) * Licensed under the GPL *//* 2001-09-28...2002-04-17 * Partition stuff by James_McMechan@hotmail.com * old style ubd by setting UBD_SHIFT to 0 * 2002-09-27...2002-10-18 massive tinkering for 2.5 * partitions have changed in 2.5 * 2003-01-29 more tinkering for 2.5.59-1 * This should now address the sysfs problems and has * the symlink for devfs to allow for booting with * the common /dev/ubd/discX/... names rather than * only /dev/ubdN/discN this version also has lots of * clean ups preparing for ubd-many. * James McMechan */#define MAJOR_NR UBD_MAJOR#define UBD_SHIFT 4#include "linux/config.h"#include "linux/module.h"#include "linux/blkdev.h"#include "linux/hdreg.h"#include "linux/init.h"#include "linux/devfs_fs_kernel.h"#include "linux/cdrom.h"#include "linux/proc_fs.h"#include "linux/ctype.h"#include "linux/capability.h"#include "linux/mm.h"#include "linux/vmalloc.h"#include "linux/blkpg.h"#include "linux/genhd.h"#include "linux/spinlock.h"#include "linux/platform_device.h"#include "asm/segment.h"#include "asm/uaccess.h"#include "asm/irq.h"#include "asm/types.h"#include "asm/tlbflush.h"#include "user_util.h"#include "mem_user.h"#include "kern_util.h"#include "kern.h"#include "mconsole_kern.h"#include "init.h"#include "irq_user.h"#include "irq_kern.h"#include "ubd_user.h"#include "os.h"#include "mem.h"#include "mem_kern.h"#include "cow.h"enum ubd_req { UBD_READ, UBD_WRITE };struct io_thread_req {	enum ubd_req op;	int fds[2];	unsigned long offsets[2];	unsigned long long offset;	unsigned long length;	char *buffer;	int sectorsize;	unsigned long sector_mask;	unsigned long long cow_offset;	unsigned long bitmap_words[2];	int error;};extern int open_ubd_file(char *file, struct openflags *openflags,			 char **backing_file_out, int *bitmap_offset_out,			 unsigned long *bitmap_len_out, int *data_offset_out,			 int *create_cow_out);extern int create_cow_file(char *cow_file, char *backing_file,			   struct openflags flags, int sectorsize,			   int alignment, int *bitmap_offset_out,			   unsigned long *bitmap_len_out,			   int *data_offset_out);extern int read_cow_bitmap(int fd, void *buf, int offset, int len);extern void do_io(struct io_thread_req *req);static inline int ubd_test_bit(__u64 bit, unsigned char *data){	__u64 n;	int bits, off;	bits = sizeof(data[0]) * 8;	n = bit / bits;	off = bit % bits;	return((data[n] & (1 << off)) != 0);}static inline void ubd_set_bit(__u64 bit, unsigned char *data){	__u64 n;	int bits, off;	bits = sizeof(data[0]) * 8;	n = bit / bits;	off = bit % bits;	data[n] |= (1 << off);}/*End stuff from ubd_user.h*/#define DRIVER_NAME "uml-blkdev"static DEFINE_SPINLOCK(ubd_io_lock);static DEFINE_SPINLOCK(ubd_lock);static void (*do_ubd)(void);static int ubd_open(struct inode * inode, struct file * filp);static int ubd_release(struct inode * inode, struct file * file);static int ubd_ioctl(struct inode * inode, struct file * file,		     unsigned int cmd, unsigned long arg);#define MAX_DEV (8)static struct block_device_operations ubd_blops = {        .owner		= THIS_MODULE,        .open		= ubd_open,        .release	= ubd_release,        .ioctl		= ubd_ioctl,};/* Protected by the queue_lock */static request_queue_t *ubd_queue;/* Protected by ubd_lock */static int fake_major = MAJOR_NR;static struct gendisk *ubd_gendisk[MAX_DEV];static struct gendisk *fake_gendisk[MAX_DEV]; #ifdef CONFIG_BLK_DEV_UBD_SYNC#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 1, .c = 0, \					 .cl = 1 })#else#define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 0, .c = 0, \					 .cl = 1 })#endif/* Not protected - changed only in ubd_setup_common and then only to * to enable O_SYNC. */static struct openflags global_openflags = OPEN_FLAGS;struct cow {	/* This is the backing file, actually */	char *file;	int fd;	unsigned long *bitmap;	unsigned long bitmap_len;	int bitmap_offset;        int data_offset;};struct ubd {	char *file;	int count;	int fd;	__u64 size;	struct openflags boot_openflags;	struct openflags openflags;	int no_cow;	struct cow cow;	struct platform_device pdev;};#define DEFAULT_COW { \	.file =			NULL, \        .fd =			-1, \        .bitmap =		NULL, \	.bitmap_offset =	0, \        .data_offset =		0, \}#define DEFAULT_UBD { \	.file = 		NULL, \	.count =		0, \	.fd =			-1, \	.size =			-1, \	.boot_openflags =	OPEN_FLAGS, \	.openflags =		OPEN_FLAGS, \        .no_cow =               0, \        .cow =			DEFAULT_COW, \}struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };static int ubd0_init(void){	struct ubd *dev = &ubd_dev[0];	if(dev->file == NULL)		dev->file = "root_fs";	return(0);}__initcall(ubd0_init);/* Only changed by fake_ide_setup which is a setup */static int fake_ide = 0;static struct proc_dir_entry *proc_ide_root = NULL;static struct proc_dir_entry *proc_ide = NULL;static void make_proc_ide(void){	proc_ide_root = proc_mkdir("ide", NULL);	proc_ide = proc_mkdir("ide0", proc_ide_root);}static int proc_ide_read_media(char *page, char **start, off_t off, int count,			       int *eof, void *data){	int len;	strcpy(page, "disk\n");	len = strlen("disk\n");	len -= off;	if (len < count){		*eof = 1;		if (len <= 0) return 0;	}	else len = count;	*start = page + off;	return len;}static void make_ide_entries(char *dev_name){	struct proc_dir_entry *dir, *ent;	char name[64];	if(proc_ide_root == NULL) make_proc_ide();	dir = proc_mkdir(dev_name, proc_ide);	if(!dir) return;	ent = create_proc_entry("media", S_IFREG|S_IRUGO, dir);	if(!ent) return;	ent->nlink = 1;	ent->data = NULL;	ent->read_proc = proc_ide_read_media;	ent->write_proc = NULL;	sprintf(name,"ide0/%s", dev_name);	proc_symlink(dev_name, proc_ide_root, name);}static int fake_ide_setup(char *str){	fake_ide = 1;	return(1);}__setup("fake_ide", fake_ide_setup);__uml_help(fake_ide_setup,"fake_ide\n""    Create ide0 entries that map onto ubd devices.\n\n");static int parse_unit(char **ptr){	char *str = *ptr, *end;	int n = -1;	if(isdigit(*str)) {		n = simple_strtoul(str, &end, 0);		if(end == str)			return(-1);		*ptr = end;	}	else if (('a' <= *str) && (*str <= 'h')) {		n = *str - 'a';		str++;		*ptr = str;	}	return(n);}static int ubd_setup_common(char *str, int *index_out){	struct ubd *dev;	struct openflags flags = global_openflags;	char *backing_file;	int n, err, i;	if(index_out) *index_out = -1;	n = *str;	if(n == '='){		char *end;		int major;		str++;		if(!strcmp(str, "sync")){			global_openflags = of_sync(global_openflags);			return(0);		}		major = simple_strtoul(str, &end, 0);		if((*end != '\0') || (end == str)){			printk(KERN_ERR 			       "ubd_setup : didn't parse major number\n");			return(1);		}		err = 1; 		spin_lock(&ubd_lock); 		if(fake_major != MAJOR_NR){ 			printk(KERN_ERR "Can't assign a fake major twice\n"); 			goto out1; 		}  		fake_major = major;		printk(KERN_INFO "Setting extra ubd major number to %d\n",		       major); 		err = 0; 	out1: 		spin_unlock(&ubd_lock);		return(err);	}	n = parse_unit(&str);	if(n < 0){		printk(KERN_ERR "ubd_setup : couldn't parse unit number "		       "'%s'\n", str);		return(1);	}	if(n >= MAX_DEV){		printk(KERN_ERR "ubd_setup : index %d out of range "		       "(%d devices, from 0 to %d)\n", n, MAX_DEV, MAX_DEV - 1);		return(1);	}	err = 1;	spin_lock(&ubd_lock);	dev = &ubd_dev[n];	if(dev->file != NULL){		printk(KERN_ERR "ubd_setup : device already configured\n");		goto out;	}	if (index_out)		*index_out = n;	for (i = 0; i < 4; i++) {		switch (*str) {		case 'r':			flags.w = 0;			break;		case 's':			flags.s = 1;			break;		case 'd':			dev->no_cow = 1;			break;		case '=':			str++;			goto break_loop;		default:			printk(KERN_ERR "ubd_setup : Expected '=' or flag letter (r,s or d)\n");			goto out;		}		str++;	}        if (*str == '=')		printk(KERN_ERR "ubd_setup : Too many flags specified\n");        else		printk(KERN_ERR "ubd_setup : Expected '='\n");	goto out;break_loop:	err = 0;	backing_file = strchr(str, ',');	if (!backing_file) {		backing_file = strchr(str, ':');	}	if(backing_file){		if(dev->no_cow)			printk(KERN_ERR "Can't specify both 'd' and a "			       "cow file\n");		else {			*backing_file = '\0';			backing_file++;		}	}	dev->file = str;	dev->cow.file = backing_file;	dev->boot_openflags = flags;out:	spin_unlock(&ubd_lock);	return(err);}static int ubd_setup(char *str){	ubd_setup_common(str, NULL);	return(1);}__setup("ubd", ubd_setup);__uml_help(ubd_setup,"ubd<n><flags>=<filename>[(:|,)<filename2>]\n""    This is used to associate a device with a file in the underlying\n""    filesystem. When specifying two filenames, the first one is the\n""    COW name and the second is the backing file name. As separator you can\n""    use either a ':' or a ',': the first one allows writing things like;\n""	ubd0=~/Uml/root_cow:~/Uml/root_backing_file\n""    while with a ',' the shell would not expand the 2nd '~'.\n""    When using only one filename, UML will detect whether to thread it like\n""    a COW file or a backing file. To override this detection, add the 'd'\n""    flag:\n""	ubd0d=BackingFile\n""    Usually, there is a filesystem in the file, but \n""    that's not required. Swap devices containing swap files can be\n""    specified like this. Also, a file which doesn't contain a\n""    filesystem can have its contents read in the virtual \n""    machine by running 'dd' on the device. <n> must be in the range\n""    0 to 7. Appending an 'r' to the number will cause that device\n""    to be mounted read-only. For example ubd1r=./ext_fs. Appending\n""    an 's' will cause data to be written to disk on the host immediately.\n\n");static int udb_setup(char *str){	printk("udb%s specified on command line is almost certainly a ubd -> "	       "udb TYPO\n", str);	return(1);}__setup("udb", udb_setup);__uml_help(udb_setup,"udb\n""    This option is here solely to catch ubd -> udb typos, which can be\n""    to impossible to catch visually unless you specifically look for\n""    them.  The only result of any option starting with 'udb' is an error\n""    in the boot output.\n\n");static int fakehd_set = 0;static int fakehd(char *str){	printk(KERN_INFO "fakehd : Changing ubd name to \"hd\".\n");	fakehd_set = 1;	return 1;}__setup("fakehd", fakehd);__uml_help(fakehd,"fakehd\n""    Change the ubd device name to \"hd\".\n\n");static void do_ubd_request(request_queue_t * q);/* Only changed by ubd_init, which is an initcall. */int thread_fd = -1;/* Changed by ubd_handler, which is serialized because interrupts only

⌨️ 快捷键说明

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