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

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 {
1.1.1.5   root       45:     CoMutex lock;
1.1       root       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: 
1.1.1.3   root       61: static int cow_open(BlockDriverState *bs, int flags)
1.1       root       62: {
                     63:     BDRVCowState *s = bs->opaque;
                     64:     struct cow_header_v2 cow_header;
1.1.1.3   root       65:     int bitmap_size;
1.1       root       66:     int64_t size;
1.1.1.6 ! root       67:     int ret;
1.1       root       68: 
                     69:     /* see if it is a cow image */
1.1.1.6 ! root       70:     ret = bdrv_pread(bs->file, 0, &cow_header, sizeof(cow_header));
        !            71:     if (ret < 0) {
        !            72:         goto fail;
        !            73:     }
        !            74: 
        !            75:     if (be32_to_cpu(cow_header.magic) != COW_MAGIC) {
        !            76:         ret = -EINVAL;
1.1       root       77:         goto fail;
                     78:     }
                     79: 
1.1.1.6 ! root       80:     if (be32_to_cpu(cow_header.version) != COW_VERSION) {
        !            81:         char version[64];
        !            82:         snprintf(version, sizeof(version),
        !            83:                "COW version %d", cow_header.version);
        !            84:         qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
        !            85:             bs->device_name, "cow", version);
        !            86:         ret = -ENOTSUP;
1.1       root       87:         goto fail;
                     88:     }
                     89: 
                     90:     /* cow image found */
                     91:     size = be64_to_cpu(cow_header.size);
                     92:     bs->total_sectors = size / 512;
                     93: 
                     94:     pstrcpy(bs->backing_file, sizeof(bs->backing_file),
                     95:             cow_header.backing_file);
                     96: 
1.1.1.3   root       97:     bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
                     98:     s->cow_sectors_offset = (bitmap_size + 511) & ~511;
1.1.1.5   root       99:     qemu_co_mutex_init(&s->lock);
1.1       root      100:     return 0;
                    101:  fail:
1.1.1.6 ! root      102:     return ret;
1.1       root      103: }
                    104: 
1.1.1.3   root      105: /*
1.1.1.6 ! root      106:  * XXX(hch): right now these functions are extremely inefficient.
1.1.1.3   root      107:  * We should just read the whole bitmap we'll need in one go instead.
                    108:  */
                    109: static inline int cow_set_bit(BlockDriverState *bs, int64_t bitnum)
                    110: {
                    111:     uint64_t offset = sizeof(struct cow_header_v2) + bitnum / 8;
                    112:     uint8_t bitmap;
                    113:     int ret;
                    114: 
                    115:     ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap));
                    116:     if (ret < 0) {
                    117:        return ret;
                    118:     }
                    119: 
                    120:     bitmap |= (1 << (bitnum % 8));
                    121: 
                    122:     ret = bdrv_pwrite_sync(bs->file, offset, &bitmap, sizeof(bitmap));
                    123:     if (ret < 0) {
                    124:        return ret;
                    125:     }
                    126:     return 0;
1.1       root      127: }
                    128: 
1.1.1.3   root      129: static inline int is_bit_set(BlockDriverState *bs, int64_t bitnum)
1.1       root      130: {
1.1.1.3   root      131:     uint64_t offset = sizeof(struct cow_header_v2) + bitnum / 8;
                    132:     uint8_t bitmap;
                    133:     int ret;
                    134: 
                    135:     ret = bdrv_pread(bs->file, offset, &bitmap, sizeof(bitmap));
                    136:     if (ret < 0) {
                    137:        return ret;
                    138:     }
1.1       root      139: 
1.1.1.3   root      140:     return !!(bitmap & (1 << (bitnum % 8)));
                    141: }
1.1       root      142: 
                    143: /* Return true if first block has been changed (ie. current version is
                    144:  * in COW file).  Set the number of continuous blocks for which that
                    145:  * is true. */
1.1.1.6 ! root      146: static int coroutine_fn cow_co_is_allocated(BlockDriverState *bs,
        !           147:         int64_t sector_num, int nb_sectors, int *num_same)
