diff options
Diffstat (limited to 'drivers/hv/hv_balloon.c')
-rw-r--r-- | drivers/hv/hv_balloon.c | 135 |
1 files changed, 129 insertions, 6 deletions
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index 91e8a72eee14..fdf6decacf06 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -11,6 +11,7 @@ #include <linux/kernel.h> #include <linux/jiffies.h> #include <linux/mman.h> +#include <linux/debugfs.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/module.h> @@ -248,7 +249,7 @@ struct dm_capabilities_resp_msg { * num_committed: Committed memory in pages. * page_file_size: The accumulated size of all page files * in the system in pages. - * zero_free: The nunber of zero and free pages. + * zero_free: The number of zero and free pages. * page_file_writes: The writes to the page file in pages. * io_diff: An indicator of file cache efficiency or page file activity, * calculated as File Cache Page Fault Count - Page Read Count. @@ -567,6 +568,11 @@ struct hv_dynmem_device { __u32 version; struct page_reporting_dev_info pr_dev_info; + + /* + * Maximum number of pages that can be hot_add-ed + */ + __u64 max_dynamic_page_count; }; static struct hv_dynmem_device dm_device; @@ -1078,6 +1084,7 @@ static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg) pr_info("Max. dynamic memory size: %llu MB\n", (*max_page_count) >> (20 - HV_HYP_PAGE_SHIFT)); + dm->max_dynamic_page_count = *max_page_count; } break; @@ -1117,6 +1124,19 @@ static unsigned long compute_balloon_floor(void) } /* + * Compute total committed memory pages + */ + +static unsigned long get_pages_committed(struct hv_dynmem_device *dm) +{ + return vm_memory_committed() + + dm->num_pages_ballooned + + (dm->num_pages_added > dm->num_pages_onlined ? + dm->num_pages_added - dm->num_pages_onlined : 0) + + compute_balloon_floor(); +} + +/* * Post our status as it relates memory pressure to the * host. Host expects the guests to post this status * periodically at 1 second intervals. @@ -1157,11 +1177,7 @@ static void post_status(struct hv_dynmem_device *dm) * asking us to balloon them out. */ num_pages_avail = si_mem_available(); - num_pages_committed = vm_memory_committed() + - dm->num_pages_ballooned + - (dm->num_pages_added > dm->num_pages_onlined ? - dm->num_pages_added - dm->num_pages_onlined : 0) + - compute_balloon_floor(); + num_pages_committed = get_pages_committed(dm); trace_balloon_status(num_pages_avail, num_pages_committed, vm_memory_committed(), dm->num_pages_ballooned, @@ -1807,6 +1823,109 @@ out: return ret; } +/* + * DEBUGFS Interface + */ +#ifdef CONFIG_DEBUG_FS + +/** + * hv_balloon_debug_show - shows statistics of balloon operations. + * @f: pointer to the &struct seq_file. + * @offset: ignored. + * + * Provides the statistics that can be accessed in hv-balloon in the debugfs. + * + * Return: zero on success or an error code. + */ +static int hv_balloon_debug_show(struct seq_file *f, void *offset) +{ + struct hv_dynmem_device *dm = f->private; + char *sname; + + seq_printf(f, "%-22s: %u.%u\n", "host_version", + DYNMEM_MAJOR_VERSION(dm->version), + DYNMEM_MINOR_VERSION(dm->version)); + + seq_printf(f, "%-22s:", "capabilities"); + if (ballooning_enabled()) + seq_puts(f, " enabled"); + + if (hot_add_enabled()) + seq_puts(f, " hot_add"); + + seq_puts(f, "\n"); + + seq_printf(f, "%-22s: %u", "state", dm->state); + switch (dm->state) { + case DM_INITIALIZING: + sname = "Initializing"; + break; + case DM_INITIALIZED: + sname = "Initialized"; + break; + case DM_BALLOON_UP: + sname = "Balloon Up"; + break; + case DM_BALLOON_DOWN: + sname = "Balloon Down"; + break; + case DM_HOT_ADD: + sname = "Hot Add"; + break; + case DM_INIT_ERROR: + sname = "Error"; + break; + default: + sname = "Unknown"; + } + seq_printf(f, " (%s)\n", sname); + + /* HV Page Size */ + seq_printf(f, "%-22s: %ld\n", "page_size", HV_HYP_PAGE_SIZE); + + /* Pages added with hot_add */ + seq_printf(f, "%-22s: %u\n", "pages_added", dm->num_pages_added); + + /* pages that are "onlined"/used from pages_added */ + seq_printf(f, "%-22s: %u\n", "pages_onlined", dm->num_pages_onlined); + + /* pages we have given back to host */ + seq_printf(f, "%-22s: %u\n", "pages_ballooned", dm->num_pages_ballooned); + + seq_printf(f, "%-22s: %lu\n", "total_pages_committed", + get_pages_committed(dm)); + + seq_printf(f, "%-22s: %llu\n", "max_dynamic_page_count", + dm->max_dynamic_page_count); + + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(hv_balloon_debug); + +static void hv_balloon_debugfs_init(struct hv_dynmem_device *b) +{ + debugfs_create_file("hv-balloon", 0444, NULL, b, + &hv_balloon_debug_fops); +} + +static void hv_balloon_debugfs_exit(struct hv_dynmem_device *b) +{ + debugfs_remove(debugfs_lookup("hv-balloon", NULL)); +} + +#else + +static inline void hv_balloon_debugfs_init(struct hv_dynmem_device *b) +{ +} + +static inline void hv_balloon_debugfs_exit(struct hv_dynmem_device *b) +{ +} + +#endif /* CONFIG_DEBUG_FS */ + static int balloon_probe(struct hv_device *dev, const struct hv_vmbus_device_id *dev_id) { @@ -1854,6 +1973,8 @@ static int balloon_probe(struct hv_device *dev, goto probe_error; } + hv_balloon_debugfs_init(&dm_device); + return 0; probe_error: @@ -1879,6 +2000,8 @@ static int balloon_remove(struct hv_device *dev) if (dm->num_pages_ballooned != 0) pr_warn("Ballooned pages: %d\n", dm->num_pages_ballooned); + hv_balloon_debugfs_exit(dm); + cancel_work_sync(&dm->balloon_wrk.wrk); cancel_work_sync(&dm->ha_wrk.wrk); |