Tizen 2.0 Release
[sdk/emulator/qemu.git] / block / cow.c
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 #include "qemu-common.h"
25 #include "block_int.h"
26 #include "module.h"
27
28 /**************************************************************/
29 /* COW block driver using file system holes */
30
31 /* user mode linux compatible COW file */
32 #define COW_MAGIC 0x4f4f4f4d  /* MOOO */
33 #define COW_VERSION 2
34
35 struct cow_header_v2 {
36     uint32_t magic;
37     uint32_t version;
38     char backing_file[1024];
39     int32_t mtime;
40     uint64_t size;
41     uint32_t sectorsize;
42 };
43
44 typedef struct BDRVCowState {
45     CoMutex lock;
46     int64_t cow_sectors_offset;
47 } BDRVCowState;
48
49 static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)
50 {
51     const struct cow_header_v2 *cow_header = (const void *)buf;
52
53     if (buf_size >= sizeof(struct cow_header_v2) &&
54         be32_to_cpu(cow_header->magic) == COW_MAGIC &&
55         be32_to_cpu(cow_header->version) == COW_VERSION)
56         return 100;
57     else
58         return 0;
59 }
60
61 static int cow_open(BlockDriverState *bs, int flags)
62 {
63     BDRVCowState *s = bs->opaque;
64     struct cow_header_v2 cow_header;
65     int bitmap_size;
66     int64_t size;
67
68     /* see if it is a cow image */
69     if (bdrv_pread(bs->file, 0, &cow_header, sizeof(cow_header)) !=
70             sizeof(cow_header)) {
71         goto fail;
72     }
73
74     if (be32_to_cpu(cow_header.magic) != COW_MAGIC ||
75         be32_to_cpu(cow_header.version) != COW_VERSION) {
76         goto fail;
77     }
78
79     /* cow image found */
80     size = be64_to_cpu(cow_header.size);
81     bs->total_sectors = size / 512;
82
83     pstrcpy(bs->backing_file, sizeof(bs->backing_file),
84             cow_header.backing_file);
85
86     bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
87     s->cow_sectors_offset = (bitmap_size + 511) & ~511;
88     qemu_co_mutex_init(&s->lock);
89     return 0;
90  fail:
91     return -1;
92 }
93
94 /*
95  * XXX(hch): right now these functions are extremly ineffcient.
96  * We should just read the whole bitmap we'll need in one go instead.
97  */
98 static inline int cow_set_bit(BlockDriverState *bs, int64_t bitnum)
99 {
100     uint64_t offset = sizeof(struct cow_header_v2) + bitnum / 8;
101     uint8_t bitmap;
102     int ret;
103
104     ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap));
105     if (ret < 0) {
106        return ret;
107     }
108
109     bitmap |= (1 << (bitnum % 8));
110
111     ret = bdrv_pwrite_sync(bs->file, offset, &bitmap, sizeof(bitmap));
112     if (ret < 0) {
113        return ret;
114     }
115     return 0;
116 }
117
118 static inline int is_bit_set(BlockDriverState *bs, int64_t bitnum)
119 {
120     uint64_t offset = sizeof(struct cow_header_v2) + bitnum / 8;
121     uint8_t bitmap;
122     int ret;
123
124     ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap));
125     if (ret < 0) {
126        return ret;
127     }
128
129     return !!(bitmap & (1 << (bitnum % 8)));
130 }
131
132 /* Return true if first block has been changed (ie. current version is
133  * in COW file).  Set the number of continuous blocks for which that
134  * is true. */
135 static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num,
136         int nb_sectors, int *num_same)
137 {
138     int changed;
139
140     if (nb_sectors == 0) {
141         *num_same = nb_sectors;
142         return 0;
143     }
144
145     changed = is_bit_set(bs, sector_num);
146     if (changed < 0) {
147         return 0; /* XXX: how to return I/O errors? */
148     }
149
150     for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) {
151         if (is_bit_set(bs, sector_num + *num_same) != changed)
152             break;
153     }
154
155     return changed;
156 }
157
158 static int cow_update_bitmap(BlockDriverState *bs, int64_t sector_num,
159         int nb_sectors)
160 {
161     int error = 0;
162     int i;
163
164     for (i = 0; i < nb_sectors; i++) {
165         error = cow_set_bit(bs, sector_num + i);
166         if (error) {
167             break;
168         }
169     }
170
171     return error;
172 }
173
174 static int cow_read(BlockDriverState *bs, int64_t sector_num,
175                     uint8_t *buf, int nb_sectors)
176 {
177     BDRVCowState *s = bs->opaque;
178     int ret, n;
179
180     while (nb_sectors > 0) {
181         if (cow_is_allocated(bs, sector_num, nb_sectors, &n)) {
182             ret = bdrv_pread(bs->file,
183                         s->cow_sectors_offset + sector_num * 512,
184                         buf, n * 512);
185             if (ret != n * 512)
186                 return -1;
187         } else {
188             if (bs->backing_hd) {
189                 /* read from the base image */
190                 ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
191                 if (ret < 0)
192                     return -1;
193             } else {
194             memset(buf, 0, n * 512);
195         }
196         }
197         nb_sectors -= n;
198         sector_num += n;
199         buf += n * 512;
200     }
201     return 0;
202 }
203
204 static coroutine_fn int cow_co_read(BlockDriverState *bs, int64_t sector_num,
205                                     uint8_t *buf, int nb_sectors)
206 {
207     int ret;
208     BDRVCowState *s = bs->opaque;
209     qemu_co_mutex_lock(&s->lock);
210     ret = cow_read(bs, sector_num, buf, nb_sectors);
211     qemu_co_mutex_unlock(&s->lock);
212     return ret;
213 }
214
215 static int cow_write(BlockDriverState *bs, int64_t sector_num,
216                      const uint8_t *buf, int nb_sectors)
217 {
218     BDRVCowState *s = bs->opaque;
219     int ret;
220
221     ret = bdrv_pwrite(bs->file, s->cow_sectors_offset + sector_num * 512,
222                       buf, nb_sectors * 512);
223     if (ret != nb_sectors * 512)
224         return -1;
225
226     return cow_update_bitmap(bs, sector_num, nb_sectors);
227 }
228
229 static coroutine_fn int cow_co_write(BlockDriverState *bs, int64_t sector_num,
230                                      const uint8_t *buf, int nb_sectors)
231 {
232     int ret;
233     BDRVCowState *s = bs->opaque;
234     qemu_co_mutex_lock(&s->lock);
235     ret = cow_write(bs, sector_num, buf, nb_sectors);
236     qemu_co_mutex_unlock(&s->lock);
237     return ret;
238 }
239
240 static void cow_close(BlockDriverState *bs)
241 {
242 }
243
244 static int cow_create(const char *filename, QEMUOptionParameter *options)
245 {
246     int fd, cow_fd;
247     struct cow_header_v2 cow_header;
248     struct stat st;
249     int64_t image_sectors = 0;
250     const char *image_filename = NULL;
251     int ret;
252
253     /* Read out options */
254     while (options && options->name) {
255         if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
256             image_sectors = options->value.n / 512;
257         } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
258             image_filename = options->value.s;
259         }
260         options++;
261     }
262
263     cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
264               0644);
265     if (cow_fd < 0)
266         return -errno;
267     memset(&cow_header, 0, sizeof(cow_header));
268     cow_header.magic = cpu_to_be32(COW_MAGIC);
269     cow_header.version = cpu_to_be32(COW_VERSION);
270     if (image_filename) {
271         /* Note: if no file, we put a dummy mtime */
272         cow_header.mtime = cpu_to_be32(0);
273
274         fd = open(image_filename, O_RDONLY | O_BINARY);
275         if (fd < 0) {
276             close(cow_fd);
277             goto mtime_fail;
278         }
279         if (fstat(fd, &st) != 0) {
280             close(fd);
281             goto mtime_fail;
282         }
283         close(fd);
284         cow_header.mtime = cpu_to_be32(st.st_mtime);
285     mtime_fail:
286         pstrcpy(cow_header.backing_file, sizeof(cow_header.backing_file),
287                 image_filename);
288     }
289     cow_header.sectorsize = cpu_to_be32(512);
290     cow_header.size = cpu_to_be64(image_sectors * 512);
291     ret = qemu_write_full(cow_fd, &cow_header, sizeof(cow_header));
292     if (ret != sizeof(cow_header)) {
293         ret = -errno;
294         goto exit;
295     }
296
297     /* resize to include at least all the bitmap */
298     ret = ftruncate(cow_fd, sizeof(cow_header) + ((image_sectors + 7) >> 3));
299     if (ret) {
300         ret = -errno;
301         goto exit;
302     }
303
304 exit:
305     close(cow_fd);
306     return ret;
307 }
308
309 static coroutine_fn int cow_co_flush(BlockDriverState *bs)
310 {
311     return bdrv_co_flush(bs->file);
312 }
313
314 static QEMUOptionParameter cow_create_options[] = {
315     {
316         .name = BLOCK_OPT_SIZE,
317         .type = OPT_SIZE,
318         .help = "Virtual disk size"
319     },
320     {
321         .name = BLOCK_OPT_BACKING_FILE,
322         .type = OPT_STRING,
323         .help = "File name of a base image"
324     },
325     { NULL }
326 };
327
328 static BlockDriver bdrv_cow = {
329     .format_name    = "cow",
330     .instance_size  = sizeof(BDRVCowState),
331
332     .bdrv_probe     = cow_probe,
333     .bdrv_open      = cow_open,
334     .bdrv_close     = cow_close,
335     .bdrv_create    = cow_create,
336
337     .bdrv_read              = cow_co_read,
338     .bdrv_write             = cow_co_write,
339     .bdrv_co_flush_to_disk  = cow_co_flush,
340     .bdrv_is_allocated      = cow_is_allocated,
341
342     .create_options = cow_create_options,
343 };
344
345 static void bdrv_cow_init(void)
346 {
347     bdrv_register(&bdrv_cow);
348 }
349
350 block_init(bdrv_cow_init);