added cow.h
[qemu] / block.c
1 /*
2  * QEMU System Emulator block driver
3  * 
4  * Copyright (c) 2003 Fabrice Bellard
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include <getopt.h>
29 #include <inttypes.h>
30 #include <unistd.h>
31 #include <sys/mman.h>
32 #include <fcntl.h>
33 #include <signal.h>
34 #include <time.h>
35 #include <sys/time.h>
36 #include <malloc.h>
37 #include <termios.h>
38 #include <sys/poll.h>
39 #include <errno.h>
40 #include <sys/wait.h>
41 #include <netinet/in.h>
42
43 #include "vl.h"
44
45 #define NO_THUNK_TYPE_SIZE
46 #include "thunk.h"
47
48 #include "cow.h"
49
50 struct BlockDriverState {
51     int fd; /* if -1, only COW mappings */
52     int64_t total_sectors;
53     int read_only;
54
55     uint8_t *cow_bitmap; /* if non NULL, COW mappings are used first */
56     uint8_t *cow_bitmap_addr; /* mmap address of cow_bitmap */
57     int cow_bitmap_size;
58     int cow_fd;
59     int64_t cow_sectors_offset;
60     int boot_sector_enabled;
61     uint8_t boot_sector_data[512];
62
63     char filename[1024];
64 };
65
66 BlockDriverState *bdrv_open(const char *filename, int snapshot)
67 {
68     BlockDriverState *bs;
69     int fd, cow_fd;
70     int64_t size;
71     char template[] = "/tmp/vl.XXXXXX";
72     struct cow_header_v2 cow_header;
73     struct stat st;
74
75     bs = malloc(sizeof(BlockDriverState));
76     if(!bs)
77         return NULL;
78     bs->read_only = 0;
79     bs->fd = -1;
80     bs->cow_fd = -1;
81     bs->cow_bitmap = NULL;
82     strcpy(bs->filename, filename);
83
84     /* open standard HD image */
85     fd = open(filename, O_RDWR | O_LARGEFILE);
86     if (fd < 0) {
87         /* read only image on disk */
88         fd = open(filename, O_RDONLY | O_LARGEFILE);
89         if (fd < 0) {
90             perror(filename);
91             goto fail;
92         }
93         if (!snapshot)
94             bs->read_only = 1;
95     }
96     bs->fd = fd;
97
98     /* see if it is a cow image */
99     if (read(fd, &cow_header, sizeof(cow_header)) != sizeof(cow_header)) {
100         fprintf(stderr, "%s: could not read header\n", filename);
101         goto fail;
102     }
103     if (cow_header.magic == htonl(COW_MAGIC) &&
104         cow_header.version == htonl(COW_VERSION)) {
105         /* cow image found */
106         size = cow_header.size;
107 #ifndef WORDS_BIGENDIAN
108         size = bswap64(size);
109 #endif    
110         bs->total_sectors = size / 512;
111
112         bs->cow_fd = fd;
113         bs->fd = -1;
114         if (cow_header.backing_file[0] != '\0') {
115             if (stat(cow_header.backing_file, &st) != 0) {
116                 fprintf(stderr, "%s: could not find original disk image '%s'\n", filename, cow_header.backing_file);
117                 goto fail;
118             }
119             if (st.st_mtime != htonl(cow_header.mtime)) {
120                 fprintf(stderr, "%s: original raw disk image '%s' does not match saved timestamp\n", filename, cow_header.backing_file);
121                 goto fail;
122             }
123             fd = open(cow_header.backing_file, O_RDONLY | O_LARGEFILE);
124             if (fd < 0)
125                 goto fail;
126             bs->fd = fd;
127         }
128         /* mmap the bitmap */
129         bs->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
130         bs->cow_bitmap_addr = mmap(get_mmap_addr(bs->cow_bitmap_size), 
131                                    bs->cow_bitmap_size, 
132                                    PROT_READ | PROT_WRITE,
133                                    MAP_SHARED, bs->cow_fd, 0);
134         if (bs->cow_bitmap_addr == MAP_FAILED)
135             goto fail;
136         bs->cow_bitmap = bs->cow_bitmap_addr + sizeof(cow_header);
137         bs->cow_sectors_offset = (bs->cow_bitmap_size + 511) & ~511;
138         snapshot = 0;
139     } else {
140         /* standard raw image */
141         size = lseek64(fd, 0, SEEK_END);
142         bs->total_sectors = size / 512;
143         bs->fd = fd;
144     }
145
146     if (snapshot) {
147         /* create a temporary COW file */
148         cow_fd = mkstemp(template);
149         if (cow_fd < 0)
150             goto fail;
151         bs->cow_fd = cow_fd;
152         unlink(template);
153         
154         /* just need to allocate bitmap */
155         bs->cow_bitmap_size = (bs->total_sectors + 7) >> 3;
156         bs->cow_bitmap_addr = mmap(get_mmap_addr(bs->cow_bitmap_size), 
157                                    bs->cow_bitmap_size, 
158                                    PROT_READ | PROT_WRITE,
159                                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
160         if (bs->cow_bitmap_addr == MAP_FAILED)
161             goto fail;
162         bs->cow_bitmap = bs->cow_bitmap_addr;
163         bs->cow_sectors_offset = 0;
164     }
165     
166     return bs;
167  fail:
168     bdrv_close(bs);
169     return NULL;
170 }
171
172 void bdrv_close(BlockDriverState *bs)
173 {
174     /* we unmap the mapping so that it is written to the COW file */
175     if (bs->cow_bitmap_addr)
176         munmap(bs->cow_bitmap_addr, bs->cow_bitmap_size);
177     if (bs->cow_fd >= 0)
178         close(bs->cow_fd);
179     if (bs->fd >= 0)
180         close(bs->fd);
181     free(bs);
182 }
183
184 static inline void set_bit(uint8_t *bitmap, int64_t bitnum)
185 {
186     bitmap[bitnum / 8] |= (1 << (bitnum%8));
187 }
188
189 static inline int is_bit_set(const uint8_t *bitmap, int64_t bitnum)
190 {
191     return !!(bitmap[bitnum / 8] & (1 << (bitnum%8)));
192 }
193
194
195 /* Return true if first block has been changed (ie. current version is
196  * in COW file).  Set the number of continuous blocks for which that
197  * is true. */
198 static int is_changed(uint8_t *bitmap,
199                       int64_t sector_num, int nb_sectors,
200                       int *num_same)
201 {
202     int changed;
203
204     if (!bitmap || nb_sectors == 0) {
205         *num_same = nb_sectors;
206         return 0;
207     }
208
209     changed = is_bit_set(bitmap, sector_num);
210     for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) {
211         if (is_bit_set(bitmap, sector_num + *num_same) != changed)
212             break;
213     }
214
215     return changed;
216 }
217
218 /* commit COW file into the raw image */
219 int bdrv_commit(BlockDriverState *bs)
220 {
221     int64_t i;
222     uint8_t *cow_bitmap;
223
224     if (!bs->cow_bitmap) {
225         fprintf(stderr, "Already committed to %s\n", bs->filename);
226         return 0;
227     }
228
229     if (bs->read_only) {
230         fprintf(stderr, "Can't commit to %s: read-only\n", bs->filename);
231         return -1;
232     }
233
234     cow_bitmap = bs->cow_bitmap;
235     for (i = 0; i < bs->total_sectors; i++) {
236         if (is_bit_set(cow_bitmap, i)) {
237             unsigned char sector[512];
238             if (bdrv_read(bs, i, sector, 1) != 0) {
239                 fprintf(stderr, "Error reading sector %lli: aborting commit\n",
240                         (long long)i);
241                 return -1;
242             }
243
244             /* Make bdrv_write write to real file for a moment. */
245             bs->cow_bitmap = NULL;
246             if (bdrv_write(bs, i, sector, 1) != 0) {
247                 fprintf(stderr, "Error writing sector %lli: aborting commit\n",
248                         (long long)i);
249                 bs->cow_bitmap = cow_bitmap;
250                 return -1;
251             }
252             bs->cow_bitmap = cow_bitmap;
253         }
254     }
255     fprintf(stderr, "Committed snapshot to %s\n", bs->filename);
256     return 0;
257 }
258
259 /* return -1 if error */
260 int bdrv_read(BlockDriverState *bs, int64_t sector_num, 
261               uint8_t *buf, int nb_sectors)
262 {
263     int ret, n, fd;
264     int64_t offset;
265     
266     while (nb_sectors > 0) {
267         if (is_changed(bs->cow_bitmap, sector_num, nb_sectors, &n)) {
268             fd = bs->cow_fd;
269             offset = bs->cow_sectors_offset;
270         } else if (sector_num == 0 && bs->boot_sector_enabled) {
271             memcpy(buf, bs->boot_sector_data, 512);
272             n = 1;
273             goto next;
274         } else {
275             fd = bs->fd;
276             offset = 0;
277         }
278
279         if (fd < 0) {
280             /* no file, just return empty sectors */
281             memset(buf, 0, n * 512);
282         } else {
283             offset += sector_num * 512;
284             lseek64(fd, offset, SEEK_SET);
285             ret = read(fd, buf, n * 512);
286             if (ret != n * 512) {
287                 return -1;
288             }
289         }
290     next:
291         nb_sectors -= n;
292         sector_num += n;
293         buf += n * 512;
294     }
295     return 0;
296 }
297
298 /* return -1 if error */
299 int bdrv_write(BlockDriverState *bs, int64_t sector_num, 
300                const uint8_t *buf, int nb_sectors)
301 {
302     int ret, fd, i;
303     int64_t offset, retl;
304     
305     if (bs->read_only)
306         return -1;
307
308     if (bs->cow_bitmap) {
309         fd = bs->cow_fd;
310         offset = bs->cow_sectors_offset;
311     } else {
312         fd = bs->fd;
313         offset = 0;
314     }
315     
316     offset += sector_num * 512;
317     retl = lseek64(fd, offset, SEEK_SET);
318     if (retl == -1) {
319         return -1;
320     }
321     ret = write(fd, buf, nb_sectors * 512);
322     if (ret != nb_sectors * 512) {
323         return -1;
324     }
325
326     if (bs->cow_bitmap) {
327         for (i = 0; i < nb_sectors; i++)
328             set_bit(bs->cow_bitmap, sector_num + i);
329     }
330     return 0;
331 }
332
333 void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
334 {
335     *nb_sectors_ptr = bs->total_sectors;
336 }
337
338 /* force a given boot sector. */
339 void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
340 {
341     bs->boot_sector_enabled = 1;
342     if (size > 512)
343         size = 512;
344     memcpy(bs->boot_sector_data, data, size);
345     memset(bs->boot_sector_data + size, 0, 512 - size);
346 }