Libvirt的job机制1--Job机制简介

本文章针对libvirt job机制做了一些说明和介绍,后续会随着认识的不断增加,更新该内容!

Job机制简介

QEMU driver 使用三种job conditions: asynchronous, agent and normal.

Async job 条件变量(condition)用于长时间运行的jobs(eg:migration),通常包含多个monitor command,允许在这些jobs运行时调用有限的monitor command sets。 这允许客户端,例如,查询统计数据(query statistical),cancel job, change parameters of the jobs。

所有其他jobs都使用normal jobs condition 来获得对monitor的独占访问权,async job发出的每个monitor command也使用normal job condition。 当获取normal job condition时,job必须指定它将要采取的操作类型(action),如果async job 正在运行,则会根据允许的job set进行检查(这个job set是在获取condition的时候设定的)。 如果job与当前async job不兼容,则需要等待async job结束后再尝试获取。

当thread希望与qemu agent monitor进行通信时,需要使用agent job condition。 可以只获取agent job(qemuDomainObjBeginAgentJob),也可以只获取normal job(qemuDomainObjBeginJob),但不能同时获取。 持有agent job和normal job将允许无响应(unresponsive)或恶意(malicious)的代理阻塞正常的libvirt API,并可能导致拒绝服务。 要抓取(grab)哪种类型的job取决于caller是希望只与agent socket 通信,还是只希望与qemu monitor socket通信。

在获取virDomainObjPtr锁后,任何想要更新状态的方法(method)都必须获取异步(asynchronous)、正常(normal)或代理作业(agent job)。 当阻塞在这些条件变量时,会释放virDomainObjPtr锁(在获取条件变量时,会将VIRDomainObjPtr锁传进去,将条件变量加入队列之后,就会将这个锁释放掉)。一旦获取了job condition,方法(methods)就可以在遇到可能休眠/等待(sleep/wait)的代码段时安全地释放virDomainObjPtr锁,并在休眠/等待之后重新获取它。当一个async job 想要与monitor通信时,它需要获取nested job(一种特殊的普通作业)来获得对monitor的独占访问权。

由于virDomainObjPtr锁在等待job condition时被删除,因此当最终获得condition时,domain可能不再是active的。 只有在验证domain仍然处于active之后,才能安全地获取monitor lock.

获取条件变量函数

获取normal job condition

qemuDomainObjBeginJob()

  1. Waits until the job is compatible with current async job or no async job is running
  2. Waits for job.cond condition ‘job.active !=0’ using virDomainObjPtr mutexjob.active !=0,说明当前存在job,需要进行阻塞)
  3. Rechecks if the job is still compatible and repeats waiting if isn’t
  4. Set job.active to the job type

qemuDomainObjEndJob

  1. Sets job.active to 0
  2. Signals on job.cond condition

获取agent job condition

qemuDomainObjBeginAgentJob()

  1. Waits until there is no other agnet job set
  2. Sets job.agentActive to the job type

qemuDomainObjEndAgentJob()

  1. Sets job.agentActive to 0
  2. Signals on job,cond condition

获取asynchronous job condtion

qemuDomainObjBeginAsyncJob()

  1. Waits until no async job is running
  2. Waits for job.cond condtion ‘job.active != 0’ using virDomainObjPtr mutex
  3. Rechecks if any async job was started while waiting on job.cond and repeats waiting in that case.
  4. Set job.asyncJob to the asynchronous job type.

qemuDomainObjEndAsyncJob()

  1. Sets job.asyncJob to 0
  2. Broadcasts on job.asyncCond condition

获取QEMU monitor lock

qemuDomainObjEnterMonitor()

  1. Acquires the qemuMonitorObjPtr lock
  2. Releases the virDomainObjPtr lock

qemuDomainObjExitMonitor()

  1. Release the qemuMonitorObjPtr lock
  2. Acquires the virDomainObjPtr lock

使用示例

访问与virDomainObjPtr直接相关的东西

    virDomainObjPtr obj;
//在获取obj的时候,就已经加锁了
     obj = qemuDomObjFromDomain(dom);
     ...do work...
