in vboxguest/vboxguest_core.c [351:410]
static void vbg_balloon_work(struct work_struct *work)
{
struct vbg_dev *gdev =
container_of(work, struct vbg_dev, mem_balloon.work);
struct vmmdev_memballoon_info *req = gdev->mem_balloon.get_req;
u32 i, chunks;
int rc, ret;
/*
* Setting this bit means that we request the value from the host and
* change the guest memory balloon according to the returned value.
*/
req->event_ack = VMMDEV_EVENT_BALLOON_CHANGE_REQUEST;
rc = vbg_req_perform(gdev, req);
if (rc < 0) {
vbg_err("%s error, rc: %d)\n", __func__, rc);
return;
}
/*
* The host always returns the same maximum amount of chunks, so
* we do this once.
*/
if (!gdev->mem_balloon.max_chunks) {
gdev->mem_balloon.pages =
devm_kcalloc(gdev->dev, req->phys_mem_chunks,
sizeof(struct page **), GFP_KERNEL);
if (!gdev->mem_balloon.pages)
return;
gdev->mem_balloon.max_chunks = req->phys_mem_chunks;
}
chunks = req->balloon_chunks;
if (chunks > gdev->mem_balloon.max_chunks) {
vbg_err("%s: illegal balloon size %u (max=%u)\n",
__func__, chunks, gdev->mem_balloon.max_chunks);
return;
}
if (chunks > gdev->mem_balloon.chunks) {
/* inflate */
for (i = gdev->mem_balloon.chunks; i < chunks; i++) {
ret = vbg_balloon_inflate(gdev, i);
if (ret < 0)
return;
gdev->mem_balloon.chunks++;
}
} else {
/* deflate */
for (i = gdev->mem_balloon.chunks; i-- > chunks;) {
ret = vbg_balloon_deflate(gdev, i);
if (ret < 0)
return;
gdev->mem_balloon.chunks--;
}
}
}