debuggers.hg

view tools/blktap/drivers/qcow2raw.c @ 0:7d21f7218375

Exact replica of unstable on 051908 + README-this
author Mukesh Rathor
date Mon May 19 15:34:57 2008 -0700 (2008-05-19)
parents
children 5c0bf00e371d
line source
1 /* qcow2raw.c
2 *
3 * Generates raw image data from an existing qcow 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 <inttypes.h>
37 #include <unistd.h>
38 #include <sys/statvfs.h>
39 #include <sys/stat.h>
40 #include <sys/ioctl.h>
41 #include <string.h>
42 #include "tapdisk.h"
43 #include "blk.h"
45 #if 1
46 #define DFPRINTF(_f, _a...) fprintf ( stderr, _f , ## _a )
47 #else
48 #define DFPRINTF(_f, _a...) ((void)0)
49 #endif
52 /* *BSD has no O_LARGEFILE */
53 #ifndef O_LARGEFILE
54 #define O_LARGEFILE 0
55 #endif
57 #define TAPDISK 1
58 #define BLOCK_PROCESSSZ 4096
60 static int maxfds, *qcowio_fd, *aio_fd, running = 1, complete = 0;
61 static int returned_read_events = 0, returned_write_events = 0;
62 static int submit_events = 0;
63 static uint32_t read_idx = 0, write_idx = 0;
64 struct disk_driver ddqcow, ddaio;
65 static uint64_t prev = 0, written = 0;
66 static char output[25];
68 void print_bytes(void *ptr, int length) {
70 int i,k;
71 unsigned char *p = ptr;
73 DFPRINTF("Buf dump, length %d:\n",length);
74 for (k = 0; k < length; k++) {
75 DFPRINTF("%x",*p);
76 *p++;
77 if (k % 16 == 0) DFPRINTF("\n");
78 else if (k % 2 == 0) DFPRINTF(" ");
79 }
80 DFPRINTF("\n");
81 return;
82 }
84 void debug_output(uint64_t progress, uint64_t size)
85 {
86 /*Output progress every 5% */
87 uint64_t blocks = size/20;
89 if (progress/blocks > prev) {
90 memcpy(output+prev+1,"=>",2);
91 prev++;
92 DFPRINTF("\r%s %llu%%",
93 output, (long long)((prev-1)*5));
94 }
95 return;
96 }
98 static inline void LOCAL_FD_SET(fd_set *readfds)
99 {
100 FD_SET(qcowio_fd[0], readfds);
101 FD_SET(aio_fd[0], readfds);
103 maxfds = (qcowio_fd[0] > aio_fd[0] ? qcowio_fd[0] : aio_fd[0]) + 1;
105 return;
106 }
108 static int send_write_responses(struct disk_driver *dd, int res, uint64_t sec,
109 int nr_secs, int idx, void *private)
110 {
111 if (res < 0) {
112 DFPRINTF("AIO FAILURE: res [%d]!\n",res);
113 return 0;
114 }
115 written += BLOCK_PROCESSSZ;
116 returned_write_events++;
117 write_idx = idx;
119 debug_output(written, dd->td_state->size << 9);
120 free(private);
121 return 0;
122 }
124 static int send_read_responses(struct disk_driver *dd, int res, uint64_t sec,
125 int nr_secs, int idx, void *private)
126 {
127 int ret;
129 if (res < 0) DFPRINTF("AIO FAILURE: res [%d]!\n",res);
131 returned_read_events++;
132 read_idx = idx;
134 ret = ddaio.drv->td_queue_write(&ddaio, idx, BLOCK_PROCESSSZ>>9, private,
135 send_write_responses, idx, private);
136 if (ret != 0) {
137 DFPRINTF("ERROR in submitting queue write!\n");
138 return 0;
139 }
141 if ( (returned_read_events == submit_events) ||
142 (returned_read_events % 10 == 0) ) {
143 ddaio.drv->td_submit(&ddaio);
144 }
146 return 0;
147 }
149 int main(int argc, char *argv[])
150 {
151 int ret = -1, fd, len,input;
152 uint64_t size;
153 fd_set readfds;
154 struct timeval timeout;
155 uint64_t i;
156 char *buf;
157 struct stat finfo;
159 if (argc != 3) {
160 fprintf(stderr, "Qcow-utils: v1.0.0\n");
161 fprintf(stderr, "usage: %s <Dest File descriptor> "
162 "<Qcow SRC IMAGE>\n",
163 argv[0]);
164 exit(-1);
165 }
167 ddqcow.td_state = malloc(sizeof(struct td_state));
168 ddaio.td_state = malloc(sizeof(struct td_state));
170 /*Open qcow source file*/
171 ddqcow.drv = &tapdisk_qcow;
172 ddqcow.private = malloc(ddqcow.drv->private_data_size);
174 if (ddqcow.drv->td_open(&ddqcow, argv[2], TD_RDONLY)!=0) {
175 DFPRINTF("Unable to open Qcow file [%s]\n",argv[2]);
176 exit(-1);
177 } else DFPRINTF("QCOW file opened, size %llu\n",
178 (long long unsigned)ddqcow.td_state->size);
180 qcowio_fd = ddqcow.io_fd;
182 /*Setup aio destination file*/
183 ret = stat(argv[1],&finfo);
184 if (ret == -1) {
185 /*Check errno*/
186 switch(errno) {
187 case ENOENT:
188 /*File doesn't exist, create*/
189 fd = open(argv[1],
190 O_RDWR | O_LARGEFILE | O_CREAT, 0644);
191 if (fd < 0) {
192 DFPRINTF("ERROR creating file [%s] "
193 "(errno %d)\n",
194 argv[1], 0 - errno);
195 exit(-1);
196 }
197 if (ftruncate(fd, (off_t)ddqcow.td_state->size<<9) < 0) {
198 DFPRINTF("Unable to create file "
199 "[%s] of size %llu (errno %d). "
200 "Exiting...\n",
201 argv[1],
202 (long long unsigned)ddqcow.td_state->size<<9,
203 0 - errno);
204 close(fd);
205 exit(-1);
206 }
207 close(fd);
208 break;
209 case ENXIO:
210 DFPRINTF("ERROR Device [%s] does not exist\n",argv[1]);
211 exit(-1);
212 default:
213 DFPRINTF("An error occurred opening Device [%s] "
214 "(errno %d)\n",
215 argv[1], 0 - errno);
216 exit(-1);
217 }
218 } else {
219 fprintf(stderr, "WARNING: All existing data in "
220 "%s will be overwritten.\nDo you wish to continue? "
221 "(y or n) ",
222 argv[1]);
223 if (getchar() != 'y') {
224 DFPRINTF("Exiting...\n");
225 exit(-1);
226 }
228 /*TODO - Test the existing file or device for adequate space*/
229 fd = open(argv[1], O_RDWR | O_LARGEFILE);
230 if (fd < 0) {
231 DFPRINTF("ERROR: opening file [%s] (errno %d)\n",
232 argv[1], 0 - errno);
233 exit(-1);
234 }
236 if (S_ISBLK(finfo.st_mode)) {
237 if (blk_getimagesize(fd, &size) != 0) {
238 close(fd);
239 return -1;
240 }
242 if (size < ddqcow.td_state->size<<9) {
243 DFPRINTF("ERROR: Not enough space on device "
244 "%s (%"PRIu64" bytes available, "
245 "%llu bytes required\n",
246 argv[1], size,
247 (long long unsigned)ddqcow.td_state->size<<9);
248 close(fd);
249 exit(-1);
250 }
251 } else {
252 if (ftruncate(fd, (off_t)ddqcow.td_state->size<<9) < 0) {
253 DFPRINTF("Unable to create file "
254 "[%s] of size %llu (errno %d). "
255 "Exiting...\n",
256 argv[1],
257 (long long unsigned)ddqcow.td_state->size<<9,
258 0 - errno);
259 close(fd);
260 exit(-1);
261 } else DFPRINTF("File [%s] truncated to length %llu "
262 "(%llu)\n",
263 argv[1],
264 (long long unsigned)ddqcow.td_state->size<<9,
265 (long long unsigned)ddqcow.td_state->size);
266 }
267 close(fd);
268 }
270 /*Open aio destination file*/
271 ddaio.drv = &tapdisk_aio;
272 ddaio.private = malloc(ddaio.drv->private_data_size);
274 if (ddaio.drv->td_open(&ddaio, argv[1], 0)!=0) {
275 DFPRINTF("Unable to open Qcow file [%s]\n", argv[1]);
276 exit(-1);
277 }
279 aio_fd = ddaio.io_fd;
281 /*Initialise the output string*/
282 memset(output,0x20,25);
283 output[0] = '[';
284 output[22] = ']';
285 output[23] = '\0';
286 DFPRINTF("%s",output);
288 i = 0;
289 while (running) {
290 timeout.tv_sec = 0;
292 if (!complete) {
293 /*Read Pages from qcow image*/
294 if ( (ret = posix_memalign((void **)&buf,
295 BLOCK_PROCESSSZ,
296 BLOCK_PROCESSSZ))
297 != 0) {
298 DFPRINTF("Unable to alloc memory (%d)\n",ret);
299 exit(-1);
300 }
302 /*Attempt to read 4k sized blocks*/
303 submit_events++;
304 ret = ddqcow.drv->td_queue_read(&ddqcow, i>>9,
305 BLOCK_PROCESSSZ>>9, buf,
306 send_read_responses, i>>9, buf);
308 if (ret < 0) {
309 DFPRINTF("UNABLE TO READ block [%llu]\n",
310 (long long unsigned)i);
311 exit(-1);
312 } else {
313 i += BLOCK_PROCESSSZ;
314 }
316 if (i >= ddqcow.td_state->size<<9) {
317 complete = 1;
318 }
320 if ((submit_events % 10 == 0) || complete)
321 ddqcow.drv->td_submit(&ddqcow);
322 timeout.tv_usec = 0;
324 } else {
325 timeout.tv_usec = 1000;
326 if (!submit_events) running = 0;
327 }
330 /*Check AIO FD*/
331 LOCAL_FD_SET(&readfds);
332 ret = select(maxfds + 1, &readfds, (fd_set *) 0,
333 (fd_set *) 0, &timeout);
335 if (ret > 0) {
336 if (FD_ISSET(qcowio_fd[0], &readfds))
337 ddqcow.drv->td_do_callbacks(&ddqcow, 0);
338 if (FD_ISSET(aio_fd[0], &readfds))
339 ddaio.drv->td_do_callbacks(&ddaio, 0);
340 }
341 if (complete && (returned_write_events == submit_events))
342 running = 0;
343 }
344 memcpy(output+prev+1,"=",1);
345 DFPRINTF("\r%s 100%%\nTRANSFER COMPLETE\n\n", output);
347 return 0;
348 }