File:  [Isaki's NoNo m68k/m88k emulator] / nono / host / diskdriver_qcow2.h
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:06:02 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
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 {};
};

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.