From ed8be7b855521865b2fdaf0766be5101d0ed648f Mon Sep 17 00:00:00 2001 From: Prakash Gupta Date: Thu, 12 Nov 2020 17:00:44 +0530 Subject: [PATCH] proc/meminfo: update offline region in Memtotal When memory block is logically offlined, it is still part of System RAM but is inactive, and can be made active or Onlined anytime. Take totalram snapshot to include offlined memory in Memtotal. This method avoids taking device_hotplug lock to meminfo. Fixes: dc00b6d99a46 ("proc/meminfo: include offlined region for mem total") Change-Id: I2b69444e6f066e1c1928278707616840308b00d0 Signed-off-by: Prakash Gupta --- drivers/soc/qcom/mem-offline.c | 26 ++++++++++++++++++++++++++ fs/proc/meminfo.c | 6 +++++- include/linux/memory.h | 4 ++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/mem-offline.c b/drivers/soc/qcom/mem-offline.c index fa5a912149b7..2964948a8a1a 100644 --- a/drivers/soc/qcom/mem-offline.c +++ b/drivers/soc/qcom/mem-offline.c @@ -46,6 +46,7 @@ static atomic_t target_migrate_pages = ATOMIC_INIT(0); static u32 offline_granule; static bool is_rpm_controller; static bool has_pend_offline_req; +static atomic_long_t totalram_pages_with_offline = ATOMIC_INIT(0); #define MODULE_CLASS_NAME "mem-offline" #define MIGRATE_TIMEOUT_SEC (20) @@ -101,6 +102,29 @@ static void fill_movable_zone_fn(struct work_struct *work); static DECLARE_WORK(fill_movable_zone_work, fill_movable_zone_fn); static DEFINE_MUTEX(page_migrate_lock); +unsigned long get_totalram_pages_count_inc_offlined(void) +{ + struct sysinfo i; + unsigned long totalram_with_offline; + + si_meminfo(&i); + totalram_with_offline = + (unsigned long)atomic_long_read(&totalram_pages_with_offline); + + if (i.totalram < totalram_with_offline) + i.totalram = totalram_with_offline; + + return i.totalram; +} + +static void update_totalram_snapshot(void) +{ + unsigned long totalram_with_offline; + + totalram_with_offline = get_totalram_pages_count_inc_offlined(); + atomic_long_set(&totalram_pages_with_offline, totalram_with_offline); +} + static void clear_pgtable_mapping(phys_addr_t start, phys_addr_t end) { unsigned long size = end - start; @@ -673,6 +697,7 @@ static int mem_event_callback(struct notifier_block *self, break; case MEM_ONLINE: + update_totalram_snapshot(); delay = ktime_ms_delta(ktime_get(), cur); record_stat(sec_nr, delay, MEMORY_ONLINE); cur = 0; @@ -680,6 +705,7 @@ static int mem_event_callback(struct notifier_block *self, (void *)sec_nr); break; case MEM_GOING_OFFLINE: + update_totalram_snapshot(); pr_debug("mem-offline: MEM_GOING_OFFLINE : start = 0x%llx end = 0x%llx\n", start_addr, end_addr); ++mem_info[(sec_nr - start_section_nr + MEMORY_OFFLINE * diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c index 0b10af0be77f..c69d9153f0e1 100644 --- a/fs/proc/meminfo.c +++ b/fs/proc/meminfo.c @@ -78,7 +78,11 @@ static int meminfo_proc_show(struct seq_file *m, void *v) pages[lru] = global_node_page_state(NR_LRU_BASE + lru); available = si_mem_available(); - i.totalram += get_offlined_pages_count(); + +#ifdef CONFIG_QCOM_MEM_OFFLINE + i.totalram = get_totalram_pages_count_inc_offlined(); +#endif + sreclaimable = global_node_page_state(NR_SLAB_RECLAIMABLE); sunreclaim = global_node_page_state(NR_SLAB_UNRECLAIMABLE); diff --git a/include/linux/memory.h b/include/linux/memory.h index ebda8bf060a4..cdedbd7bfef2 100644 --- a/include/linux/memory.h +++ b/include/linux/memory.h @@ -39,6 +39,10 @@ int arch_get_memory_phys_device(unsigned long start_pfn); unsigned long memory_block_size_bytes(void); int set_memory_block_size_order(unsigned int order); +#ifdef CONFIG_QCOM_MEM_OFFLINE +unsigned long get_totalram_pages_count_inc_offlined(void); +#endif + /* These states are exposed to userspace as text strings in sysfs */ #define MEM_ONLINE (1<<0) /* exposed to userspace */ #define MEM_GOING_OFFLINE (1<<1) /* exposed to userspace */