ia64/xen-unstable
changeset 13125:08fa19392d75
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@xensource.com>
- Remove global QCOW flags
- rename sparseness flag to -r fore 'reserve'
- Add ROUNDUP macro
- Check for qtruncate failures
Signed-off-by: Julian Chesterfield <julian@xensource.com>
author | Julian Chesterfield <julian@xensource.com> |
---|---|
date | Tue Dec 19 20:42:56 2006 +0000 (2006-12-19) |
parents | 057f7c4dbed1 |
children | 381f119b15a0 |
files | tools/blktap/drivers/block-qcow.c tools/blktap/drivers/qcow-create.c |
line diff
1.1 --- a/tools/blktap/drivers/block-qcow.c Tue Dec 19 12:00:11 2006 +0000 1.2 +++ b/tools/blktap/drivers/block-qcow.c Tue Dec 19 20:42:56 2006 +0000 1.3 @@ -47,6 +47,11 @@ 1.4 #define ASSERT(_p) ((void)0) 1.5 #endif 1.6 1.7 +#define ROUNDUP(l, s) \ 1.8 +({ \ 1.9 + (uint64_t)( \ 1.10 + (l + (s - 1)) - ((l + (s - 1)) % s)); \ 1.11 +}) 1.12 1.13 /******AIO DEFINES******/ 1.14 #define REQUEST_ASYNC_FD 1 1.15 @@ -76,9 +81,9 @@ struct pending_aio { 1.16 1.17 #define QCOW_CRYPT_NONE 0x00 1.18 #define QCOW_CRYPT_AES 0x01 1.19 -#define QCOW_SPARSE_FILE 0x02 1.20 1.21 #define QCOW_OFLAG_COMPRESSED (1LL << 63) 1.22 +#define SPARSE_FILE 0x01 1.23 1.24 #ifndef O_BINARY 1.25 #define O_BINARY 0 1.26 @@ -418,8 +423,9 @@ static void encrypt_sectors(struct tdqco 1.27 1.28 static int qtruncate(int fd, off_t length, int sparse) 1.29 { 1.30 - int current, ret, i; 1.31 - int sectors = length/DEFAULT_SECTOR_SIZE; 1.32 + int ret, i; 1.33 + int current = 0, rem = 0; 1.34 + int sectors = (length + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE; 1.35 struct stat st; 1.36 char buf[DEFAULT_SECTOR_SIZE]; 1.37 1.38 @@ -429,22 +435,45 @@ static int qtruncate(int fd, off_t lengt 1.39 */ 1.40 memset(buf, 0x00, DEFAULT_SECTOR_SIZE); 1.41 ret = fstat(fd, &st); 1.42 - if((ret == -1) || S_ISBLK(st.st_mode)) 1.43 + if (ret == -1) 1.44 return -1; 1.45 + if (S_ISBLK(st.st_mode)) 1.46 + return 0; 1.47 + 1.48 + current = (st.st_size + DEFAULT_SECTOR_SIZE - 1)/DEFAULT_SECTOR_SIZE; 1.49 + rem = st.st_size % DEFAULT_SECTOR_SIZE; 1.50 1.51 - if(st.st_size < length) { 1.52 + /* If we are extending this file, we write zeros to the end -- 1.53 + * this tries to ensure that the extents allocated wind up being 1.54 + * contiguous on disk. 1.55 + */ 1.56 + if(st.st_size < sectors * DEFAULT_SECTOR_SIZE) { 1.57 /*We are extending the file*/ 1.58 - lseek(fd, 0, SEEK_END); 1.59 - for (i = 0; i < sectors; i++ ) { 1.60 + if (lseek(fd, 0, SEEK_END)==-1) { 1.61 + fprintf(stderr, 1.62 + "Lseek EOF failed (%d), internal error\n", 1.63 + errno); 1.64 + return -1; 1.65 + } 1.66 + if (rem) { 1.67 + ret = write(fd, buf, rem); 1.68 + if (ret != rem) 1.69 + return -1; 1.70 + } 1.71 + for (i = current; i < sectors; i++ ) { 1.72 ret = write(fd, buf, DEFAULT_SECTOR_SIZE); 1.73 if (ret != DEFAULT_SECTOR_SIZE) 1.74 return -1; 1.75 } 1.76 1.77 - } else if(sparse && (st.st_size > length)) 1.78 - ftruncate(fd, length); 1.79 - 1.80 - return 1; 1.81 + } else if(sparse && (st.st_size > sectors * DEFAULT_SECTOR_SIZE)) 1.82 + if (ftruncate(fd, sectors * DEFAULT_SECTOR_SIZE)==-1) { 1.83 + fprintf(stderr, 1.84 + "Ftruncate failed (%d), internal error\n", 1.85 + errno); 1.86 + return -1; 1.87 + } 1.88 + return 0; 1.89 } 1.90 1.91 1.92 @@ -497,7 +526,12 @@ static uint64_t get_cluster_offset(struc 1.93 1.94 /*Truncate file for L2 table 1.95 *(initialised to zero in case we crash)*/ 1.96 - qtruncate(s->fd, l2_offset + (s->l2_size * sizeof(uint64_t)), s->sparse); 1.97 + if (qtruncate(s->fd, 1.98 + l2_offset + (s->l2_size * sizeof(uint64_t)), 1.99 + s->sparse) != 0) { 1.100 + DPRINTF("ERROR truncating file\n"); 1.101 + return 0; 1.102 + } 1.103 s->fd_end = l2_offset + (s->l2_size * sizeof(uint64_t)); 1.104 1.105 /*Update the L1 table entry on disk 1.106 @@ -564,8 +598,12 @@ cache_miss: 1.107 (s->l2_size * sizeof(uint64_t)); 1.108 cluster_offset = (cluster_offset + s->cluster_size - 1) 1.109 & ~(s->cluster_size - 1); 1.110 - qtruncate(s->fd, cluster_offset + 1.111 - (s->cluster_size * s->l2_size), s->sparse); 1.112 + if (qtruncate(s->fd, cluster_offset + 1.113 + (s->cluster_size * s->l2_size), 1.114 + s->sparse) != 0) { 1.115 + DPRINTF("ERROR truncating file\n"); 1.116 + return 0; 1.117 + } 1.118 s->fd_end = cluster_offset + 1.119 (s->cluster_size * s->l2_size); 1.120 for (i = 0; i < s->l2_size; i++) { 1.121 @@ -623,8 +661,11 @@ found: 1.122 cluster_offset = 1.123 (cluster_offset + s->cluster_size - 1) 1.124 & ~(s->cluster_size - 1); 1.125 - qtruncate(s->fd, cluster_offset + 1.126 - s->cluster_size, s->sparse); 1.127 + if (qtruncate(s->fd, cluster_offset + 1.128 + s->cluster_size, s->sparse)!=0) { 1.129 + DPRINTF("ERROR truncating file\n"); 1.130 + return 0; 1.131 + } 1.132 s->fd_end = (cluster_offset + s->cluster_size); 1.133 /* if encrypted, we must initialize the cluster 1.134 content which won't be written */ 1.135 @@ -909,15 +950,14 @@ int tdqcow_open (struct td_state *bs, co 1.136 1.137 /*Finally check the L1 table cksum*/ 1.138 be32_to_cpus(&exthdr->cksum); 1.139 - cksum = gen_cksum((char *)s->l1_table, s->l1_size * sizeof(uint64_t)); 1.140 - if(exthdr->cksum != cksum) { 1.141 + cksum = gen_cksum((char *)s->l1_table, 1.142 + s->l1_size * sizeof(uint64_t)); 1.143 + if(exthdr->cksum != cksum) 1.144 goto end_xenhdr; 1.145 - } 1.146 1.147 be32_to_cpus(&exthdr->min_cluster_alloc); 1.148 be32_to_cpus(&exthdr->flags); 1.149 - if (exthdr->flags & QCOW_SPARSE_FILE) 1.150 - s->sparse = 1; 1.151 + s->sparse = (exthdr->flags & SPARSE_FILE); 1.152 s->min_cluster_alloc = exthdr->min_cluster_alloc; 1.153 } 1.154 1.155 @@ -1210,10 +1250,10 @@ int tdqcow_do_callbacks(struct td_state 1.156 } 1.157 1.158 int qcow_create(const char *filename, uint64_t total_size, 1.159 - const char *backing_file, int flags) 1.160 + const char *backing_file, int sparse) 1.161 { 1.162 int fd, header_size, backing_filename_len, l1_size, i; 1.163 - int shift, length, adjust, ret = 0; 1.164 + int shift, length, adjust, flags = 0, ret = 0; 1.165 QCowHeader header; 1.166 QCowHeader_ext exthdr; 1.167 char backing_filename[1024], *ptr; 1.168 @@ -1305,11 +1345,7 @@ int qcow_create(const char *filename, ui 1.169 DPRINTF("L1 Table offset: %d, size %d\n", 1.170 header_size, 1.171 (int)(l1_size * sizeof(uint64_t))); 1.172 - if (flags & QCOW_CRYPT_AES) { 1.173 - header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES); 1.174 - } else { 1.175 - header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE); 1.176 - } 1.177 + header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE); 1.178 1.179 ptr = calloc(1, l1_size * sizeof(uint64_t)); 1.180 exthdr.cksum = cpu_to_be32(gen_cksum(ptr, l1_size * sizeof(uint64_t))); 1.181 @@ -1317,29 +1353,32 @@ int qcow_create(const char *filename, ui 1.182 free(ptr); 1.183 1.184 /*adjust file length to 4 KByte boundary*/ 1.185 - length = header_size + l1_size * sizeof(uint64_t); 1.186 - if (length % 4096 > 0) { 1.187 - length = ((length >> 12) + 1) << 12; 1.188 - qtruncate(fd, length, 0); 1.189 - DPRINTF("Adjusted filelength to %d for 4 " 1.190 - "Kbyte alignment\n",length); 1.191 + length = ROUNDUP(header_size + (l1_size * sizeof(uint64_t)),PAGE_SIZE); 1.192 + if (qtruncate(fd, length, 0)!=0) { 1.193 + DPRINTF("ERROR truncating file\n"); 1.194 + return -1; 1.195 } 1.196 1.197 - if (!(flags & QCOW_SPARSE_FILE)) { 1.198 - /*Filesize is length + l1_size * (1 << s->l2_bits) + (size*512)*/ 1.199 + if (sparse == 0) { 1.200 + /*Filesize is length+l1_size*(1 << s->l2_bits)+(size*512)*/ 1.201 total_length = length + (l1_size * (1 << 9)) + (size * 512); 1.202 - qtruncate(fd, total_length, 0); 1.203 + if (qtruncate(fd, total_length, 0)!=0) { 1.204 + DPRINTF("ERROR truncating file\n"); 1.205 + return -1; 1.206 + } 1.207 printf("File truncated to length %"PRIu64"\n",total_length); 1.208 - } 1.209 + } else 1.210 + flags = SPARSE_FILE; 1.211 + 1.212 exthdr.flags = cpu_to_be32(flags); 1.213 1.214 /* write all the data */ 1.215 lseek(fd, 0, SEEK_SET); 1.216 ret += write(fd, &header, sizeof(header)); 1.217 ret += write(fd, &exthdr, sizeof(exthdr)); 1.218 - if (backing_file) { 1.219 + if (backing_file) 1.220 ret += write(fd, backing_filename, backing_filename_len); 1.221 - } 1.222 + 1.223 lseek(fd, header_size, SEEK_SET); 1.224 tmp = 0; 1.225 for (i = 0;i < l1_size; i++) { 1.226 @@ -1360,7 +1399,10 @@ int qcow_make_empty(struct td_state *bs) 1.227 lseek(s->fd, s->l1_table_offset, SEEK_SET); 1.228 if (write(s->fd, s->l1_table, l1_length) < 0) 1.229 return -1; 1.230 - qtruncate(s->fd, s->l1_table_offset + l1_length, s->sparse); 1.231 + if (qtruncate(s->fd, s->l1_table_offset + l1_length, s->sparse)!=0) { 1.232 + DPRINTF("ERROR truncating file\n"); 1.233 + return -1; 1.234 + } 1.235 1.236 memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t)); 1.237 memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t));
2.1 --- a/tools/blktap/drivers/qcow-create.c Tue Dec 19 12:00:11 2006 +0000 2.2 +++ b/tools/blktap/drivers/qcow-create.c Tue Dec 19 20:42:56 2006 +0000 2.3 @@ -47,15 +47,13 @@ 2.4 #define DFPRINTF(_f, _a...) ((void)0) 2.5 #endif 2.6 2.7 -#define QCOW_NONSPARSE_FILE 0x00 2.8 -#define QCOW_SPARSE_FILE 0x02 2.9 #define MAX_NAME_LEN 1000 2.10 2.11 void help(void) 2.12 { 2.13 fprintf(stderr, "Qcow-utils: v1.0.0\n"); 2.14 fprintf(stderr, 2.15 - "usage: qcow-create [-h help] [-p reserve] <SIZE(MB)> <FILENAME> " 2.16 + "usage: qcow-create [-h help] [-r reserve] <SIZE(MB)> <FILENAME> " 2.17 "[<BACKING_FILENAME>]\n"); 2.18 exit(-1); 2.19 } 2.20 @@ -63,12 +61,12 @@ void help(void) 2.21 int main(int argc, char *argv[]) 2.22 { 2.23 int ret = -1, c, backed = 0; 2.24 - int flags = QCOW_SPARSE_FILE; 2.25 + int sparse = 1; 2.26 uint64_t size; 2.27 char filename[MAX_NAME_LEN], bfilename[MAX_NAME_LEN]; 2.28 2.29 for(;;) { 2.30 - c = getopt(argc, argv, "hp"); 2.31 + c = getopt(argc, argv, "hr"); 2.32 if (c == -1) 2.33 break; 2.34 switch(c) { 2.35 @@ -76,9 +74,12 @@ int main(int argc, char *argv[]) 2.36 help(); 2.37 exit(0); 2.38 break; 2.39 - case 'p': 2.40 - flags = QCOW_NONSPARSE_FILE; 2.41 + case 'r': 2.42 + sparse = 0; 2.43 break; 2.44 + default: 2.45 + fprintf(stderr, "Unknown option\n"); 2.46 + help(); 2.47 } 2.48 } 2.49 2.50 @@ -96,6 +97,7 @@ int main(int argc, char *argv[]) 2.51 } 2.52 2.53 if (optind != argc) { 2.54 + /*Backing file argument*/ 2.55 backed = 1; 2.56 if (snprintf(bfilename, MAX_NAME_LEN, "%s",argv[optind++]) >= 2.57 MAX_NAME_LEN) { 2.58 @@ -106,12 +108,14 @@ int main(int argc, char *argv[]) 2.59 2.60 DFPRINTF("Creating file size %llu, name %s\n",(long long unsigned)size, filename); 2.61 if (!backed) 2.62 - ret = qcow_create(filename,size,NULL,flags); 2.63 + ret = qcow_create(filename,size,NULL,sparse); 2.64 else 2.65 - ret = qcow_create(filename,size,bfilename,flags); 2.66 + ret = qcow_create(filename,size,bfilename,sparse); 2.67 2.68 - if (ret < 0) DPRINTF("Unable to create QCOW file\n"); 2.69 - else DPRINTF("QCOW file successfully created\n"); 2.70 + if (ret < 0) 2.71 + DPRINTF("Unable to create QCOW file\n"); 2.72 + else 2.73 + DPRINTF("QCOW file successfully created\n"); 2.74 2.75 return 0; 2.76 }