⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 block-qcow2.c.svn-base

📁 我们自己开发的一个OSEK操作系统!不知道可不可以?
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
    sn = &s->snapshots[snapshot_index];    if (update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, -1) < 0)        goto fail;    if (grow_l1_table(bs, sn->l1_size) < 0)        goto fail;    s->l1_size = sn->l1_size;    l1_size2 = s->l1_size * sizeof(uint64_t);    /* copy the snapshot l1 table to the current l1 table */    if (bdrv_pread(s->hd, sn->l1_table_offset,                   s->l1_table, l1_size2) != l1_size2)        goto fail;    if (bdrv_pwrite(s->hd, s->l1_table_offset,                    s->l1_table, l1_size2) != l1_size2)        goto fail;    for(i = 0;i < s->l1_size; i++) {        be64_to_cpus(&s->l1_table[i]);    }    if (update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1) < 0)        goto fail;#ifdef DEBUG_ALLOC    check_refcounts(bs);#endif    return 0; fail:    return -EIO;}static int qcow_snapshot_delete(BlockDriverState *bs, const char *snapshot_id){    BDRVQcowState *s = bs->opaque;    QCowSnapshot *sn;    int snapshot_index, ret;    snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id);    if (snapshot_index < 0)        return -ENOENT;    sn = &s->snapshots[snapshot_index];    ret = update_snapshot_refcount(bs, sn->l1_table_offset, sn->l1_size, -1);    if (ret < 0)        return ret;    /* must update the copied flag on the current cluster offsets */    ret = update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 0);    if (ret < 0)        return ret;    free_clusters(bs, sn->l1_table_offset, sn->l1_size * sizeof(uint64_t));    qemu_free(sn->id_str);    qemu_free(sn->name);    memmove(sn, sn + 1, (s->nb_snapshots - snapshot_index - 1) * sizeof(*sn));    s->nb_snapshots--;    ret = qcow_write_snapshots(bs);    if (ret < 0) {        /* XXX: restore snapshot if error ? */        return ret;    }#ifdef DEBUG_ALLOC    check_refcounts(bs);#endif    return 0;}static int qcow_snapshot_list(BlockDriverState *bs,                              QEMUSnapshotInfo **psn_tab){    BDRVQcowState *s = bs->opaque;    QEMUSnapshotInfo *sn_tab, *sn_info;    QCowSnapshot *sn;    int i;    sn_tab = qemu_mallocz(s->nb_snapshots * sizeof(QEMUSnapshotInfo));    if (!sn_tab)        goto fail;    for(i = 0; i < s->nb_snapshots; i++) {        sn_info = sn_tab + i;        sn = s->snapshots + i;        pstrcpy(sn_info->id_str, sizeof(sn_info->id_str),                sn->id_str);        pstrcpy(sn_info->name, sizeof(sn_info->name),                sn->name);        sn_info->vm_state_size = sn->vm_state_size;        sn_info->date_sec = sn->date_sec;        sn_info->date_nsec = sn->date_nsec;        sn_info->vm_clock_nsec = sn->vm_clock_nsec;    }    *psn_tab = sn_tab;    return s->nb_snapshots; fail:    qemu_free(sn_tab);    *psn_tab = NULL;    return -ENOMEM;}/*********************************************************//* refcount handling */static int refcount_init(BlockDriverState *bs){    BDRVQcowState *s = bs->opaque;    int ret, refcount_table_size2, i;    s->refcount_block_cache = qemu_malloc(s->cluster_size);    if (!s->refcount_block_cache)        goto fail;    refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t);    s->refcount_table = qemu_malloc(refcount_table_size2);    if (!s->refcount_table)        goto fail;    if (s->refcount_table_size > 0) {        ret = bdrv_pread(s->hd, s->refcount_table_offset,                         s->refcount_table, refcount_table_size2);        if (ret != refcount_table_size2)            goto fail;        for(i = 0; i < s->refcount_table_size; i++)            be64_to_cpus(&s->refcount_table[i]);    }    return 0; fail:    return -ENOMEM;}static void refcount_close(BlockDriverState *bs){    BDRVQcowState *s = bs->opaque;    qemu_free(s->refcount_block_cache);    qemu_free(s->refcount_table);}static int load_refcount_block(BlockDriverState *bs,                               int64_t refcount_block_offset){    BDRVQcowState *s = bs->opaque;    int ret;    ret = bdrv_pread(s->hd, refcount_block_offset, s->refcount_block_cache,                     s->cluster_size);    if (ret != s->cluster_size)        return -EIO;    s->refcount_block_cache_offset = refcount_block_offset;    return 0;}static int get_refcount(BlockDriverState *bs, int64_t cluster_index){    BDRVQcowState *s = bs->opaque;    int refcount_table_index, block_index;    int64_t refcount_block_offset;    refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);    if (refcount_table_index >= s->refcount_table_size)        return 0;    refcount_block_offset = s->refcount_table[refcount_table_index];    if (!refcount_block_offset)        return 0;    if (refcount_block_offset != s->refcount_block_cache_offset) {        /* better than nothing: return allocated if read error */        if (load_refcount_block(bs, refcount_block_offset) < 0)            return 1;    }    block_index = cluster_index &        ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);    return be16_to_cpu(s->refcount_block_cache[block_index]);}/* return < 0 if error */static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size){    BDRVQcowState *s = bs->opaque;    int i, nb_clusters;    nb_clusters = (size + s->cluster_size - 1) >> s->cluster_bits;    for(;;) {        if (get_refcount(bs, s->free_cluster_index) == 0) {            s->free_cluster_index++;            for(i = 1; i < nb_clusters; i++) {                if (get_refcount(bs, s->free_cluster_index) != 0)                    goto not_found;                s->free_cluster_index++;            }#ifdef DEBUG_ALLOC2            printf("alloc_clusters: size=%lld -> %lld\n",                   size,                   (s->free_cluster_index - nb_clusters) << s->cluster_bits);#endif            return (s->free_cluster_index - nb_clusters) << s->cluster_bits;        } else {        not_found:            s->free_cluster_index++;        }    }}static int64_t alloc_clusters(BlockDriverState *bs, int64_t size){    int64_t offset;    offset = alloc_clusters_noref(bs, size);    update_refcount(bs, offset, size, 1);    return offset;}/* only used to allocate compressed sectors. We try to allocate   contiguous sectors. size must be <= cluster_size */static int64_t alloc_bytes(BlockDriverState *bs, int size){    BDRVQcowState *s = bs->opaque;    int64_t offset, cluster_offset;    int free_in_cluster;    assert(size > 0 && size <= s->cluster_size);    if (s->free_byte_offset == 0) {        s->free_byte_offset = alloc_clusters(bs, s->cluster_size);    } redo:    free_in_cluster = s->cluster_size -        (s->free_byte_offset & (s->cluster_size - 1));    if (size <= free_in_cluster) {        /* enough space in current cluster */        offset = s->free_byte_offset;        s->free_byte_offset += size;        free_in_cluster -= size;        if (free_in_cluster == 0)            s->free_byte_offset = 0;        if ((offset & (s->cluster_size - 1)) != 0)            update_cluster_refcount(bs, offset >> s->cluster_bits, 1);    } else {        offset = alloc_clusters(bs, s->cluster_size);        cluster_offset = s->free_byte_offset & ~(s->cluster_size - 1);        if ((cluster_offset + s->cluster_size) == offset) {            /* we are lucky: contiguous data */            offset = s->free_byte_offset;            update_cluster_refcount(bs, offset >> s->cluster_bits, 1);            s->free_byte_offset += size;        } else {            s->free_byte_offset = offset;            goto redo;        }    }    return offset;}static void free_clusters(BlockDriverState *bs,                          int64_t offset, int64_t size){    update_refcount(bs, offset, size, -1);}static int grow_refcount_table(BlockDriverState *bs, int min_size){    BDRVQcowState *s = bs->opaque;    int new_table_size, new_table_size2, refcount_table_clusters, i, ret;    uint64_t *new_table;    int64_t table_offset;    uint64_t data64;    uint32_t data32;    int old_table_size;    int64_t old_table_offset;    if (min_size <= s->refcount_table_size)        return 0;    /* compute new table size */    refcount_table_clusters = s->refcount_table_size >> (s->cluster_bits - 3);    for(;;) {        if (refcount_table_clusters == 0) {            refcount_table_clusters = 1;        } else {            refcount_table_clusters = (refcount_table_clusters * 3 + 1) / 2;        }        new_table_size = refcount_table_clusters << (s->cluster_bits - 3);        if (min_size <= new_table_size)            break;    }#ifdef DEBUG_ALLOC2    printf("grow_refcount_table from %d to %d\n",           s->refcount_table_size,           new_table_size);#endif    new_table_size2 = new_table_size * sizeof(uint64_t);    new_table = qemu_mallocz(new_table_size2);    if (!new_table)        return -ENOMEM;    memcpy(new_table, s->refcount_table,           s->refcount_table_size * sizeof(uint64_t));    for(i = 0; i < s->refcount_table_size; i++)        cpu_to_be64s(&new_table[i]);    /* Note: we cannot update the refcount now to avoid recursion */    table_offset = alloc_clusters_noref(bs, new_table_size2);    ret = bdrv_pwrite(s->hd, table_offset, new_table, new_table_size2);    if (ret != new_table_size2)        goto fail;    for(i = 0; i < s->refcount_table_size; i++)        be64_to_cpus(&new_table[i]);    data64 = cpu_to_be64(table_offset);    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset),                    &data64, sizeof(data64)) != sizeof(data64))        goto fail;    data32 = cpu_to_be32(refcount_table_clusters);    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_clusters),                    &data32, sizeof(data32)) != sizeof(data32))        goto fail;    qemu_free(s->refcount_table);    old_table_offset = s->refcount_table_offset;    old_table_size = s->refcount_table_size;    s->refcount_table = new_table;    s->refcount_table_size = new_table_size;    s->refcount_table_offset = table_offset;    update_refcount(bs, table_offset, new_table_size2, 1);    free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t));    return 0; fail:    free_clusters(bs, table_offset, new_table_size2);    qemu_free(new_table);    return -EIO;}/* addend must be 1 or -1 *//* XXX: cache several refcount block clusters ? */static int update_cluster_refcount(BlockDriverState *bs,                                   int64_t cluster_index,                                   int addend){    BDRVQcowState *s = bs->opaque;    int64_t offset, refcount_block_offset;    int ret, refcount_table_index, block_index, refcount;    uint64_t data64;    refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);    if (refcount_table_index >= s->refcount_table_size) {        if (addend < 0)            return -EINVAL;        ret = grow_refcount_table(bs, refcount_table_index + 1);        if (ret < 0)            return ret;    }    refcount_block_offset = s->refcount_table[refcount_table_index];    if (!refcount_block_offset) {        if (addend < 0)            return -EINVAL;        /* create a new refcount block */        /* Note: we cannot update the refcount now to avoid recursion */        offset = alloc_clusters_noref(bs, s->cluster_size);        memset(s->refcount_block_cache, 0, s->cluster_size);        ret = bdrv_pwrite(s->hd, offset, s->refcount_block_cache, s->cluster_size);        if (ret != s->cluster_size)            return -EINVAL;        s->refcount_table[refcount_table_index] = offset;        data64 = cpu_to_be64(offset);        ret = bdrv_pwrite(s->hd, s->refcount_table_offset +                          refcount_table_index * sizeof(uint64_t),                          &data64, sizeof(data64));        if (ret != sizeof(data64))            return -EINVAL;        refcount_block_offset = offset;        s->refcount_block_cache_offset = offset;        update_refcount(bs, offset, s->cluster_size, 1);    } else {        if (refcount_block_offset != s->refcount_block_cache_offset) {            if (load_refcount_block(bs, refcount_block_offset) < 0)                return -EIO;        }    }    /* we can update the count and save it */    block_index = cluster_index &        ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);    refcount = be16_to_cpu(s->refcount_block_cache[block_index]);    refcount += addend;    if (refcount < 0 || refcount > 0xffff)        return -EINVAL;    if (refcount == 0 && cluster_index < s->free_cluster_index) {        s->free_cluster_index = cluster_index;    }    s->refcount_block_cache[block_index] = cpu_to_be16(refcount);    if (bdrv_pwrite(s->hd,                    refcount_block_offset + (block_index << REFCOUNT_SHIFT),                    &s->refcount_block_cache[block_index], 2) != 2)        return -EIO;    return refcount;}static void update_refcount(BlockDriverState *bs,                            int64_t offset, int64_t length,                            int addend){    BDRVQcowState *s = bs->opaque;    int64_t start, last, cluster_offset;#ifdef DEBUG_ALLOC2    printf("update_refcount: offset=%lld size=%lld addend=%d\n",           offset, length, addend);#endif    if (length <= 0)        return;    start = offset & ~(s->cluster_size - 1);    last = (offset + length - 1) & ~(s->cluster_size - 1);    for(cluster_offset = start; cluster_offset <= last; 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -