ia64/xen-unstable

view tools/blktap/drivers/img2qcow.c @ 15783:c93e2a822d6f

[xen, xencomm] xencomm multiple page support
Current implementation doesn't allow struct xencomm_desc::address
array to be more than single page. On IA64 it causes 64GB+ domain
creation failure. This patch generalizes xencomm to allow multipage

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author kfraser@localhost.localdomain
date Tue Aug 28 15:32:27 2007 +0100 (2007-08-28)
parents 8407279d3751
children b6cc74f275fd
line source
1 /* img2qcow.c
2 *
3 * Generates a qcow format disk and fills it from an existing image.
4 *
5 * (c) 2006 Julian Chesterfield and Andrew Warfield
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version 2
9 * as published by the Free Software Foundation; or, when distributed
10 * separately from the Linux kernel or incorporated into other
11 * software packages, subject to the following license:
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a copy
14 * of this source file (the "Software"), to deal in the Software without
15 * restriction, including without limitation the rights to use, copy, modify,
16 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
17 * and to permit persons to whom the Software is furnished to do so, subject to
18 * the following conditions:
19 *
20 * The above copyright notice and this permission notice shall be included in
21 * all copies or substantial portions of the Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29 * IN THE SOFTWARE.
30 */
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <sys/statvfs.h>
38 #include <sys/stat.h>
39 #include <sys/ioctl.h>
40 #include <linux/fs.h>
41 #include <string.h>
42 #include "tapdisk.h"
44 #if 1
45 #define DFPRINTF(_f, _a...) fprintf ( stderr, _f , ## _a )
46 #else
47 #define DFPRINTF(_f, _a...) ((void)0)
48 #endif
50 #define TAPDISK 1
51 #define BLOCK_PROCESSSZ 4096
53 static int maxfds, *io_fd, running = 1, complete = 0;
54 static int returned_events = 0, submit_events = 0;
55 static uint64_t prev = 0;
56 static char output[25];
58 void print_bytes(void *ptr, int length) {
60 int i,k;
61 unsigned char *p = ptr;
63 DFPRINTF("Buf dump, length %d:\n",length);
64 for (k = 0; k < length; k++) {
65 DFPRINTF("%x",*p);
66 *p++;
67 if(k % 16 == 0) DFPRINTF("\n");
68 else if(k % 2 == 0) DFPRINTF(" ");
69 }
70 DFPRINTF("\n");
71 return;
72 }
74 void debug_output(uint64_t progress, uint64_t size)
75 {
76 uint64_t blocks = size/20;
78 /*Output progress every 5% */
79 if (progress/blocks > prev) {
80 memcpy(output+prev+1,"=>",2);
81 prev++;
82 DFPRINTF("\r%s %llu%%", output,
83 (long long)(prev-1)*5);
84 }
85 return;
86 }
88 static inline void LOCAL_FD_SET(fd_set *readfds)
89 {
90 FD_SET(io_fd[0], readfds);
91 maxfds = io_fd[0] + 1;
93 return;
94 }
96 static int get_image_info(struct td_state *s, int fd)
97 {
98 int ret;
99 long size;
100 unsigned long total_size;
101 struct statvfs statBuf;
102 struct stat stat;
104 ret = fstat(fd, &stat);
105 if (ret != 0) {
106 DFPRINTF("ERROR: fstat failed, Couldn't stat image");
107 return -EINVAL;
108 }
110 if (S_ISBLK(stat.st_mode)) {
111 /*Accessing block device directly*/
112 s->size = 0;
113 if (ioctl(fd,BLKGETSIZE,&s->size)!=0) {
114 DFPRINTF("ERR: BLKGETSIZE failed, "
115 "couldn't stat image");
116 return -EINVAL;
117 }
119 DFPRINTF("Image size: \n\tpre sector_shift [%llu]\n\tpost "
120 "sector_shift [%llu]\n",
121 (long long unsigned)(s->size << SECTOR_SHIFT),
122 (long long unsigned)s->size);
124 /*Get the sector size*/
125 #if defined(BLKSSZGET)
126 {
127 int arg;
128 s->sector_size = DEFAULT_SECTOR_SIZE;
129 ioctl(fd, BLKSSZGET, &s->sector_size);
131 if (s->sector_size != DEFAULT_SECTOR_SIZE)
132 DFPRINTF("Note: sector size is %ld (not %d)\n",
133 s->sector_size, DEFAULT_SECTOR_SIZE);
134 }
135 #else
136 s->sector_size = DEFAULT_SECTOR_SIZE;
137 #endif
139 } else {
140 /*Local file? try fstat instead*/
141 s->size = (stat.st_size >> SECTOR_SHIFT);
142 s->sector_size = DEFAULT_SECTOR_SIZE;
143 DFPRINTF("Image size: [%llu]\n",
144 (long long unsigned)s->size);
145 }
147 return 0;
148 }
150 static int send_responses(struct disk_driver *dd, int res, uint64_t sec,
151 int nr_secs, int idx, void *private)
152 {
153 if (res < 0) DFPRINTF("AIO FAILURE: res [%d]!\n",res);
155 returned_events++;
157 free(private);
158 return 0;
159 }
161 int main(int argc, char *argv[])
162 {
163 struct disk_driver dd;
164 struct td_state *s;
165 int ret = -1, fd, len;
166 fd_set readfds;
167 struct timeval timeout;
168 uint64_t i;
169 char *buf;
171 if (argc != 3) {
172 fprintf(stderr, "Qcow-utils: v1.0.0\n");
173 fprintf(stderr, "usage: %s <QCOW FILENAME> <SRC IMAGE>\n",
174 argv[0]);
175 exit(-1);
176 }
178 s = malloc(sizeof(struct td_state));
180 /*Open image*/
181 fd = open(argv[2], O_RDONLY | O_LARGEFILE);
183 if (fd == -1) {
184 DFPRINTF("Unable to open [%s], (err %d)!\n",argv[2],0 - errno);
185 exit(-1);
186 }
188 get_image_info(s, fd);
190 /*Create qcow file*/
191 ret = qcow_create(argv[1],s->size<<SECTOR_SHIFT,NULL,0);
193 if (ret < 0) {
194 DFPRINTF("Unable to create QCOW file\n");
195 exit(-1);
196 } else DFPRINTF("Qcow file created: size %llu sectors\n",
197 (long long unsigned)s->size);
199 dd.td_state = s;
200 dd.drv = &tapdisk_qcow;
201 dd.private = malloc(dd.drv->private_data_size);
203 /*Open qcow file*/
204 if (dd.drv->td_open(&dd, argv[1], 0)!=0) {
205 DFPRINTF("Unable to open Qcow file [%s]\n",argv[1]);
206 exit(-1);
207 }
209 io_fd = dd.io_fd;
211 /*Initialise the output string*/
212 memset(output,0x20,25);
213 output[0] = '[';
214 output[22] = ']';
215 output[23] = '\0';
216 DFPRINTF("%s",output);
218 i = 0;
219 while (running) {
220 timeout.tv_sec = 0;
222 if (!complete) {
223 /*Read sector from image*/
224 if (lseek(fd, i, SEEK_SET) == (off_t)-1) {
225 DFPRINTF("Unable to access file offset %llu\n",
226 (long long)i);
227 exit(-1);
228 }
230 if( (ret = posix_memalign((void **)&buf,
231 BLOCK_PROCESSSZ,
232 BLOCK_PROCESSSZ)) != 0) {
233 DFPRINTF("Unable to read memalign buf (%d)\n",ret);
234 exit(-1);
235 }
237 /*We attempt to read 4k sized blocks*/
238 len = read(fd, buf, BLOCK_PROCESSSZ);
239 if (len < 512) {
240 DFPRINTF("Unable to read sector %llu\n",
241 (long long unsigned) (i >> 9));
242 complete = 1;
243 continue;
244 }
246 if (len % 512) {
247 len = (len >> 9) << 9;
248 }
250 ret = dd.drv->td_queue_write(&dd, i >> 9,
251 len >> 9, buf,
252 send_responses, 0, buf);
254 if (!ret) submit_events++;
256 if (ret < 0) {
257 DFPRINTF("UNABLE TO WRITE block [%llu]\n",
258 (long long unsigned) (i >> 9));
259 } else i += len;
261 if (i >> 9 == s->size) complete = 1;
263 debug_output(i,s->size << 9);
265 if ((submit_events % 10 == 0) || complete)
266 dd.drv->td_submit(&dd);
267 timeout.tv_usec = 0;
269 } else {
270 timeout.tv_usec = 1000;
271 if (!submit_events) running = 0;
272 }
275 /*Check AIO FD*/
276 LOCAL_FD_SET(&readfds);
277 ret = select(maxfds + 1, &readfds, (fd_set *) 0,
278 (fd_set *) 0, &timeout);
280 if (ret > 0) dd.drv->td_do_callbacks(&dd, 0);
281 if (complete && (returned_events == submit_events))
282 running = 0;
283 }
284 memcpy(output+prev+1,"=",1);
285 DFPRINTF("\r%s 100%%\nTRANSFER COMPLETE\n\n", output);
286 dd.drv->td_close(&dd);
287 free(dd.private);
288 free(s);
290 return 0;
291 }