Statistics
| Branch: | Revision:

root / block / cow.c @ 2063392a

History | View | Annotate | Download (8.6 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
    int64_t cow_sectors_offset;
46
} BDRVCowState;
47

    
48
static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)
49
{
50
    const struct cow_header_v2 *cow_header = (const void *)buf;
51

    
52
    if (buf_size >= sizeof(struct cow_header_v2) &&
53
        be32_to_cpu(cow_header->magic) == COW_MAGIC &&
54
        be32_to_cpu(cow_header->version) == COW_VERSION)
55
        return 100;
56
    else
57
        return 0;
58
}
59

    
60
static int cow_open(BlockDriverState *bs, int flags)
61
{
62
    BDRVCowState *s = bs->opaque;
63
    struct cow_header_v2 cow_header;
64
    int bitmap_size;
65
    int64_t size;
66

    
67
    /* see if it is a cow image */
68
    if (bdrv_pread(bs->file, 0, &cow_header, sizeof(cow_header)) !=
69
            sizeof(cow_header)) {
70
        goto fail;
71
    }
72

    
73
    if (be32_to_cpu(cow_header.magic) != COW_MAGIC ||
74
        be32_to_cpu(cow_header.version) != COW_VERSION) {
75
        goto fail;
76
    }
77

    
78
    /* cow image found */
79
    size = be64_to_cpu(cow_header.size);
80
    bs->total_sectors = size / 512;
81

    
82
    pstrcpy(bs->backing_file, sizeof(bs->backing_file),
83
            cow_header.backing_file);
84

    
85
    bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
86
    s->cow_sectors_offset = (bitmap_size + 511) & ~511;
87
    return 0;
88
 fail:
89
    return -1;
90
}
91

    
92
/*
93
 * XXX(hch): right now these functions are extremly ineffcient.
94
 * We should just read the whole bitmap we'll need in one go instead.
95
 */
96
static inline int cow_set_bit(BlockDriverState *bs, int64_t bitnum)
97
{
98
    uint64_t offset = sizeof(struct cow_header_v2) + bitnum / 8;
99
    uint8_t bitmap;
100

    
101
    if (bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap)) !=
102
            sizeof(bitmap)) {
103
       return -errno;
104
    }
105

    
106
    bitmap |= (1 << (bitnum % 8));
107

    
108
    if (bdrv_pwrite(bs->file, offset, &bitmap, sizeof(bitmap)) !=
109
            sizeof(bitmap)) {
110
       return -errno;
111
    }
112
    return 0;
113
}
114

    
115
static inline int is_bit_set(BlockDriverState *bs, int64_t bitnum)
116
{
117
    uint64_t offset = sizeof(struct cow_header_v2) + bitnum / 8;
118
    uint8_t bitmap;
119

    
120
    if (bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap)) !=
121
            sizeof(bitmap)) {
122
       return -errno;
123
    }
124

    
125
    return !!(bitmap & (1 << (bitnum % 8)));
126
}
127

    
128
/* Return true if first block has been changed (ie. current version is
129
 * in COW file).  Set the number of continuous blocks for which that
130
 * is true. */
131
static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num,
132
        int nb_sectors, int *num_same)
133
{
134
    int changed;
135

    
136
    if (nb_sectors == 0) {
137
        *num_same = nb_sectors;
138
        return 0;
139
    }
140

    
141
    changed = is_bit_set(bs, sector_num);
142
    if (changed < 0) {
143
        return 0; /* XXX: how to return I/O errors? */
144
    }
145

    
146
    for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) {
147
        if (is_bit_set(bs, sector_num + *num_same) != changed)
148
            break;
149
    }
150

    
151
    return changed;
152
}
153

    
154
static int cow_update_bitmap(BlockDriverState *bs, int64_t sector_num,
155
        int nb_sectors)
156
{
157
    int error = 0;
158
    int i;
159

    
160
    for (i = 0; i < nb_sectors; i++) {
161
        error = cow_set_bit(bs, sector_num + i);
162
        if (error) {
163
            break;
164
        }
165
    }
166

    
167
    return error;
168
}
169

    
170
static int cow_read(BlockDriverState *bs, int64_t sector_num,
171
                    uint8_t *buf, int nb_sectors)