1.1       root      148: {
                    149:     int changed;
                    150: 
1.1.1.3   root      151:     if (nb_sectors == 0) {
1.1       root      152:        *num_same = nb_sectors;
                    153:        return 0;
                    154:     }
                    155: 
1.1.1.3   root      156:     changed = is_bit_set(bs, sector_num);
                    157:     if (changed < 0) {
                    158:         return 0; /* XXX: how to return I/O errors? */
                    159:     }
                    160: 
1.1       root      161:     for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) {
1.1.1.3   root      162:        if (is_bit_set(bs, sector_num + *num_same) != changed)
1.1       root      163:            break;
                    164:     }
                    165: 
                    166:     return changed;
                    167: }
                    168: 
1.1.1.3   root      169: static int cow_update_bitmap(BlockDriverState *bs, int64_t sector_num,
                    170:         int nb_sectors)
1.1       root      171: {
1.1.1.3   root      172:     int error = 0;
                    173:     int i;
                    174: 
                    175:     for (i = 0; i < nb_sectors; i++) {
                    176:         error = cow_set_bit(bs, sector_num + i);
                    177:         if (error) {
                    178:             break;
                    179:         }
                    180:     }
                    181: 
                    182:     return error;
1.1       root      183: }
                    184: 
1.1.1.6 ! root      185: static int coroutine_fn cow_read(BlockDriverState *bs, int64_t sector_num,
        !           186:                                  uint8_t *buf, int nb_sectors)
1.1       root      187: {
                    188:     BDRVCowState *s = bs->opaque;
                    189:     int ret, n;
                    190: 
                    191:     while (nb_sectors > 0) {
1.1.1.6 ! root      192:         if (bdrv_co_is_allocated(bs, sector_num, nb_sectors, &n)) {
1.1.1.3   root      193:             ret = bdrv_pread(bs->file,
                    194:                         s->cow_sectors_offset + sector_num * 512,
                    195:                         buf, n * 512);
1.1.1.6 ! root      196:             if (ret < 0) {
        !           197:                 return ret;
        !           198:             }
1.1       root      199:         } else {
                    200:             if (bs->backing_hd) {
                    201:                 /* read from the base image */
                    202:                 ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
1.1.1.6 ! root      203:                 if (ret < 0) {
        !           204:                     return ret;
        !           205:                 }
1.1       root      206:             } else {
1.1.1.6 ! root      207:                 memset(buf, 0, n * 512);
        !           208:             }
1.1       root      209:         }
                    210:         nb_sectors -= n;
                    211:         sector_num += n;
                    212:         buf += n * 512;
                    213:     }
                    214:     return 0;
                    215: }
                    216: 
1.1.1.5   root      217: static coroutine_fn int cow_co_read(BlockDriverState *bs, int64_t sector_num,
                    218:                                     uint8_t *buf, int nb_sectors)
                    219: {
                    220:     int ret;
                    221:     BDRVCowState *s = bs->opaque;
                    222:     qemu_co_mutex_lock(&s->lock);
                    223:     ret = cow_read(bs, sector_num, buf, nb_sectors);
                    224:     qemu_co_mutex_unlock(&s->lock);
                    225:     return ret;
                    226: }
                    227: 
1.1       root      228: static int cow_write(BlockDriverState *bs, int64_t sector_num,
                    229:                      const uint8_t *buf, int nb_sectors)
                    230: {
                    231:     BDRVCowState *s = bs->opaque;
1.1.1.3   root      232:     int ret;
1.1       root      233: 
1.1.1.3   root      234:     ret = bdrv_pwrite(bs->file, s->cow_sectors_offset + sector_num * 512,
                    235:                       buf, nb_sectors * 512);
1.1.1.6 ! root      236:     if (ret < 0) {
        !           237:         return ret;
        !           238:     }
1.1.1.3   root      239: 
                    240:     return cow_update_bitmap(bs, sector_num, nb_sectors);
1.1       root      241: }
                    242: 
1.1.1.5   root      243: static coroutine_fn int cow_co_write(BlockDriverState *bs, int64_t sector_num,
                    244:                                      const uint8_t *buf, int nb_sectors)
                    245: {
                    246:     int ret;
                    247:     BDRVCowState *s = bs->opaque;
                    248:     qemu_co_mutex_lock(&s->lock);
                    249:     ret = cow_write(bs, sector_num, buf, nb_sectors);
                    250:     qemu_co_mutex_unlock(&s->lock);
                    251:     return ret;
                    252: }
                    253: 
