|
|
nono 1.7.0
//
// nono
// Copyright (C) 2024 nono project
// Licensed under nono-license.txt
//
//
// ディスクイメージドライバ (QCOW2 形式)
//
#pragma once
#include "diskdriver.h"
#include "autofd.h"
#include "vectorbool64.h"
#include <vector>
// ディスクイメージ (QCOW2 形式)
class DiskDriverQcow2 : public DiskImageDriver
{
using inherited = DiskImageDriver;
public:
DiskDriverQcow2(const std::string& objname_, const std::string& pathname_);
~DiskDriverQcow2() override;
bool Match() override;
bool Attach(std::string& errmsg) override;
bool Open(bool read_only) override;
void Close() override;
bool Read(void *buf, off_t offset, size_t size) override;
bool Write(const void *buf, off_t offset, size_t size) override;
private:
int HasCompressed();
bool ReadTable(std::vector<uint64>& buf, uint64 offset);
off_t AllocCluster(const void *buf);
bool WriteEntry(uint64 baseoff, uint64 index, uint64 data);
bool ReadRefcount();
uint64 AllocRefcount();
bool FindCluster(uint64 *);
static bool is_mem_zero(const void *, size_t);
static const char *CryptMethodToStr(uint32);
static const char *CompressionTypeToStr(uint32);
autofd fd {};
uint32 version {};
uint32 L1_size {};
uint64 L1_table_offset {};
uint32 cluster_bits {};
uint64 L2_entries {};
uint64 refcount_table_offset {};
uint32 refcount_table_clusters {};
// クラスタのバイトサイズ。
uint64 cluster_size {};
// 下位側を取り出すためのマスク。64KB/クラスタなら 0xffff になる。
uint64 cluster_mask {};
// L1/L2 インデックスを分けるためのビット数とマスク。
uint32 L2_entries_bits {};
uint64 L2_entries_mask {};
uint compress_offset_bits {};
uint64 compress_sector_mask {};
// L1 テーブルは常にメモリに全コピーを持つ。
std::vector<uint64> L1_table {};
// L2 テーブルは現在参照中の1つのキャッシュを持つ。
std::vector<uint64> L2_table {};
// 現在 L2_table[] でキャッシュしている箇所の L1 index。
// L1_table[0] の L2 をキャッシュしていれば $0。
// (uint64)-1 ならキャッシュなし。
uint64 cached_L1_index {};
// データクラスタのキャッシュ。
std::vector<uint8> data_cluster {};
// 現在 data_cluster[] でキャッシュしている箇所のデータクラスタ番号。
// ゲストイメージの先頭クラスタなら $0。
// (uint64)-1 ならキャッシュなし。
uint64 cached_data_index {};
// refblock (2段目) の1クラスタ内の要素数。標準では 32768。
uint32 refblock_capacity {};
// refblock_capacity のビット数。標準では 15 になる。
uint32 refblock_bits {};
// refblock (2段目) の下位を取り出すマスク。標準では 0x7fff になる。
uint64 refblock_mask {};
// refcount はイメージ上は 1,2,4,8,16,32,64 ビットの可能性がある
// (ただし通常は 16 ビットしかないと思われる)。
// オンメモリでは bool で扱い、空き(refcount==0)なら true に反転して
// 保持する (count trailing zero で空きを探すため)。
// 読み込みはオープン時に行い、書き込みはライトスルーキャッシュ方式。
VectorBool64 freemap {};
std::vector<uint64> refcount_block_offset {};
};
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.