172
{
173
    BDRVCowState *s = bs->opaque;
174
    int ret, n;
175

    
176
    while (nb_sectors > 0) {
177
        if (cow_is_allocated(bs, sector_num, nb_sectors, &n)) {
178
            ret = bdrv_pread(bs->file,
179
                        s->cow_sectors_offset + sector_num * 512,
180
                        buf, n * 512);
181
            if (ret != n * 512)
182
                return -1;
183
        } else {
184
            if (bs->backing_hd) {
185
                /* read from the base image */
186
                ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
187
                if (ret < 0)
188
                    return -1;
189
            } else {
190
            memset(buf, 0, n * 512);
191
        }
192
        }
193
        nb_sectors -= n;
194
        sector_num += n;
195
        buf += n * 512;
196
    }
197
    return 0;
198
}
199

    
200
static int cow_write(BlockDriverState *bs, int64_t sector_num,
201
                     const uint8_t *buf, int nb_sectors)
202
{
203
    BDRVCowState *s = bs->opaque;
204
    int ret;
205

    
206
    ret = bdrv_pwrite(bs->file, s->cow_sectors_offset + sector_num * 512,
207
                      buf, nb_sectors * 512);
208
    if (ret != nb_sectors * 512)
209
        return -1;
210

    
211
    return cow_update_bitmap(bs, sector_num, nb_sectors);
212
}
213

    
214
static void cow_close(BlockDriverState *bs)
215
{
216
}
217

    
218
static int cow_create(const char *filename, QEMUOptionParameter *options)
219
{
220
    int fd, cow_fd;
221
    struct cow_header_v2 cow_header;
222
    struct stat st;
223
    int64_t image_sectors = 0;
224
    const char *image_filename = NULL;
225
    int ret;
226

    
227
    /* Read out options */
228
    while (options && options->name) {
229
        if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
230
            image_sectors = options->value.n / 512;
231
        } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
232
            image_filename = options->value.s;
233
        }
234
        options++;
235
    }
236

    
237
    cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
238
              0644);
239
    if (cow_fd < 0)
240
        return -errno;
241
    memset(&cow_header, 0, sizeof(cow_header));
242
    cow_header.magic = cpu_to_be32(COW_MAGIC);
243
    cow_header.version = cpu_to_be32(COW_VERSION);
244
    if (image_filename) {
245
        /* Note: if no file, we put a dummy mtime */
246
        cow_header.mtime = cpu_to_be32(0);
247

    
248
        fd = open(image_filename, O_RDONLY | O_BINARY);
249
        if (fd < 0) {
250
            close(cow_fd);
251
            goto mtime_fail;
252
        }
253
        if (fstat(fd, &st) != 0) {
254
            close(fd);
255
            goto mtime_fail;
256
        }
257
        close(fd);
258
        cow_header.mtime = cpu_to_be32(st.st_mtime);
259
    mtime_fail:
260
        pstrcpy(cow_header.backing_file, sizeof(cow_header.backing_file),
261
                image_filename);
262
    }
263
    cow_header.sectorsize = cpu_to_be32(512);
264
    cow_header.size = cpu_to_be64(image_sectors * 512);
265
    ret = qemu_write_full(cow_fd, &cow_header, sizeof(cow_header));
266
    if (ret != sizeof(cow_header)) {
267
        ret = -errno;
268
        goto exit;
269
    }
270

    
271
    /* resize to include at least all the bitmap */
272
    ret = ftruncate(cow_fd, sizeof(cow_header) + ((image_sectors + 7) >> 3));
273
    if (ret) {
274
        ret = -errno;
275
        goto exit;
276
    }
277

    
278
exit:
279
    close(cow_fd);
280
    return ret;
281
}
282

    
283
static void cow_flush(BlockDriverState *bs)
284
{
285
    bdrv_flush(bs->file);
286
}
287

    
288
static QEMUOptionParameter cow_create_options[] = {
289
    {
290
        .name = BLOCK_OPT_SIZE,
291
        .type = OPT_SIZE,
292
        .help = "Virtual disk size"
293
    },
294
    {
295
        .name = BLOCK_OPT_BACKING_FILE,
296
        .type = OPT_STRING,
297
        .help = "File name of a base image"
298
    },
299
    { NULL }
300
};
301

    
302
static BlockDriver bdrv_cow = {
303
    .format_name        = "cow",
304
    .instance_size        = sizeof(BDRVCowState),
305
    .bdrv_probe                = cow_probe,
306
    .bdrv_open                = cow_open,
307
    .bdrv_read                = cow_read,
308
    .bdrv_write                = cow_write,
309
    .bdrv_close                = cow_close,
310
    .bdrv_create        = cow_create,
311
    .bdrv_flush                = cow_flush,
312
    .bdrv_is_allocated        = cow_is_allocated,
313

    
314
    .create_options = cow_create_options,
315
};
316

    
317
static void bdrv_cow_init(void)
318
{
319
    bdrv_register(&bdrv_cow);
320
}
321

    
322
block_init(bdrv_cow_init);