概要
VixDiskLib_QueryAllocatedBlocks
は VDDK API 6.7 から追加された API です
指定の vmdk ですでに使われているブロック領域を取得することができます
環境
- CentOS 7
- VCSA 6.5.0 9451637
- VDDK API 6.7.1
サンプルコード
コード全体は以下の通りです
ポイントは後半になります
このあとで説明します
#include <iostream>
#include <cstring>
#include "vixDiskLib.h"
using std::cout;
using std::endl;
#define VIXDISKLIB_VERSION_MAJOR 6
#define VIXDISKLIB_VERSION_MINOR 7
static struct {
VixDiskLibConnection connection;
char *libdir;
char *cfgFile;
} params;
static void LogFunc(const char *fmt, va_list args) {
printf("Log: ");
vprintf(fmt, args);
}
static void WarnFunc(const char *fmt, va_list args) {
printf("Warning: ");
vprintf(fmt, args);
}
static void PanicFunc(const char *fmt, va_list args) {
printf("Panic: ");
vprintf(fmt, args);
exit(10);
}
int main() {
VixError err;
err = VixDiskLib_InitEx(VIXDISKLIB_VERSION_MAJOR, VIXDISKLIB_VERSION_MINOR, &LogFunc, &WarnFunc, &PanicFunc, params.libdir, "init.cfg");
printf("%lu\n", err);
VixDiskLibConnectParams cnxParams = {0};
cnxParams.vmxSpec = {(char*)"moref=vm-20"};
cnxParams.specType = VIXDISKLIB_SPEC_VMX;
cnxParams.serverName = {(char*)"192.168.100.20"};
cnxParams.credType = VIXDISKLIB_CRED_UID;
cnxParams.creds.uid.userName = {(char*)"administrator@vsphere.local"};
cnxParams.creds.uid.password = {(char*)"xxxxxxxxxxxx"};
cnxParams.thumbPrint = {(char*)"96:09:d6:5b:e0:83:58:1b:ba:2b:cc:78:22:88:33:36:64:50:32:eb"};
err = VixDiskLib_ConnectEx(&cnxParams, 0, NULL, "nbd", ¶ms.connection);
printf("%lu\n", err);
VixDiskLibHandle _handle = NULL;
err = VixDiskLib_Open(params.connection, "[datastore2] dist/dist.vmdk", VIXDISKLIB_FLAG_OPEN_SINGLE_LINK , &_handle);
printf("%lu\n", err);
VixDiskLibBlockList *buf = new VixDiskLibBlockList;
VixDiskLibSectorType start = 0;
VixDiskLibSectorType sectorCount = 62914560; // -> 30GB / 512
VixDiskLibSectorType chunk = 8192;
// VixDiskLibSectorType chunk = 128;
VixDiskLibSectorType sum = 0;
err = VixDiskLib_QueryAllocatedBlocks(_handle, start, sectorCount, chunk, &buf);
printf("%lu\n", err);
printf("%lu\n", buf->numBlocks);
for (int i = 0; i < buf->numBlocks; i++) {
VixDiskLibBlock vb = buf->blocks[i];
printf("i: %d\n", i);
printf("offset: %lu\n", vb.offset);
printf("length: %lu\n", vb.length);
sum = sum + vb.length;
}
printf("sum length: %lu\n", sum / chunk);
delete[] buf;
VixDiskLib_Disconnect(params.connection);
return 0;
}
説明
VixDiskLib_QueryAllocatedBlocks
には 5 つの引数が必要になります
_handle
はディスクのハンドラです
start
が探索を開始するオフセットです
基本は 0 を指定すれば OK です
sectorCount
は操作対象のディスクのセクタ数を入力します
今回であれば 30GB のシンプロビジョニングのディスクを対象にしています
シンプロビジョニングなのでディスク使用量はもっと少ないかもしれませんがここで指定する値は VM に接続したハードディスクのサイズを入力してください
なおこの値は mob で取得できます
config.hardware.device[2000]
の capacityInBytes
を 512 で割った値になります
セクタの求め方は「ディスクサイズ / 512」になります
512 は VIXDISKLIB_SECTOR_SIZE
の値になります
1 セクタに含まれるバイト数で割ることでセクタ数を算出することができます
chunk
は取得する領域のサイズの単位 (?) になります
VixDiskLib_QueryAllocatedBlocks
は結果としてブロック数が取得できるのですが、その数が chunk
の大きさによって変わります
chunk を大きくすればブロック数が少なくなり、chunk を小さくすればブロック数が多くなります
また chunk は 128 から 131072 の範囲で指定する必要があります
最後の buf
は結果を格納する VixDiskLibBlockList
のポインタ変数です
関数に渡す場合は更にポイントとして渡します
VixDiskLibBlockList *buf = new VixDiskLibBlockList;
VixDiskLibSectorType start = 0;
VixDiskLibSectorType sectorCount = 62914560; // -> 30GB / 512
VixDiskLibSectorType chunk = 8192;
// VixDiskLibSectorType chunk = 128;
VixDiskLibSectorType sum = 0;
err = VixDiskLib_QueryAllocatedBlocks(_handle, start, sectorCount, chunk, &buf);
あとは結果を参照します
for (int i = 0; i < buf->numBlocks; i++) {
VixDiskLibBlock vb = buf->blocks[i];
printf("i: %d\n", i);
printf("offset: %lu\n", vb.offset);
printf("length: %lu\n", vb.length);
sum = sum + vb.length;
}
buf->numBlocks
にブロック数が格納されているのでその分ループします
ブロック情報は buf->blocks
に配列として格納されています
VixDiskLibBlock
の構造体として取得できるのであとはそれに含まれる offset
と length
を表示するだけです
よくわからなかったこと
chunk サイズを変更させると length の合計が変わりました
結果として取得できるブロックが指定の chunk サイズ単位ごとに取得できるため実際には使われていない領域も結果に含まれている可能性がありそうです
128 を指定したほうが sum が小さくなったのでおそらくそういうことなのではと推測しています
またこの VixDiskLib_QueryAllocatedBlocks
は vSphere API の QueryChangedDiskAreas と組み合わせて使うようです
VixDiskLib_QueryAllocatedBlocks
でアロケート済みの領域を取得してかつ QueryChangedDiskAreas
で変更のあった領域を取得し双方の領域の積集合を取ることで増分領域を正確に取得できることができるようになるようです (参考: バックアップとリカバリの例)
QueryChangedDiskAreas
のレスポンスも offset と length のリストなので確かに言っていることはできそうなのですが実は QueryChangedDiskAreas
側の引数に chunk サイズを指定するオプションがありません
今回の検証結果を見ると VixDiskLib_QueryAllocatedBlocks
のである offset と length の値は chunk サイズによって変わるので QueryChangedDiskAreas
側の chunk サイズがわからないことには比較できないかなと思っています
もしかすると情報が出てくるのかもしれませんが自分が調べた限りでは出てきませんでした
やろうとしたら QueryChangedDiskAreas
の「*」で取得した結果 (offset, length) と VixDiskLib_QueryAllocatedBlocks
で取得した結果 (offset, length) を chunk サイズを変更しつつ比較して QueryChangedDiskAreas
の chunk サイズを見つけるしかないのかもしれません
(それか実は自分の理解が全く違っていて、そもそも双方の API は比較することができないのかもしれません、、)
P.S
あとでわかったのですが QueryChangedDiskAreas
と VixDiskLib_QueryAllocatedBlocks
はそもそも結果を比較して使うものではなさそうです
VixDiskLib_QueryAllocatedBlocks
はフルバックアップ用で QueryChangedDiskAreas
が増分バックアップ用になっているようです
それ以外で気になったこと
chunk サイズ以外で気になったこととしては length の単位です
調べるとバイトらしいのですが合計したバイトサイズと実際の vmdk のサイズが全然違っていました
実際の vmdk のサイズと比較する場合は length だけではダメなのかもしれません
最後に
VixDiskLib_QueryAllocatedBlocks
をコールしてみました
使い方はわかったのですが結果が何を示しているかいまいち理解することができませんでした
VDDK API 内で扱われるセクタ、チャンクサイズ、ブロック、offset、length が何を意味しているか理解しないとそもそも VDDK API を使いこなすのは難しいのかもしれません
无意中在网上搜到你的文档,我正在做vmware的全量、增量备份。虽然已经有很多付费软件实现了此功能。但是目前还没有看到一些开源的软件。目前全量备份的功能我已经通过VixDiskLib_QueryAllocatedBlocks实现了,但是增量功能还有些问题,多次运行增量备份后磁盘数据会损坏😒。this chinese,you can translate to japanese
返信削除