|
|
1.1 root 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:
1.1.1.3 ! root 60: static int cow_open(BlockDriverState *bs, int flags)
1.1 root 61: {
62: BDRVCowState *s = bs->opaque;
63: struct cow_header_v2 cow_header;
1.1.1.3 ! root 64: int bitmap_size;
1.1 root 65: int64_t size;
66:
67: /* see if it is a cow image */
1.1.1.3 ! root 68: if (bdrv_pread(bs->file, 0, &cow_header, sizeof(cow_header)) !=
! 69: sizeof(cow_header)) {
1.1 root 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:
1.1.1.3 ! root 85: bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
! 86: s->cow_sectors_offset = (bitmap_size + 511) & ~511;
1.1 root 87: return 0;
88: fail:
89: return -1;
90: }
91:
1.1.1.3 ! root 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;
1.1 root 114: }
115:
1.1.1.3 ! root 116: static inline int is_bit_set(BlockDriverState *bs, int64_t bitnum)
1.1 root 117: {
1.1.1.3 ! root 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: }
1.1 root 126:
1.1.1.3 ! root 127: return !!(bitmap & (1 << (bitnum % 8)));
! 128: }
1.1 root 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. */
1.1.1.3 ! root 133: static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num,
! 134: int nb_sectors, int *num_same)
1.1 root 135: {
136: int changed;
137:
1.1.1.3 ! root 138: if (nb_sectors == 0) {
1.1 root 139: *num_same = nb_sectors;
140: return 0;
141: }
142:
1.1.1.3 ! root 143: changed = is_bit_set(bs, sector_num);
! 144: if (changed < 0) {
! 145: return 0; /* XXX: how to return I/O errors? */
! 146: }
! 147:
1.1 root 148: for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) {
1.1.1.3 ! root 149: if (is_bit_set(bs, sector_num + *num_same) != changed)
1.1 root 150: break;
151: }
152:
153: return changed;
154: }
155:
1.1.1.3 ! root 156: static int cow_update_bitmap(BlockDriverState *bs, int64_t sector_num,
! 157: int nb_sectors)
1.1 root 158: {
1.1.1.3 ! root 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;
1.1 root 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) {
1.1.1.3 ! root 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);
1.1 root 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;
1.1.1.3 ! root 206: int ret;
1.1 root 207:
1.1.1.3 ! root 208: ret = bdrv_pwrite(bs->file, s->cow_sectors_offset + sector_num * 512,
! 209: buf, nb_sectors * 512);
1.1 root 210: if (ret != nb_sectors * 512)
211: return -1;
1.1.1.3 ! root 212:
! 213: return cow_update_bitmap(bs, sector_num, nb_sectors);
1.1 root 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;
1.1.1.3 ! root 227: int ret;
1.1 root 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)
1.1.1.3 ! root 242: return -errno;
1.1 root 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);
1.1.1.3 ! root 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:
1.1 root 273: /* resize to include at least all the bitmap */
1.1.1.3 ! root 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:
1.1 root 281: close(cow_fd);
1.1.1.3 ! root 282: return ret;
1.1 root 283: }
284:
285: static void cow_flush(BlockDriverState *bs)
286: {
1.1.1.3 ! root 287: bdrv_flush(bs->file);
1.1 root 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);
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.