参考资料
【openstack相关】
http://lists.openstack.org/pipermail/openstack-dev/2015-January/054652.html
http://stackalytics.com/report/blueprint/nova/enabled-qemu-memballoon-stats
https://openstack.nimeyo.com/902/openstack-dev-libvirt-memory-ballooning-nova
【虚拟化相关】
http://smilejay.com/2012/11/use-ballooning-in-kvm/
http://libvirt.org/formatdomain.html#elementsMemoryAllocation
http://www.espenbraastad.no/post/memory-ballooning/
virsh相关命令
virsh domstats —balloon
visrh dommemstat
http://www.openstack.cn/?p=4540
http://niusmallnan.com/_build/html/_templates/openstack/libvirt_memory_usage.html
http://blog.csdn.net/tpiperatgod/article/details/46377555
注:这个命令获取的是guest内部的内存信息
使用virsh dommemstat通过balloon获取guest内存使用情况的函数update_balloon_stats,
他只是获取了SWAPIN,SWAPOUT,major pagefault,min pagefault,free内存,total内存统计,其中我们最关心的是free内存统计就是NR_FREE_PAGES,对我们指导意义不大,linux都是尽最大的努力的使用内存,其中很多是cache占用了,而NR_FREE_PAGES中不包括cache,这样我们以为虚拟机中的内存不多,其实可能比较多,其实我们比较关注的是memavailable对应的内存大小
MemAvailable: 20751532 kB
centos7内核搞了一个算法来评估memavailable,可以参考meminfo_proc_show函数实现
virsh setmem
【automatic ballooning】
http://www.linux-kvm.org/page/Projects/auto-ballooning
https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg571627.html
https://www.mail-archive.com/qemu-devel@nongnu.org/msg211168.html
【代码分析】
1. 前端代码
后端调整balloon size时是通过virtio config changed中断通知virtio-ballon设备,在virtio-balloon的config-change handle中会通worker读取virtio-pci的config空间,找到相应的size设置,然后决定做fill还是leak,最后把balloon的结果size写到config空间中
static void virtballoon_changed(struct virtio_device *vdev)
{
struct virtio_balloon *vb = vdev->priv;
wake_up(&vb->config_change);
}
static int balloon(void *_vballoon)
{
struct virtio_balloon *vb = _vballoon;
set_freezable();
while (!kthread_should_stop()) {
s64 diff;
try_to_freeze();
wait_event_interruptible(vb->config_change,
(diff = towards_target(vb)) != 0
|| vb->need_stats_update
|| kthread_should_stop()
|| freezing(current));
if (vb->need_stats_update)
stats_handle_request(vb);
if (diff > 0)
fill_balloon(vb, diff);
else if (diff < 0)
leak_balloon(vb, -diff);
update_balloon_size(vb);
}
return 0;
}
static void stats_request(struct virtqueue *vq)
{
struct virtio_balloon *vb = vq->vdev->priv;
vb->need_stats_update = 1;
wake_up(&vb->config_change);
}
这个是后端通知前端更新stats的处理函数。
2. 后端代码
从qemu的balloon_stats_set_poll_interval函数来看,它会设置一个stats_timer,
s->stats_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, balloon_stats_poll_cb, s);
每隔stats_poll_interval时间就会virtio_notify前端virtio-balloon设备update stats,前端最终会调用注册的callback stats_request,stats_request会设置need_stats_update,然后wakeup balloon内核线程,该内核线程回去更新stats。
并且后端还提供了一个qmp info balloon,该qmp最终会去读balloon stats