skip swapcache for super fast device
Subsystems (9)
Minchan Kim
maintainerv2 cover skip swapcache for super fast device
With fast swap storage, platform want to use swap more aggressively and swap-in is crucial to application latency.
The rw_page based synchronous devices like zram, pmem and btt are such fast storage. When I profile swapin performance with zram lz4 decompress test, S/W overhead is more than 70%. Maybe, it would be bigger in nvdimm.
This patch aims for reducing swap-in latency via skipping swapcache if swap device is synchronous device like rw_page based device.
It enhances 45% my swapin test(5G sequential swapin, no readahead, from 2.41sec to 1.64sec).
Andrew, [1] is zram specific patch so could be applied separately but this patch is based on that so I include it in this series.
* From v1
* style fix
* a bug fix
* drop page-cluster based readahead off
* This regression could be solved by other patch from Huang.
http://lkml.kernel.org/r/[email protected]
Minchan Kim (4):
[1] zram: set BDI_CAP_STABLE_WRITES once
[2] bdi: introduce BDI_CAP_SYNCHRONOUS_IO
[3] mm:swap: introduce SWP_SYNCHRONOUS_IO
[4] mm:swap: skip swapcache for swapin of synchronous device
drivers/block/brd.c | 2 ++ drivers/block/zram/zram_drv.c | 16 +++++-------- drivers/nvdimm/btt.c | 3 +++ drivers/nvdimm/pmem.c | 2 ++ include/linux/backing-dev.h | 8 +++++++ include/linux/swap.h | 14 +++++++++++- mm/memory.c | 52 ++++++++++++++++++++++++++++++------------- mm/page_io.c | 6 ++--- mm/swapfile.c | 14 ++++++++---- 9 files changed, 83 insertions(+), 34 deletions(-)
Signature · 7 lines
2.7.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Minchan Kim
maintainerPATCH v2 1/4 zram: set BDI_CAP_STABLE_WRITES once
[1] fixed weird thing(i.e., reset BDI_CAP_STABLE_WRITES flag unconditionally whenever revalidat_disk is called) so zram doesn't need to reset the flag any more whenever revalidating the bdev. Instead, set the flag just once when the zram device is created.
It shouldn't change any behavior.
[1] 19b7ccf8651d, block: get rid of blk_integrity_revalidate()
--- drivers/block/zram/zram_drv.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-)
drivers/block/zram/zram_drv.c +6 -10
@@ -122,14 +122,6 @@ static inline bool is_partial_io(struct bio_vec *bvec) }#endif -static void zram_revalidate_disk (struct zram *zram) -{ -revalidate_disk (zram->disk); -/* revalidate_disk reset the BDI_CAP_STABLE_WRITES so set again */ - zram->disk->queue->backing_dev_info->capabilities |= -BDI_CAP_STABLE_WRITES ; -} -/* * Check if request is within bounds and aligned on zram logical blocks. */
@@ -1371,7 +1363,8 @@ static ssize_t disksize_store(struct device *dev, zram->comp = comp; zram->disksize = disksize;set_capacity (zram->disk, zram->disksize >>SECTOR_SHIFT ); -zram_revalidate_disk (zram); + +revalidate_disk (zram->disk);up_write (&zram->init_lock);return len;
@@ -1418,7 +1411,7 @@ static ssize_t reset_store(struct device *dev,/* Make sure all the pending I/O are finished */ fsync_bdev (bdev);zram_reset_device (zram); -zram_revalidate_disk (zram); +revalidate_disk (zram->disk);bdput (bdev);mutex_lock (&bdev->bd_mutex);
@@ -1537,6 +1530,7 @@ static int zram_add(void)/* zram devices sort of resembles non-rotational disks */ queue_flag_set_unlocked (QUEUE_FLAG_NONROT , zram->disk->queue);queue_flag_clear_unlocked (QUEUE_FLAG_ADD_RANDOM , zram->disk->queue); +/* * To ensure that we always get PAGE_SIZE aligned * and n*PAGE_SIZED sized I/O requests.
@@ -1561,6 +1555,8 @@ static int zram_add(void)if (ZRAM_LOGICAL_BLOCK_SIZE ==PAGE_SIZE )blk_queue_max_write_zeroes_sectors (zram->disk->queue,UINT_MAX ); + zram->disk->queue->backing_dev_info->capabilities |= +BDI_CAP_STABLE_WRITES ;add_disk (zram->disk); ret = sysfs_create_group(&disk_to_dev(zram->disk)->kobj,
Signature · 7 lines
2.7.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Minchan Kim
maintainerPATCH v2 2/4 bdi: introduce BDI_CAP_SYNCHRONOUS_IO
In reply to Minchan KimBy discussion[1], someday we will remove rw_page function. If so, we need something to detect such super-fast storage which synchronous IO operation like current rw_page is always win.
This patch introduces BDI_CAP_SYNCHRONOUS_IO to indicate such devices. With it, we could use various optimization techniques.
[1] lkml.kernel.org/r/<[email protected]>
--- drivers/block/brd.c | 2 ++ drivers/block/zram/zram_drv.c | 2 +- drivers/nvdimm/btt.c | 3 +++ drivers/nvdimm/pmem.c | 2 ++ include/linux/backing-dev.h | 8 ++++++++ 5 files changed, 16 insertions(+), 1 deletion(-)
drivers/block/brd.c +2 -0
@@ -20,6 +20,7 @@#include <linux/radix-tree.h> #include <linux/fs.h> #include <linux/slab.h> +#include <linux/backing-dev.h> #ifdef CONFIG_BLK_DEV_RAM_DAX #include <linux/pfn_t.h> #include <linux/dax.h>
@@ -449,6 +450,7 @@ static struct brd_device *brd_alloc(int i) disk->flags =GENHD_FL_EXT_DEVT ;sprintf (disk->disk_name,"ram%d" , i);set_capacity (disk, rd_size *2 ); + disk->queue->backing_dev_info->capabilities |=BDI_CAP_SYNCHRONOUS_IO ;#ifdef CONFIG_BLK_DEV_RAM_DAX queue_flag_set_unlocked (QUEUE_FLAG_DAX , brd->brd_queue);
drivers/block/zram/zram_drv.c +1 -1
@@ -1556,7 +1556,7 @@ static int zram_add(void)blk_queue_max_write_zeroes_sectors (zram->disk->queue,UINT_MAX ); zram->disk->queue->backing_dev_info->capabilities |= -BDI_CAP_STABLE_WRITES ; + (BDI_CAP_STABLE_WRITES |BDI_CAP_SYNCHRONOUS_IO );add_disk (zram->disk); ret = sysfs_create_group(&disk_to_dev(zram->disk)->kobj,
drivers/nvdimm/btt.c +3 -0
@@ -23,6 +23,7 @@#include <linux/ndctl.h> #include <linux/fs.h> #include <linux/nd.h> +#include <linux/backing-dev.h> #include "btt.h" #include "nd.h"
@@ -1402,6 +1403,8 @@ static int btt_blk_init(struct btt *btt) btt->btt_disk->private_data = btt; btt->btt_disk->queue = btt->btt_queue; btt->btt_disk->flags =GENHD_FL_EXT_DEVT ; + btt->btt_disk->queue->backing_dev_info->capabilities |= +BDI_CAP_SYNCHRONOUS_IO ;blk_queue_make_request (btt->btt_queue, btt_make_request);blk_queue_logical_block_size (btt->btt_queue, btt->sector_size);
drivers/nvdimm/pmem.c +2 -0
@@ -31,6 +31,7 @@#include <linux/uio.h> #include <linux/dax.h> #include <linux/nd.h> +#include <linux/backing-dev.h> #include "pmem.h" #include "pfn.h" #include "nd.h"
@@ -394,6 +395,7 @@ static int pmem_attach_disk(struct device *dev, disk->fops = &pmem_fops; disk->queue = q; disk->flags =GENHD_FL_EXT_DEVT ; + disk->queue->backing_dev_info->capabilities |=BDI_CAP_SYNCHRONOUS_IO ;nvdimm_namespace_disk_name (ndns, disk->disk_name);set_capacity (disk, (pmem->size - pmem->pfn_pad - pmem->data_offset) /512 );
include/linux/backing-dev.h +8 -0
@@ -123,6 +123,8 @@ int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio);* BDI_CAP_STRICTLIMIT: Keep number of dirty pages below bdi threshold. * * BDI_CAP_CGROUP_WRITEBACK: Supports cgroup-aware writeback. +* BDI_CAP_SYNCHRONOUS_IO: Device is so fast that asynchronous IO would be +* inefficient. */ #define BDI_CAP_NO_ACCT_DIRTY 0x00000001#define BDI_CAP_NO_WRITEBACK 0x00000002
@@ -130,6 +132,7 @@ int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio);#define BDI_CAP_STABLE_WRITES 0x00000008#define BDI_CAP_STRICTLIMIT 0x00000010#define BDI_CAP_CGROUP_WRITEBACK 0x00000020 +#define BDI_CAP_SYNCHRONOUS_IO 0x00000040#define BDI_CAP_NO_ACCT_AND_WRITEBACK \ (BDI_CAP_NO_WRITEBACK | BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_ACCT_WB)
@@ -177,6 +180,11 @@ long wait_iff_congested(struct pglist_data *pgdat, int sync, long timeout);int pdflush_proc_obsolete (struct ctl_table *table,int write,void __user *buffer,size_t *lenp,loff_t *ppos); +static inline bool bdi_cap_synchronous_io (struct backing_dev_info *bdi) +{ +return bdi->capabilities &BDI_CAP_SYNCHRONOUS_IO ; +} +static inline bool bdi_cap_stable_pages_required (struct backing_dev_info *bdi) {return bdi->capabilities &BDI_CAP_STABLE_WRITES ;
Signature · 7 lines
2.7.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v2 2/4] bdi: introduce BDI_CAP_SYNCHRONOUS_IO
I'm only seeing patch 2 of 4 - please resend the whole series so that it can properly be reviewed.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Minchan Kim
maintainerRe: [PATCH v2 2/4] bdi: introduce BDI_CAP_SYNCHRONOUS_IO
Quoted 2 lines · Christoph Hellwig
I'm only seeing patch 2 of 4 - please resend the whole series so that it can properly be reviewed.
Yub, I will resend.
Thanks for the review in advance.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Minchan Kim
maintainerPATCH v2 3/4 mm:swap: introduce SWP_SYNCHRONOUS_IO
In reply to Minchan KimIf rw-page based fast storage is used for swap devices, we need to detect it to enhance swap IO operations.
This patch is preparation for optimizing of swap-in operation with next patch.
--- include/linux/swap.h | 3 ++- mm/swapfile.c | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-)
include/linux/swap.h +2 -1
@@ -170,8 +170,9 @@ enum {SWP_AREA_DISCARD = (1 <<8 ),/* single-time swap area discards */ SWP_PAGE_DISCARD = (1 <<9 ),/* freed swap page-cluster discards */ SWP_STABLE_WRITES = (1 <<10 ),/* no overwrite PG_writeback pages */ +SWP_SYNCHRONOUS_IO = (1 <<11 ),/* synchronous IO is efficient */ /* add others here before... */ - SWP_SCANNING = (1 << 11), /* refcount in scan_swap_map */ + SWP_SCANNING = (1 << 12), /* refcount in scan_swap_map */ };#define SWAP_CLUSTER_MAX 32UL
mm/swapfile.c +3 -0
@@ -3168,6 +3168,9 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)if (bdi_cap_stable_pages_required (inode_to_bdi (inode))) p->flags |=SWP_STABLE_WRITES ; +if (bdi_cap_synchronous_io (inode_to_bdi (inode))) + p->flags |=SWP_SYNCHRONOUS_IO ; +if (p->bdev &&blk_queue_nonrot (bdev_get_queue (p->bdev))) {int cpu;unsigned long ci, nr_cluster;
Signature · 7 lines
2.7.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Minchan Kim
maintainerPATCH v2 4/4 mm:swap: skip swapcache for swapin of synchronous device
In reply to Minchan KimWith fast swap storage, platform want to use swap more aggressively and swap-in is crucial to application latency.
The rw_page based synchronous devices like zram, pmem and btt are such fast storage. When I profile swapin performance with zram lz4 decompress test, S/W overhead is more than 70%. Maybe, it would be bigger in nvdimm.
This patch aims for reducing swap-in latency via skipping swapcache if swap device is synchronous device like rw_page based device. It enhances 45% my swapin test(5G sequential swapin, no readahead, from 2.41sec to 1.64sec).
--- include/linux/swap.h | 11 +++++++++++ mm/memory.c | 52 ++++++++++++++++++++++++++++++++++++---------------- mm/page_io.c | 6 +++--- mm/swapfile.c | 11 +++++++---- 4 files changed, 57 insertions(+), 23 deletions(-)
include/linux/swap.h +11 -0
@@ -461,6 +461,7 @@ extern int page_swapcount(struct page *);extern int __swp_swapcount (swp_entry_t entry);extern int swp_swapcount (swp_entry_t entry);extern struct swap_info_struct *page_swap_info (struct page *); +extern struct swap_info_struct *swp_swap_info (swp_entry_t entry);extern bool reuse_swap_page (struct page *,int *);extern int try_to_free_swap (struct page *);struct backing_dev_info ;
@@ -469,6 +470,16 @@ extern void exit_swap_address_space(unsigned int type);#else /* CONFIG_SWAP */ +static inline int swap_readpage (struct page *page,bool do_poll) +{ +return 0 ; +} + +static inline struct swap_info_struct *swp_swap_info (swp_entry_t entry) +{ +return NULL ; +} +#define swap_address_space (entry) (NULL)#define get_nr_swap_pages () 0L#define total_swap_pages 0L
mm/memory.c +36 -16
102 lines not on this page · raw message
mm/page_io.c +3 -3
@@ -346,7 +346,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc,return ret; } -int swap_readpage (struct page *page,bool do_poll) +int swap_readpage (struct page *page,bool synchronous) {struct bio *bio;int ret =0 ;
@@ -354,7 +354,7 @@ int swap_readpage(struct page *page, bool do_poll)blk_qc_t qc;struct gendisk *disk; -VM_BUG_ON_PAGE (!PageSwapCache (page), page); +VM_BUG_ON_PAGE (!PageSwapCache (page) && !synchronous, page);VM_BUG_ON_PAGE (!PageLocked (page), page);VM_BUG_ON_PAGE (PageUptodate (page), page);if (frontswap_load (page) ==0 ) {
@@ -402,7 +402,7 @@ int swap_readpage(struct page *page, bool do_poll)count_vm_event (PSWPIN );bio_get (bio); qc =submit_bio (bio); -while (do_poll) { +while (synchronous) {set_current_state (TASK_UNINTERRUPTIBLE );if (!READ_ONCE (bio->bi_private))break ;
mm/swapfile.c +7 -4
@@ -3454,10 +3454,15 @@ int swapcache_prepare(swp_entry_t entry)return __swap_duplicate (entry,SWAP_HAS_CACHE ); } +struct swap_info_struct *swp_swap_info (swp_entry_t entry) +{ +return swap_info[swp_type (entry)]; +} +struct swap_info_struct *page_swap_info (struct page *page) { -swp_entry_t swap = { .val =page_private (page) }; -return swap_info[swp_type (swap)]; +swp_entry_t entry = { .val =page_private (page) }; +return swp_swap_info (entry); }/*
@@ -3465,7 +3470,6 @@ struct swap_info_struct *page_swap_info(struct page *page)*/ struct address_space *__page_file_mapping (struct page *page) { -VM_BUG_ON_PAGE (!PageSwapCache (page), page);return page_swap_info (page)->swap_file->f_mapping; }EXPORT_SYMBOL_GPL (__page_file_mapping);
@@ -3473,7 +3477,6 @@ EXPORT_SYMBOL_GPL(__page_file_mapping);pgoff_t __page_file_index (struct page *page) {swp_entry_t swap = { .val =page_private (page) }; -VM_BUG_ON_PAGE (!PageSwapCache (page), page);return swp_offset (swap); }EXPORT_SYMBOL_GPL (__page_file_index);
Signature · 7 lines
2.7.4 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>