tapdisk2 logtapdisk2 的log 分為兩部分 /var/log/messages , /tmp/tapdisk.log.${PID} tapdisk syslog 以 tapdisk[1231] 開頭,這裡1231是進程號tapdisk log 一般以 count.time.timeseconds 開頭tapdisk error log內容以 TAPDISK ERROR 開頭,或者以 tap-err 開頭struct error {
int cnt;
int err;
char *func;
char msg[MAX_ENTRY_LEN];
};
struct ehandle {
int cnt;
int dropped;
struct error errors[MAX_ERROR_MESSAGES];
};
struct tlog {
char *p;
int size;
uint64_t cnt;
char *buf;
int level;
char *file;
int append;
};具體的代碼請參考 tapdisk-log.h / tapdisk-log.ctapdisk2 imagetapdisk2 提供了 td_image_t 結構,用於儲存 tapdisk2 讀寫的image盤資訊td_image_t - > driver 是不同類型的 disk_type 所提供的,儲存為 td_driver_handle 類型,其中 td_driver_handle -> ops 為 struct tap_disk * 結構。 td_image_t -> flags ,其值可以為:#define TD_OPEN_QUIET 0x00001
#define TD_OPEN_QUERY 0x00002
#define TD_OPEN_RDONLY 0x00004
#define TD_OPEN_STRICT 0x00008
#define TD_OPEN_SHAREABLE 0x00010
#define TD_OPEN_ADD_CACHE 0x00020
#define TD_OPEN_VHD_INDEX 0x00040
#define TD_OPEN_LOG_DIRTY 0x00080tapdisk_image_check_td_request 用於從 td_image_t 中檢查 td_request_t 請求的合法性,e.g. td_request_t -> op 至少為TD_OP_READ或者TD_OP_WRITE,request 的sectors 不能越界。tapdisk_image_check_ring_request 用於檢查 blkif_request, blkif_response 的合法性。這兩個函數唯一需要的是 image是否有TD_OPEN_RDONLY的flagtapdisk2 queuetlist 是 tiocb 的 list,其中 tiocb 是 tapdisk2 對 struct iocb 的結構的封裝。 對於 struct iocb 的 IO 請求,有相應的 callback 函數 td_queue_callback_t cbstruct tqueue {
int size;
const struct tio *tio;
void *tio_data;
struct opioctx opioctx;
int queued;
struct iocb **iocbs;
/* number of iocbs pending in the aio layer */
int iocbs_pending;
/* number of tiocbs pending in the queue --
* this is likely to be larger than iocbs_pending
* due to request coalescing */
int tiocbs_pending;
/* iocbs may be deferred if the aio ring is full.
* tapdisk_queue_complete will ensure deferred
* iocbs are queued as slots become available. */
struct tlist deferred;
int tiocbs_deferred;
/* optional tapdisk filter */
struct tfilter *filter;
uint64_t deferrals;
};tapdisk 除了要通過各種 driver 來區分各種鏡像的類型之外,還要區分不同的 IO類型,即 tapdisk 通過何種方式來讀寫鏡像。目前支援的有兩種: aio, rwio
Hide tapdisk support for different raw I/O interfaces behind a newstruct tio. Libaio remains to dominate the interface, requiringeveryone to dispatch iocb/ioevent structs.Backends: - lio: Kernel AIO via libaio. - rwio: Canonical read/write() mode.
struct tio {const char *name;
size_t data_size;
int (*tio_setup) (struct tqueue *queue, int qlen);
void (*tio_destroy) (struct tqueue *queue);
int (*tio_submit) (struct tqueue *queue);
};
enum {
TIO_DRV_LIO = 1,
TIO_DRV_RWIO = 2,
};tqueue -> tio 指向這個 struct tio 結構,通過 tio_submit 函數真正發出 IO 請求。queue_tiocb :把 struct tiocb* 指向的結構體加入到隊列中。注意 tiocb 是一個封裝了 libaio 的 struct iocb 結構的一個結構體。同時 struct iocb -> data 所指向的 void 指標指向這個 struct tiocb。defer_tiocb :把 struct tiocb* 指向的結構插入到 deferred list ( tqueue -> deferred ) 的末尾。queue_deferred_tiocb : 取出 tqueue -> deferred 隊列頭的 struct tiocb 結構,調用 queue_tiocb 加入到 tqueue -> iocbs 隊列中complete_tiocb : 每一個 struct tiocb 結構體都會事先註冊好一個回呼函數 cb,對於libaio 返回的 struct iocb 結構,判斷 libaio 的返回狀態,之後調用 tiocb->cb(tiocb->arg, tiocb, err)cancel_tiocbs : 對於 tqueue未完成的 tqueue->iocbs 隊列裡的所有 IO 請求,調用 complete_tiocb 取消這些請求。對於兩種IO模式,我們跳過 rwio, 直接去看 lio,下面是lio 對應的 struct tio 結構:static const struct tio td_tio_lio = {
.name = "lio",
.data_size = sizeof(struct lio),
.tio_setup = tapdisk_lio_setup,
.tio_destroy = tapdisk_lio_destroy,
.tio_submit = tapdisk_lio_submit,
};tapdisk_init_queue : 用於初始化 struct tqueue 結構,其中又調用了 tapdisk_queue_init_io , 該方法 會調用 tio->tio_setup 初始化 IO queue tapdisk_free_queue : 用於釋放 tqueue 佔用的資源tapdisk_debug_queue : 列印出當前 tqueue 的狀態,對於 deferred queue 裡的所有 IO 請求,同時列印詳細資料tapdisk_lio_setup_aio : 首先檢查核心版本,從而調用 __lio_setup_aio_poll 或者 __lio_setup_aio_eventfdtapdisk_lio_destroy_aio : 關閉 lio -> event_fd, 釋放 lio -> aio_ctxtapdisk_lio_setup : 調用 tapdisk_lio_setup_aio 擷取一個 aio 的 event_fd,接著調用 tapdisk_server_register_event,把這個 event_fd 註冊到事件 SCHEDULER_POLL_READ_FD 上面,對應的 callback 函數為 tapdisk_lio_eventtapdisk_lio_event : tapdisk_lio_event 是回呼函數,首先調用 tapdisk_lio_ack_event 來讀一個 uint64_t 大小的內容,之後調用 io_getevents, io_split, 得到對應的 event 個數, 影響的 tiocbs 的個數。最後對於所有的 tiocbs, 調用 complete_tiocb 完成IOtapdisk_lio_submit : 調用 io_merge 對IO請求做合并最佳化,之後調用 io_submit 把請求通過 aio 提交上去。