• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Block driver for the COW format
3  *
4  * Copyright (c) 2004 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 #ifndef _WIN32
25 #include "qemu-common.h"
26 #include "block_int.h"
27 #include "module.h"
28 #include <sys/mman.h>
29 
30 /**************************************************************/
31 /* COW block driver using file system holes */
32 
33 /* user mode linux compatible COW file */
34 #define COW_MAGIC 0x4f4f4f4d  /* MOOO */
35 #define COW_VERSION 2
36 
37 struct cow_header_v2 {
38     uint32_t magic;
39     uint32_t version;
40     char backing_file[1024];
41     int32_t mtime;
42     uint64_t size;
43     uint32_t sectorsize;
44 };
45 
46 typedef struct BDRVCowState {
47     int fd;
48     uint8_t *cow_bitmap; /* if non NULL, COW mappings are used first */
49     uint8_t *cow_bitmap_addr; /* mmap address of cow_bitmap */
50     int cow_bitmap_size;
51     int64_t cow_sectors_offset;
52 } BDRVCowState;
53 
cow_probe(const uint8_t * buf,int buf_size,const char * filename)54 static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)
55 {
56     const struct cow_header_v2 *cow_header = (const void *)buf;
57 
58     if (buf_size >= sizeof(struct cow_header_v2) &&
59         be32_to_cpu(cow_header->magic) == COW_MAGIC &&
60         be32_to_cpu(cow_header->version) == COW_VERSION)
61         return 100;
62     else
63         return 0;
64 }
65 
cow_open(BlockDriverState * bs,const char * filename,int flags)66 static int cow_open(BlockDriverState *bs, const char *filename, int flags)
67 {
68     BDRVCowState *s = bs->opaque;
69     int fd;
70     struct cow_header_v2 cow_header;
71     int64_t size;
72 
73     fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
74     if (fd < 0) {
75         fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
76         if (fd < 0)
77             return -1;
78     }
79     s->fd = fd;
80     /* see if it is a cow image */
81     if (read(fd, &cow_header, sizeof(cow_header)) != sizeof(cow_header)) {
82         goto fail;
83     }
84 
85     if (be32_to_cpu(cow_header.magic) != COW_MAGIC ||
86         be32_to_cpu(cow_header.version) != COW_VERSION) {
87         goto fail;
88     }
89 
90     /* cow image found */
91     size = be64_to_cpu(cow_header.size);
92     bs->total_sectors = size / 512;
93 
94     pstrcpy(bs->backing_file, sizeof(bs->backing_file),
95             cow_header.backing_file);
96 
97     /* mmap the bitmap */
98     s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
99     s->cow_bitmap_addr = (void *)mmap(get_mmap_addr(s->cow_bitmap_size),
100                                       s->cow_bitmap_size,
101                                       PROT_READ | PROT_WRITE,
102                                       MAP_SHARED, s->fd, 0);
103     if (s->cow_bitmap_addr == MAP_FAILED)
104         goto fail;
105     s->cow_bitmap = s->cow_bitmap_addr + sizeof(cow_header);
106     s->cow_sectors_offset = (s->cow_bitmap_size + 511) & ~511;
107     return 0;
108  fail:
109     close(fd);
110     return -1;
111 }
112 
cow_set_bit(uint8_t * bitmap,int64_t bitnum)113 static inline void cow_set_bit(uint8_t *bitmap, int64_t bitnum)
114 {
115     bitmap[bitnum / 8] |= (1 << (bitnum%8));
116 }
117 
is_bit_set(const uint8_t * bitmap,int64_t bitnum)118 static inline int is_bit_set(const uint8_t *bitmap, int64_t bitnum)
119 {
120     return !!(bitmap[bitnum / 8] & (1 << (bitnum%8)));
121 }
122 
123 
124 /* Return true if first block has been changed (ie. current version is
125  * in COW file).  Set the number of continuous blocks for which that
126  * is true. */
is_changed(uint8_t * bitmap,int64_t sector_num,int nb_sectors,int * num_same)127 static inline int is_changed(uint8_t *bitmap,
128                              int64_t sector_num, int nb_sectors,
129                              int *num_same)
130 {
131     int changed;
132 
133     if (!bitmap || nb_sectors == 0) {
134 	*num_same = nb_sectors;
135 	return 0;
136     }
137 
138     changed = is_bit_set(bitmap, sector_num);
139     for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) {
140 	if (is_bit_set(bitmap, sector_num + *num_same) != changed)
141 	    break;
142     }
143 
144     return changed;
145 }
146 
cow_is_allocated(BlockDriverState * bs,int64_t sector_num,int nb_sectors,int * pnum)147 static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num,
148                             int nb_sectors, int *pnum)
149 {
150     BDRVCowState *s = bs->opaque;
151     return is_changed(s->cow_bitmap, sector_num, nb_sectors, pnum);
152 }
153 
cow_read(BlockDriverState * bs,int64_t sector_num,uint8_t * buf,int nb_sectors)154 static int cow_read(BlockDriverState *bs, int64_t sector_num,
155                     uint8_t *buf, int nb_sectors)
156 {
157     BDRVCowState *s = bs->opaque;
158     int ret, n;
159 
160     while (nb_sectors > 0) {
161         if (is_changed(s->cow_bitmap, sector_num, nb_sectors, &n)) {
162             lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
163             ret = read(s->fd, buf, n * 512);
164             if (ret != n * 512)
165                 return -1;
166         } else {
167             if (bs->backing_hd) {
168                 /* read from the base image */
169                 ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
170                 if (ret < 0)
171                     return -1;
172             } else {
173             memset(buf, 0, n * 512);
174         }
175         }
176         nb_sectors -= n;
177         sector_num += n;
178         buf += n * 512;
179     }
180     return 0;
181 }
182 
cow_write(BlockDriverState * bs,int64_t sector_num,const uint8_t * buf,int nb_sectors)183 static int cow_write(BlockDriverState *bs, int64_t sector_num,
184                      const uint8_t *buf, int nb_sectors)
185 {
186     BDRVCowState *s = bs->opaque;
187     int ret, i;
188 
189     lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
190     ret = write(s->fd, buf, nb_sectors * 512);
191     if (ret != nb_sectors * 512)
192         return -1;
193     for (i = 0; i < nb_sectors; i++)
194         cow_set_bit(s->cow_bitmap, sector_num + i);
195     return 0;
196 }
197 
cow_close(BlockDriverState * bs)198 static void cow_close(BlockDriverState *bs)
199 {
200     BDRVCowState *s = bs->opaque;
201     munmap((void *)s->cow_bitmap_addr, s->cow_bitmap_size);
202     close(s->fd);
203 }
204 
cow_create(const char * filename,QEMUOptionParameter * options)205 static int cow_create(const char *filename, QEMUOptionParameter *options)
206 {
207     int fd, cow_fd;
208     struct cow_header_v2 cow_header;
209     struct stat st;
210     int64_t image_sectors = 0;
211     const char *image_filename = NULL;
212 
213     /* Read out options */
214     while (options && options->name) {
215         if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
216             image_sectors = options->value.n / 512;
217         } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
218             image_filename = options->value.s;
219         }
220         options++;
221     }
222 
223     cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
224               0644);
225     if (cow_fd < 0)
226         return -1;
227     memset(&cow_header, 0, sizeof(cow_header));
228     cow_header.magic = cpu_to_be32(COW_MAGIC);
229     cow_header.version = cpu_to_be32(COW_VERSION);
230     if (image_filename) {
231         /* Note: if no file, we put a dummy mtime */
232         cow_header.mtime = cpu_to_be32(0);
233 
234         fd = open(image_filename, O_RDONLY | O_BINARY);
235         if (fd < 0) {
236             close(cow_fd);
237             goto mtime_fail;
238         }
239         if (fstat(fd, &st) != 0) {
240             close(fd);
241             goto mtime_fail;
242         }
243         close(fd);
244         cow_header.mtime = cpu_to_be32(st.st_mtime);
245     mtime_fail:
246         pstrcpy(cow_header.backing_file, sizeof(cow_header.backing_file),
247                 image_filename);
248     }
249     cow_header.sectorsize = cpu_to_be32(512);
250     cow_header.size = cpu_to_be64(image_sectors * 512);
251     write(cow_fd, &cow_header, sizeof(cow_header));
252     /* resize to include at least all the bitmap */
253     ftruncate(cow_fd, sizeof(cow_header) + ((image_sectors + 7) >> 3));
254     close(cow_fd);
255     return 0;
256 }
257 
cow_flush(BlockDriverState * bs)258 static void cow_flush(BlockDriverState *bs)
259 {
260     BDRVCowState *s = bs->opaque;
261     fsync(s->fd);
262 }
263 
264 static QEMUOptionParameter cow_create_options[] = {
265     {
266         .name = BLOCK_OPT_SIZE,
267         .type = OPT_SIZE,
268         .help = "Virtual disk size"
269     },
270     {
271         .name = BLOCK_OPT_BACKING_FILE,
272         .type = OPT_STRING,
273         .help = "File name of a base image"
274     },
275     { NULL }
276 };
277 
278 static BlockDriver bdrv_cow = {
279     .format_name	= "cow",
280     .instance_size	= sizeof(BDRVCowState),
281     .bdrv_probe		= cow_probe,
282     .bdrv_open		= cow_open,
283     .bdrv_read		= cow_read,
284     .bdrv_write		= cow_write,
285     .bdrv_close		= cow_close,
286     .bdrv_create	= cow_create,
287     .bdrv_flush		= cow_flush,
288     .bdrv_is_allocated	= cow_is_allocated,
289 
290     .create_options = cow_create_options,
291 };
292 
bdrv_cow_init(void)293 static void bdrv_cow_init(void)
294 {
295     bdrv_register(&bdrv_cow);
296 }
297 
298 block_init(bdrv_cow_init);
299 #endif
300