tapdisk2
struct tap_disk {
const char *disk_type;
td_flag_t flags;
int private_data_size;
int (*td_open) (td_driver_t *, const char *, td_flag_t);
int (*td_close) (td_driver_t *);
int (*td_get_parent_id) (td_driver_t *, td_disk_id_t *);
int (*td_validate_parent) (td_driver_t *, td_driver_t *, td_flag_t);
void (*td_queue_read) (td_driver_t *, td_request_t);
void (*td_queue_write) (td_driver_t *, td_request_t);
void (*td_debug) (td_driver_t *);
};
tap_disk 結構抽象了 tapdisk2 所有支援的 disk 類型,如 vhd, qcow, img 等等,可以從 disktypes.h 中找到所有的 disk_info_t
typedef struct disk_info {
int idnum;
char name[50]; /* e.g. "RAMDISK" */
char handle[10]; /* xend handle, e.g. 'ram' */
int single_handler; /* is there a single controller for all */
/* instances of disk type? */
#ifdef TAPDISK
struct tap_disk *drv;
#endif
} disk_info_t;
static disk_info_t vhd_disk = {
DISK_TYPE_VHD,
"virtual server image (vhd)",
"vhd",
0,
#ifdef TAPDISK
&tapdisk_vhd,
#endif
};
以 vhd 為例,vhd_disk.handle = "vhd",這個必須在 tapdisk 的配置中指定出來。vhd_disk.tapdisk_vhd 在 block-vhd.c 中有指定
struct tap_disk tapdisk_vhd = {
.disk_type = "tapdisk_vhd",
.flags = 0,
.private_data_size = sizeof(struct vhd_state),
.td_open = _vhd_open,
.td_close = _vhd_close,
.td_queue_read = vhd_queue_read,
.td_queue_write = vhd_queue_write,
.td_get_parent_id = vhd_get_parent_id,
.td_validate_parent = vhd_validate_parent,
.td_debug = vhd_debug,
};
tapdisk2 定義了如下的 tap_disk 數組,比較常用的是 tapdisk_aio, tapdisk_vhd, 今後也許xen社區會增加對 ovf 格式image的支援
const struct tap_disk *tapdisk_disk_drivers[] = {
[DISK_TYPE_AIO] = &tapdisk_aio,
#if 0
[DISK_TYPE_SYNC] = &tapdisk_sync,
[DISK_TYPE_VMDK] = &tapdisk_vmdk,
#endif
[DISK_TYPE_VHD] = &tapdisk_vhd,
[DISK_TYPE_RAM] = &tapdisk_ram,
[DISK_TYPE_QCOW] = &tapdisk_qcow,
[DISK_TYPE_BLOCK_CACHE] = &tapdisk_block_cache,
[DISK_TYPE_VINDEX] = &tapdisk_vhd_index,
[DISK_TYPE_LOG] = &tapdisk_log,
[DISK_TYPE_REMUS] = &tapdisk_remus,
0,
};
同時 tapdisk 還定義了不同類型的 disk_info_t,並儲存在dtypes數組中 e.g.
static disk_info_t *dtypes[] = {
&aio_disk,
&null_disk, /* &sync_disk, */
&null_disk, /* &vmdk_disk, */
&null_disk, /* &vhdsync_disk, */
&vhd_disk,
&ram_disk,
&qcow_disk,
&block_cache_disk,
&null_disk,
&log_disk,
&remus_disk,
};
static disk_info_t vhd_disk = {
DISK_TYPE_VHD,
"virtual server image (vhd)",
"vhd",
0,
#ifdef TAPDISK
&tapdisk_vhd,
#endif
};
static disk_info_t aio_disk = {
DISK_TYPE_AIO,
"raw image (aio)",
"aio",
0,
#ifdef TAPDISK
&tapdisk_aio,
#endif
};
tapdisk-interface 是一種介面模式的實現方式,td_xxx 這樣的函數通過傳入的 td_image_t 參數得到 td_driver_t 對應的指標,再通過 td_driver_t 來調用driver 裡相應的 td_xxx函數。
td_load: 通過 image->type 和 image->name 找到相應的 td_image_t ,取出對應的 driver 結構填入傳入的 image 指標裡
td_open: 先調用 tapdisk_driver_allocate 建立相應的driver。 其中 image->type 表示image使用的 disk_type,如 vhd, qcow 等。如果尚未 TD_DRIVER_OPEN,則調用driver->ops->td_open 去開啟 image。
td_close: 通過 image->driver, 查看 driver->refcnt, 如果refcnt 為0,則清除 TD_DRIVER_OPEN 標籤,並調用 driver->ops->td_close(driver)
td_get_parent_id:參數透傳給driver,調用driver->ops->td_get_parent_id
td_validate_parent : 同上
td_queue_write:調用 tapdisk_image_check_td_request ,tapdisk_image_check_td_request 主要就是檢查這個 td_request_t 的合法性,比如讀寫的sectors有沒有越界,operation 號是否正確等。最後調用 driver->ops->td_queue_write 完成 IO請求。每一個 td_request_t 會有一個註冊的 callback 函數 void* cb, void* cb_data,用於IO請求失敗後的叫用作業
td_queue_read:同上