示例#1
0
/* Writes num_sectors to the log (all log sectors are 4096 bytes),
 * from buffer 'buffer'.  Upon return, *sectors_written will contain
 * the number of sectors successfully written.
 *
 * It is assumed that 'buffer' is at least 4096*num_sectors large.
 *
 * 0 is returned on success, -errno otherwise */
static int vhdx_log_write_sectors(BlockDriverState *bs, VHDXLogEntries *log,
                                  uint32_t *sectors_written, void *buffer,
                                  uint32_t num_sectors)
{
    int ret = 0;
    uint64_t offset;
    uint32_t write;
    void *buffer_tmp;
    BDRVVHDXState *s = bs->opaque;

    ret = vhdx_user_visible_write(bs, s);
    if (ret < 0) {
        goto exit;
    }

    write = log->write;

    buffer_tmp = buffer;
    while (num_sectors) {

        offset = log->offset + write;
        write = vhdx_log_inc_idx(write, log->length);
        if (write == log->read) {
            /* full */
            break;
        }
        ret = bdrv_pwrite(bs->file->bs, offset, buffer_tmp,
                          VHDX_LOG_SECTOR_SIZE);
        if (ret < 0) {
            goto exit;
        }
        buffer_tmp += VHDX_LOG_SECTOR_SIZE;

        log->write = write;
        *sectors_written = *sectors_written + 1;
        num_sectors--;
    }

exit:
    return ret;
}
示例#2
0
文件: vhdx-log.c 项目: Aakriti/qemu
/* Flush the entire log (as described by 'logs') to the VHDX image
 * file, and then set the log to 'empty' status once complete.
 *
 * The log entries should be validate prior to flushing */
static int vhdx_log_flush(BlockDriverState *bs, BDRVVHDXState *s,
                          VHDXLogSequence *logs)
{
    int ret = 0;
    int i;
    uint32_t cnt, sectors_read;
    uint64_t new_file_size;
    void *data = NULL;
    VHDXLogDescEntries *desc_entries = NULL;
    VHDXLogEntryHeader hdr_tmp = { 0 };

    cnt = logs->count;

    data = qemu_blockalign(bs, VHDX_LOG_SECTOR_SIZE);

    ret = vhdx_user_visible_write(bs, s);
    if (ret < 0) {
        goto exit;
    }

    /* each iteration represents one log sequence, which may span multiple
     * sectors */
    while (cnt--) {
        ret = vhdx_log_peek_hdr(bs, &logs->log, &hdr_tmp);
        if (ret < 0) {
            goto exit;
        }
        /* if the log shows a FlushedFileOffset larger than our current file
         * size, then that means the file has been truncated / corrupted, and
         * we must refused to open it / use it */
        if (hdr_tmp.flushed_file_offset > bdrv_getlength(bs->file)) {
            ret = -EINVAL;
            goto exit;
        }

        ret = vhdx_log_read_desc(bs, s, &logs->log, &desc_entries);
        if (ret < 0) {
            goto exit;
        }

        for (i = 0; i < desc_entries->hdr.descriptor_count; i++) {
            if (!memcmp(&desc_entries->desc[i].signature, "desc", 4)) {
                /* data sector, so read a sector to flush */
                ret = vhdx_log_read_sectors(bs, &logs->log, &sectors_read,
                                            data, 1, false);
                if (ret < 0) {
                    goto exit;
                }
                if (sectors_read != 1) {
                    ret = -EINVAL;
                    goto exit;
                }
            }

            ret = vhdx_log_flush_desc(bs, &desc_entries->desc[i], data);
            if (ret < 0) {
                goto exit;
            }
        }
        if (bdrv_getlength(bs->file) < desc_entries->hdr.last_file_offset) {
            new_file_size = desc_entries->hdr.last_file_offset;
            if (new_file_size % (1024*1024)) {
                /* round up to nearest 1MB boundary */
                new_file_size = ((new_file_size >> 20) + 1) << 20;
                bdrv_truncate(bs->file, new_file_size);
            }
        }