Statistics
| Branch: | Revision:

root / block / cow.c @ 2dedf83e

History | View | Annotate | Download (8.9 kB)

1 ea2384d3 bellard
/*
2 ea2384d3 bellard
 * Block driver for the COW format
3 5fafdf24 ths
 *
4 ea2384d3 bellard
 * Copyright (c) 2004 Fabrice Bellard
5 5fafdf24 ths
 *
6 ea2384d3 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 ea2384d3 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 ea2384d3 bellard
 * in the Software without restriction, including without limitation the rights
9 ea2384d3 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 ea2384d3 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 ea2384d3 bellard
 * furnished to do so, subject to the following conditions:
12 ea2384d3 bellard
 *
13 ea2384d3 bellard
 * The above copyright notice and this permission notice shall be included in
14 ea2384d3 bellard
 * all copies or substantial portions of the Software.
15 ea2384d3 bellard
 *
16 ea2384d3 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 ea2384d3 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 ea2384d3 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 ea2384d3 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 ea2384d3 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 ea2384d3 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 ea2384d3 bellard
 * THE SOFTWARE.
23 ea2384d3 bellard
 */
24 ea2384d3 bellard
#ifndef _WIN32
25 faf07963 pbrook
#include "qemu-common.h"
26 ea2384d3 bellard
#include "block_int.h"
27 5efa9d5a Anthony Liguori
#include "module.h"
28 ea2384d3 bellard
#include <sys/mman.h>
29 ea2384d3 bellard
30 ea2384d3 bellard
/**************************************************************/
31 ea2384d3 bellard
/* COW block driver using file system holes */
32 ea2384d3 bellard
33 ea2384d3 bellard
/* user mode linux compatible COW file */
34 ea2384d3 bellard
#define COW_MAGIC 0x4f4f4f4d  /* MOOO */
35 ea2384d3 bellard
#define COW_VERSION 2
36 ea2384d3 bellard
37 ea2384d3 bellard
struct cow_header_v2 {
38 ea2384d3 bellard
    uint32_t magic;
39 ea2384d3 bellard
    uint32_t version;
40 ea2384d3 bellard
    char backing_file[1024];
41 ea2384d3 bellard
    int32_t mtime;
42 ea2384d3 bellard
    uint64_t size;
43 ea2384d3 bellard
    uint32_t sectorsize;
44 ea2384d3 bellard
};
45 ea2384d3 bellard
46 ea2384d3 bellard
typedef struct BDRVCowState {
47 ea2384d3 bellard
    int fd;
48 ea2384d3 bellard
    uint8_t *cow_bitmap; /* if non NULL, COW mappings are used first */
49 ea2384d3 bellard
    uint8_t *cow_bitmap_addr; /* mmap address of cow_bitmap */
50 ea2384d3 bellard
    int cow_bitmap_size;
51 ea2384d3 bellard
    int64_t cow_sectors_offset;
52 ea2384d3 bellard
} BDRVCowState;
53 ea2384d3 bellard
54 ea2384d3 bellard
static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)
55 ea2384d3 bellard
{
56 ea2384d3 bellard
    const struct cow_header_v2 *cow_header = (const void *)buf;
57 ea2384d3 bellard
58 712e7874 bellard
    if (buf_size >= sizeof(struct cow_header_v2) &&
59 712e7874 bellard
        be32_to_cpu(cow_header->magic) == COW_MAGIC &&
60 5fafdf24 ths
        be32_to_cpu(cow_header->version) == COW_VERSION)
61 ea2384d3 bellard
        return 100;
62 ea2384d3 bellard
    else
63 ea2384d3 bellard
        return 0;
64 ea2384d3 bellard
}
65 ea2384d3 bellard
66 83f64091 bellard
static int cow_open(BlockDriverState *bs, const char *filename, int flags)
67 ea2384d3 bellard
{
68 ea2384d3 bellard
    BDRVCowState *s = bs->opaque;
69 ea2384d3 bellard
    int fd;
70 ea2384d3 bellard
    struct cow_header_v2 cow_header;
71 ea2384d3 bellard
    int64_t size;
72 ea2384d3 bellard
73 ea2384d3 bellard
    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
74 ea2384d3 bellard
    if (fd < 0) {
75 ea2384d3 bellard
        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
76 ea2384d3 bellard
        if (fd < 0)
77 ea2384d3 bellard
            return -1;
78 ea2384d3 bellard
    }
79 ea2384d3 bellard
    s->fd = fd;
80 ea2384d3 bellard
    /* see if it is a cow image */
81 ea2384d3 bellard
    if (read(fd, &cow_header, sizeof(cow_header)) != sizeof(cow_header)) {
82 ea2384d3 bellard
        goto fail;
83 ea2384d3 bellard
    }
84 ea2384d3 bellard
85 ea2384d3 bellard
    if (be32_to_cpu(cow_header.magic) != COW_MAGIC ||
86 ea2384d3 bellard
        be32_to_cpu(cow_header.version) != COW_VERSION) {
87 ea2384d3 bellard
        goto fail;
88 ea2384d3 bellard
    }
89 3b46e624 ths
90 ea2384d3 bellard
    /* cow image found */
91 ea2384d3 bellard
    size = be64_to_cpu(cow_header.size);
92 ea2384d3 bellard
    bs->total_sectors = size / 512;
93 ea2384d3 bellard
94 5fafdf24 ths
    pstrcpy(bs->backing_file, sizeof(bs->backing_file),
95 ea2384d3 bellard
            cow_header.backing_file);
96 3b46e624 ths
97 ea2384d3 bellard
    /* mmap the bitmap */
98 ea2384d3 bellard
    s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
99 3f4cb3d3 blueswir1
    s->cow_bitmap_addr = (void *)mmap(get_mmap_addr(s->cow_bitmap_size),
100 3f4cb3d3 blueswir1
                                      s->cow_bitmap_size,
101 3f4cb3d3 blueswir1
                                      PROT_READ | PROT_WRITE,
102 3f4cb3d3 blueswir1
                                      MAP_SHARED, s->fd, 0);
103 ea2384d3 bellard
    if (s->cow_bitmap_addr == MAP_FAILED)
104 ea2384d3 bellard
        goto fail;
105 ea2384d3 bellard
    s->cow_bitmap = s->cow_bitmap_addr + sizeof(cow_header);
106 ea2384d3 bellard
    s->cow_sectors_offset = (s->cow_bitmap_size + 511) & ~511;
107 ea2384d3 bellard
    return 0;
108 ea2384d3 bellard
 fail:
109 ea2384d3 bellard
    close(fd);
110 ea2384d3 bellard
    return -1;
111 ea2384d3 bellard
}
112 ea2384d3 bellard
113 2b03a7a5 bellard
static inline void cow_set_bit(uint8_t *bitmap, int64_t bitnum)
114 ea2384d3 bellard
{
115 ea2384d3 bellard
    bitmap[bitnum / 8] |= (1 << (bitnum%8));
116 ea2384d3 bellard
}
117 ea2384d3 bellard
118 ea2384d3 bellard
static inline int is_bit_set(const uint8_t *bitmap, int64_t bitnum)
119 ea2384d3 bellard
{
120 ea2384d3 bellard
    return !!(bitmap[bitnum / 8] & (1 << (bitnum%8)));
121 ea2384d3 bellard
}
122 ea2384d3 bellard
123 ea2384d3 bellard
124 ea2384d3 bellard
/* Return true if first block has been changed (ie. current version is
125 ea2384d3 bellard
 * in COW file).  Set the number of continuous blocks for which that
126 ea2384d3 bellard
 * is true. */
