All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH V2] zram:calculate available memory when zram is used
@ 2021-06-05 16:24 yongw.pur
  2021-06-05 17:07 ` Greg KH
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: yongw.pur @ 2021-06-05 16:24 UTC (permalink / raw)
  To: minchan, ngupta, senozhatsky, axboe, akpm, songmuchun, david,
	linux-kernel, linux-block, linux-mm, willy, linux-api
  Cc: wangyong

From: wangyong <yongw.pur@gmail.com>

When zram is used, available+Swap free memory is obviously
bigger than we actually can use, because zram can compress
memory by compression algorithm and zram compressed data
will occupy memory too.

So, we can count the compression ratio of zram in the kernel.
The space will be saved by zram and other swap device are
calculated as follows:
zram[swapfree - swapfree * compress ratio] + swapdev[swapfree]
We can evaluate the available memory of the whole system as:
MemAvailable+zram[swapfree - swapfree * compress ratio]+swapdev[swapfree]

Add an entry to the /proc/meminfo file, returns swap will save space.
Which name is more appropriate is still under consideration.
There are several alternative names: SwapAvailable, SwapSaved,
SwapCompressible

Signed-off-by: wangyong <yongw.pur@gmail.com>
---
 drivers/block/zram/zcomp.h    |  1 +
 drivers/block/zram/zram_drv.c | 19 +++++++++
 drivers/block/zram/zram_drv.h |  1 +
 fs/proc/meminfo.c             |  1 +
 include/linux/swap.h          | 10 +++++
 mm/swapfile.c                 | 95 +++++++++++++++++++++++++++++++++++++++++++
 mm/vmscan.c                   |  1 +
 7 files changed, 128 insertions(+)

diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h
index 40f6420..deb2dbf 100644
--- a/drivers/block/zram/zcomp.h
+++ b/drivers/block/zram/zcomp.h
@@ -40,4 +40,5 @@ int zcomp_decompress(struct zcomp_strm *zstrm,
 		const void *src, unsigned int src_len, void *dst);
 
 bool zcomp_set_max_streams(struct zcomp *comp, int num_strm);
+int get_zram_major(void);
 #endif /* _ZCOMP_H_ */
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index fcaf275..8f527e0 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -59,6 +59,10 @@ static void zram_free_page(struct zram *zram, size_t index);
 static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
 				u32 index, int offset, struct bio *bio);
 
+int get_zram_major(void)
+{
+	return zram_major;
+}
 
 static int zram_slot_trylock(struct zram *zram, u32 index)
 {
@@ -1040,6 +1044,19 @@ static ssize_t compact_store(struct device *dev,
 	return len;
 }
 
+static ssize_t min_compr_ratio_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct zram *zram = dev_to_zram(dev);
+	ssize_t ret;
+
+	down_read(&zram->init_lock);
+	ret = scnprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&zram->stats.min_compr_ratio));
+	up_read(&zram->init_lock);
+
+	return ret;
+}
+
 static ssize_t io_stat_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -1132,6 +1149,7 @@ static ssize_t debug_stat_show(struct device *dev,
 	return ret;
 }
 
+static DEVICE_ATTR_RO(min_compr_ratio);
 static DEVICE_ATTR_RO(io_stat);
 static DEVICE_ATTR_RO(mm_stat);
 #ifdef CONFIG_ZRAM_WRITEBACK
@@ -1859,6 +1877,7 @@ static struct attribute *zram_disk_attrs[] = {
 	&dev_attr_idle.attr,
 	&dev_attr_max_comp_streams.attr,
 	&dev_attr_comp_algorithm.attr,
+	&dev_attr_min_compr_ratio.attr,
 #ifdef CONFIG_ZRAM_WRITEBACK
 	&dev_attr_backing_dev.attr,
 	&dev_attr_writeback.attr,
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index 80c3b43..5717e06 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -88,6 +88,7 @@ struct zram_stats {
 	atomic64_t bd_reads;		/* no. of reads from backing device */
 	atomic64_t bd_writes;		/* no. of writes from backing device */
 #endif
+	atomic_t min_compr_ratio;
 };
 
 struct zram {
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c
index 6fa761c..34a174b 100644
--- a/fs/proc/meminfo.c
+++ b/fs/proc/meminfo.c
@@ -86,6 +86,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
 
 	show_val_kb(m, "SwapTotal:      ", i.totalswap);
 	show_val_kb(m, "SwapFree:       ", i.freeswap);
+	show_val_kb(m, "SwapAvailable:	", count_avail_swaps());
 	show_val_kb(m, "Dirty:          ",
 		    global_node_page_state(NR_FILE_DIRTY));
 	show_val_kb(m, "Writeback:      ",
diff --git a/include/linux/swap.h b/include/linux/swap.h
index bb48893..798f09b 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -515,6 +515,8 @@ extern int init_swap_address_space(unsigned int type, unsigned long nr_pages);
 extern void exit_swap_address_space(unsigned int type);
 extern struct swap_info_struct *get_swap_device(swp_entry_t entry);
 sector_t swap_page_sector(struct page *page);
+extern void update_zram_zstats(void);
+extern u64 count_avail_swaps(void);
 
 static inline void put_swap_device(struct swap_info_struct *si)
 {
@@ -689,6 +691,14 @@ static inline swp_entry_t get_swap_page(struct page *page)
 	return entry;
 }
 
+void update_zram_zstats(void)
+{
+}
+
+u64 count_avail_swaps(void)
+{
+}
+
 #endif /* CONFIG_SWAP */
 
 #ifdef CONFIG_THP_SWAP
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 1e07d1c..fc934845 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -44,6 +44,7 @@
 #include <asm/tlbflush.h>
 #include <linux/swapops.h>
 #include <linux/swap_cgroup.h>
+#include "../drivers/block/zram/zram_drv.h"
 
 static bool swap_count_continued(struct swap_info_struct *, pgoff_t,
 				 unsigned char);
@@ -3387,6 +3388,100 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 	return error;
 }
 
+u64 count_avail_swap(struct swap_info_struct *si)
+{
+	u64 result;
+	struct zram *z;
+	unsigned int free;
+	unsigned int ratio;
+
+	result = 0;
+	if (!si)
+		return 0;
+
+	//zram calculate available mem
+	if (si->flags & SWP_USED && si->swap_map) {
+		if (si->bdev->bd_disk->major == get_zram_major()) {
+			z = (struct zram *)si->bdev->bd_disk->private_data;
+			down_read(&z->init_lock);
+			ratio = atomic_read(&z->stats.min_compr_ratio);
+			free = (si->pages << (PAGE_SHIFT - 10))
+				- (si->inuse_pages << (PAGE_SHIFT - 10));
+			if (!ratio)
+				result += free / 2;
+			else
+				result = free * (100 - 10000 / ratio) / 100;
+			up_read(&z->init_lock);
+		}
+	} else
+		result += (si->pages << (PAGE_SHIFT - 10))
+				- (si->inuse_pages << (PAGE_SHIFT - 10));
+
+	return result;
+}
+
+u64 count_avail_swaps(void)
+{
+	int type;
+	u64 result;
+	struct swap_info_struct *si;
+
+	result = 0;
+	spin_lock(&swap_lock);
+	for (type = 0; type < nr_swapfiles; type++) {
+		si = swap_info[type];
+		spin_lock(&si->lock);
+		result += count_avail_swap(si);
+		spin_unlock(&si->lock);
+	}
+	spin_unlock(&swap_lock);
+
+	return result;
+}
+
+void update_zram_zstat(struct swap_info_struct *si)
+{
+	struct zram *z;
+	struct zram_stats *stat;
+	int ratio;
+	u64 orig_size, compr_data_size;
+
+	if (!si)
+		return;
+
+	//update zram min compress ratio
+	if (si->flags & SWP_USED && si->swap_map) {
+		if (si->bdev->bd_disk->major == get_zram_major()) {
+			z = (struct zram *)si->bdev->bd_disk->private_data;
+			down_read(&z->init_lock);
+			stat = &z->stats;
+			ratio = atomic_read(&stat->min_compr_ratio);
+			orig_size = atomic64_read(&stat->pages_stored) << PAGE_SHIFT;
+			compr_data_size = atomic64_read(&stat->compr_data_size);
+			if (compr_data_size && (!ratio
+					    || ((orig_size * 100) / compr_data_size < ratio)))
+				atomic_set(&stat->min_compr_ratio,
+					   (orig_size * 100) / compr_data_size);
+			up_read(&z->init_lock);
+		}
+	}
+}
+
+void update_zram_zstats(void)
+{
+	int type;
+	struct swap_info_struct *si;
+
+	spin_lock(&swap_lock);
+	for (type = 0; type < nr_swapfiles; type++) {
+		si = swap_info[type];
+		spin_lock(&si->lock);
+		update_zram_zstat(si);
+		spin_unlock(&si->lock);
+	}
+	spin_unlock(&swap_lock);
+}
+
 void si_swapinfo(struct sysinfo *val)
 {
 	unsigned int type;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index eb31452..ffaf59b 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -4159,6 +4159,7 @@ static int kswapd(void *p)
 						alloc_order);
 		reclaim_order = balance_pgdat(pgdat, alloc_order,
 						highest_zoneidx);
+		update_zram_zstats();
 		if (reclaim_order < alloc_order)
 			goto kswapd_try_sleep;
 	}
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [RFC PATCH V2] zram:calculate available memory when zram is used
  2021-06-05 16:24 [RFC PATCH V2] zram:calculate available memory when zram is used yongw.pur
@ 2021-06-05 17:07 ` Greg KH
  2021-06-06 10:45   ` David Hildenbrand
  2021-06-05 22:17 ` kernel test robot
  2021-06-05 22:17 ` [RFC PATCH] zram: count_avail_swap() can be static kernel test robot
  2 siblings, 1 reply; 5+ messages in thread
From: Greg KH @ 2021-06-05 17:07 UTC (permalink / raw)
  To: yongw.pur
  Cc: minchan, ngupta, senozhatsky, axboe, akpm, songmuchun, david,
	linux-kernel, linux-block, linux-mm, willy, linux-api

On Sat, Jun 05, 2021 at 09:24:00AM -0700, yongw.pur@gmail.com wrote:
> From: wangyong <yongw.pur@gmail.com>
> 
> When zram is used, available+Swap free memory is obviously
> bigger than we actually can use, because zram can compress
> memory by compression algorithm and zram compressed data
> will occupy memory too.
> 
> So, we can count the compression ratio of zram in the kernel.
> The space will be saved by zram and other swap device are
> calculated as follows:
> zram[swapfree - swapfree * compress ratio] + swapdev[swapfree]
> We can evaluate the available memory of the whole system as:
> MemAvailable+zram[swapfree - swapfree * compress ratio]+swapdev[swapfree]
> 
> Add an entry to the /proc/meminfo file, returns swap will save space.
> Which name is more appropriate is still under consideration.
> There are several alternative names: SwapAvailable, SwapSaved,
> SwapCompressible
> 
> Signed-off-by: wangyong <yongw.pur@gmail.com>
> ---
>  drivers/block/zram/zcomp.h    |  1 +
>  drivers/block/zram/zram_drv.c | 19 +++++++++
>  drivers/block/zram/zram_drv.h |  1 +
>  fs/proc/meminfo.c             |  1 +
>  include/linux/swap.h          | 10 +++++
>  mm/swapfile.c                 | 95 +++++++++++++++++++++++++++++++++++++++++++
>  mm/vmscan.c                   |  1 +
>  7 files changed, 128 insertions(+)

You are adding a new sysfs file with no new Documentation/ABI entry.
Also are you sure you are allowed to add a new proc file entry without
breaking existing tools?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFC PATCH V2] zram:calculate available memory when zram is used
  2021-06-05 16:24 [RFC PATCH V2] zram:calculate available memory when zram is used yongw.pur
  2021-06-05 17:07 ` Greg KH
