๏ปฟ# Virtio Balloon
๊ด๋ จ ์์ค:mm/balloon.c,drivers/virtio/virtio_balloon.c,include/linux/balloon.h,include/uapi/linux/virtio_balloon.h
๊ฐ์ (Overview)
Virtio Balloon์ ๊ฐ์๋จธ์ ์์ ํธ์คํธ(ํ์ดํผ๋ฐ์ด์ )์ ๊ฒ์คํธ ๊ฐ์ ๋์ ์ผ๋ก ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ๋ฉ์ปค๋์ฆ์ ๋๋ค. ๊ฒ์คํธ OS๋ "balloon"์ inflateํ์ฌ ์ฌ์ฉ ์ค์ธ ํ์ด์ง๋ฅผ ํธ์คํธ์๊ฒ ๋ฐํํ๊ณ , deflateํ์ฌ ํธ์คํธ๋ก๋ถํฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ค์ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ์ฌ๋ฌ ๊ฐ์๋จธ์ ๊ฐ ๋ฉ๋ชจ๋ฆฌ ์ค๋ฒ์ปค๋ฐ์ด ๊ฐ๋ฅํด์ง๋๋ค.
์ปค๋์ mm/balloon.c์ ๊ณต์ฉ ์ธํฐํ์ด์ค๋ฅผ, drivers/virtio/virtio_balloon.c์ Virtio ๋๋ผ์ด๋ฒ ๊ตฌํ์ ์ ๊ณตํฉ๋๋ค. ๊ณต์ฉ ์ธํฐํ์ด์ค๋ ํ์ด์ง ํ ๋น, enqueue/dequeue, ๋ง์ด๊ทธ๋ ์ด์
์ ๋ด๋นํ๋ฉฐ, ๋๋ผ์ด๋ฒ ์ธก์ virtqueue๋ฅผ ํตํด ํธ์คํธ์ ํต์ ํฉ๋๋ค. Linux 7.0์์๋ Free Page Hint, Free Page Reporting, OOM ์ ์๋ deflate ๋ฑ ๋ค์ํ ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋์ด ์์ต๋๋ค.
์์ค ํ์ผ ๊ฒฝ๋ก
mm/balloon.c โ ๊ณต์ฉ balloon ์ธํฐํ์ด์ค
drivers/virtio/virtio_balloon.c โ Virtio balloon ๋๋ผ์ด๋ฒ
include/linux/balloon.h โ balloon_dev_info ์ ์
include/uapi/linux/virtio_balloon.h โ feature ํ๋๊ทธ, ํต๊ณ ์ ์
๋น ๋ฅธ ์ ๊ฒ ๋ช ๋ น
# balloon ํ์ด์ง ์ ํ์ธ
cat /proc/ballooninfo
# Virtio balloon ๋ชจ๋ ์ํ ํ์ธ
lsmod | grep virtio_balloon
# virtio ๋๋ฐ์ด์ค ์ ๋ณด ํ์ธ
ls /sys/class/misc/balloon*
# ๊ฒ์คํธ ๋ฉ๋ชจ๋ฆฌ ํต๊ณ (balloon ํต๊ณ)
dmesg | grep -i balloon
# Free Page Reporting ์ํ ํ์ธ
cat /sys/kernel/mm/page_reporting/reporting
# OOM ์๋ฆผ ์ค์ ํ์ธ (deflate_on_oom)
dmesg | grep "deflate on oom"
# ๋ฉ๋ชจ๋ฆฌ ์๋ ฅ ํ์ธ (balloon inflate/deflate ํธ๋ฆฌ๊ฑฐ)
grep -i balloon /proc/vmstat
# balloon ๋ง์ด๊ทธ๋ ์ด์
ํ์ฑํ ํ์ธ
grep BALLOON /proc/vmstat
# virtio ๋๋ฐ์ด์ค ๋๋ผ์ด๋ฒ ์ ๋ณด
lspci -v | grep -i virtio
# ๊ฒ์คํธ์์ ํธ์คํธ ํต์ ์ํ (virtqueue)
dmesg | grep "virtio.*balloon"
ํต์ฌ ์๋ฃ๊ตฌ์กฐ
struct balloon_dev_info
include/linux/balloon.h:53 โ ๋ชจ๋ balloon ๋๋ฐ์ด์ค์ ๊ณต์ฉ ํ์ด์ง ๊ด๋ฆฌ ๊ตฌ์กฐ์ฒด
struct balloon_dev_info {
unsigned long isolated_pages; /* ๋ง์ด๊ทธ๋ ์ด์
์ ์ํด ๊ฒฉ๋ฆฌ๋ ํ์ด์ง ์ */
struct list_head pages; /* ํธ์คํธ์๊ฒ ํ ๋น๋ ํ์ด์ง ๋ชฉ๋ก (LRU) */
int (*migratepage)(struct balloon_dev_info *, struct page *newpage,
struct page *page, enum migrate_mode mode); /* ํ์ด์ง ๋ง์ด๊ทธ๋ ์ด์
์ฝ๋ฐฑ */
bool adjust_managed_page_count; /* managed_page_count ์กฐ์ ์ฌ๋ถ */
};
isolated_pages: Compaction ์ค๋ ๋๊ฐ ๋ง์ด๊ทธ๋ ์ด์
์ ์ํด ๊ฒฉ๋ฆฌํ balloon ํ์ด์ง ์pages: balloon_page_insert()๋ก ์ถ๊ฐ๋๋ ํ์ด์ง๋ค์ ์ฐ๊ฒฐ ๋ฆฌ์คํธmigratepage: ๋๋ผ์ด๋ฒ๋ณ ๋ง์ด๊ทธ๋ ์ด์
์ฝ๋ฐฑ (virtio๋ virtballoon_migratepage)adjust_managed_page_count: OOM deflate ์ adjust_managed_page_count ํ๋๊ทธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ์นด์ดํฐ๋ฅผ ์กฐ์ struct virtio_balloon
drivers/virtio/virtio_balloon.c:55 โ Virtio balloon ๋๋ผ์ด๋ฒ์ ํต์ฌ ๊ตฌ์กฐ์ฒด
struct virtio_balloon {
struct virtio_device *vdev;
struct virtqueue *inflate_vq, *deflate_vq, *stats_vq, *free_page_vq;
struct workqueue_struct *balloon_wq; /* Free Page Hint ์ ์ฉ ์ํฌํ */
struct work_struct report_free_page_work; /* Free Page Reporting ์์
*/
struct work_struct update_balloon_stats_work; /* ํต๊ณ ์
๋ฐ์ดํธ ์์
*/
struct work_struct update_balloon_size_work; /* ํฌ๊ธฐ ์กฐ์ ์์
*/
spinlock_t stop_update_lock;
bool stop_update;
unsigned long config_read_bitmap;
struct list_head free_page_list; /* Free Page Hint์ฉ ํ ๋น๋ ํ์ด์ง ๋ชฉ๋ก */
spinlock_t free_page_list_lock;
unsigned long num_free_page_blocks; /* free_page_list์ ๋ธ๋ก ์ */
u32 cmd_id_received_cache; /* ํธ์คํธ๋ก๋ถํฐ ๋ฐ์ cmd_id ์บ์ */
__virtio32 cmd_id_active; /* ํ์ฌ ํ์ฑํ๋ cmd_id */
__virtio32 cmd_id_stop; /* ์ ์ง ์ ํธ cmd_id */
wait_queue_head_t acked; /* ํธ์คํธ ack ๋๊ธฐ ํ */
unsigned int num_pages; /* ํ์ฌ balloon์ ์๋ ํ์ด์ง ์ */
struct balloon_dev_info vb_dev_info; /* ๊ณต์ฉ balloon ๋๋ฐ์ด์ค ์ ๋ณด */
struct mutex balloon_lock; /* inflate/deflate ๋๊ธฐํ ๋ฎคํ
์ค */
unsigned int num_pfns; /* ํธ์คํธ์ ์๋ ค์ค PFN ๋ฐฐ์ด ๊ธธ์ด */
__virtio32 pfns[VIRTIO_BALLOON_ARRAY_PFNS_MAX]; /* PFN ๋ฐฐ์ด (์ต๋ 256๊ฐ) */
struct virtio_balloon_stat stats[VIRTIO_BALLOON_S_NR]; /* ๋ฉ๋ชจ๋ฆฌ ํต๊ณ */
struct shrinker *shrinker; /* Free Page Hint์ฉ shrinker */
struct notifier_block oom_nb; /* OOM ์๋ฆผ ๋ธ๋ก */
struct virtqueue *reporting_vq; /* Free Page Reporting virtqueue */
struct page_reporting_dev_info pr_dev_info; /* page reporting ๋๋ฐ์ด์ค ์ ๋ณด */
spinlock_t wakeup_lock;
bool processing_wakeup_event;
u32 wakeup_signal_mask;
};
virtio_balloon_config (ํธ์คํธ โ ๊ฒ์คํธ ๊ณต์ )
include/uapi/linux/virtio_balloon.h:46 โ ํธ์คํธ์ ๊ฒ์คํธ๊ฐ ๊ณต์ ํ๋ ์ค์ ๊ตฌ์กฐ์ฒด
struct virtio_balloon_config {
__le32 num_pages; /* ํธ์คํธ๊ฐ ๊ฒ์คํธ์๊ฒ ๋ฐํ์ ์์ฒญํ ํ์ด์ง ์ */
__le32 actual; /* ๊ฒ์คํธ๊ฐ ์ค์ ๋ก balloon์ ๋ฃ์ ํ์ด์ง ์ */
union {
__le32 free_page_hint_cmd_id; /* Free Page Hint ๋ช
๋ น ID */
__le32 free_page_report_cmd_id; /* deprecated ๋ณ์นญ */
};
__le32 poison_val; /* PAGE_POISON ๊ฐ */
};
virtio_balloon_stat (๋ฉ๋ชจ๋ฆฌ ํต๊ณ)
include/uapi/linux/virtio_balloon.h:126 โ ํธ์คํธ์๊ฒ ์ ์ก๋๋ ๋ฉ๋ชจ๋ฆฌ ํต๊ณ ๊ตฌ์กฐ์ฒด
struct virtio_balloon_stat {
__virtio16 tag; /* ํต๊ณ ํ์
(VIRTIO_BALLOON_S_* ์์) */
__virtio64 val; /* ํต๊ณ ๊ฐ */
} __attribute__((packed));
virtio_balloon_feature ํ๋๊ทธ
include/uapi/linux/virtio_balloon.h:34 โ ์ง์ ๊ธฐ๋ฅ ๋นํธ๋งต
#define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* ํ์ด์ง ๋ฐํ ์ ํธ์คํธ์๊ฒ ์๋ฆผ ํ์ */
#define VIRTIO_BALLOON_F_STATS_VQ 1 /* ๋ฉ๋ชจ๋ฆฌ ํต๊ณ virtqueue ์ง์ */
#define VIRTIO_BALLOON_F_DEFLATE_ON_OOM 2 /* OOM ๋ฐ์ ์ ์๋ balloon ํด์ */
#define VIRTIO_BALLOON_F_FREE_PAGE_HINT 3 /* Free Page Hint virtqueue ์ง์ */
#define VIRTIO_BALLOON_F_PAGE_POISON 4 /* ํ์ด์ง ํฌ์ด์ฆ๋ ์ฌ์ฉ */
#define VIRTIO_BALLOON_F_REPORTING 5 /* Free Page Reporting virtqueue ์ง์ */
ํต์ฌ ํจ์
1. balloon_page_alloc
mm/balloon.c:147 โ balloon์ ์ฌ์ฉํ ์ ํ์ด์ง๋ฅผ ํ ๋น
struct page *balloon_page_alloc(void)
{
gfp_t gfp_flags = __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN;
if (IS_ENABLED(CONFIG_BALLOON_MIGRATION))
gfp_flags |= GFP_HIGHUSER_MOVABLE; /* ๋ง์ด๊ทธ๋ ์ด์
๊ฐ๋ฅํ ๊ณ ์ ์ฌ์ฉ์ ์์ญ */
else
gfp_flags |= GFP_HIGHUSER; /* ์ผ๋ฐ ๊ณ ์ ์ฌ์ฉ์ ์์ญ */
return alloc_page(gfp_flags);
}
CONFIG_BALLOON_MIGRATION์ด ํ์ฑํ๋๋ฉด GFP_HIGHUSER_MOVABLE๋ฅผ ์ฌ์ฉํ์ฌ ํ์ด์ง ๋ง์ด๊ทธ๋ ์ด์
๊ฐ๋ฅ2. balloon_page_list_enqueue
mm/balloon.c:75 โ ํ์ด์ง ๋ชฉ๋ก์ balloon์ ์ถ๊ฐ
size_t balloon_page_list_enqueue(struct balloon_dev_info *b_dev_info,
struct list_head *pages)
{
struct page *page, *tmp;
unsigned long flags;
size_t n_pages = 0;
spin_lock_irqsave(&balloon_pages_lock, flags);
list_for_each_entry_safe(page, tmp, pages, lru) {
list_del(&page->lru);
balloon_page_enqueue_one(b_dev_info, page); /* ํ์ด์ง ์ฝ์
+ ์นด์ดํฐ ์ฆ๊ฐ */
n_pages++;
}
spin_unlock_irqrestore(&balloon_pages_lock, flags);
return n_pages;
}
balloon_dev_info->pages ๋ชฉ๋ก์ ์ถ๊ฐballoon_page_enqueue_one์์ adjust_managed_page_count ํ๋๊ทธ์ ๋ฐ๋ผ managed page count๋ฅผ ์กฐ์ ํ๊ณ , NR_BALLOON_PAGES ๋
ธ๋ ์ํ๋ฅผ ์ฆ๊ฐ์ํด3. balloon_page_list_dequeue
mm/balloon.c:111 โ balloon์์ ํ์ด์ง๋ฅผ ์ ๊ฑฐํ์ฌ ๋ฐํ
size_t balloon_page_list_dequeue(struct balloon_dev_info *b_dev_info,
struct list_head *pages, size_t n_req_pages)
{
struct page *page, *tmp;
unsigned long flags;
size_t n_pages = 0;
spin_lock_irqsave(&balloon_pages_lock, flags);
list_for_each_entry_safe(page, tmp, &b_dev_info->pages, lru) {
if (n_pages == n_req_pages)
break;
list_del(&page->lru);
if (b_dev_info->adjust_managed_page_count)
adjust_managed_page_count(page, 1); /* managed count ๋ณต์ */
balloon_page_finalize(page); /* ํ์ด์ง ์ ๋ฆฌ */
__count_vm_event(BALLOON_DEFLATE);
list_add(&page->lru, pages);
dec_node_page_state(page, NR_BALLOON_PAGES);
n_pages++;
}
spin_unlock_irqrestore(&balloon_pages_lock, flags);
return n_pages;
}
4. fill_balloon (virtio)
drivers/virtio/virtio_balloon.c:242 โ ํธ์คํธ์๊ฒ inflate ์์ฒญ (๊ฒ์คํธ โ ํธ์คํธ)
static unsigned int fill_balloon(struct virtio_balloon *vb, size_t num)
{
unsigned int num_allocated_pages;
struct page *page, *next;
unsigned int num_pfns;
LIST_HEAD(pages);
num = min(num, ARRAY_SIZE(vb->pfns)); /* ํ ๋ฒ์ ์ต๋ 256๊ฐ */
for (num_pfns = 0; num_pfns < num;
num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
page = balloon_page_alloc();
if (!page) {
msleep(200); /* ํ ๋น ์คํจ ์ 200ms ๋๊ธฐ ํ ์ฌ์๋ */
break;
}
list_add(&page->lru, &pages);
}
mutex_lock(&vb->balloon_lock);
vb->num_pfns = 0;
list_for_each_entry_safe(page, next, &pages, lru) {
list_del(&page->lru);
balloon_page_enqueue(&vb->vb_dev_info, page); /* balloon ๋ชฉ๋ก์ ์ถ๊ฐ */
set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE;
}
num_allocated_pages = vb->num_pfns;
if (vb->num_pfns != 0)
tell_host(vb, vb->inflate_vq); /* ํธ์คํธ์๊ฒ PFN ๋ชฉ๋ก ์ ์ก */
mutex_unlock(&vb->balloon_lock);
return num_allocated_pages;
}
balloon_lock ๋ฎคํ
์ค๋ก ๋์์ฑ ๋ณดํธ5. leak_balloon (virtio)
drivers/virtio/virtio_balloon.c:301 โ ํธ์คํธ์์ deflate ์์ฒญ (ํธ์คํธ โ ๊ฒ์คํธ)
static unsigned int leak_balloon(struct virtio_balloon *vb, size_t num)
{
unsigned int num_freed_pages;
struct page *page;
struct balloon_dev_info *vb_dev_info = &vb->vb_dev_info;
LIST_HEAD(pages);
num = min(num, ARRAY_SIZE(vb->pfns));
mutex_lock(&vb->balloon_lock);
num = min(num, (size_t)vb->num_pages); /* ํ์ฌ balloon ํ์ด์ง ์ ์ ํ */
for (vb->num_pfns = 0; vb->num_pfns < num;
vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
page = balloon_page_dequeue(vb_dev_info);
if (!page)
break;
set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
list_add(&page->lru, &pages);
vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE;
}
num_freed_pages = vb->num_pfns;
if (vb->num_pfns != 0)
tell_host(vb, vb->deflate_vq); /* ํธ์คํธ์๊ฒ ํด์ ์๋ฆผ */
release_pages_balloon(vb, &pages); /* ํ์ด์ง ํด์ (put_page) */
mutex_unlock(&vb->balloon_lock);
return num_freed_pages;
}
MUST_TELL_HOST ๊ธฐ๋ฅ์ด ์์ผ๋ฉด ๋ฐ๋์ virtqueue๋ฅผ ํตํด ํธ์คํธ์๊ฒ ๋จผ์ ์๋ ค์ผ ํจํธ์ถ ํ๋ฆ
Inflate ํ๋ฆ (๊ฒ์คํธ โ ํธ์คํธ ๋ฉ๋ชจ๋ฆฌ ๋ฐํ)
virtballoon_changed
โโ start_update_balloon_size
โโ queue_work(update_balloon_size_work)
โโ update_balloon_size_func
โโ towards_target (์ฐจ์ด ๊ณ์ฐ)
โโ fill_balloon (diff > 0)
โโ balloon_page_alloc (GFP_HIGHUSER_MOVABLE)
โโ balloon_page_enqueue โ balloon_page_insert
โ โโ __SetPageOffline
โ โโ SetPageMovableOps (CONFIG_BALLOON_MIGRATION)
โ โโ list_add(&page->lru, &balloon->pages)
โโ set_page_pfns (PFN ๋ณํ: page โ balloon PFN)
โโ tell_host โ virtqueue_add_outbuf โ virtqueue_kick
โโ wait_event(vb->acked, virtqueue_get_buf)
Deflate ํ๋ฆ (ํธ์คํธ โ ๊ฒ์คํธ ๋ฉ๋ชจ๋ฆฌ ๋ฐํ)
update_balloon_size_func
โโ towards_target (์ฐจ์ด ๊ณ์ฐ)
โโ leak_balloon (diff < 0)
โโ balloon_page_dequeue โ balloon_page_list_dequeue
โ โโ list_del(&page->lru)
โ โโ adjust_managed_page_count (์นด์ดํฐ ๋ณต์)
โ โโ balloon_page_finalize โ set_page_private(0)
โโ set_page_pfns
โโ tell_host โ deflate_vq
โโ release_pages_balloon โ put_page (์ค์ ํด์ )
Free Page Hint ํ๋ฆ (๋น ํ์ด์ง๋ฅผ ํธ์คํธ์๊ฒ ํํธ)
virtballoon_changed
โโ virtio_balloon_queue_free_page_work
โโ queue_work(report_free_page_work)
โโ report_free_page_func
โโ cmd_id_received == DONE?
โ โโ return_free_pages_to_mm (๋ชจ๋ free page ๋ฐํ)
โโ cmd_id_received != STOP && ๋ณ๊ฒฝ๋จ?
โโ virtio_balloon_report_free_page
โโ send_cmd_id_start (์์ ๋ช
๋ น ์ ์ก)
โโ send_free_pages
โ โโ loop: get_free_page_and_send
โ โโ alloc_pages (free page block ํ ๋น)
โ โโ virtqueue_add_inbuf (host์๊ฒ ์ ๋ฌ)
โ โโ list_add(free_page_list)
โโ send_cmd_id_stop (์ ์ง ๋ช
๋ น ์ ์ก)
OOM ์ deflate ํ๋ฆ
OOM ๋ฐ์
โโ virtio_balloon_oom_notify
โโ leak_balloon(vb, 256) /* ์ต๋ 256 ํ์ด์ง ํด์ */
โโ update_balloon_size (ํธ์คํธ์๊ฒ ์ ํฌ๊ธฐ ์๋ฆผ)
ํ์ด์ง ๋ง์ด๊ทธ๋ ์ด์ ํ๋ฆ (CONFIG_BALLOON_MIGRATION)
Compaction ์ค๋ ๋
โโ balloon_page_isolate (๊ฒฉ๋ฆฌ)
โโ balloon_page_device (page_private๋ก ๋๋ฐ์ด์ค ํ์ธ)
โโ list_del (๋ชฉ๋ก์์ ์ ๊ฑฐ)
โโ isolated_pages++
โโ balloon_page_migrate (๋ง์ด๊ทธ๋ ์ด์
)
โโ b_dev_info->migratepage โ virtballoon_migratepage
โ โโ mutex_trylock (๋ฝ ํ๋ ์คํจ ์ -EAGAIN)
โ โโ 1๋จ๊ณ: newpage inflate (tell_host via inflate_vq)
โ โโ 2๋จ๊ณ: old page deflate (tell_host via deflate_vq)
โโ balloon_page_insert (์ ํ์ด์ง๋ฅผ balloon ๋ชฉ๋ก์ ์ถ๊ฐ)
โโ balloon_page_finalize โ put_page (์ด์ ํ์ด์ง ํด์ )
์กฐ๊ฑด๋ณ ๋น๊ต
feature ํ๋๊ทธ๋ณ ๋์
| ํ๋๊ทธ | ๋นํธ | ๋์ | ๋๋ผ์ด๋ฒ์ ๋ฏธ์น๋ ์ํฅ |
|---|---|---|---|
| MUST_TELL_HOST | 0 | ํ์ด์ง ๋ฐํ ์ ํธ์คํธ์๊ฒ ๋ฐ๋์ ์๋ฆผ | deflate ์ virtqueue ํต์ ํ์ |
| STATS_VQ | 1 | ๋ฉ๋ชจ๋ฆฌ ํต๊ณ ์ ์ก virtqueue ์ง์ | stats_vq ์์ฑ, ํต๊ณ ์์ง ์ํฌํ |
| DEFLATE_ON_OOM | 2 | OOM ์ ์๋์ผ๋ก balloon ํด์ | oom_nb ๋ฑ๋ก, ์ต๋ 256 ํ์ด์ง ํด์ |
| FREE_PAGE_HINT | 3 | Free Page Hint virtqueue ์ง์ | free_page_vq, shrinker, ์ ์ฉ ์ํฌํ |
| PAGE_POISON | 4 | ํ์ด์ง ํฌ์ด์ฆ๋ ์ฌ์ฉ | poison_val์ ํธ์คํธ์๊ฒ ์ค์ |
| REPORTING | 5 | Free Page Reporting virtqueue ์ง์ | reporting_vq, page_reporting_dev_info |
inflate vs deflate ๋น๊ต
| ํญ๋ชฉ | fill_balloon (inflate) | leak_balloon (deflate) |
|---|---|---|
| ๋ฐฉํฅ | ๊ฒ์คํธ โ ํธ์คํธ (๋ฉ๋ชจ๋ฆฌ ๋ฐํ) | ํธ์คํธ โ ๊ฒ์คํธ (๋ฉ๋ชจ๋ฆฌ ๋ณต์) |
| ํ ๋น/ํด์ | `balloon_page_alloc` (ํ ๋น) | `balloon_page_dequeue` (ํด์ ) |
| virtqueue | `inflate_vq` | `deflate_vq` |
| ํ์ด์ง ์นด์ดํฐ | `num_pages` ์ฆ๊ฐ | `num_pages` ๊ฐ์ |
| managed count | `adjust_managed_page_count(page, -1)` | `adjust_managed_page_count(page, 1)` |
| VM ์ด๋ฒคํธ | `BALLOON_INFLATE` | `BALLOON_DEFLATE` |
| ๋ ธ๋ ์ํ | `NR_BALLOON_PAGES` ์ฆ๊ฐ | `NR_BALLOON_PAGES` ๊ฐ์ |
| ์คํจ ์ฒ๋ฆฌ | ํ ๋น ์คํจ ์ 200ms ๋๊ธฐ ํ ๋ถ๋ถ ์งํ | dequeue ์คํจ ์ BUG() (๋น์ ์ ์ํ) |
Free Page Hint vs Free Page Reporting ๋น๊ต
| ํญ๋ชฉ | Free Page Hint | Free Page Reporting |
|---|---|---|
| virtqueue | `free_page_vq` | `reporting_vq` |
| ํ ๋น ๋จ์ | `VIRTIO_BALLOON_HINT_BLOCK_ORDER` (MAX_PAGE_ORDER) | `page_reporting_dev_info.order` |
| ๋์ ๋ฐฉ์ | ๋ฅ๋์ ์ผ๋ก free page๋ฅผ ํ ๋นํ์ฌ ํธ์คํธ์๊ฒ ์ ๋ฌ | ํธ์คํธ๊ฐ ์์ฒญํ ํ์ด์ง๋ฅผ ์ง์ ๋ณด๊ณ |
| cmd_id | START โ STOP ๋ช ๋ น ๊ตํ | ๋ถํ์ |
| shrinker | `virtio_balloon_shrinker_scan/count` | ๋ถํ์ |
| ์ํฌํ | `balloon_wq` (์ ์ฉ) | `page_reporting_dev_info.report` ์ฝ๋ฐฑ |
ํ์ด์ง ๋ง์ด๊ทธ๋ ์ด์ ์ํ
| ์ํ | page ํ๋๊ทธ | page_private | isolation |
|---|---|---|---|
| ์ผ๋ฐ balloon ํ์ด์ง | `PageOffline=true`, `PageMovableOps=true` | balloon_dev_info ํฌ์ธํฐ | `isolated_pages=0` |
| ๊ฒฉ๋ฆฌ๋ ํ์ด์ง | ๋์ผ | ๋์ผ | `list_del` + `isolated_pages++` |
| ํด์ ๋ ํ์ด์ง | `PageOffline` ์ ์ง (sticky) | 0 (clear) | ์์ |