Home | History | Annotate | Download | only in block
      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 void cow_flush(BlockDriverState *bs)
    286 {
    287     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);
    325