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

📄 tapdisk.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* tapdisk.c * * separate disk process, spawned by blktapctrl. Inherits code from driver  * plugins *  * Copyright (c) 2005 Julian Chesterfield and Andrew Warfield. * */#define MSG_SIZE 4096#define TAPDISK#include <stdio.h>#include <stdlib.h>#include <sys/mman.h>#include <fcntl.h>#include <string.h>#include <signal.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/poll.h>#include <unistd.h>#include <errno.h>#include <pthread.h>#include <time.h>#include <err.h>#include <poll.h>#include <sys/statvfs.h>#include <sys/ioctl.h>#include "blktaplib.h"#include "tapdisk.h"#if 1                                                                        #define ASSERT(_p) \    if ( !(_p) ) { DPRINTF("Assertion '%s' failed, line %d, file %s", #_p , \    __LINE__, __FILE__); *(int*)0=0; }#else#define ASSERT(_p) ((void)0)#endif #define INPUT 0#define OUTPUT 1static int maxfds, fds[2], run = 1;static pid_t process;int connected_disks = 0;fd_list_entry_t *fd_start = NULL;int do_cow_read(struct disk_driver *dd, blkif_request_t *req, 		int sidx, uint64_t sector, int nr_secs);#define td_for_each_disk(tds, drv) \        for (drv = tds->disks; drv != NULL; drv = drv->next)static void usage(void) {	fprintf(stderr, "blktap-utils: v1.0.0\n");	fprintf(stderr, "usage: tapdisk <READ fifo> <WRITE fifo>\n");        exit(-1);}static void daemonize(void){	int i;	if (getppid()==1) return; /* already a daemon */	if (fork() != 0) exit(0);#if 0	/*Set new program session ID and close all descriptors*/	setsid();	for (i = getdtablesize(); i >= 0; --i) close(i);	/*Send all I/O to /dev/null */	i = open("/dev/null",O_RDWR);	dup(i); 	dup(i);#endif	return;}static void free_driver(struct disk_driver *d){	if (d->name)		free(d->name);	if (d->private)		free(d->private);	free(d);}static void unmap_disk(struct td_state *s){	tapdev_info_t *info = s->ring_info;	struct disk_driver *dd, *tmp;	fd_list_entry_t *entry;	dd = s->disks;	while (dd) {		tmp = dd->next;		dd->drv->td_close(dd);		free_driver(dd);		dd = tmp;	}	if (info != NULL && info->mem > 0)	        munmap(info->mem, getpagesize() * BLKTAP_MMAP_REGION_SIZE);	entry = s->fd_entry;	*entry->pprev = entry->next;	if (entry->next)		entry->next->pprev = entry->pprev;	close(info->fd);	free(s->fd_entry);	free(s->blkif);	free(s->ring_info);	free(s);	return;}static void sig_handler(int sig){	/*Received signal to close. If no disks are active, we close app.*/	if (connected_disks < 1) run = 0;	}static inline int LOCAL_FD_SET(fd_set *readfds){	fd_list_entry_t *ptr;	struct disk_driver *dd;	ptr = fd_start;	while (ptr != NULL) {		if (ptr->tap_fd) {			FD_SET(ptr->tap_fd, readfds);			td_for_each_disk(ptr->s, dd) {				if (dd->io_fd[READ]) 					FD_SET(dd->io_fd[READ], readfds);				maxfds = (dd->io_fd[READ] > maxfds ? 					  dd->io_fd[READ] : maxfds);			}			maxfds = (ptr->tap_fd > maxfds ? ptr->tap_fd : maxfds);		}		ptr = ptr->next;	}	return 0;}static inline fd_list_entry_t *add_fd_entry(int tap_fd, struct td_state *s){	fd_list_entry_t **pprev, *entry;	int i;	DPRINTF("Adding fd_list_entry\n");	/*Add to linked list*/	s->fd_entry   = entry = malloc(sizeof(fd_list_entry_t));	entry->tap_fd = tap_fd;	entry->s      = s;	entry->next   = NULL;	pprev = &fd_start;	while (*pprev != NULL)		pprev = &(*pprev)->next;	*pprev = entry;	entry->pprev = pprev;	return entry;}static inline struct td_state *get_state(int cookie){	fd_list_entry_t *ptr;	ptr = fd_start;	while (ptr != NULL) {		if (ptr->cookie == cookie) return ptr->s;		ptr = ptr->next;	}	return NULL;}static struct tap_disk *get_driver(int drivertype){	/* blktapctrl has passed us the driver type */	return dtypes[drivertype]->drv;}static struct td_state *state_init(void){	int i;	struct td_state *s;	blkif_t *blkif;	s = malloc(sizeof(struct td_state));	blkif = s->blkif = malloc(sizeof(blkif_t));	s->ring_info = calloc(1, sizeof(tapdev_info_t));	for (i = 0; i < MAX_REQUESTS; i++) {		blkif->pending_list[i].secs_pending = 0;		blkif->pending_list[i].submitting = 0;	}	return s;}static int map_new_dev(struct td_state *s, int minor){	int tap_fd;	tapdev_info_t *info = s->ring_info;	char *devname;	fd_list_entry_t *ptr;	int page_size;	if (asprintf(&devname,"%s/%s%d", BLKTAP_DEV_DIR, BLKTAP_DEV_NAME, minor) == -1)		return -1;	tap_fd = open(devname, O_RDWR);	if (tap_fd == -1) 	{		DPRINTF("open failed on dev %s!",devname);		goto fail;	} 	info->fd = tap_fd;	/*Map the shared memory*/	page_size = getpagesize();	info->mem = mmap(0, page_size * BLKTAP_MMAP_REGION_SIZE, 			  PROT_READ | PROT_WRITE, MAP_SHARED, info->fd, 0);	if ((long int)info->mem == -1) 	{		DPRINTF("mmap failed on dev %s!\n",devname);		goto fail;	}	/* assign the rings to the mapped memory */ 	info->sring = (blkif_sring_t *)((unsigned long)info->mem);	BACK_RING_INIT(&info->fe_ring, info->sring, page_size);		info->vstart = 	        (unsigned long)info->mem + (BLKTAP_RING_PAGES * page_size);	ioctl(info->fd, BLKTAP_IOCTL_SENDPID, process );	ioctl(info->fd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_INTERPOSE );	free(devname);	/*Update the fd entry*/	ptr = fd_start;	while (ptr != NULL) {		if (s == ptr->s) {			ptr->tap_fd = tap_fd;			break;		}		ptr = ptr->next;	}		return minor; fail:	free(devname);	return -1;}static struct disk_driver *disk_init(struct td_state *s, 				     struct tap_disk *drv, 				     char *name, td_flag_t flags){	struct disk_driver *dd;	dd = calloc(1, sizeof(struct disk_driver));	if (!dd)		return NULL;		dd->private = malloc(drv->private_data_size);	if (!dd->private) {		free(dd);		return NULL;	}	dd->drv      = drv;	dd->td_state = s;	dd->name     = name;	dd->flags    = flags;	return dd;}static int open_disk(struct td_state *s, 		     struct tap_disk *drv, char *path, td_flag_t flags){	int err;	char *dup;	td_flag_t pflags;	struct disk_id id;	struct disk_driver *d;	dup = strdup(path);	if (!dup)		return -ENOMEM;	memset(&id, 0, sizeof(struct disk_id));	s->disks = d = disk_init(s, drv, dup, flags);	if (!d)		return -ENOMEM;	err = drv->td_open(d, path, flags);	if (err) {		free_driver(d);		s->disks = NULL;		return -ENOMEM;	}	pflags = flags | TD_RDONLY;	/* load backing files as necessary */	while ((err = d->drv->td_get_parent_id(d, &id)) == 0) {		struct disk_driver *new;				if (id.drivertype > MAX_DISK_TYPES || 		    !get_driver(id.drivertype) || !id.name)			goto fail;		dup = strdup(id.name);		if (!dup)			goto fail;		new = disk_init(s, get_driver(id.drivertype), dup, pflags);		if (!new)			goto fail;		err = new->drv->td_open(new, new->name, pflags);		if (err)			goto fail;		err = d->drv->td_validate_parent(d, new, 0);		if (err) {			d->next = new;			goto fail;		}		d = d->next = new;		free(id.name);	}	s->info |= ((flags & TD_RDONLY) ? VDISK_READONLY : 0);	if (err >= 0)		return 0; fail:	DPRINTF("failed opening disk\n");	if (id.name)		free(id.name);	d = s->disks;	while (d) {		struct disk_driver *tmp = d->next;		d->drv->td_close(d);		free_driver(d);		d = tmp;	}	s->disks = NULL;	return -1;}static int read_msg(char *buf){	int length, len, msglen, tap_fd, *io_fd;	char *ptr, *path;	image_t *img;	msg_hdr_t *msg;	msg_newdev_t *msg_dev;	msg_pid_t *msg_pid;	struct tap_disk *drv;	int ret = -1;	struct td_state *s = NULL;	fd_list_entry_t *entry;	length = read(fds[READ], buf, MSG_SIZE);	if (length > 0 && length >= sizeof(msg_hdr_t)) 	{		msg = (msg_hdr_t *)buf;		DPRINTF("Tapdisk: Received msg, len %d, type %d, UID %d\n",			length,msg->type,msg->cookie);		switch (msg->type) {		case CTLMSG_PARAMS: 						ptr = buf + sizeof(msg_hdr_t);			len = (length - sizeof(msg_hdr_t));			path = calloc(1, len);						memcpy(path, ptr, len); 			DPRINTF("Received CTLMSG_PARAMS: [%s]\n", path);			/*Assign driver*/			drv = get_driver(msg->drivertype);			if (drv == NULL)				goto params_done;							DPRINTF("Loaded driver: name [%s], type [%d]\n",				drv->disk_type, msg->drivertype);			/* Allocate the disk structs */			s = state_init();			if (s == NULL)				goto params_done;			/*Open file*/			ret = open_disk(s, drv, path, 					((msg->readonly) ? TD_RDONLY : 0));			if (ret)				goto params_done;			entry = add_fd_entry(0, s);			entry->cookie = msg->cookie;			DPRINTF("Entered cookie %d\n", entry->cookie);						memset(buf, 0x00, MSG_SIZE); 					params_done:			if (ret == 0) {				msglen = sizeof(msg_hdr_t) + sizeof(image_t);				msg->type = CTLMSG_IMG;				img = (image_t *)(buf + sizeof(msg_hdr_t));				img->size = s->size;				img->secsize = s->sector_size;				img->info = s->info;			} else {				msglen = sizeof(msg_hdr_t);				msg->type = CTLMSG_IMG_FAIL;				msg->len = msglen;			}

⌨️ 快捷键说明

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