127 ea2384d3 bellard
static inline int is_changed(uint8_t *bitmap,
128 ea2384d3 bellard
                             int64_t sector_num, int nb_sectors,
129 ea2384d3 bellard
                             int *num_same)
130 ea2384d3 bellard
{
131 ea2384d3 bellard
    int changed;
132 ea2384d3 bellard
133 ea2384d3 bellard
    if (!bitmap || nb_sectors == 0) {
134 ea2384d3 bellard
        *num_same = nb_sectors;
135 ea2384d3 bellard
        return 0;
136 ea2384d3 bellard
    }
137 ea2384d3 bellard
138 ea2384d3 bellard
    changed = is_bit_set(bitmap, sector_num);
139 ea2384d3 bellard
    for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) {
140 ea2384d3 bellard
        if (is_bit_set(bitmap, sector_num + *num_same) != changed)
141 ea2384d3 bellard
            break;
142 ea2384d3 bellard
    }
143 ea2384d3 bellard
144 ea2384d3 bellard
    return changed;
145 ea2384d3 bellard
}
146 ea2384d3 bellard
147 5fafdf24 ths
static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num,
148 ea2384d3 bellard
                            int nb_sectors, int *pnum)
149 ea2384d3 bellard
{
150 ea2384d3 bellard
    BDRVCowState *s = bs->opaque;
151 ea2384d3 bellard
    return is_changed(s->cow_bitmap, sector_num, nb_sectors, pnum);
152 ea2384d3 bellard
}
153 ea2384d3 bellard
154 5fafdf24 ths
static int cow_read(BlockDriverState *bs, int64_t sector_num,
155 ea2384d3 bellard
                    uint8_t *buf, int nb_sectors)
