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

📄 block-qcow.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
	/*We store a local record of the request*/	while (nb_sectors > 0) {		cluster_offset = 			get_cluster_offset(s, sector << 9, 0, 0, 0, 0);		index_in_cluster = sector & (s->cluster_sectors - 1);		n = s->cluster_sectors - index_in_cluster;		if (n > nb_sectors)			n = nb_sectors;		if (s->aio.iocb_free_count == 0 || !tap_aio_lock(&s->aio, sector)) 			return cb(dd, -EBUSY, sector, nb_sectors, id, private);				if(!cluster_offset) {			tap_aio_unlock(&s->aio, sector);			ret = cb(dd, BLK_NOT_ALLOCATED, 				 sector, n, id, private);			if (ret == -EBUSY) {				/* mark remainder of request				 * as busy and try again later */				return cb(dd, -EBUSY, sector + n,					  nb_sectors - n, id, private);			} else				rsp += ret;		} else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {			tap_aio_unlock(&s->aio, sector);			if (decompress_cluster(s, cluster_offset) < 0) {				rsp += cb(dd, -EIO, sector, 					  nb_sectors, id, private);				goto done;			}			memcpy(buf, s->cluster_cache + index_in_cluster * 512, 			       512 * n);			rsp += cb(dd, 0, sector, n, id, private);		} else {			tap_aio_read(&s->aio, s->fd, n * 512, 				   (cluster_offset + index_in_cluster * 512),				   buf, cb, id, sector, private);		}		nb_sectors -= n;		sector += n;		buf += n * 512;	}done:	return rsp;}static int tdqcow_queue_write(struct disk_driver *dd, uint64_t sector,		       int nb_sectors, char *buf, td_callback_t cb,		       int id, void *private){	struct tdqcow_state *s = (struct tdqcow_state *)dd->private;	int ret = 0, index_in_cluster, n, i;	uint64_t cluster_offset, sec, nr_secs;	sec     = sector;	nr_secs = nb_sectors;	/*Check we can get a lock*/	for (i = 0; i < nb_sectors; i++)		if (!tap_aio_can_lock(&s->aio, sector + i))  			return cb(dd, -EBUSY, sector, nb_sectors, id, private);		   	/*We store a local record of the request*/	while (nb_sectors > 0) {		index_in_cluster = sector & (s->cluster_sectors - 1);		n = s->cluster_sectors - index_in_cluster;		if (n > nb_sectors)			n = nb_sectors;		if (s->aio.iocb_free_count == 0 || !tap_aio_lock(&s->aio, sector))			return cb(dd, -EBUSY, sector, nb_sectors, id, private);		cluster_offset = get_cluster_offset(s, sector << 9, 1, 0,						    index_in_cluster, 						    index_in_cluster+n);		if (!cluster_offset) {			DPRINTF("Ooops, no write cluster offset!\n");			tap_aio_unlock(&s->aio, sector);			return cb(dd, -EIO, sector, nb_sectors, id, private);		}		if (s->crypt_method) {			encrypt_sectors(s, sector, s->cluster_data, 					(unsigned char *)buf, n, 1,					&s->aes_encrypt_key);			tap_aio_write(&s->aio, s->fd, n * 512, 				    (cluster_offset + index_in_cluster*512),				    (char *)s->cluster_data, cb, id, sector, 				    private);		} else {			tap_aio_write(&s->aio, s->fd, n * 512, 				    (cluster_offset + index_in_cluster*512),				    buf, cb, id, sector, private);		}				nb_sectors -= n;		sector += n;		buf += n * 512;	}	s->cluster_cache_offset = -1; /* disable compressed cache */	return 0;} 		static int tdqcow_submit(struct disk_driver *dd){        struct tdqcow_state *prv = (struct tdqcow_state *)dd->private;	return tap_aio_submit(&prv->aio);}static int tdqcow_close(struct disk_driver *dd){	struct tdqcow_state *s = (struct tdqcow_state *)dd->private;	uint32_t cksum, out;	int fd, offset;	/*Update the hdr cksum*/	if(s->min_cluster_alloc == s->l2_size) {		cksum = gen_cksum((char *)s->l1_table, s->l1_size * sizeof(uint64_t));		printf("Writing cksum: %d",cksum);		fd = open(s->name, O_WRONLY | O_LARGEFILE); /*Open without O_DIRECT*/		offset = sizeof(QCowHeader) + sizeof(uint32_t);		lseek(fd, offset, SEEK_SET);		out = cpu_to_be32(cksum);		if (write(fd, &out, sizeof(uint32_t))) ;		close(fd);	}	io_destroy(s->aio.aio_ctx.aio_ctx);	free(s->name);	free(s->l1_table);	free(s->l2_cache);	free(s->cluster_cache);	free(s->cluster_data);	close(s->fd);		return 0;}static int tdqcow_do_callbacks(struct disk_driver *dd, int sid){        int ret, i, nr_events, rsp = 0,*ptr;        struct io_event *ep;        struct tdqcow_state *prv = (struct tdqcow_state *)dd->private;        if (sid > MAX_IOFD) return 1;        nr_events = tap_aio_get_events(&prv->aio.aio_ctx);repeat:        for (ep = prv->aio.aio_events, i = nr_events; i-- > 0; ep++) {                struct iocb        *io  = ep->obj;                struct pending_aio *pio;                pio = &prv->aio.pending_aio[(long)io->data];		tap_aio_unlock(&prv->aio, pio->sector);		if (prv->crypt_method)			encrypt_sectors(prv, pio->sector, 					(unsigned char *)pio->buf, 					(unsigned char *)pio->buf, 					pio->nb_sectors, 0, 					&prv->aes_decrypt_key);		rsp += pio->cb(dd, ep->res == io->u.c.nbytes ? 0 : 1, 			       pio->sector, pio->nb_sectors,			       pio->id, pio->private);                prv->aio.iocb_free[prv->aio.iocb_free_count++] = io;        }        if (nr_events) {                nr_events = tap_aio_more_events(&prv->aio.aio_ctx);                goto repeat;        }        tap_aio_continue(&prv->aio.aio_ctx);        return rsp;}int qcow_create(const char *filename, uint64_t total_size,		const char *backing_file, int sparse){	int fd, header_size, backing_filename_len, l1_size, i;	int shift, length, adjust, flags = 0, ret = 0;	QCowHeader header;	QCowHeader_ext exthdr;	char backing_filename[PATH_MAX], *ptr;	uint64_t tmp, size, total_length;	struct stat st;	DPRINTF("Qcow_create: size %llu\n",(long long unsigned)total_size);	fd = open(filename, 		  O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,		  0644);	if (fd < 0)		return -1;	memset(&header, 0, sizeof(header));	header.magic = cpu_to_be32(QCOW_MAGIC);	header.version = cpu_to_be32(QCOW_VERSION);	/*Create extended header fields*/	exthdr.xmagic = cpu_to_be32(XEN_MAGIC);	header_size = sizeof(header) + sizeof(QCowHeader_ext);	backing_filename_len = 0;	size = (total_size >> SECTOR_SHIFT);	if (backing_file) {		if (strcmp(backing_file, "fat:")) {			const char *p;			/* XXX: this is a hack: we do not attempt to 			 *check for URL like syntax */			p = strchr(backing_file, ':');			if (p && (p - backing_file) >= 2) {				/* URL like but exclude "c:" like filenames */				strncpy(backing_filename, backing_file,					sizeof(backing_filename));			} else {				if (realpath(backing_file, backing_filename) == NULL ||				    stat(backing_filename, &st) != 0) {					return -1;				}			}			header.backing_file_offset = cpu_to_be64(header_size);			backing_filename_len = strlen(backing_filename);			header.backing_file_size = cpu_to_be32(				backing_filename_len);			header_size += backing_filename_len;						/*Set to the backing file size*/			if(get_filesize(backing_filename, &size, &st)) {				return -1;			}			DPRINTF("Backing file size detected: %lld sectors" 				"(total %lld [%lld MB])\n", 				(long long)size, 				(long long)(size << SECTOR_SHIFT), 				(long long)(size >> 11));		} else {			backing_file = NULL;			DPRINTF("Setting file size: %lld (total %lld)\n", 				(long long) total_size, 				(long long) (total_size << SECTOR_SHIFT));		}		header.mtime = cpu_to_be32(st.st_mtime);		header.cluster_bits = 9; /* 512 byte cluster to avoid copying					    unmodifyed sectors */		header.l2_bits = 12; /* 32 KB L2 tables */		exthdr.min_cluster_alloc = cpu_to_be32(1);	} else {		DPRINTF("Setting file size: %lld sectors" 			"(total %lld [%lld MB])\n", 			(long long) size, 			(long long) (size << SECTOR_SHIFT), 			(long long) (size >> 11));		header.cluster_bits = 12; /* 4 KB clusters */		header.l2_bits = 9; /* 4 KB L2 tables */		exthdr.min_cluster_alloc = cpu_to_be32(1 << 9);	}	/*Set the header size value*/	header.size = cpu_to_be64(size * 512);		header_size = (header_size + 7) & ~7;	if (header_size % 4096 > 0) {		header_size = ((header_size >> 12) + 1) << 12;	}	shift = header.cluster_bits + header.l2_bits;	l1_size = ((size * 512) + (1LL << shift) - 1) >> shift;	header.l1_table_offset = cpu_to_be64(header_size);	DPRINTF("L1 Table offset: %d, size %d\n",		header_size,		(int)(l1_size * sizeof(uint64_t)));	header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);	ptr = calloc(1, l1_size * sizeof(uint64_t));	exthdr.cksum = cpu_to_be32(gen_cksum(ptr, l1_size * sizeof(uint64_t)));	printf("Created cksum: %d\n",exthdr.cksum);	free(ptr);	/*adjust file length to system page size boundary*/	length = ROUNDUP(header_size + (l1_size * sizeof(uint64_t)),		getpagesize());	if (qtruncate(fd, length, 0)!=0) {		DPRINTF("ERROR truncating file\n");		return -1;	}	if (sparse == 0) {		/*Filesize is length+l1_size*(1 << s->l2_bits)+(size*512)*/		total_length = length + (l1_size * (1 << 9)) + (size * 512);		if (qtruncate(fd, total_length, 0)!=0) {                        DPRINTF("ERROR truncating file\n");                        return -1;		}		printf("File truncated to length %"PRIu64"\n",total_length);	} else		flags = SPARSE_FILE;	exthdr.flags = cpu_to_be32(flags);		/* write all the data */	lseek(fd, 0, SEEK_SET);	ret += write(fd, &header, sizeof(header));	ret += write(fd, &exthdr, sizeof(exthdr));	if (backing_file)		ret += write(fd, backing_filename, backing_filename_len);	lseek(fd, header_size, SEEK_SET);	tmp = 0;	for (i = 0;i < l1_size; i++) {		ret += write(fd, &tmp, sizeof(tmp));	}	close(fd);	return 0;}static int qcow_make_empty(struct tdqcow_state *s){	uint32_t l1_length = s->l1_size * sizeof(uint64_t);	memset(s->l1_table, 0, l1_length);	lseek(s->fd, s->l1_table_offset, SEEK_SET);	if (write(s->fd, s->l1_table, l1_length) < 0)		return -1;	if (qtruncate(s->fd, s->l1_table_offset + l1_length, s->sparse)!=0) {		DPRINTF("ERROR truncating file\n");		return -1;	}	memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));	memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t));	memset(s->l2_cache_counts, 0, L2_CACHE_SIZE * sizeof(uint32_t));	return 0;}static int qcow_get_cluster_size(struct tdqcow_state *s){	return s->cluster_size;}/* XXX: put compressed sectors first, then all the cluster aligned   tables to avoid losing bytes in alignment */static int qcow_compress_cluster(struct tdqcow_state *s, int64_t sector_num,                           const uint8_t *buf){	z_stream strm;	int ret, out_len;	uint8_t *out_buf;	uint64_t cluster_offset;	out_buf = malloc(s->cluster_size + (s->cluster_size / 1000) + 128);	if (!out_buf)		return -1;	/* best compression, small window, no zlib header */	memset(&strm, 0, sizeof(strm));	ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION,			   Z_DEFLATED, -12, 			   9, Z_DEFAULT_STRATEGY);	if (ret != 0) {		free(out_buf);		return -1;	}	strm.avail_in = s->cluster_size;	strm.next_in = (uint8_t *)buf;	strm.avail_out = s->cluster_size;	strm.next_out = out_buf;	ret = deflate(&strm, Z_FINISH);	if (ret != Z_STREAM_END && ret != Z_OK) {		free(out_buf);		deflateEnd(&strm);		return -1;	}	out_len = strm.next_out - out_buf;	deflateEnd(&strm);	if (ret != Z_STREAM_END || out_len >= s->cluster_size) {		/* could not compress: write normal cluster */		//tdqcow_queue_write(bs, sector_num, buf, s->cluster_sectors);	} else {		cluster_offset = get_cluster_offset(s, sector_num << 9, 2,                                             out_len, 0, 0);		cluster_offset &= s->cluster_offset_mask;		lseek(s->fd, cluster_offset, SEEK_SET);		if (write(s->fd, out_buf, out_len) != out_len) {			free(out_buf);			return -1;		}	}		free(out_buf);	return 0;}static int tdqcow_get_parent_id(struct disk_driver *dd, struct disk_id *id){	off_t off;	char *buf, *filename;	int len, secs, err = -EINVAL;	struct tdqcow_state *child  = (struct tdqcow_state *)dd->private;	if (!child->backing_file_offset)		return TD_NO_PARENT;	/* read the backing file name */	len  = child->backing_file_size;	off  = child->backing_file_offset - (child->backing_file_offset % 512);	secs = (len + (child->backing_file_offset - off) + 511) >> 9;	if (posix_memalign((void **)&buf, 512, secs << 9)) 		return -1;	if (lseek(child->fd, off, SEEK_SET) == (off_t)-1)		goto out;	if (read(child->fd, buf, secs << 9) != secs << 9)		goto out;	filename       = buf + (child->backing_file_offset - off);	filename[len]  = '\0';	id->name       = strdup(filename);	id->drivertype = DISK_TYPE_QCOW;	err            = 0; out:	free(buf);	return err;}static int tdqcow_validate_parent(struct disk_driver *child,			   struct disk_driver *parent, td_flag_t flags){	struct stat stats;	uint64_t psize, csize;	struct tdqcow_state *c = (struct tdqcow_state *)child->private;	struct tdqcow_state *p = (struct tdqcow_state *)parent->private;		if (stat(p->name, &stats))		return -EINVAL;	if (get_filesize(p->name, &psize, &stats))		return -EINVAL;	if (stat(c->name, &stats))		return -EINVAL;	if (get_filesize(c->name, &csize, &stats))		return -EINVAL;	if (csize != psize)		return -EINVAL;	return 0;}struct tap_disk tapdisk_qcow = {	.disk_type           = "tapdisk_qcow",	.private_data_size   = sizeof(struct tdqcow_state),	.td_open             = tdqcow_open,	.td_queue_read       = tdqcow_queue_read,	.td_queue_write      = tdqcow_queue_write,	.td_submit           = tdqcow_submit,	.td_close            = tdqcow_close,	.td_do_callbacks     = tdqcow_do_callbacks,	.td_get_parent_id    = tdqcow_get_parent_id,	.td_validate_parent  = tdqcow_validate_parent};

⌨️ 快捷键说明

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