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>
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  }