Statistics
| Branch: | Revision:

root / block / cow.c @ 893a9cb4

History | View | Annotate | Download (8.9 kB)

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
    int fd;
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, const char *filename, int flags)
62
{
63
    BDRVCowState *s = bs->opaque;
64
    int fd;
65
    struct cow_header_v2 cow_header;
66
    int bitmap_size;
67
    int64_t size;
68

    
69
    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
70
    if (fd < 0) {
71
        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
72
        if (fd < 0)
73
            return -1;
74
    }
75
    s->fd = fd;
76
    /* see if it is a cow image */
77
    if (pread(fd, &cow_header, sizeof(cow_header), 0) != sizeof(cow_header)) {
78
        goto fail;
79
    }
80

    
81
    if (be32_to_cpu(cow_header.magic) != COW_MAGIC ||
82
        be32_to_cpu(cow_header.version) != COW_VERSION) {
83
        goto fail;
84
    }
85

    
86
    /* cow image found */
87
    size = be64_to_cpu(cow_header.size);
88
    bs->total_sectors = size / 512;
89

    
90
    pstrcpy(bs->backing_file, sizeof(bs->backing_file),
91
            cow_header.backing_file);
92

    
93
    bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
94
    s->cow_sectors_offset = (bitmap_size + 511) & ~511;
95
    return 0;
96
 fail:
97
    close(fd);
98
    return -1;
99
}
100

    
101
/*
102
 * XXX(hch): right now these functions are extremly ineffcient.
103
 * We should just read the whole bitmap we'll need in one go instead.
104
 */
105
static inline int cow_set_bit(BlockDriverState *bs, int64_t bitnum)
106
{
107
    BDRVCowState *s = bs->opaque;
108
    uint64_t offset = sizeof(struct cow_header_v2) + bitnum / 8;
109
    uint8_t bitmap;
110

    
111
    if (pread(s->fd, &bitmap, sizeof(bitmap), offset) !=
112
            sizeof(bitmap)) {
113
       return -errno;
114
    }
115

    
116
    bitmap |= (1 << (bitnum % 8));
117

    
118
    if (pwrite(s->fd, &bitmap, sizeof(bitmap), offset) !=
119
            sizeof(bitmap)) {
120
       return -errno;
121
    }
122
    return 0;
123
}
124

    
125
static inline int is_bit_set(BlockDriverState *bs, int64_t bitnum)
126
{
127
    BDRVCowState *s = bs->opaque;
128
    uint64_t offset = sizeof(struct cow_header_v2) + bitnum / 8;
129
    uint8_t bitmap;
130

    
131
    if (pread(s->fd, &bitmap, sizeof(bitmap), offset) !=
132
            sizeof(bitmap)) {
133
       return -errno;
134
    }
135

    
136
    return !!(bitmap & (1 << (bitnum % 8)));
137
}
138

    
139
/* Return true if first block has been changed (ie. current version is
140
 * in COW file).  Set the number of continuous blocks for which that
141
 * is true. */
142
static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num,
143
        int nb_sectors, int *num_same)
144
{
145
    int changed;
146

    
147
    if (nb_sectors == 0) {
148
        *num_same = nb_sectors;
149
        return 0;
150
    }
151

    
152
    changed = is_bit_set(bs, sector_num);
153
    if (changed < 0) {
154
        return 0; /* XXX: how to return I/O errors? */
155
    }
156

    
157
    for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) {
158
        if (is_bit_set(bs, sector_num + *num_same) != changed)
159
            break;
160
    }
161

    
162
    return changed;
163
}
164

    
165
static int cow_update_bitmap(BlockDriverState *bs, int64_t sector_num,
166
        int nb_sectors)
167
{
168
    int error = 0;
169
    int i;
170

    
171
    for (i = 0; i < nb_sectors; i++) {
172
        error = cow_set_bit(bs, sector_num + i);
173
        if (error) {
174
            break;
175
        }
176
    }
177

    
178
    return error;
179
}
180

    
181
static int cow_read(BlockDriverState *bs, int64_t sector_num,
182
                    uint8_t *buf, int nb_sectors)
183
{
184
    BDRVCowState *s = bs->opaque;
185
    int ret, n;
186

    
187
    while (nb_sectors > 0) {
188
        if (cow_is_allocated(bs, sector_num, nb_sectors, &n)) {
189
            ret = pread(s->fd, buf, n * 512,
190
                        s->cow_sectors_offset + sector_num * 512);
191
            if (ret != n * 512)
192
                return -1;
193
        } else {
194
            if (bs->backing_hd) {
195
                /* read from the base image */
196
                ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
197
                if (ret < 0)
198
                    return -1;
199
            } else {
200
            memset(buf, 0, n * 512);
201
        }
202
        }
203
        nb_sectors -= n;
204
        sector_num += n;
205
        buf += n * 512;
206
    }
207
    return 0;
208
}
209

    
210
static int cow_write(BlockDriverState *bs, int64_t sector_num,
211
                     const uint8_t *buf, int nb_sectors)
