diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index cd242fd9db18..60650ecf9166 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -1630,6 +1631,27 @@ static void zram_slot_free_notify(struct block_device *bdev, zram_slot_unlock(zram, index); } +/* Moto huangzq2: check sync_io state on swap entry, + * return 0 on wb page, else return 1. + */ +#ifdef CONFIG_ZRAM_WRITEBACK +static int zram_ioctl(struct block_device *bdev, fmode_t mode, + unsigned int cmd, unsigned long index) +{ + struct zram *zram; + int has_sync_io = 1; + + if (cmd != SWP_SYNCHRONOUS_IO) return -EINVAL; + + zram = bdev->bd_disk->private_data; + zram_slot_lock(zram, index); + has_sync_io = zram_test_flag(zram, index, ZRAM_WB) ? 0 : 1; + zram_slot_unlock(zram, index); + + return has_sync_io; +} +#endif + static int zram_rw_page(struct block_device *bdev, sector_t sector, struct page *page, unsigned int op) { @@ -1822,6 +1844,9 @@ static int zram_open(struct block_device *bdev, fmode_t mode) static const struct block_device_operations zram_devops = { .open = zram_open, .swap_slot_free_notify = zram_slot_free_notify, +#ifdef CONFIG_ZRAM_WRITEBACK + .ioctl = zram_ioctl, +#endif .rw_page = zram_rw_page, .owner = THIS_MODULE }; diff --git a/include/linux/swap.h b/include/linux/swap.h index b407d3963649..bb50a6d0eee4 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -397,6 +397,7 @@ extern void end_swap_bio_write(struct bio *bio); extern int __swap_writepage(struct page *page, struct writeback_control *wbc, bio_end_io_t end_write_func); extern int swap_set_page_dirty(struct page *page); +extern bool swap_slot_has_sync_io(swp_entry_t entry); int add_swap_extent(struct swap_info_struct *sis, unsigned long start_page, unsigned long nr_pages, sector_t start_block); diff --git a/mm/memory.c b/mm/memory.c index 47c12f886c0d..609e32cfbb0e 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -3089,9 +3089,18 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) if (!page) { struct swap_info_struct *si = swp_swap_info(entry); + bool skip_swapcache = false; - if (si->flags & SWP_SYNCHRONOUS_IO && - __swap_count(entry) == 1) { + /* Moto huangzq2: check sync_io on each page if we enabled Zram wb. + * Zram writeback will remove SWP_SYNCHRONOUS_IO flag as it has disk + * IO operation on writeback page during swap in. + */ + if (si->flags & SWP_SYNCHRONOUS_IO && __swap_count(entry) == 1) + skip_swapcache = true; + else if (__swap_count(entry) == 1 && swap_slot_has_sync_io(entry)) + skip_swapcache = true; + + if (skip_swapcache) { /* skip swapcache */ page = alloc_page_vma(GFP_HIGHUSER_MOVABLE | __GFP_CMA | __GFP_OFFLINABLE, vma, @@ -3115,8 +3124,8 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) ret = VM_FAULT_RETRY; goto out; } else { - page = swapin_readahead(entry, GFP_HIGHUSER_MOVABLE, - vmf); + page = swapin_readahead(entry, GFP_HIGHUSER_MOVABLE | __GFP_CMA + | __GFP_OFFLINABLE, vmf); swapcache = page; } diff --git a/mm/page_io.c b/mm/page_io.c index bc370c8e1667..e91f008af794 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -71,6 +71,22 @@ void end_swap_bio_write(struct bio *bio) bio_put(bio); } +/* Moto huangzq2: check sync_io state on swap entry */ +bool swap_slot_has_sync_io(swp_entry_t entry) +{ + struct swap_info_struct *sis; + struct gendisk *disk; + + sis = swp_swap_info(entry); + disk = sis->bdev->bd_disk; + if (disk->fops->ioctl) { + return disk->fops->ioctl(sis->bdev, 0, + SWP_SYNCHRONOUS_IO, swp_offset(entry)) == 1; + } + + return false; +} + static void swap_slot_free_notify(struct page *page) { struct swap_info_struct *sis;