@ 2021-06-05 22:17 ` kernel test robot
  2021-06-05 22:17 ` [RFC PATCH] zram: count_avail_swap() can be static kernel test robot
  2 siblings, 0 replies; 5+ messages in thread
From: kernel test robot @ 2021-06-05 22:17 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 4312 bytes --]

Hi,

[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on block/for-next]
[also build test WARNING on linus/master v5.13-rc4]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/yongw-pur-gmail-com/zram-calculate-available-memory-when-zram-is-used/20210606-002716
base:   https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git for-next
config: i386-randconfig-s002-20210605 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.3-341-g8af24329-dirty
        # https://github.com/0day-ci/linux/commit/0c03fad8de27ba94fa9ac9731c45c32b3dac90a4
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review yongw-pur-gmail-com/zram-calculate-available-memory-when-zram-is-used/20210606-002716
        git checkout 0c03fad8de27ba94fa9ac9731c45c32b3dac90a4
        # save the attached .config to linux build tree
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
>> mm/swapfile.c:3396:5: sparse: sparse: symbol 'count_avail_swap' was not declared. Should it be static?
>> mm/swapfile.c:3447:6: sparse: sparse: symbol 'update_zram_zstat' was not declared. Should it be static?
   mm/swapfile.c:488:35: sparse: sparse: context imbalance in 'swap_do_scheduled_discard' - different lock contexts for basic block
   mm/swapfile.c:655:9: sparse: sparse: context imbalance in 'scan_swap_map_try_ssd_cluster' - different lock contexts for basic block
   mm/swapfile.c:945:20: sparse: sparse: context imbalance in 'scan_swap_map_slots' - unexpected unlock
   mm/swapfile.c:1028:23: sparse: sparse: context imbalance in 'swap_free_cluster' - different lock contexts for basic block
   mm/swapfile.c:1209:9: sparse: sparse: context imbalance in 'swap_info_get' - wrong count at exit
   mm/swapfile.c:1221:36: sparse: sparse: context imbalance in 'swap_info_get_cont' - unexpected unlock
   mm/swapfile.c:1303:25: sparse: sparse: context imbalance in 'get_swap_device' - different lock contexts for basic block
   mm/swapfile.c:384:9: sparse: sparse: context imbalance in '__swap_entry_free' - different lock contexts for basic block
   mm/swapfile.c:1358:23: sparse: sparse: context imbalance in 'swap_entry_free' - different lock contexts for basic block
   mm/swapfile.c:1415:34: sparse: sparse: context imbalance in 'put_swap_page' - different lock contexts for basic block
   mm/swapfile.c:1476:28: sparse: sparse: context imbalance in 'swapcache_free_entries' - unexpected unlock
   mm/swapfile.c:384:9: sparse: sparse: context imbalance in 'page_swapcount' - different lock contexts for basic block
   mm/swapfile.c: note: in included file (through include/linux/rbtree.h, include/linux/mm_types.h, include/linux/mmzone.h, ...):
   include/linux/rcupdate.h:709:9: sparse: sparse: context imbalance in '__swap_count' - unexpected unlock
   mm/swapfile.c:384:9: sparse: sparse: context imbalance in 'swap_swapcount' - different lock contexts for basic block
   include/linux/rcupdate.h:709:9: sparse: sparse: context imbalance in '__swp_swapcount' - unexpected unlock
   mm/swapfile.c:384:9: sparse: sparse: context imbalance in 'swp_swapcount' - different lock contexts for basic block
   mm/swapfile.c:384:9: sparse: sparse: context imbalance in 'swap_page_trans_huge_swapped' - different lock contexts for basic block
   mm/swapfile.c:1734:44: sparse: sparse: context imbalance in 'reuse_swap_page' - unexpected unlock
   include/linux/rcupdate.h:709:9: sparse: sparse: context imbalance in '__swap_duplicate' - unexpected unlock
   include/linux/rcupdate.h:709:9: sparse: sparse: context imbalance in 'add_swap_count_continuation' - unexpected unlock