1.1       root      254: static void cow_close(BlockDriverState *bs)
                    255: {
                    256: }
                    257: 
                    258: static int cow_create(const char *filename, QEMUOptionParameter *options)
                    259: {
                    260:     struct cow_header_v2 cow_header;
                    261:     struct stat st;
                    262:     int64_t image_sectors = 0;
                    263:     const char *image_filename = NULL;
1.1.1.3   root      264:     int ret;
1.1.1.6 ! root      265:     BlockDriverState *cow_bs;
1.1       root      266: 
                    267:     /* Read out options */
                    268:     while (options && options->name) {
                    269:         if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
                    270:             image_sectors = options->value.n / 512;
                    271:         } else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
                    272:             image_filename = options->value.s;
                    273:         }
                    274:         options++;
                    275:     }
                    276: 
1.1.1.6 ! root      277:     ret = bdrv_create_file(filename, options);
        !           278:     if (ret < 0) {
        !           279:         return ret;
        !           280:     }
        !           281: 
        !           282:     ret = bdrv_file_open(&cow_bs, filename, BDRV_O_RDWR);
        !           283:     if (ret < 0) {
        !           284:         return ret;
        !           285:     }
        !           286: 
1.1       root      287:     memset(&cow_header, 0, sizeof(cow_header));
                    288:     cow_header.magic = cpu_to_be32(COW_MAGIC);
                    289:     cow_header.version = cpu_to_be32(COW_VERSION);
                    290:     if (image_filename) {
                    291:         /* Note: if no file, we put a dummy mtime */
                    292:         cow_header.mtime = cpu_to_be32(0);
                    293: 
1.1.1.6 ! root      294:         if (stat(image_filename, &st) != 0) {
1.1       root      295:             goto mtime_fail;
                    296:         }
                    297:         cow_header.mtime = cpu_to_be32(st.st_mtime);
                    298:     mtime_fail:
                    299:         pstrcpy(cow_header.backing_file, sizeof(cow_header.backing_file),
                    300:                 image_filename);
                    301:     }
                    302:     cow_header.sectorsize = cpu_to_be32(512);
                    303:     cow_header.size = cpu_to_be64(image_sectors * 512);
1.1.1.6 ! root      304:     ret = bdrv_pwrite(cow_bs, 0, &cow_header, sizeof(cow_header));
        !           305:     if (ret < 0) {
1.1.1.3   root      306:         goto exit;
                    307:     }
                    308: 
1.1       root      309:     /* resize to include at least all the bitmap */
1.1.1.6 ! root      310:     ret = bdrv_truncate(cow_bs,
        !           311:         sizeof(cow_header) + ((image_sectors + 7) >> 3));
        !           312:     if (ret < 0) {
1.1.1.3   root      313:         goto exit;
                    314:     }
                    315: 
                    316: exit:
1.1.1.6 ! root      317:     bdrv_delete(cow_bs);
1.1.1.3   root      318:     return ret;
1.1       root      319: }
                    320: 
                    321: static QEMUOptionParameter cow_create_options[] = {
                    322:     {
                    323:         .name = BLOCK_OPT_SIZE,
                    324:         .type = OPT_SIZE,
                    325:         .help = "Virtual disk size"
                    326:     },
                    327:     {
                    328:         .name = BLOCK_OPT_BACKING_FILE,
                    329:         .type = OPT_STRING,
                    330:         .help = "File name of a base image"
                    331:     },
                    332:     { NULL }
                    333: };
                    334: 
                    335: static BlockDriver bdrv_cow = {
1.1.1.5   root      336:     .format_name    = "cow",
                    337:     .instance_size  = sizeof(BDRVCowState),
                    338: 
                    339:     .bdrv_probe     = cow_probe,
                    340:     .bdrv_open      = cow_open,
                    341:     .bdrv_close     = cow_close,
                    342:     .bdrv_create    = cow_create,
                    343: 
                    344:     .bdrv_read              = cow_co_read,
                    345:     .bdrv_write             = cow_co_write,
1.1.1.6 ! root      346:     .bdrv_co_is_allocated   = cow_co_is_allocated,
1.1       root      347: 
                    348:     .create_options = cow_create_options,
                    349: };
                    350: 
                    351: static void bdrv_cow_init(void)
                    352: {
                    353:     bdrv_register(&bdrv_cow);
                    354: }
                    355: 
                    356: 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.