//在以上工作结束之后,解锁,以便其他线程对这个dom进行操作
     virDomainObjEndAPI(&obj);

这里应该只是查询virDomianObjPtr中的数据,并未更改这个结构体中的数据内容以及与qemu进行通信;

更新与virDomainObjPtr相关的东西

     virDomainObjPtr obj;
#1   obj = qemuDomObjFromDomain(dom);
#2	qemuDomainObjBeginJob(obj, QEMU_JOB_TYPE);

     ...do work...
#3	qemuDomainObjEndJob(obj);
#4	virDomainObjEndAPI(&obj);

#2#3获取和释放dom->privatedata.cond条件变量

这里的应用场景,最典型的是qemuDomainSuspend函数,调用的是:

qemuDomainObjBeginJob(driver, vm, QEMU_JOB_SUSPEND)

基于virDomainObjPtr调用monitor command

     virDomainObjPtr obj;
     qemuDomainObjPrivatePtr priv;
     obj = qemuDomObjFromDomain(dom);
     qemuDomainObjBeginJob(obj, QEMU_JOB_TYPE);
     ...do prep work...
     if (virDomainObjIsActive(vm)) {
         qemuDomainObjEnterMonitor(obj);
         qemuMonitorXXXX(priv->mon);
         qemuDomainObjExitMonitor(obj);
  }
     ...do final work...
     qemuDomainObjEndJob(obj);
         virDomainObjEndAPI(&obj);

基于virDomainObjPtr调用agent command

     virDomainObjPtr obj;
     qemuAgentPtr agent;
     obj = qemuDomObjFromDomain(dom);
     qemuDomainObjBeginAgentJob(obj, QEMU_AGENT_JOB_TYPE);
     ...do prep work...
     if (!qemuDomainAgentAvailable(obj, true))
         goto cleanup;
     agent = qemuDomainObjEnterAgent(obj);
     qemuAgentXXXX(agent, ..);
     qemuDomainObjExitAgent(obj, agent);
     ...do final work...
     qemuDomainObjEndAgentJob(obj);
     virDomainObjEndAPI(&obj);

异步job和嵌套job运行

     virDomainObjPtr obj;
     qemuDomainObjPrivatePtr priv;

     obj = qemuDomObjFromDomain(dom);
     qemuDomainObjBeginAsyncJob(obj, QEMU_ASYNC_JOB_TYPE);
     qemuDomainObjSetAsyncJobMask(obj, allowedJobs);
     ...do prep work...
     if (qemuDomainObjEnterMonitorAsync(driver, obj,                                       QEMU_ASYNC_JOB_TYPE) < 0) {

         /* domain died in the meantime */
         goto error;
     }
     ...start qemu job...
     qemuDomainObjExitMonitor(driver, obj);
     while (!finished) {
         if (qemuDomainObjEnterMonitorAsync(driver, obj,
                                            QEMU_ASYNC_JOB_TYPE) < 0) {
             /* domain died in the meantime */
             goto error;
         }
         ...monitor job progress...
         qemuDomainObjExitMonitor(driver, obj);
         virObjectUnlock(obj);
         sleep(aWhile);
         virObjectLock(obj);
     }

     ...do final work...
     qemuDomainObjEndAsyncJob(obj);
     virDomainObjEndAPI(&obj);

协调远程服务器进行迁移

     virDomainObjPtr obj;
     qemuDomainObjPrivatePtr priv;

     obj = qemuDomObjFromDomain(dom);

     qemuDomainObjBeginAsyncJob(obj, QEMU_ASYNC_JOB_TYPE);

     ...do prep work...


     if (virDomainObjIsActive(vm)) {
         qemuDomainObjEnterRemote(obj);
         ...communicate with remote...
         qemuDomainObjExitRemote(obj);
         /* domain may have been stopped while we were talking to remote */
         if (!virDomainObjIsActive(vm)) {
             qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                             _("guest unexpectedly quit"));
         }
     }

     ...do final work...

     qemuDomainObjEndAsyncJob(obj);
     virDomainObjEndAPI(&obj);

这里只是对libvirt中的job机制进行初步的说明,并未进行详细的讲解其原理,后续文档会针对内部原理进行讲解

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值