156 ea2384d3 bellard
{
157 ea2384d3 bellard
    BDRVCowState *s = bs->opaque;
158 ea2384d3 bellard
    int ret, n;
159 3b46e624 ths
160 ea2384d3 bellard
    while (nb_sectors > 0) {
161 ea2384d3 bellard
        if (is_changed(s->cow_bitmap, sector_num, nb_sectors, &n)) {
162 d5249393 bellard
            lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
163 ea2384d3 bellard
            ret = read(s->fd, buf, n * 512);
164 5fafdf24 ths
            if (ret != n * 512)
165 ea2384d3 bellard
                return -1;
166 ea2384d3 bellard
        } else {
167 83f64091 bellard
            if (bs->backing_hd) {
168 83f64091 bellard
                /* read from the base image */
169 83f64091 bellard
                ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
170 83f64091 bellard
                if (ret < 0)
171 83f64091 bellard
                    return -1;
172 83f64091 bellard
            } else {
173 ea2384d3 bellard
            memset(buf, 0, n * 512);
174 ea2384d3 bellard
        }
175 83f64091 bellard
        }
176 ea2384d3 bellard
        nb_sectors -= n;
177 ea2384d3 bellard
        sector_num += n;
178 ea2384d3 bellard
        buf += n * 512;
179 ea2384d3 bellard
    }
180 ea2384d3 bellard
    return 0;
181 ea2384d3 bellard
}
182 ea2384d3 bellard
183 5fafdf24 ths
static int cow_write(BlockDriverState *bs, int64_t sector_num,
184 ea2384d3 bellard
                     const uint8_t *buf, int nb_sectors)