212
{
213
    BDRVCowState *s = bs->opaque;
214
    int ret;
215

    
216
    ret = pwrite(s->fd, buf, nb_sectors * 512,
217
                 s->cow_sectors_offset + sector_num * 512);
218
    if (ret != nb_sectors * 512)
219
        return -1;
220

    
221
    return cow_update_bitmap(bs, sector_num, nb_sectors);
222
}
223

    
224
static void cow_close(BlockDriverState *bs)
225
{
226
    BDRVCowState *s = bs->opaque;
227
    close(s->fd);
228
}
229

    
230
static int cow_create(const char *filename, QEMUOptionParameter *options)
231
{
232
    int fd, cow_fd;
233
    struct cow_header_v2 cow_header;
234
    struct stat st;
235
    int64_t image_sectors = 0;
236
    const char *image_filename = NULL;
237
    int ret;
238

    
239
    /* Read out options */
240
    while (options && options->name) {
241
        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
242
            image_sectors = options->value.n / 512;
243
        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
244
            image_filename = options->value.s;
245
        }
246
        options++;
247
    }
248

    
249
    cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
250
              0644);
251
    if (cow_fd < 0)
252
        return -errno;
253
    memset(&cow_header, 0, sizeof(cow_header));
254
    cow_header.magic = cpu_to_be32(COW_MAGIC);
255
    cow_header.version = cpu_to_be32(COW_VERSION);
256
    if (image_filename) {
257
        /* Note: if no file, we put a dummy mtime */
258
        cow_header.mtime = cpu_to_be32(0);
259

    
260
        fd = open(image_filename, O_RDONLY | O_BINARY);
261
        if (fd < 0) {
262
            close(cow_fd);
263
            goto mtime_fail;
264
        }
265
        if (fstat(fd, &st) != 0) {
266
            close(fd);
267
            goto mtime_fail;
268
        }
269
        close(fd);
270
        cow_header.mtime = cpu_to_be32(st.st_mtime);
271
    mtime_fail:
272
        pstrcpy(cow_header.backing_file, sizeof(cow_header.backing_file),
273
                image_filename);
274
    }
275
    cow_header.sectorsize = cpu_to_be32(512);
276
    cow_header.size = cpu_to_be64(image_sectors * 512);
277
    ret = qemu_write_full(cow_fd, &cow_header, sizeof(cow_header));
278
    if (ret != sizeof(cow_header)) {
279
        ret = -errno;
280
        goto exit;
281
    }
282

    
283
    /* resize to include at least all the bitmap */
284
    ret = ftruncate(cow_fd, sizeof(cow_header) + ((image_sectors + 7) >> 3));
285
    if (ret) {
286
        ret = -errno;
287
        goto exit;
288
    }
289

    
290
exit:
291
    close(cow_fd);
292
    return ret;
293
}
294

    
295
static void cow_flush(BlockDriverState *bs)
296
{
297
    BDRVCowState *s = bs->opaque;
298
    qemu_fdatasync(s->fd);
299
}
300

    
301
static QEMUOptionParameter cow_create_options[] = {
302
    {
303
        .name = BLOCK_OPT_SIZE,
304
        .type = OPT_SIZE,
305
        .help = "Virtual disk size"
306
    },
307
    {
308
        .name = BLOCK_OPT_BACKING_FILE,
309
        .type = OPT_STRING,
310
        .help = "File name of a base image"
311
    },
312
    { NULL }
313
};
314

    
315
static BlockDriver bdrv_cow = {
316
    .format_name        = "cow",
317
    .instance_size        = sizeof(BDRVCowState),
318
    .bdrv_probe                = cow_probe,
319
    .bdrv_file_open        = cow_open,
320
    .bdrv_read                = cow_read,
321
    .bdrv_write                = cow_write,
322
    .bdrv_close                = cow_close,
323
    .bdrv_create        = cow_create,
324
    .bdrv_flush                = cow_flush,
325
    .bdrv_is_allocated        = cow_is_allocated,
326

    
327
    .create_options = cow_create_options,
328
};
329

    
330
static void bdrv_cow_init(void)
331
{
332
    bdrv_register(&bdrv_cow);
333
}
334

    
335
block_init(bdrv_cow_init);