tapdisk2主流程

main()会fork个进程,子进程负责执行tapdisk2_main_processor(params);
tapdisk2_main_processor(params):
params的举例如:storage_vhd:{conf:/guest/VMguohu800529/conf/174942.conf},这个是要传给tdc的字符串参数
调用函数 tapdisk2_create_device(params, &path, &control_path, &type)
创建控制设备/dev/xen/blktap-2/control
初始化server这个全局变量
监听/var/run/blktap-control/ctl(pid)这个socket地址
创建字符设备/dev/xen/blktap-2/blktapX,作为接收请求的环设备
创建块设备/dev/xen/blktap-2/tapdevX,作为后端的块设备
path = {conf:/guest/VMguohu800156/conf/174569.conf}
control_path = /var/run/blktap-control/ctl(pid)
准备server的aio_queue,初始化tio指向的地方,和tio_data的空间
创建一个监听td_control.path( /var/run/blktap-control/ctl(pid) )的socket,基于这个socket的事件被加入了scheduler的链
给控制设备/dev/xen/blktap-2/control发一个ioctl,code=BLKTAP2_IOCTL_ALLOC_TAP=200

调用函数 tapdisk2_open_device(type, path, params)
初始化一个vbd,包括callback,ipc的fd,并初始化req链表,并把vbd加入到server的vbd链
填充vbd设备的driver链表
基于driver链表,填充image链表。在这里会创建每一个image,并执行VHD的打开流程
vbd的
初始化vbd设备的ring设备
把blktapX的fd注册事件在scheduler,回调函数是tapdisk_vbd_ring_event,负责从ring环取数据。这个回调函数将进入blktap的处理流程

调用函数 tapdisk_server_register_storage_event()
把storage_fd注册到server的事件里面
aio_queue,即为与tdc联系的queue,它的tio_data存储着tdc相关的内容,例如storage_id和storage_fd
aio_queue的tio_data,作为storage_io结构的storage_fd,注册事件在scheduler,事件id为storage_io的storage_id,亦即storage_event_id

调用 tapdisk_server_run(path),开始进入服务端流程

tapdisk2_create_device(const char *params, char **path, char **control_path, int *type):
调用 tapdisk2_check_environment(),检查下环境,主要是查看/proc/misc,并寻找里面有没有一个blktap-control。如果有则造一个字符设备,路径为/dev/xen/blktap-2/control
调用 tapdisk_parse_disk_type(params, path, type),获得参数和类型。path = {conf:/guest/VMguohu800156/conf/174569.conf},type=VHD
调用 tapdisk_server_initialize(NULL, NULL, *type)初始化tapdisk的server里面的一些参数,包括vbd链表,scheduler集合,ipc等
调用 tapdisk_control_open(control_path),创建一个监听td_control.path( /var/run/blktap-control/ctl(pid) )的socket,基于这个socket的事件被加入了scheduler的链表里
调用 tapdisk_server_complete(*type),会把server.aio_queue给创建出来
调用 tapdisk2_prepare_device():
给控制设备/dev/xen/blktap-2/control发一个ioctl,code=BLKTAP2_IOCTL_ALLOC_TAP=200
创建字符设备/dev/xen/blktap-2/blktapX
创建块设备/dev/xen/blktap-2/tapdevX

tapdisk2_open_device(int type, const char *path, const char *name):
调用 tapdisk_vbd_initialize(-1, -1, TAPDISK2_VBD),初始化一个vbd,包括callback,ipc的fd,并初始化req链表,并把vbd加入到server的vbd链
tapdisk_vbd_initialize(int rfd, int wfd, uint16_t uuid):
调用tapdisk_server_get_vbd(uuid),根据uuid,找到对应的vbd结构
如果能找到,就不用初始化了,直接返回-EEXIST
如果找不到,就分配空间,td_vbd_t *vbd = calloc(1, sizeof(td_vbd_t))
记录一下ipc的一些fd,即:
vbd->uuid     = uuid;
vbd->ipc.rfd  = rfd;
vbd->ipc.wfd  = wfd;
vbd->ipc.uuid = uuid;
vbd->ring.fd  = -1;
//回调函数,用于往ring环里填写rsp请求
vbd->callback = tapdisk_vbd_callback;
//vbd->argument其实就是vbd本身
vbd->argument = vbd;
初始化vbd里的每一个request,总数为 BLKTAP_MAX_REQUESTS = BLK_RING_SIZE * 2 个,即:
for (i = 0; i < BLKTAP_MAX_REQUESTS; i++) tapdisk_vbd_initialize_vreq(vbd->request_list + i);
加入到server的vbd链表里,即tapdisk_server_add_vbd(vbd);
       