185 ea2384d3 bellard
{
186 ea2384d3 bellard
    BDRVCowState *s = bs->opaque;
187 ea2384d3 bellard
    int ret, i;
188 3b46e624 ths
189 d5249393 bellard
    lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
190 ea2384d3 bellard
    ret = write(s->fd, buf, nb_sectors * 512);
191 5fafdf24 ths
    if (ret != nb_sectors * 512)
192 ea2384d3 bellard
        return -1;
193 ea2384d3 bellard
    for (i = 0; i < nb_sectors; i++)
194 2b03a7a5 bellard
        cow_set_bit(s->cow_bitmap, sector_num + i);
195 ea2384d3 bellard
    return 0;
196 ea2384d3 bellard
}
197 ea2384d3 bellard
198 e2731add bellard
static void cow_close(BlockDriverState *bs)
199 ea2384d3 bellard
{
200 ea2384d3 bellard
    BDRVCowState *s = bs->opaque;
201 3f4cb3d3 blueswir1
    munmap((void *)s->cow_bitmap_addr, s->cow_bitmap_size);
202 ea2384d3 bellard
    close(s->fd);
203 ea2384d3 bellard
}
204 ea2384d3 bellard
205 0e7e1989 Kevin Wolf
static int cow_create(const char *filename, QEMUOptionParameter *options)
206 ea2384d3 bellard
{
207 ea2384d3 bellard
    int fd, cow_fd;
208 ea2384d3 bellard
    struct cow_header_v2 cow_header;
209 ea2384d3 bellard
    struct stat st;
210 0e7e1989 Kevin Wolf
    int64_t image_sectors = 0;
211 0e7e1989 Kevin Wolf
    const char *image_filename = NULL;
212 31f38120 Kirill A. Shutemov
    int ret;
213 0e7e1989 Kevin Wolf
214 0e7e1989 Kevin Wolf
    /* Read out options */
215 0e7e1989 Kevin Wolf
    while (options && options->name) {
216 0e7e1989 Kevin Wolf
        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
217 0e7e1989 Kevin Wolf
            image_sectors = options->value.n / 512;
218 0e7e1989 Kevin Wolf
        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
219 0e7e1989 Kevin Wolf
            image_filename = options->value.s;
220 0e7e1989 Kevin Wolf
        }
221 0e7e1989 Kevin Wolf
        options++;
222 0e7e1989 Kevin Wolf
    }
223 ea2384d3 bellard
224 5fafdf24 ths
    cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
225 ea2384d3 bellard
              0644);
226 ea2384d3 bellard
    if (cow_fd < 0)
227 ea2384d3 bellard
        return -1;
228 ea2384d3 bellard
    memset(&cow_header, 0, sizeof(cow_header));
229 ea2384d3 bellard
    cow_header.magic = cpu_to_be32(COW_MAGIC);
230 ea2384d3 bellard
    cow_header.version = cpu_to_be32(COW_VERSION);
231 ea2384d3 bellard
    if (image_filename) {
232 83f64091 bellard
        /* Note: if no file, we put a dummy mtime */
233 83f64091 bellard
        cow_header.mtime = cpu_to_be32(0);
234 83f64091 bellard
235 ea2384d3 bellard
        fd = open(image_filename, O_RDONLY | O_BINARY);
236 ea2384d3 bellard
        if (fd < 0) {
237 ea2384d3 bellard
            close(cow_fd);
238 83f64091 bellard
            goto mtime_fail;
239 ea2384d3 bellard
        }
240 ea2384d3 bellard
        if (fstat(fd, &st) != 0) {
241 ea2384d3 bellard
            close(fd);
242 83f64091 bellard
            goto mtime_fail;
243 ea2384d3 bellard
        }
244 ea2384d3 bellard
        close(fd);
245 ea2384d3 bellard
        cow_header.mtime = cpu_to_be32(st.st_mtime);
246 83f64091 bellard
    mtime_fail:
247 83f64091 bellard
        pstrcpy(cow_header.backing_file, sizeof(cow_header.backing_file),
248 83f64091 bellard
                image_filename);
249 ea2384d3 bellard
    }
250 ea2384d3 bellard
    cow_header.sectorsize = cpu_to_be32(512);
251 ea2384d3 bellard
    cow_header.size = cpu_to_be64(image_sectors * 512);
252 31f38120 Kirill A. Shutemov
    ret = qemu_write_full(cow_fd, &cow_header, sizeof(cow_header));
