zram: use frontswap for zram swap usecase
Subsystems (7)
Minchan Kim
maintainercover zram: use frontswap for zram swap usecase
This patchset uses frontswap for zram swap usecase and remove swap_slot_free_notify swap specific operation in block device. It shows 13% swapout improvement for MADV_PAGEOUT.
Minchan Kim (3):
frontswap: support backing_dev
zram: support frontswap
zram: remove swap_slot_free_notify
Documentation/filesystems/locking.rst | 5 -- drivers/block/zram/Kconfig | 1 + drivers/block/zram/zram_drv.c | 116 ++++++++++++++++++++++---- drivers/block/zram/zram_drv.h | 1 + include/linux/blkdev.h | 2 - include/linux/frontswap.h | 7 +- mm/frontswap.c | 4 +- mm/swapfile.c | 11 +-- mm/zswap.c | 2 +- 9 files changed, 110 insertions(+), 39 deletions(-)
Signature · 1 line
2.41.0.255.g8b1d071c50-goog
Minchan Kim
maintainerPATCH 1/3 frontswap: support backing_dev
Modify frontswap to be used as a block device driver for swap partitions.
--- include/linux/frontswap.h | 7 +++++-- mm/frontswap.c | 4 ++-- mm/swapfile.c | 3 ++- mm/zswap.c | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-)
include/linux/frontswap.h +5 -2
@@ -7,8 +7,10 @@#include <linux/bitops.h> #include <linux/jump_label.h> +struct block_device ; +struct frontswap_ops { -void (*init)(unsigned );/* this swap type was just swapon'ed */ +void (*init)(unsigned ,struct block_device *);/* this swap type was just swapon'ed */ int (*store)(unsigned ,pgoff_t ,struct page *);/* store a page */ int (*load)(unsigned ,pgoff_t ,struct page *,bool *);/* load a page */ void (*invalidate_page)(unsigned ,pgoff_t );/* page no longer needed */
@@ -17,7 +19,8 @@ struct frontswap_ops {int frontswap_register_ops (const struct frontswap_ops *ops); -extern void frontswap_init (unsigned type,unsigned long *map); +extern void frontswap_init (unsigned type,unsigned long *map, +struct block_device *bdev);extern int __frontswap_store (struct page *page);extern int __frontswap_load (struct page *page);extern void __frontswap_invalidate_page (unsigned ,pgoff_t );
mm/frontswap.c +2 -2
@@ -107,7 +107,7 @@ int frontswap_register_ops(const struct frontswap_ops *ops)/* * Called when a swap device is swapon'd. */ -void frontswap_init (unsigned type,unsigned long *map) +void frontswap_init (unsigned type,unsigned long *map,struct block_device *bdev) {struct swap_info_struct *sis = swap_info[type];
@@ -128,7 +128,7 @@ void frontswap_init(unsigned type, unsigned long *map)if (!frontswap_enabled ())return ; - frontswap_ops->init (type); + frontswap_ops->init (type, bdev); } static bool __frontswap_test(struct swap_info_struct *sis,
mm/swapfile.c +2 -1
@@ -2339,7 +2339,8 @@ static void enable_swap_info(struct swap_info_struct *p, int prio, unsigned long *frontswap_map) {if (IS_ENABLED (CONFIG_FRONTSWAP )) -frontswap_init (p->type, frontswap_map); +frontswap_init (p->type, frontswap_map, p->bdev); +spin_lock (&swap_lock);spin_lock (&p->lock);setup_swap_info (p, prio, swap_map, cluster_info);
mm/zswap.c +1 -1
@@ -1510,7 +1510,7 @@ static void zswap_frontswap_invalidate_area(unsigned type) zswap_trees[type] =NULL ; } -static void zswap_frontswap_init (unsigned type) +static void zswap_frontswap_init (unsigned type,struct block_device *bdev) {struct zswap_tree *tree;
Signature · 1 line
2.41.0.255.g8b1d071c50-goog
Minchan Kim
maintainerPATCH 2/3 zram: support frontswap
In reply to Minchan KimWith frontswap, zram can perform swapout 13% faster, which restores its original performance with rw_page.
200M swapout using MADV_PAGEOUT:
Before: 4355ms After: 3786ms
--- drivers/block/zram/Kconfig | 1 + drivers/block/zram/zram_drv.c | 98 +++++++++++++++++++++++++++++++++++ drivers/block/zram/zram_drv.h | 1 + 3 files changed, 100 insertions(+)
drivers/block/zram/Kconfig +1 -0
@@ -4,6 +4,7 @@ config ZRAM depends on BLOCK && SYSFS && MMU depends on CRYPTO_LZO || CRYPTO_ZSTD || CRYPTO_LZ4 || CRYPTO_LZ4HC || CRYPTO_842 select ZSMALLOC + select FRONTSWAP help Creates virtual block devices called /dev/zramX (X = 0, 1, ...). Pages written to these disks are compressed and stored in memory
drivers/block/zram/zram_drv.c +98 -0
128 lines not on this page · raw message
drivers/block/zram/zram_drv.h +1 -0
@@ -139,5 +139,6 @@ struct zram {#ifdef CONFIG_ZRAM_MEMORY_TRACKING struct dentry *debugfs_dir;#endif + struct list_head list; };#endif
Signature · 1 line
2.41.0.255.g8b1d071c50-goog
Re: [PATCH 2/3] zram: support frontswap
Hello,
Quoted 61 lines · Minchan Kim
With frontswap, zram can perform swapout 13% faster, which restores its original performance with
rw_page.200M swapout using
MADV_PAGEOUT:
Before: 4355ms After: 3786msSigned-off-by Minchan Kim <[email protected]>--- drivers/block/zram/Kconfig | 1 + drivers/block/zram/zram_drv.c | 98 +++++++++++++++++++++++++++++++++++ drivers/block/zram/zram_drv.h | 1 + 3 files changed, 100 insertions(+)drivers/block/zram/Kconfig +1
-0@@ -4,6 +4,7 @@ config ZRAM depends on BLOCK && SYSFS && MMU depends on CRYPTO_LZO || CRYPTO_ZSTD || CRYPTO_LZ4 || CRYPTO_LZ4HC || CRYPTO_842 select ZSMALLOC + select FRONTSWAP help Creates virtual block devices called /dev/zramX (X = 0, 1, ...). Pages written to these disks are compressed and stored in memorydrivers/block/zram/zram_drv.c +21
-0@@ -33,6 +33,8 @@#include <linux/debugfs.h> #include <linux/cpuhotplug.h> #include <linux/part_stat.h> +#include <linux/swap.h> +#include <linux/frontswap.h> #include "zram_drv.h" @@ -2170,6 +2172,90 @@ static struct attribute *zram_disk_attrs[] = {ATTRIBUTE_GROUPS (zram_disk); +static struct zram *zram_swaps[MAX_SWAPFILES ]; +static LIST_HEAD (zram_list); +static DEFINE_SPINLOCK (zram_list_lock); + +static int zram_frontswap_store (unsigned int type,pgoff_t index, +struct page *page) +{ +int err; +struct zram *zram = zram_swaps[type]; + + err =zram_write_page (zram, page, index); +if (!err) { +zram_slot_lock (zram, index); +zram_accessed (zram, index); +zram_slot_unlock (zram, index); + } + +return err; +}
drivers/block/zram/zram_drv.c static struct attribute *zram_disk_attrs[] = { · line 2203
Quoted 10 lines
drivers/block/zram/zram_drv.c +10
-0+ +static int zram_frontswap_load (unsigned int type,pgoff_t index, +struct page *page,bool *exclusive) +{ +int err; +struct zram *zram = zram_swaps[type]; + +zram_slot_lock (zram, index); +if (zram_test_flag (zram, index,ZRAM_WB )) { +zram_slot_lock (zram, index);
Looks like zram_slot_unlock should be here instead of zram_slot_lock.
Quoted 8 lines
drivers/block/zram/zram_drv.c +8
-0+return -1 ; + } + + err =zram_read_from_zspool (zram, page, index); +if (!err) +zram_accessed (zram, index); +zram_slot_unlock (zram, index); +
drivers/block/zram/zram_drv.c static struct attribute *zram_disk_attrs[] = { · line 2221
Quoted 10 lines
drivers/block/zram/zram_drv.c +10
-0+return err; +} + +static void zram_frontswap_invalidate_area (unsigned int type) +{ +struct zram *zram = zram_swaps[type]; + +if (!zram) +return ; +}
It makes sense? Maybe we just leave this function empty?
Quoted 88 lines
drivers/block/zram/zram_drv.c +49
-0+ +static void zram_frontswap_init (unsigned int type,struct block_device *bdev) +{ +struct zram *zram; + +spin_lock (&zram_list_lock); +list_for_each_entry (zram, &zram_list, list) { +if (&zram_devops == bdev->bd_disk->fops) { + zram_swaps[type] = zram; +break ; + } + } +spin_unlock (&zram_list_lock); +} + +static void zram_frontswap_invalidate_page (unsigned int type,pgoff_t offset) +{ +struct zram *zram = zram_swaps[type]; + +if (!zram_slot_trylock (zram, offset)) { +atomic64_inc (&zram->stats.miss_free); +return ; + } + +zram_free_page (zram, offset); +zram_slot_unlock (zram, offset); +} + +static const struct frontswap_ops zram_frontswap_ops = { + .store = zram_frontswap_store, + .load = zram_frontswap_load, + .init = zram_frontswap_init, + .invalidate_area = zram_frontswap_invalidate_area, + .invalidate_page = zram_frontswap_invalidate_page, + .init = zram_frontswap_init +}; +/* * Allocate and initialize new zram device. the function returns * '>= 0' device_id upon success, and negative value otherwise. @@ -2246,6 +2332,10 @@ static int zram_add(void)comp_algorithm_set (zram,ZRAM_PRIMARY_COMP , default_compressor); +spin_lock (&zram_list_lock); +list_add (&zram->list, &zram_list); +spin_unlock (&zram_list_lock); +zram_debugfs_register (zram);pr_info ("Added device: %s\n" , zram->disk->disk_name);return device_id;@@ -2303,6 +2393,11 @@ static int zram_remove(struct zram *zram)zram_reset_device (zram);put_disk (zram->disk); + +spin_lock (&zram_list_lock); +list_del (&zram->list); +spin_unlock (&zram_list_lock); +kfree (zram);return 0 ; }@@ -2428,6 +2523,9 @@ static int __init zram_init(void) num_devices--; } +if (frontswap_register_ops (&zram_frontswap_ops)) +pr_info ("Frontswap is not used, which is suboptimal for zram swap.\n" ); +return 0 ; out_error:drivers/block/zram/zram_drv.h +1
-0@@ -139,5 +139,6 @@ struct zram {#ifdef CONFIG_ZRAM_MEMORY_TRACKING struct dentry *debugfs_dir;#endif + struct list_head list; };#endif Signature · 1 line
2.41.0.255.g8b1d071c50-goog
Signature · 2 lines
Thank you, Alexey
Minchan Kim
maintainerRe: [PATCH 2/3] zram: support frontswap
Quoted 68 lines · Alexey Romanov
Hello,
Quoted 65 lines · Minchan Kim
With frontswap, zram can perform swapout 13% faster, which restores its original performance with
rw_page.200M swapout using
MADV_PAGEOUT:
Before: 4355ms After: 3786msSigned-off-by Minchan Kim <[email protected]>--- drivers/block/zram/Kconfig | 1 + drivers/block/zram/zram_drv.c | 98 +++++++++++++++++++++++++++++++++++ drivers/block/zram/zram_drv.h | 1 + 3 files changed, 100 insertions(+)drivers/block/zram/Kconfig +1
-0@@ -4,6 +4,7 @@ config ZRAM depends on BLOCK && SYSFS && MMU depends on CRYPTO_LZO || CRYPTO_ZSTD || CRYPTO_LZ4 || CRYPTO_LZ4HC || CRYPTO_842 select ZSMALLOC + select FRONTSWAP help Creates virtual block devices called /dev/zramX (X = 0, 1, ...). Pages written to these disks are compressed and stored in memorydrivers/block/zram/zram_drv.c +25
-0@@ -33,6 +33,8 @@#include <linux/debugfs.h> #include <linux/cpuhotplug.h> #include <linux/part_stat.h> +#include <linux/swap.h> +#include <linux/frontswap.h> #include "zram_drv.h" @@ -2170,6 +2172,90 @@ static struct attribute *zram_disk_attrs[] = {ATTRIBUTE_GROUPS (zram_disk); +static struct zram *zram_swaps[MAX_SWAPFILES ]; +static LIST_HEAD (zram_list); +static DEFINE_SPINLOCK (zram_list_lock); + +static int zram_frontswap_store (unsigned int type,pgoff_t index, +struct page *page) +{ +int err; +struct zram *zram = zram_swaps[type]; + + err =zram_write_page (zram, page, index); +if (!err) { +zram_slot_lock (zram, index); +zram_accessed (zram, index); +zram_slot_unlock (zram, index); + } + +return err; +} + +static int zram_frontswap_load (unsigned int type,pgoff_t index, +struct page *page,bool *exclusive) +{
Quoted 8 lines
drivers/block/zram/zram_drv.c static struct attribute *zram_disk_attrs[] = { · line 2203
Quoted 6 lines
drivers/block/zram/zram_drv.c +6
-0+int err; +struct zram *zram = zram_swaps[type]; + +zram_slot_lock (zram, index); +if (zram_test_flag (zram, index,ZRAM_WB )) { +zram_slot_lock (zram, index);Looks like
zram_slot_unlockshould be here instead ofzram_slot_lock.
me/ slabs self.
Quoted 13 lines
Quoted 13 lines
drivers/block/zram/zram_drv.c +12
-0+return -1 ; + } + + err =zram_read_from_zspool (zram, page, index); +if (!err) +zram_accessed (zram, index); +zram_slot_unlock (zram, index); + +return err; +} + +static void zram_frontswap_invalidate_area (unsigned int type)
Quoted 8 lines
drivers/block/zram/zram_drv.c static struct attribute *zram_disk_attrs[] = { · line 2221
Quoted 6 lines
drivers/block/zram/zram_drv.c +6
-0+{ +struct zram *zram = zram_swaps[type]; + +if (!zram) +return ; +}It makes sense? Maybe we just leave this function empty?
Sorry, it was wrong version from my git tree. I had destroy zram in the case originally
but since I decide to drop this patchset, never mind.
Thanks for spending time for review, Alexey.
Minchan Kim
maintainerPATCH 3/3 zram: remove swap_slot_free_notify
In reply to Minchan KimFrontswap replaces the need for swap_slot_free_notify in block_device. Therefore, we can remove it.
--- Documentation/filesystems/locking.rst | 5 ----- drivers/block/zram/zram_drv.c | 20 +------------------- include/linux/blkdev.h | 2 -- mm/swapfile.c | 8 -------- 4 files changed, 1 insertion(+), 34 deletions(-)
Documentation/filesystems/locking.rst +0 -5
@@ -477,7 +477,6 @@ block_device_operations unsigned long *); void (*unlock_native_capacity) (struct gendisk *); int (*getgeo)(struct block_device *, struct hd_geometry *); - void (*swap_slot_free_notify) (struct block_device *, unsigned long); locking rules:
@@ -491,12 +490,8 @@ compat_ioctl: no direct_access: no unlock_native_capacity: no getgeo: no -swap_slot_free_notify: no (see below) ======================= =================== -swap_slot_free_notify is called with swap_lock and sometimes the page lock -held. - file_operations ===============
drivers/block/zram/zram_drv.c +1 -19
@@ -1947,23 +1947,6 @@ static void zram_submit_bio(struct bio *bio) } } -static void zram_slot_free_notify (struct block_device *bdev, -unsigned long index) -{ -struct zram *zram; - - zram = bdev->bd_disk->private_data; - -atomic64_inc (&zram->stats.notify_free); -if (!zram_slot_trylock (zram, index)) { -atomic64_inc (&zram->stats.miss_free); -return ; - } - -zram_free_page (zram, index); -zram_slot_unlock (zram, index); -} -static void zram_destroy_comps (struct zram *zram) {u32 prio;
@@ -2117,7 +2100,6 @@ static int zram_open(struct block_device *bdev, fmode_t mode)static const struct block_device_operations zram_devops = { .open = zram_open, .submit_bio = zram_submit_bio, - .swap_slot_free_notify = zram_slot_free_notify, .owner =THIS_MODULE };
@@ -2206,7 +2188,7 @@ static int zram_frontswap_load(unsigned int type, pgoff_t index, err =zram_read_from_zspool (zram, page, index);if (!err) -zram_accessed (zram, index); +zram_free_page (zram, index);zram_slot_unlock (zram, index);return err;
include/linux/blkdev.h +0 -2
@@ -1390,8 +1390,6 @@ struct block_device_operations {int (*getgeo)(struct block_device *,struct hd_geometry *);int (*set_read_only)(struct block_device *bdev,bool ro);void (*free_disk)(struct gendisk *disk); -/* this callback is with swap_lock and sometimes page table lock held */ -void (*swap_slot_free_notify) (struct block_device *,unsigned long );int (*report_zones)(struct gendisk *,sector_t sector,unsigned int nr_zones,report_zones_cb cb,void *data);char *(*devnode)(struct gendisk *disk,umode_t *mode);
mm/swapfile.c +0 -8
@@ -726,7 +726,6 @@ static void swap_range_free(struct swap_info_struct *si, unsigned long offset, {unsigned long begin = offset;unsigned long end = offset + nr_entries -1 ; -void (*swap_slot_free_notify)(struct block_device *,unsigned long );if (offset < si->lowest_bit) si->lowest_bit = offset;
@@ -739,16 +738,9 @@ static void swap_range_free(struct swap_info_struct *si, unsigned long offset, }atomic_long_add (nr_entries, &nr_swap_pages);WRITE_ONCE (si->inuse_pages, si->inuse_pages - nr_entries); -if (si->flags &SWP_BLKDEV ) - swap_slot_free_notify = - si->bdev->bd_disk->fops->swap_slot_free_notify; -else - swap_slot_free_notify =NULL ;while (offset <= end) {arch_swap_invalidate_page (si->type, offset);frontswap_invalidate_page (si->type, offset); -if (swap_slot_free_notify) -swap_slot_free_notify (si->bdev, offset); offset++; }clear_shadow_from_swap_cache (si->type, begin, end);
Signature · 1 line
2.41.0.255.g8b1d071c50-goog
Re: [PATCH 3/3] zram: remove swap_slot_free_notify
Hello,
Quoted 73 lines · Minchan Kim
Frontswap replaces the need for
swap_slot_free_notifyinblock_device. Therefore, we can remove it.Signed-off-by Minchan Kim <[email protected]>--- Documentation/filesystems/locking.rst | 5 ----- drivers/block/zram/zram_drv.c | 20 +------------------- include/linux/blkdev.h | 2 -- mm/swapfile.c | 8 -------- 4 files changed, 1 insertion(+), 34 deletions(-)Documentation/filesystems/locking.rst +0
-5@@ -477,7 +477,6 @@ block_device_operations unsigned long *); void (*unlock_native_capacity) (struct gendisk *); int (*getgeo)(struct block_device *, struct hd_geometry *); - void (*swap_slot_free_notify) (struct block_device *, unsigned long); locking rules:@@ -491,12 +490,8 @@ compat_ioctl: no direct_access: no unlock_native_capacity: no getgeo: no -swap_slot_free_notify: no (see below) ======================= =================== -swap_slot_free_notify is called with swap_lock and sometimes the page lock -held. - file_operations ===============drivers/block/zram/zram_drv.c +0
-18@@ -1947,23 +1947,6 @@ static void zram_submit_bio(struct bio *bio) } } -static void zram_slot_free_notify (struct block_device *bdev, -unsigned long index) -{ -struct zram *zram; - - zram = bdev->bd_disk->private_data; - -atomic64_inc (&zram->stats.notify_free); -if (!zram_slot_trylock (zram, index)) { -atomic64_inc (&zram->stats.miss_free); -return ; - } - -zram_free_page (zram, index); -zram_slot_unlock (zram, index); -} -static void zram_destroy_comps (struct zram *zram) {u32 prio;@@ -2117,7 +2100,6 @@ static int zram_open(struct block_device *bdev, fmode_t mode)static const struct block_device_operations zram_devops = { .open = zram_open, .submit_bio = zram_submit_bio, - .swap_slot_free_notify = zram_slot_free_notify, .owner =THIS_MODULE };
drivers/block/zram/zram_drv.c static int zram_frontswap_load(unsigned int type, pgoff_t index, · line 2191
Quoted 5 lines
drivers/block/zram/zram_drv.c +1
-1@@ -2206,7 +2188,7 @@ static int zram_frontswap_load(unsigned int type, pgoff_t index, err =zram_read_from_zspool (zram, page, index);if (!err) -zram_accessed (zram, index); +zram_free_page (zram, index);
Probably it should be in the previous commit.
Quoted 49 lines
drivers/block/zram/zram_drv.c +0
-0zram_slot_unlock (zram, index);return err;include/linux/blkdev.h +0
-2@@ -1390,8 +1390,6 @@ struct block_device_operations {int (*getgeo)(struct block_device *,struct hd_geometry *);int (*set_read_only)(struct block_device *bdev,bool ro);void (*free_disk)(struct gendisk *disk); -/* this callback is with swap_lock and sometimes page table lock held */ -void (*swap_slot_free_notify) (struct block_device *,unsigned long );int (*report_zones)(struct gendisk *,sector_t sector,unsigned int nr_zones,report_zones_cb cb,void *data);char *(*devnode)(struct gendisk *disk,umode_t *mode);mm/swapfile.c +0
-8@@ -726,7 +726,6 @@ static void swap_range_free(struct swap_info_struct *si, unsigned long offset, {unsigned long begin = offset;unsigned long end = offset + nr_entries -1 ; -void (*swap_slot_free_notify)(struct block_device *,unsigned long );if (offset < si->lowest_bit) si->lowest_bit = offset;@@ -739,16 +738,9 @@ static void swap_range_free(struct swap_info_struct *si, unsigned long offset, }atomic_long_add (nr_entries, &nr_swap_pages);WRITE_ONCE (si->inuse_pages, si->inuse_pages - nr_entries); -if (si->flags &SWP_BLKDEV ) - swap_slot_free_notify = - si->bdev->bd_disk->fops->swap_slot_free_notify; -else - swap_slot_free_notify =NULL ;while (offset <= end) {arch_swap_invalidate_page (si->type, offset);frontswap_invalidate_page (si->type, offset); -if (swap_slot_free_notify) -swap_slot_free_notify (si->bdev, offset); offset++; }clear_shadow_from_swap_cache (si->type, begin, end);Signature · 1 line
2.41.0.255.g8b1d071c50-goog
Signature · 2 lines
Thank you, Alexey
Quoted 3 lines · Minchan Kim
This patchset uses frontswap for zram swap usecase and remove
swap_slot_free_notifyswap specific operation in block device. It shows 13% swapout improvement forMADV_PAGEOUT.
Err, no. frontswap needs to go away, and not be tried to a block driver. If you want compressed swap without a block driver please use zswap and help improvig it and the swap abstraction to not require a backing allocation for it.
We need to fix swap and not pile hacks on top of hacks.
Nhat Pham
maintainerQuoted 6 lines · Christoph Hellwig
Quoted 3 lines · Minchan Kim
This patchset uses frontswap for zram swap usecase and remove
swap_slot_free_notifyswap specific operation in block device. It shows 13% swapout improvement forMADV_PAGEOUT.
Quoted 7 lines
Err, no. frontswap needs to go away, and not be tried to a block driver. If you want compressed swap without a block driver please use zswap and help improvig it and the swap abstraction to not require a backing allocation for it.
We need to fix swap and not pile hacks on top of hacks.
+1. Based on earlier discussions, it seems like the agreed upon way forward is to remove the frontswap interface:
Minchan Kim
maintainerQuoted 12 lines · Nhat Pham
Quoted 11 lines · Christoph Hellwig
Quoted 3 lines · Minchan Kim
This patchset uses frontswap for zram swap usecase and remove
swap_slot_free_notifyswap specific operation in block device. It shows 13% swapout improvement forMADV_PAGEOUT.Err, no. frontswap needs to go away, and not be tried to a block driver. If you want compressed swap without a block driver please use zswap and help improvig it and the swap abstraction to not require a backing allocation for it.
Quoted 7 lines
Quoted 2 lines
We need to fix swap and not pile hacks on top of hacks.
+1. Based on earlier discussions, it seems like the agreed upon way forward is to remove the frontswap interface:
Thanks for feedback.
Understood. I also agree frontswap is hack so let me this patchset. I hope swap abstraction goes to the way Chris Li suggested in the end.