Annotation of qemu/block/cow.c, revision 1.1.1.4

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: 
1.1.1.4 ! root      285: static int cow_flush(BlockDriverState *bs)
1.1       root      286: {
1.1.1.4 ! root      287:     return 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);

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.