Please review and possibly fold the followup patch.

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 43547 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [RFC PATCH] zram: count_avail_swap() can be static
  2021-06-05 16:24 [RFC PATCH V2] zram:calculate available memory when zram is used yongw.pur
  2021-06-05 17:07 ` Greg KH
  2021-06-05 22:17 ` kernel test robot
@ 2021-06-05 22:17 ` kernel test robot
  2 siblings, 0 replies; 5+ messages in thread
From: kernel test robot @ 2021-06-05 22:17 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 1017 bytes --]

mm/swapfile.c:3396:5: warning: symbol 'count_avail_swap' was not declared. Should it be static?
mm/swapfile.c:3447:6: warning: symbol 'update_zram_zstat' was not declared. Should it be static?

Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: kernel test robot <lkp@intel.com>
---
 swapfile.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mm/swapfile.c b/mm/swapfile.c
index 83074567cf830..7758f75ae20a2 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -3393,7 +3393,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 	return error;
 }
 
-u64 count_avail_swap(struct swap_info_struct *si)
+static u64 count_avail_swap(struct swap_info_struct *si)
 {
 	u64 result;
 	struct zram *z;
@@ -3444,7 +3444,7 @@ u64 count_avail_swaps(void)
 	return result;
 }
 
-void update_zram_zstat(struct swap_info_struct *si)
+static void update_zram_zstat(struct swap_info_struct *si)
 {
 	struct zram *z;
 	struct zram_stats *stat;

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [RFC PATCH V2] zram:calculate available memory when zram is used
  2021-06-05 17:07 ` Greg KH