253 31f38120 Kirill A. Shutemov
    if (ret != sizeof(cow_header)) {
254 31f38120 Kirill A. Shutemov
        ret = -1;
255 31f38120 Kirill A. Shutemov
        goto exit;
256 31f38120 Kirill A. Shutemov
    }
257 31f38120 Kirill A. Shutemov
258 ea2384d3 bellard
    /* resize to include at least all the bitmap */
259 31f38120 Kirill A. Shutemov
    ret = ftruncate(cow_fd, sizeof(cow_header) + ((image_sectors + 7) >> 3));
260 31f38120 Kirill A. Shutemov
    if (ret) {
261 31f38120 Kirill A. Shutemov
        ret = -errno;
262 31f38120 Kirill A. Shutemov
        goto exit;
263 31f38120 Kirill A. Shutemov
    }
264 31f38120 Kirill A. Shutemov
265 31f38120 Kirill A. Shutemov
    ret = 0;
266 31f38120 Kirill A. Shutemov
exit:
267 ea2384d3 bellard
    close(cow_fd);
268 31f38120 Kirill A. Shutemov
    return ret;
269 ea2384d3 bellard
}
270 ea2384d3 bellard
271 7a6cba61 pbrook
static void cow_flush(BlockDriverState *bs)
272 7a6cba61 pbrook
{
273 7a6cba61 pbrook
    BDRVCowState *s = bs->opaque;
274 6f1953c4 Christoph Hellwig
    qemu_fdatasync(s->fd);
275 7a6cba61 pbrook
}
276 7a6cba61 pbrook
277 0e7e1989 Kevin Wolf
static QEMUOptionParameter cow_create_options[] = {
278 db08adf5 Kevin Wolf
    {
279 db08adf5 Kevin Wolf
        .name = BLOCK_OPT_SIZE,
280 db08adf5 Kevin Wolf
        .type = OPT_SIZE,
281 db08adf5 Kevin Wolf
        .help = "Virtual disk size"
282 db08adf5 Kevin Wolf
    },
283 db08adf5 Kevin Wolf
    {
284 db08adf5 Kevin Wolf
        .name = BLOCK_OPT_BACKING_FILE,
285 db08adf5 Kevin Wolf
        .type = OPT_STRING,
286 db08adf5 Kevin Wolf
        .help = "File name of a base image"
287 db08adf5 Kevin Wolf
    },
288 0e7e1989 Kevin Wolf
    { NULL }
289 0e7e1989 Kevin Wolf
};
290 0e7e1989 Kevin Wolf
291 5efa9d5a Anthony Liguori
static BlockDriver bdrv_cow = {
292 e60f469c aurel32
    .format_name        = "cow",
293 e60f469c aurel32
    .instance_size        = sizeof(BDRVCowState),
294 e60f469c aurel32
    .bdrv_probe                = cow_probe,
295 e60f469c aurel32
    .bdrv_open                = cow_open,
296 e60f469c aurel32
    .bdrv_read                = cow_read,
297 e60f469c aurel32
    .bdrv_write                = cow_write,
298 e60f469c aurel32
    .bdrv_close                = cow_close,
299 e60f469c aurel32
    .bdrv_create        = cow_create,
300 e60f469c aurel32
    .bdrv_flush                = cow_flush,
301 e60f469c aurel32
    .bdrv_is_allocated        = cow_is_allocated,
302 0e7e1989 Kevin Wolf
303 0e7e1989 Kevin Wolf
    .create_options = cow_create_options,
304 ea2384d3 bellard
};
305 5efa9d5a Anthony Liguori
306 5efa9d5a Anthony Liguori
static void bdrv_cow_init(void)
307 5efa9d5a Anthony Liguori
{
308 5efa9d5a Anthony Liguori
    bdrv_register(&bdrv_cow);
309 5efa9d5a Anthony Liguori
}
310 5efa9d5a Anthony Liguori
311 5efa9d5a Anthony Liguori
block_init(bdrv_cow_init);
312 ea2384d3 bellard
#endif