# HG changeset patch
# User Julian Chesterfield <julian@xxxxxxxxxxxxx>
# Date 1166560976 0
# Node ID 08fa19392d75eae17d5e90cd38bec834afdf7f25
# Parent 057f7c4dbed1c75a3fbe446d346cee04cff31497
Qcow driver code cleanup:
- Remove global QCOW flags
- rename sparseness flag to -r fore 'reserve'
- Add ROUNDUP macro
- Check for qtruncate failures
Signed-off-by: Julian Chesterfield <julian@xxxxxxxxxxxxx>
---
tools/blktap/drivers/block-qcow.c | 130 ++++++++++++++++++++++++-------------
tools/blktap/drivers/qcow-create.c | 26 ++++---
2 files changed, 101 insertions(+), 55 deletions(-)
diff -r 057f7c4dbed1 -r 08fa19392d75 tools/blktap/drivers/block-qcow.c
--- a/tools/blktap/drivers/block-qcow.c Tue Dec 19 12:00:11 2006 +0000
+++ b/tools/blktap/drivers/block-qcow.c Tue Dec 19 20:42:56 2006 +0000
@@ -47,6 +47,11 @@
#define ASSERT(_p) ((void)0)
#endif
+#define ROUNDUP(l, s) \
+({ \
+ (uint64_t)( \
+ (l + (s - 1)) - ((l + (s - 1)) % s)); \
+})
/******AIO DEFINES******/
#define REQUEST_ASYNC_FD 1
@@ -76,9 +81,9 @@ struct pending_aio {
#define QCOW_CRYPT_NONE 0x00
#define QCOW_CRYPT_AES 0x01
-#define QCOW_SPARSE_FILE 0x02
#define QCOW_OFLAG_COMPRESSED (1LL << 63)
+#define SPARSE_FILE 0x01
#ifndef O_BINARY
#define O_BINARY 0
@@ -418,8 +423,9 @@ static void encrypt_sectors(struct tdqco
static int qtruncate(int fd, off_t length, int sparse)
{
- int current, ret, i;
- int sectors = length/DEFAULT_SECTOR_SIZE;
+ int ret, i;
+ int current = 0, rem = 0;
+ int sectors = (length + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE;
struct stat st;
char buf[DEFAULT_SECTOR_SIZE];
@@ -429,22 +435,45 @@ static int qtruncate(int fd, off_t lengt
*/
memset(buf, 0x00, DEFAULT_SECTOR_SIZE);
ret = fstat(fd, &st);
- if((ret == -1) || S_ISBLK(st.st_mode))
+ if (ret == -1)
return -1;
-
- if(st.st_size < length) {
+ if (S_ISBLK(st.st_mode))
+ return 0;
+
+ current = (st.st_size + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE;
+ rem = st.st_size % DEFAULT_SECTOR_SIZE;
+
+ /* If we are extending this file, we write zeros to the end --
+ * this tries to ensure that the extents allocated wind up being
+ * contiguous on disk.
+ */
+ if(st.st_size < sectors * DEFAULT_SECTOR_SIZE) {
/*We are extending the file*/
- lseek(fd, 0, SEEK_END);
- for (i = 0; i < sectors; i++ ) {
+ if (lseek(fd, 0, SEEK_END)==-1) {
+ fprintf(stderr,
+ "Lseek EOF failed (%d), internal error\n",
+ errno);
+ return -1;
+ }
+ if (rem) {
+ ret = write(fd, buf, rem);
+ if (ret != rem)
+ return -1;
+ }
+ for (i = current; i < sectors; i++ ) {
ret = write(fd, buf, DEFAULT_SECTOR_SIZE);
if (ret != DEFAULT_SECTOR_SIZE)
return -1;
}
- } else if(sparse && (st.st_size > length))
- ftruncate(fd, length);
-
- return 1;
+ } else if(sparse && (st.st_size > sectors * DEFAULT_SECTOR_SIZE))
+ if (ftruncate(fd, sectors * DEFAULT_SECTOR_SIZE)==-1) {
+ fprintf(stderr,
+ "Ftruncate failed (%d), internal error\n",
+ errno);
+ return -1;
+ }
+ return 0;
}
@@ -497,7 +526,12 @@ static uint64_t get_cluster_offset(struc
/*Truncate file for L2 table
*(initialised to zero in case we crash)*/
- qtruncate(s->fd, l2_offset + (s->l2_size * sizeof(uint64_t)),
s->sparse);
+ if (qtruncate(s->fd,
+ l2_offset + (s->l2_size * sizeof(uint64_t)),
+ s->sparse) != 0) {
+ DPRINTF("ERROR truncating file\n");
+ return 0;
+ }
s->fd_end = l2_offset + (s->l2_size * sizeof(uint64_t));
/*Update the L1 table entry on disk
@@ -564,8 +598,12 @@ cache_miss:
(s->l2_size * sizeof(uint64_t));
cluster_offset = (cluster_offset + s->cluster_size - 1)
& ~(s->cluster_size - 1);
- qtruncate(s->fd, cluster_offset +
- (s->cluster_size * s->l2_size), s->sparse);
+ if (qtruncate(s->fd, cluster_offset +
+ (s->cluster_size * s->l2_size),
+ s->sparse) != 0) {
+ DPRINTF("ERROR truncating file\n");
+ return 0;
+ }
s->fd_end = cluster_offset +
(s->cluster_size * s->l2_size);
for (i = 0; i < s->l2_size; i++) {
@@ -623,8 +661,11 @@ found:
cluster_offset =
(cluster_offset + s->cluster_size - 1)
& ~(s->cluster_size - 1);
- qtruncate(s->fd, cluster_offset +
- s->cluster_size, s->sparse);
+ if (qtruncate(s->fd, cluster_offset +
+ s->cluster_size, s->sparse)!=0) {
+ DPRINTF("ERROR truncating file\n");
+ return 0;
+ }
s->fd_end = (cluster_offset + s->cluster_size);
/* if encrypted, we must initialize the cluster
content which won't be written */
@@ -909,15 +950,14 @@ int tdqcow_open (struct td_state *bs, co
/*Finally check the L1 table cksum*/
be32_to_cpus(&exthdr->cksum);
- cksum = gen_cksum((char *)s->l1_table, s->l1_size *
sizeof(uint64_t));
- if(exthdr->cksum != cksum) {
+ cksum = gen_cksum((char *)s->l1_table,
+ s->l1_size * sizeof(uint64_t));
+ if(exthdr->cksum != cksum)
goto end_xenhdr;
- }
be32_to_cpus(&exthdr->min_cluster_alloc);
be32_to_cpus(&exthdr->flags);
- if (exthdr->flags & QCOW_SPARSE_FILE)
- s->sparse = 1;
+ s->sparse = (exthdr->flags & SPARSE_FILE);
s->min_cluster_alloc = exthdr->min_cluster_alloc;
}
@@ -1210,10 +1250,10 @@ int tdqcow_do_callbacks(struct td_state
}
int qcow_create(const char *filename, uint64_t total_size,
- const char *backing_file, int flags)
+ const char *backing_file, int sparse)
{
int fd, header_size, backing_filename_len, l1_size, i;
- int shift, length, adjust, ret = 0;
+ int shift, length, adjust, flags = 0, ret = 0;
QCowHeader header;
QCowHeader_ext exthdr;
char backing_filename[1024], *ptr;
@@ -1305,11 +1345,7 @@ int qcow_create(const char *filename, ui
DPRINTF("L1 Table offset: %d, size %d\n",
header_size,
(int)(l1_size * sizeof(uint64_t)));
- if (flags & QCOW_CRYPT_AES) {
- header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
- } else {
- header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
- }
+ 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)));
@@ -1317,29 +1353,32 @@ int qcow_create(const char *filename, ui
free(ptr);
/*adjust file length to 4 KByte boundary*/
- length = header_size + l1_size * sizeof(uint64_t);
- if (length % 4096 > 0) {
- length = ((length >> 12) + 1) << 12;
- qtruncate(fd, length, 0);
- DPRINTF("Adjusted filelength to %d for 4 "
- "Kbyte alignment\n",length);
- }
-
- if (!(flags & QCOW_SPARSE_FILE)) {
- /*Filesize is length + l1_size * (1 << s->l2_bits) +
(size*512)*/
+ length = ROUNDUP(header_size + (l1_size * sizeof(uint64_t)),PAGE_SIZE);
+ 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);
- qtruncate(fd, total_length, 0);
+ 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) {
+ 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++) {
@@ -1360,7 +1399,10 @@ int qcow_make_empty(struct td_state *bs)
lseek(s->fd, s->l1_table_offset, SEEK_SET);
if (write(s->fd, s->l1_table, l1_length) < 0)
return -1;
- qtruncate(s->fd, s->l1_table_offset + l1_length, s->sparse);
+ 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));
diff -r 057f7c4dbed1 -r 08fa19392d75 tools/blktap/drivers/qcow-create.c
--- a/tools/blktap/drivers/qcow-create.c Tue Dec 19 12:00:11 2006 +0000
+++ b/tools/blktap/drivers/qcow-create.c Tue Dec 19 20:42:56 2006 +0000
@@ -47,15 +47,13 @@
#define DFPRINTF(_f, _a...) ((void)0)
#endif
-#define QCOW_NONSPARSE_FILE 0x00
-#define QCOW_SPARSE_FILE 0x02
#define MAX_NAME_LEN 1000
void help(void)
{
fprintf(stderr, "Qcow-utils: v1.0.0\n");
fprintf(stderr,
- "usage: qcow-create [-h help] [-p reserve] <SIZE(MB)>
<FILENAME> "
+ "usage: qcow-create [-h help] [-r reserve] <SIZE(MB)>
<FILENAME> "
"[<BACKING_FILENAME>]\n");
exit(-1);
}
@@ -63,12 +61,12 @@ int main(int argc, char *argv[])
int main(int argc, char *argv[])
{
int ret = -1, c, backed = 0;
- int flags = QCOW_SPARSE_FILE;
+ int sparse = 1;
uint64_t size;
char filename[MAX_NAME_LEN], bfilename[MAX_NAME_LEN];
for(;;) {
- c = getopt(argc, argv, "hp");
+ c = getopt(argc, argv, "hr");
if (c == -1)
break;
switch(c) {
@@ -76,9 +74,12 @@ int main(int argc, char *argv[])
help();
exit(0);
break;
- case 'p':
- flags = QCOW_NONSPARSE_FILE;
+ case 'r':
+ sparse = 0;
break;
+ default:
+ fprintf(stderr, "Unknown option\n");
+ help();
}
}
@@ -96,6 +97,7 @@ int main(int argc, char *argv[])
}
if (optind != argc) {
+ /*Backing file argument*/
backed = 1;
if (snprintf(bfilename, MAX_NAME_LEN, "%s",argv[optind++]) >=
MAX_NAME_LEN) {
@@ -106,12 +108,14 @@ int main(int argc, char *argv[])
DFPRINTF("Creating file size %llu, name %s\n",(long long unsigned)size,
filename);
if (!backed)
- ret = qcow_create(filename,size,NULL,flags);
+ ret = qcow_create(filename,size,NULL,sparse);
else
- ret = qcow_create(filename,size,bfilename,flags);
+ ret = qcow_create(filename,size,bfilename,sparse);
- if (ret < 0) DPRINTF("Unable to create QCOW file\n");
- else DPRINTF("QCOW file successfully created\n");
+ if (ret < 0)
+ DPRINTF("Unable to create QCOW file\n");
+ else
+ DPRINTF("QCOW file successfully created\n");
return 0;
}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|