@ 2021-06-06 10:45   ` David Hildenbrand
  0 siblings, 0 replies; 5+ messages in thread
From: David Hildenbrand @ 2021-06-06 10:45 UTC (permalink / raw)
  To: Greg KH, yongw.pur
  Cc: minchan, ngupta, senozhatsky, axboe, akpm, songmuchun,
	linux-kernel, linux-block, linux-mm, willy, linux-api

On 05.06.21 19:07, Greg KH wrote:
> On Sat, Jun 05, 2021 at 09:24:00AM -0700, yongw.pur@gmail.com wrote:
>> From: wangyong <yongw.pur@gmail.com>
>>
>> When zram is used, available+Swap free memory is obviously
>> bigger than we actually can use, because zram can compress
>> memory by compression algorithm and zram compressed data
>> will occupy memory too.
>>
>> So, we can count the compression ratio of zram in the kernel.
>> The space will be saved by zram and other swap device are
>> calculated as follows:
>> zram[swapfree - swapfree * compress ratio] + swapdev[swapfree]
>> We can evaluate the available memory of the whole system as:
>> MemAvailable+zram[swapfree - swapfree * compress ratio]+swapdev[swapfree]
>>
>> Add an entry to the /proc/meminfo file, returns swap will save space.
>> Which name is more appropriate is still under consideration.
>> There are several alternative names: SwapAvailable, SwapSaved,
>> SwapCompressible
>>
>> Signed-off-by: wangyong <yongw.pur@gmail.com>
>> ---
>>   drivers/block/zram/zcomp.h    |  1 +
>>   drivers/block/zram/zram_drv.c | 19 +++++++++
>>   drivers/block/zram/zram_drv.h |  1 +
>>   fs/proc/meminfo.c             |  1 +
>>   include/linux/swap.h          | 10 +++++
>>   mm/swapfile.c                 | 95 +++++++++++++++++++++++++++++++++++++++++++
>>   mm/vmscan.c                   |  1 +
>>   7 files changed, 128 insertions(+)
> 
> You are adding a new sysfs file with no new Documentation/ABI entry.

Indeed. And in the best case, the change would be accompanied with a man 
page update patch for the "proc" man page.

> Also are you sure you are allowed to add a new proc file entry without
> breaking existing tools?

I think adding new entries is not a problem. Parsers have to deal with 
new entries popping up. For example, we introduced "ShadowCallStack:" in 
2020 via 628d06a48f57 ("scs: Add page accounting for shadow call stack 
allocations").


-- 
Thanks,

David / dhildenb


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-06-06 10:45 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-05 16:24 [RFC PATCH V2] zram:calculate available memory when zram is used yongw.pur
2021-06-05 17:07 ` Greg KH
2021-06-06 10:45   ` David Hildenbrand
2021-06-05 22:17 ` kernel test robot
2021-06-05 22:17 ` [RFC PATCH] zram: count_avail_swap() can be static kernel test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.