调用 tapdisk_vbd_parse_stack(vbd, name);  其实是基于路径里的conf填写一个VBD,再把name作为参数,构造一个driver,加入到vbd的driver_stack链表里
调用 tapdisk_vbd_open(vbd, path, type, TAPDISK_STORAGE_TYPE_DEFAULT, devname, 0)
函数功能是打开并初始化好一个vbd,使他能够正常使用
基于vbd的driver链,初始化vbd的image链
初始化每一个image,具体会调用到td_open,进入VHD的初始化工作流程
对blktapX做内存映射到vbd的ring结构,作为io环
其中,环的大小在tapdisk_vbd_map_device有指定,默认为BLKTAP_MMAP_REGION_SIZE页,如果blktap能够识别BLKTAP2_IOCTL_GET_MMAP_PAGES指令,则采用blktap返回的环大小
BLKTAP_MMAP_REGION_SIZE = BLKTAP_RING_PAGES + MMAP_PAGES
其中,BLKTAP_RING_PAGES  = 1
MMAP_PAGES = MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST
MAX_PENDING_REQS = BLK_RING_SIZE = 32
BLKIF_MAX_SEGMENTS_PER_REQUEST = 11 (blkif.h里指定)
把vbd的ring设备注册event

调用 tapdisk_vbd_get_image_info(vbd, &image),把vbd的第一个image的一些信息,size,secsize,info写入image这个变量
给ring驱动设备发ioctl,即ioctl(vbd->ring.fd, BLKTAP2_IOCTL_CREATE_DEVICE, &params);

tapdisk_vbd_open(td_vbd_t *vbd, const char *name, uint16_t type,  uint16_t storage, const char *ring, td_flag_t flags):
调用tapdisk_vbd_open_stack(vbd, storage, flags)。其实是不断重试,调用__tapdisk_vbd_open_vdi(vbd, 0)
__tapdisk_vbd_open_vdi(td_vbd_t *vbd, td_flag_t extra_flags):
会循环vbd里的每一个driver,任一driver命名driver_info,对其:
搞到file和type,即
file = driver_info->params;
type = driver_info->type;
调用images = tapdisk_vbd_open_level(vbd, file, type, parent_info, flags),处理这个driver的image链
tapdisk_vbd_open_level(td_vbd_t *vbd, char* params, int driver_type, td_disk_info_t *parent_info, td_flag_t flags):
这个函数只会做个死循环,直到找不到image,循环如下:
首先生成个image = tapdisk_image_allocate(name, type, vbd->storage, flags, vbd);
再生成driver = tapdisk_driver_allocate(image->type, image->name, image->flags, image->storage);
image->driver = driver;
image->info = driver->info;
试图寻找共享的image,即err = td_load(image);
如果找不到,就试图打开,即err = td_open(image):
其实是调用driver里的td_open函数,打开image,即err = driver->ops->td_open(driver, image->name, image->flags);
其实是调用storage-vhd.c的tap_disk tapdisk_vhd结构的td_open(_storage_vhd_open)
此时进入VHD的打开流程

获得父镜像,err = td_get_parent_id(image, &id);
加入到镜像链表里, list_add_tail(&image->next, images);

调用ist_splice(images, &vbd->images),把images加入到vbd的images链表里
拿到vbd的第一个image,写入parent_info,即:
tmp = tapdisk_vbd_first_image(vbd);
parent_info = &tmp->info;

如果有td_flag_test(vbd->flags, TD_OPEN_LOG_DIRTY),就读取相关的vbd,即:
err = tapdisk_vbd_add_dirty_log(vbd);
如果有td_flag_test(vbd->flags, TD_OPEN_ADD_CACHE),就读取相关的vbd,即:
err = tapdisk_vbd_add_block_cache(vbd);
调用tapdisk_vbd_validate_chain(vbd),检查下image链的正确性

tapdisk_server_complete(int type):
对于DISK_TYPE_STORAGE_VHD的类型,将调用tapdisk_init_queue(&server.aio_queue, TAPDISK_TIOCBS, TIO_DRV_STORAGE_IO, NULL)
其中:
TAPDISK_TIOCBS = TAPDISK_DATA_REQUESTS + 50 
TAPDISK_DATA_REQUESTS = MAX_REQUESTS * MAX_SEGMENTS_PER_REQ
MAX_REQUESTS = BLK_RING_SIZE = 32
MAX_SEGMENTS_PER_REQ = 11
所以,往下创建的aio_queue的queue->size为32 * 11 + 50 = 402
tapdisk_init_queue(struct tqueue *queue, int size, int drv, struct tfilter *filter):
调用tapdisk_queue_init_io(queue, drv),基于drv的类型(比如tdc的类型storage),把queue的tio以及tio_data结构初始化
tapdisk_queue_init_io(struct tqueue *queue, int drv):
根据这个queue要接入的后端类型,指定接口函数列表。
TIO_DRV_STORAGE_IO类型,tio = &td_tio_storage_io;
初始化queue的tio_data,即queue->tio_data = calloc(1, tio->data_size);
queue->tio = tio;
如果tio有tio->setup,则调用,即tio->tio_setup(queue, queue->size); 这里会把tio_data(实际为td_tio_storage_io结构)里面的几个io_events数组都初始化

把q里的iocb数组给初始化,分配好空间,queue->iocbs = calloc(size, sizeof(struct iocb *));
初始化q里面的opioctx用于对io的合并,opio_init(&queue->opioctx, size);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值