Statistics
| Branch: | Revision:

root / block / cow.c @ 205ef796

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
    int ret;
101

    
102
    ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap));
103
    if (ret < 0) {
104
       return ret;
105
    }
106

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

    
109
    ret = bdrv_pwrite_sync(bs->file, offset, &bitmap, sizeof(bitmap));
110
    if (ret < 0) {
111
       return ret;
112
    }
113
    return 0;
114
}
115

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

    
122
    ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap));
123
    if (ret < 0) {
124
       return ret;
125
    }
126

    
127
    return !!(bitmap & (1 << (bitnum % 8)));
128
}
129

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

    
138
    if (nb_sectors == 0) {
139
        *num_same = nb_sectors;
140
        return 0;
141
    }
142

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

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

    
153
    return changed;
154
}
155

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

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

    
169
    return error;
170
}
171

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

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

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

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

    
213
    return cow_update_bitmap(bs, sector_num, nb_sectors);
214
}
215

    
216
static void cow_close(BlockDriverState *bs)
217
{
218
}
219

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

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

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

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

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

    
280
exit:
281
    close(cow_fd);
282
    return ret;
283
}
284

    
285
static int cow_flush(BlockDriverState *bs)
286
{
287
    return bdrv_flush(bs->file);
288
}
289

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

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

    
316
    .create_options = cow_create_options,
317
};
318

    
319
static void bdrv_cow_init(void)
320
{
321
    bdrv_register(&bdrv_cow);
322
}
323

    
324
block_init(bdrv_cow_init);