Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6b760f93 authored by huangzq2's avatar huangzq2 Committed by Harshit Jain
Browse files

mm: zram: fix swapcached issue on Zram Writeback



Afer Zram backing dev setuped, zram will be treated as a ASYNC IO
swap device, no longer SYNC IO device, because WB pages do have IO
operation on swap in, so the optimization on skiping swapcache
for fast swap device will no longer be applyed on such case.

Now we refactor this optimization, skip the swapcache by checking
SYNC IO state on each swap page via ioctl. Reuse ioctl because we
should not break the GKI.

Change-Id: If01167b7ca178370833fc6e02385bb34ef84318a
Signed-off-by: default avatarhuangzq2 <huangzq2@motorola.com>
Reviewed-on: https://gerrit.mot.com/1897414


SLTApproved: Slta Waiver
SME-Granted: SME Approvals Granted
Tested-by: Jira Key
Reviewed-by: default avatarXiangpo Zhao <zhaoxp3@motorola.com>
Submit-Approved: Jira Key
Signed-off-by: default avatarUtsavBalar1231 <utsavbalar1231@gmail.com>
parent f33570fd
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <linux/genhd.h>
#include <linux/highmem.h>
#include <linux/slab.h>
#include <linux/swap.h>
#include <linux/backing-dev.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
@@ -1741,6 +1742,28 @@ 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.
 */
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;

#ifdef CONFIG_ZRAM_WRITEBACK
	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);
#endif

	return has_sync_io;
}


static int zram_rw_page(struct block_device *bdev, sector_t sector,
		       struct page *page, bool is_write)
{
@@ -1938,6 +1961,7 @@ 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,
	.ioctl = zram_ioctl,
	.rw_page = zram_rw_page,
	.owner = THIS_MODULE
};
+1 −0
Original line number Diff line number Diff line
@@ -396,6 +396,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);
+7 −1
Original line number Diff line number Diff line
@@ -3214,8 +3214,14 @@ int do_swap_page(struct vm_fault *vmf)
	 * and can then take the readahead path instead of SWP_SYNCHRONOUS_IO.
	 */
	si = swp_swap_info(entry);
	/* 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(si, entry) == 1)
		skip_swapcache = true;
	else if (__swap_count(si, entry) == 1 && swap_slot_has_sync_io(entry))
		skip_swapcache = true;

	page = lookup_swap_cache(entry, vma, vmf->address);
	swapcache = page;
@@ -3243,7 +3249,7 @@ int do_swap_page(struct vm_fault *vmf)
			ret = VM_FAULT_RETRY;
			goto out;
		} else {
			page = swapin_readahead(entry, GFP_HIGHUSER_MOVABLE,
			page = swapin_readahead(entry, GFP_HIGHUSER_MOVABLE | __GFP_CMA,
						vmf);
			swapcache = page;
		}
+16 −0
Original line number Diff line number Diff line
@@ -73,6 +73,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 end_swap_bio_read(struct bio *bio)
{
	struct page *page = bio->bi_io_vec[0].bv_page;