Beispiel #1
0
/* Reads the log header, and subsequent descriptors (if any).  This
 * will allocate all the space for buffer, which must be NULL when
 * passed into this function. Each descriptor will also be validated,
 * and error returned if any are invalid. */
static int vhdx_log_read_desc(BlockDriverState *bs, BDRVVHDXState *s,
                              VHDXLogEntries *log, VHDXLogDescEntries **buffer)
{
    int ret = 0;
    uint32_t desc_sectors;
    uint32_t sectors_read;
    VHDXLogEntryHeader hdr;
    VHDXLogDescEntries *desc_entries = NULL;
    int i;

    assert(*buffer == NULL);

    ret = vhdx_log_peek_hdr(bs, log, &hdr);
    if (ret < 0) {
        goto exit;
    }
    vhdx_log_entry_hdr_le_import(&hdr);
    if (vhdx_log_hdr_is_valid(log, &hdr, s) == false) {
        ret = -EINVAL;
        goto exit;
    }

    desc_sectors = vhdx_compute_desc_sectors(hdr.descriptor_count);
    desc_entries = qemu_blockalign(bs, desc_sectors * VHDX_LOG_SECTOR_SIZE);

    ret = vhdx_log_read_sectors(bs, log, &sectors_read, desc_entries,
                                desc_sectors, false);
    if (ret < 0) {
        goto free_and_exit;
    }
    if (sectors_read != desc_sectors) {
        ret = -EINVAL;
        goto free_and_exit;
    }

    /* put in proper endianness, and validate each desc */
    for (i = 0; i < hdr.descriptor_count; i++) {
        vhdx_log_desc_le_import(&desc_entries->desc[i]);
        if (vhdx_log_desc_is_valid(&desc_entries->desc[i], &hdr) == false) {
            ret = -EINVAL;
            goto free_and_exit;
        }
    }

    *buffer = desc_entries;
    goto exit;

free_and_exit:
    qemu_vfree(desc_entries);
exit:
    return ret;
}
Beispiel #2
0
/* Allow peeking at the hdr entry at the beginning of the current
 * read index, without advancing the read index */
static int vhdx_log_peek_hdr(BlockDriverState *bs, VHDXLogEntries *log,
                             VHDXLogEntryHeader *hdr)
{
    int ret = 0;
    uint64_t offset;
    uint32_t read;

    assert(hdr != NULL);

    /* peek is only supported on sector boundaries */
    if (log->read % VHDX_LOG_SECTOR_SIZE) {
        ret = -EFAULT;
        goto exit;
    }

    read = log->read;
    /* we are guaranteed that a) log sectors are 4096 bytes,
     * and b) the log length is a multiple of 1MB. So, there
     * is always a round number of sectors in the buffer */
    if ((read + sizeof(VHDXLogEntryHeader)) > log->length) {
        read = 0;
    }

    if (read == log->write) {
        ret = -EINVAL;
        goto exit;
    }

    offset = log->offset + read;

    ret = bdrv_pread(bs->file->bs, offset, hdr, sizeof(VHDXLogEntryHeader));
    if (ret < 0) {
        goto exit;
    }
    vhdx_log_entry_hdr_le_import(hdr);

exit:
    return ret;
}