xen块设备体系结构 - tapdisk2 (2)

tapdisk2 log

tapdisk2 的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.c

tapdisk2 image

tapdisk2 提供了 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            0x00080


tapdisk_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的flag

tapdisk2 queue

tlist 是 tiocb 的 list,其中 tiocb 是 tapdisk2 对 struct iocb 的结构的封装。 对于 struct iocb 的 IO 请求,有相应的 callback 函数 td_queue_callback_t cb

struct 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 new
struct tio. Libaio remains to dominate the interface, requiring
everyone 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_eventfd

tapdisk_lio_destroy_aio :  关闭 lio -> event_fd, 释放 lio -> aio_ctx

tapdisk_lio_setup : 调用 tapdisk_lio_setup_aio 获取一个 aio 的 event_fd,接着调用 tapdisk_server_register_event,把这个 event_fd 注册到事件 SCHEDULER_POLL_READ_FD 上面,对应的 callback 函数为 tapdisk_lio_event

tapdisk_lio_event : tapdisk_lio_event 是回调函数,首先调用 tapdisk_lio_ack_event 来读一个 uint64_t 大小的内容,之后调用 io_getevents, io_split, 得到对应的 event 个数, 影响的 tiocbs 的个数。最后对于所有的 tiocbs, 调用 complete_tiocb 完成IO

tapdisk_lio_submit : 调用 io_merge 对IO请求做合并优化,之后调用 io_submit 把请求通过 aio 提交上去。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值