/* Reads num_sectors from the log (all log sectors are 4096 bytes), * into buffer 'buffer'. Upon return, *sectors_read will contain * the number of sectors successfully read. * * It is assumed that 'buffer' is already allocated, and of sufficient * size (i.e. >= 4096*num_sectors). * * If 'peek' is true, then the tail (read) pointer for the circular buffer is * not modified. * * 0 is returned on success, -errno otherwise. */ static int vhdx_log_read_sectors(BlockDriverState *bs, VHDXLogEntries *log, uint32_t *sectors_read, void *buffer, uint32_t num_sectors, bool peek) { int ret = 0; uint64_t offset; uint32_t read; read = log->read; *sectors_read = 0; while (num_sectors) { if (read == log->write) { /* empty */ break; } offset = log->offset + read; ret = bdrv_pread(bs->file, offset, buffer, VHDX_LOG_SECTOR_SIZE); if (ret < 0) { goto exit; } read = vhdx_log_inc_idx(read, log->length); *sectors_read = *sectors_read + 1; num_sectors--; } exit: if (!peek) { log->read = read; } return ret; }
/* 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; }