18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * drivers/block/zram/zram_group/group_writeback.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2020-2022 Huawei Technologies Co., Ltd. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/mm.h> 98c2ecf20Sopenharmony_ci#include <linux/memcontrol.h> 108c2ecf20Sopenharmony_ci#include <linux/blk_types.h> 118c2ecf20Sopenharmony_ci#include <linux/zswapd.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include "../zram_drv.h" 148c2ecf20Sopenharmony_ci#include "zram_group.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#ifdef CONFIG_HYPERHOLD 178c2ecf20Sopenharmony_ci#include "hyperhold.h" 188c2ecf20Sopenharmony_ci#endif 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define CHECK(cond, ...) ((cond) || (pr_err(__VA_ARGS__), false)) 218c2ecf20Sopenharmony_ci#define CHECK_BOUND(var, min, max) \ 228c2ecf20Sopenharmony_ci CHECK((var) >= (min) && (var) <= (max), \ 238c2ecf20Sopenharmony_ci "%s %u out of bounds %u ~ %u!\n", \ 248c2ecf20Sopenharmony_ci #var, (var), (min), (max)) 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistatic u16 zram_get_memcg_id(struct zram *zram, u32 index) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci return (zram->table[index].flags & ZRAM_GRPID_MASK) >> ZRAM_SIZE_SHIFT; 298c2ecf20Sopenharmony_ci} 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic void zram_set_memcg_id(struct zram *zram, u32 index, u16 gid) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci unsigned long old = zram->table[index].flags & (~ZRAM_GRPID_MASK); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci zram->table[index].flags = old | ((u64)gid << ZRAM_SIZE_SHIFT); 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_GROUP_WRITEBACK 398c2ecf20Sopenharmony_cistatic bool obj_can_wb(struct zram *zram, u32 index, u16 gid) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci /* overwrited obj, just skip */ 428c2ecf20Sopenharmony_ci if (zram_get_memcg_id(zram, index) != gid) { 438c2ecf20Sopenharmony_ci pr_debug("obj %u is from group %u instead of group %u.\n", 448c2ecf20Sopenharmony_ci index, zram_get_memcg_id(zram, index), gid); 458c2ecf20Sopenharmony_ci return false; 468c2ecf20Sopenharmony_ci } 478c2ecf20Sopenharmony_ci if (!zgrp_obj_is_isolated(zram->zgrp, index)) { 488c2ecf20Sopenharmony_ci pr_debug("obj %u is not isolated.\n", index); 498c2ecf20Sopenharmony_ci return false; 508c2ecf20Sopenharmony_ci } 518c2ecf20Sopenharmony_ci /* need not to writeback, put back the obj as HOTEST */ 528c2ecf20Sopenharmony_ci if (zram_test_flag(zram, index, ZRAM_SAME)) { 538c2ecf20Sopenharmony_ci pr_debug("obj %u is filled with same element.\n", index); 548c2ecf20Sopenharmony_ci goto insert; 558c2ecf20Sopenharmony_ci } 568c2ecf20Sopenharmony_ci if (zram_test_flag(zram, index, ZRAM_WB)) { 578c2ecf20Sopenharmony_ci pr_debug("obj %u is writeback.\n", index); 588c2ecf20Sopenharmony_ci goto insert; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci /* obj is needed by a pagefault req, do not writeback it. */ 618c2ecf20Sopenharmony_ci if (zram_test_flag(zram, index, ZRAM_FAULT)) { 628c2ecf20Sopenharmony_ci pr_debug("obj %u is needed by a pagefault request.\n", index); 638c2ecf20Sopenharmony_ci goto insert; 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci /* should never happen */ 668c2ecf20Sopenharmony_ci if (zram_test_flag(zram, index, ZRAM_GWB)) { 678c2ecf20Sopenharmony_ci pr_debug("obj %u is group writeback.\n", index); 688c2ecf20Sopenharmony_ci BUG(); 698c2ecf20Sopenharmony_ci return false; 708c2ecf20Sopenharmony_ci } 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci return true; 738c2ecf20Sopenharmony_ciinsert: 748c2ecf20Sopenharmony_ci zgrp_obj_insert(zram->zgrp, index, gid); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci return false; 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic void copy_obj(struct hpio *hpio, u32 offset, char *obj, u32 size, bool to) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci u32 page_id, start; 828c2ecf20Sopenharmony_ci char *buf = NULL; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci page_id = offset / PAGE_SIZE; 858c2ecf20Sopenharmony_ci start = offset % PAGE_SIZE; 868c2ecf20Sopenharmony_ci if (size + start <= PAGE_SIZE) { 878c2ecf20Sopenharmony_ci buf = page_to_virt(hyperhold_io_page(hpio, page_id)); 888c2ecf20Sopenharmony_ci if (to) 898c2ecf20Sopenharmony_ci memcpy(buf + start, obj, size); 908c2ecf20Sopenharmony_ci else 918c2ecf20Sopenharmony_ci memcpy(obj, buf + start, size); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci return; 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci buf = page_to_virt(hyperhold_io_page(hpio, page_id)); 968c2ecf20Sopenharmony_ci if (to) 978c2ecf20Sopenharmony_ci memcpy(buf + start, obj, PAGE_SIZE - start); 988c2ecf20Sopenharmony_ci else 998c2ecf20Sopenharmony_ci memcpy(obj, buf + start, PAGE_SIZE - start); 1008c2ecf20Sopenharmony_ci buf = page_to_virt(hyperhold_io_page(hpio, page_id + 1)); 1018c2ecf20Sopenharmony_ci if (to) 1028c2ecf20Sopenharmony_ci memcpy(buf, obj + PAGE_SIZE - start, size + start - PAGE_SIZE); 1038c2ecf20Sopenharmony_ci else 1048c2ecf20Sopenharmony_ci memcpy(obj + PAGE_SIZE - start, buf, size + start - PAGE_SIZE); 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic u32 move_obj_to_hpio(struct zram *zram, u32 index, u16 gid, 1088c2ecf20Sopenharmony_ci struct hpio *hpio, u32 offset) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci u32 size = 0; 1118c2ecf20Sopenharmony_ci unsigned long handle; 1128c2ecf20Sopenharmony_ci char *src = NULL; 1138c2ecf20Sopenharmony_ci u32 ext_size; 1148c2ecf20Sopenharmony_ci u32 eid; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci eid = hyperhold_io_extent(hpio); 1178c2ecf20Sopenharmony_ci ext_size = hyperhold_extent_size(eid); 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci zram_slot_lock(zram, index); 1208c2ecf20Sopenharmony_ci if (!obj_can_wb(zram, index, gid)) 1218c2ecf20Sopenharmony_ci goto unlock; 1228c2ecf20Sopenharmony_ci size = zram_get_obj_size(zram, index); 1238c2ecf20Sopenharmony_ci /* no space, put back the obj as COLDEST */ 1248c2ecf20Sopenharmony_ci if (size + offset > ext_size) { 1258c2ecf20Sopenharmony_ci pr_debug("obj %u size is %u, but ext %u only %u space left.\n", 1268c2ecf20Sopenharmony_ci index, size, eid, ext_size - offset); 1278c2ecf20Sopenharmony_ci zgrp_obj_putback(zram->zgrp, index, gid); 1288c2ecf20Sopenharmony_ci size = 0; 1298c2ecf20Sopenharmony_ci goto unlock; 1308c2ecf20Sopenharmony_ci } 1318c2ecf20Sopenharmony_ci handle = zram_get_handle(zram, index); 1328c2ecf20Sopenharmony_ci src = zs_map_object(zram->mem_pool, handle, ZS_MM_RO); 1338c2ecf20Sopenharmony_ci copy_obj(hpio, offset, src, size, true); 1348c2ecf20Sopenharmony_ci zs_unmap_object(zram->mem_pool, handle); 1358c2ecf20Sopenharmony_ci zs_free(zram->mem_pool, handle); 1368c2ecf20Sopenharmony_ci zram_set_handle(zram, index, hyperhold_address(eid, offset)); 1378c2ecf20Sopenharmony_ci zram_set_flag(zram, index, ZRAM_GWB); 1388c2ecf20Sopenharmony_ci wbgrp_obj_insert(zram->zgrp, index, eid); 1398c2ecf20Sopenharmony_ci wbgrp_obj_stats_inc(zram->zgrp, gid, eid, size); 1408c2ecf20Sopenharmony_ci zgrp_obj_stats_dec(zram->zgrp, gid, size); 1418c2ecf20Sopenharmony_ci pr_debug("move obj %u of group %u to hpio %p of eid %u, size = %u, offset = %u\n", 1428c2ecf20Sopenharmony_ci index, gid, hpio, eid, size, offset); 1438c2ecf20Sopenharmony_ciunlock: 1448c2ecf20Sopenharmony_ci zram_slot_unlock(zram, index); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci return size; 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic void move_obj_from_hpio(struct zram *zram, int index, struct hpio *hpio) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci u32 size = 0; 1528c2ecf20Sopenharmony_ci unsigned long handle = 0; 1538c2ecf20Sopenharmony_ci u32 eid, offset; 1548c2ecf20Sopenharmony_ci u64 addr; 1558c2ecf20Sopenharmony_ci char *dst = NULL; 1568c2ecf20Sopenharmony_ci u16 gid; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci eid = hyperhold_io_extent(hpio); 1598c2ecf20Sopenharmony_ciretry: 1608c2ecf20Sopenharmony_ci zram_slot_lock(zram, index); 1618c2ecf20Sopenharmony_ci if (!zram_test_flag(zram, index, ZRAM_GWB)) 1628c2ecf20Sopenharmony_ci goto unlock; 1638c2ecf20Sopenharmony_ci addr = zram_get_handle(zram, index); 1648c2ecf20Sopenharmony_ci if (hyperhold_addr_extent(addr) != eid) 1658c2ecf20Sopenharmony_ci goto unlock; 1668c2ecf20Sopenharmony_ci size = zram_get_obj_size(zram, index); 1678c2ecf20Sopenharmony_ci if (handle) 1688c2ecf20Sopenharmony_ci goto move; 1698c2ecf20Sopenharmony_ci handle = zs_malloc(zram->mem_pool, size, GFP_NOWAIT); 1708c2ecf20Sopenharmony_ci if (handle) 1718c2ecf20Sopenharmony_ci goto move; 1728c2ecf20Sopenharmony_ci zram_slot_unlock(zram, index); 1738c2ecf20Sopenharmony_ci handle = zs_malloc(zram->mem_pool, size, GFP_NOIO | __GFP_NOFAIL); 1748c2ecf20Sopenharmony_ci if (handle) 1758c2ecf20Sopenharmony_ci goto retry; 1768c2ecf20Sopenharmony_ci BUG(); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci return; 1798c2ecf20Sopenharmony_cimove: 1808c2ecf20Sopenharmony_ci offset = hyperhold_addr_offset(addr); 1818c2ecf20Sopenharmony_ci dst = zs_map_object(zram->mem_pool, handle, ZS_MM_WO); 1828c2ecf20Sopenharmony_ci copy_obj(hpio, offset, dst, size, false); 1838c2ecf20Sopenharmony_ci zs_unmap_object(zram->mem_pool, handle); 1848c2ecf20Sopenharmony_ci zram_set_handle(zram, index, handle); 1858c2ecf20Sopenharmony_ci zram_clear_flag(zram, index, ZRAM_GWB); 1868c2ecf20Sopenharmony_ci gid = zram_get_memcg_id(zram, index); 1878c2ecf20Sopenharmony_ci zgrp_obj_insert(zram->zgrp, index, gid); 1888c2ecf20Sopenharmony_ci wbgrp_obj_stats_dec(zram->zgrp, gid, eid, size); 1898c2ecf20Sopenharmony_ci zgrp_obj_stats_inc(zram->zgrp, gid, size); 1908c2ecf20Sopenharmony_ci pr_debug("move obj %u of group %u from hpio %p of eid %u, size = %u, offset = %u\n", 1918c2ecf20Sopenharmony_ci index, gid, hpio, eid, size, offset); 1928c2ecf20Sopenharmony_ciunlock: 1938c2ecf20Sopenharmony_ci zram_slot_unlock(zram, index); 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci#define NR_ISOLATE 32 1988c2ecf20Sopenharmony_cistatic bool move_extent_from_hpio(struct zram *zram, struct hpio *hpio) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci u32 idxs[NR_ISOLATE]; 2018c2ecf20Sopenharmony_ci u32 eid; 2028c2ecf20Sopenharmony_ci u32 nr; 2038c2ecf20Sopenharmony_ci int i; 2048c2ecf20Sopenharmony_ci bool last = false; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci eid = hyperhold_io_extent(hpio); 2078c2ecf20Sopenharmony_cirepeat: 2088c2ecf20Sopenharmony_ci nr = wbgrp_isolate_objs(zram->zgrp, eid, idxs, NR_ISOLATE, &last); 2098c2ecf20Sopenharmony_ci for (i = 0; i < nr; i++) 2108c2ecf20Sopenharmony_ci move_obj_from_hpio(zram, idxs[i], hpio); 2118c2ecf20Sopenharmony_ci if (last) 2128c2ecf20Sopenharmony_ci return true; 2138c2ecf20Sopenharmony_ci if (nr) 2148c2ecf20Sopenharmony_ci goto repeat; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci return false; 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistruct hpio_priv { 2208c2ecf20Sopenharmony_ci struct zram *zram; 2218c2ecf20Sopenharmony_ci u16 gid; 2228c2ecf20Sopenharmony_ci}; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_cistatic void write_endio(struct hpio *hpio) 2258c2ecf20Sopenharmony_ci{ 2268c2ecf20Sopenharmony_ci struct hpio_priv *priv = hyperhold_io_private(hpio); 2278c2ecf20Sopenharmony_ci struct zram *zram = priv->zram; 2288c2ecf20Sopenharmony_ci u16 gid = priv->gid; 2298c2ecf20Sopenharmony_ci u32 eid = hyperhold_io_extent(hpio); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci if (hyperhold_io_success(hpio)) 2328c2ecf20Sopenharmony_ci goto out; 2338c2ecf20Sopenharmony_ci if (move_extent_from_hpio(zram, hpio)) { 2348c2ecf20Sopenharmony_ci zgrp_ext_delete(zram->zgrp, eid, gid); 2358c2ecf20Sopenharmony_ci hyperhold_should_free_extent(eid); 2368c2ecf20Sopenharmony_ci } 2378c2ecf20Sopenharmony_ciout: 2388c2ecf20Sopenharmony_ci hyperhold_io_complete(hpio); 2398c2ecf20Sopenharmony_ci hyperhold_io_put(hpio); 2408c2ecf20Sopenharmony_ci kfree(priv); 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_cistatic u32 collect_objs(struct zram *zram, u16 gid, struct hpio *hpio, u32 ext_size) 2448c2ecf20Sopenharmony_ci{ 2458c2ecf20Sopenharmony_ci u32 offset = 0; 2468c2ecf20Sopenharmony_ci u32 last_offset; 2478c2ecf20Sopenharmony_ci u32 nr; 2488c2ecf20Sopenharmony_ci u32 idxs[NR_ISOLATE]; 2498c2ecf20Sopenharmony_ci int i; 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_cimore: 2528c2ecf20Sopenharmony_ci last_offset = offset; 2538c2ecf20Sopenharmony_ci nr = zgrp_isolate_objs(zram->zgrp, gid, idxs, NR_ISOLATE, NULL); 2548c2ecf20Sopenharmony_ci for (i = 0; i < nr; i++) 2558c2ecf20Sopenharmony_ci offset += move_obj_to_hpio(zram, idxs[i], gid, hpio, offset); 2568c2ecf20Sopenharmony_ci pr_debug("%u data attached, offset = %u.\n", offset - last_offset, offset); 2578c2ecf20Sopenharmony_ci if (offset < ext_size && offset != last_offset) 2588c2ecf20Sopenharmony_ci goto more; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci return offset; 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_cistatic u64 write_one_extent(struct zram *zram, u16 gid) 2648c2ecf20Sopenharmony_ci{ 2658c2ecf20Sopenharmony_ci int eid; 2668c2ecf20Sopenharmony_ci struct hpio *hpio = NULL; 2678c2ecf20Sopenharmony_ci struct hpio_priv *priv = NULL; 2688c2ecf20Sopenharmony_ci u32 size = 0; 2698c2ecf20Sopenharmony_ci int ret; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci priv = kmalloc(sizeof(struct hpio_priv), GFP_NOIO); 2728c2ecf20Sopenharmony_ci if (!priv) 2738c2ecf20Sopenharmony_ci return 0; 2748c2ecf20Sopenharmony_ci priv->gid = gid; 2758c2ecf20Sopenharmony_ci priv->zram = zram; 2768c2ecf20Sopenharmony_ci eid = hyperhold_alloc_extent(); 2778c2ecf20Sopenharmony_ci if (eid < 0) 2788c2ecf20Sopenharmony_ci goto err; 2798c2ecf20Sopenharmony_ci hpio = hyperhold_io_get(eid, GFP_NOIO, REQ_OP_WRITE); 2808c2ecf20Sopenharmony_ci if (!hpio) 2818c2ecf20Sopenharmony_ci goto free_extent; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci zgrp_get_ext(zram->zgrp, eid); 2848c2ecf20Sopenharmony_ci size = collect_objs(zram, gid, hpio, hyperhold_extent_size(eid)); 2858c2ecf20Sopenharmony_ci if (size == 0) { 2868c2ecf20Sopenharmony_ci pr_err("group %u has no data in zram.\n", gid); 2878c2ecf20Sopenharmony_ci zgrp_put_ext(zram->zgrp, eid); 2888c2ecf20Sopenharmony_ci goto put_hpio; 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci zgrp_ext_insert(zram->zgrp, eid, gid); 2918c2ecf20Sopenharmony_ci if (zgrp_put_ext(zram->zgrp, eid)) { 2928c2ecf20Sopenharmony_ci zgrp_ext_delete(zram->zgrp, eid, gid); 2938c2ecf20Sopenharmony_ci hyperhold_should_free_extent(eid); 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci ret = hyperhold_write_async(hpio, write_endio, priv); 2978c2ecf20Sopenharmony_ci if (ret) 2988c2ecf20Sopenharmony_ci goto move_back; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci return size; 3018c2ecf20Sopenharmony_cimove_back: 3028c2ecf20Sopenharmony_ci if (move_extent_from_hpio(zram, hpio)) { 3038c2ecf20Sopenharmony_ci zgrp_ext_delete(zram->zgrp, eid, gid); 3048c2ecf20Sopenharmony_ci hyperhold_should_free_extent(eid); 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci eid = -EINVAL; 3078c2ecf20Sopenharmony_ciput_hpio: 3088c2ecf20Sopenharmony_ci hyperhold_io_put(hpio); 3098c2ecf20Sopenharmony_cifree_extent: 3108c2ecf20Sopenharmony_ci if (eid >= 0) 3118c2ecf20Sopenharmony_ci hyperhold_free_extent(eid); 3128c2ecf20Sopenharmony_cierr: 3138c2ecf20Sopenharmony_ci kfree(priv); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci return 0; 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_cistatic void read_endio(struct hpio *hpio) 3198c2ecf20Sopenharmony_ci{ 3208c2ecf20Sopenharmony_ci struct hpio_priv *priv = hyperhold_io_private(hpio); 3218c2ecf20Sopenharmony_ci struct zram *zram = priv->zram; 3228c2ecf20Sopenharmony_ci u16 gid = priv->gid; 3238c2ecf20Sopenharmony_ci u32 eid = hyperhold_io_extent(hpio); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci if (!hyperhold_io_success(hpio)) { 3268c2ecf20Sopenharmony_ci BUG(); 3278c2ecf20Sopenharmony_ci goto out; 3288c2ecf20Sopenharmony_ci } 3298c2ecf20Sopenharmony_ci if (move_extent_from_hpio(zram, hpio)) { 3308c2ecf20Sopenharmony_ci zgrp_ext_delete(zram->zgrp, eid, gid); 3318c2ecf20Sopenharmony_ci hyperhold_should_free_extent(eid); 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ciout: 3348c2ecf20Sopenharmony_ci hyperhold_io_complete(hpio); 3358c2ecf20Sopenharmony_ci hyperhold_io_put(hpio); 3368c2ecf20Sopenharmony_ci kfree(priv); 3378c2ecf20Sopenharmony_ci} 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_cistatic u64 read_one_extent(struct zram *zram, u32 eid, u16 gid) 3408c2ecf20Sopenharmony_ci{ 3418c2ecf20Sopenharmony_ci struct hpio *hpio = NULL; 3428c2ecf20Sopenharmony_ci u32 ext_size = 0; 3438c2ecf20Sopenharmony_ci int ret; 3448c2ecf20Sopenharmony_ci struct hpio_priv *priv = NULL; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci priv = kmalloc(sizeof(struct hpio_priv), GFP_NOIO); 3478c2ecf20Sopenharmony_ci if (!priv) 3488c2ecf20Sopenharmony_ci goto err; 3498c2ecf20Sopenharmony_ci priv->gid = gid; 3508c2ecf20Sopenharmony_ci priv->zram = zram; 3518c2ecf20Sopenharmony_ci hpio = hyperhold_io_get(eid, GFP_NOIO, REQ_OP_READ); 3528c2ecf20Sopenharmony_ci if (!hpio) 3538c2ecf20Sopenharmony_ci goto err; 3548c2ecf20Sopenharmony_ci ext_size = hyperhold_extent_size(eid); 3558c2ecf20Sopenharmony_ci ret = hyperhold_read_async(hpio, read_endio, priv); 3568c2ecf20Sopenharmony_ci if (ret) 3578c2ecf20Sopenharmony_ci goto err; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci return ext_size; 3608c2ecf20Sopenharmony_cierr: 3618c2ecf20Sopenharmony_ci hyperhold_io_put(hpio); 3628c2ecf20Sopenharmony_ci kfree(priv); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci return 0; 3658c2ecf20Sopenharmony_ci} 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_cistatic void sync_read_endio(struct hpio *hpio) 3688c2ecf20Sopenharmony_ci{ 3698c2ecf20Sopenharmony_ci hyperhold_io_complete(hpio); 3708c2ecf20Sopenharmony_ci} 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_cistatic int read_one_obj_sync(struct zram *zram, u32 index) 3738c2ecf20Sopenharmony_ci{ 3748c2ecf20Sopenharmony_ci struct hpio *hpio = NULL; 3758c2ecf20Sopenharmony_ci int ret; 3768c2ecf20Sopenharmony_ci u32 eid; 3778c2ecf20Sopenharmony_ci u16 gid; 3788c2ecf20Sopenharmony_ci u32 size; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci if (!zram_test_flag(zram, index, ZRAM_GWB)) 3818c2ecf20Sopenharmony_ci return 0; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci pr_debug("read obj %u.\n", index); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci gid = zram_get_memcg_id(zram, index); 3868c2ecf20Sopenharmony_ci eid = hyperhold_addr_extent(zram_get_handle(zram, index)); 3878c2ecf20Sopenharmony_ci size = zram_get_obj_size(zram, index); 3888c2ecf20Sopenharmony_ci wbgrp_fault_stats_inc(zram->zgrp, gid, eid, size); 3898c2ecf20Sopenharmony_cicheck: 3908c2ecf20Sopenharmony_ci if (!zram_test_flag(zram, index, ZRAM_GWB)) 3918c2ecf20Sopenharmony_ci return 0; 3928c2ecf20Sopenharmony_ci if (!zram_test_flag(zram, index, ZRAM_FAULT)) 3938c2ecf20Sopenharmony_ci goto read; 3948c2ecf20Sopenharmony_ci zram_slot_unlock(zram, index); 3958c2ecf20Sopenharmony_ci wait_event(zram->zgrp->wbgrp.fault_wq, !zram_test_flag(zram, index, ZRAM_FAULT)); 3968c2ecf20Sopenharmony_ci zram_slot_lock(zram, index); 3978c2ecf20Sopenharmony_ci goto check; 3988c2ecf20Sopenharmony_ciread: 3998c2ecf20Sopenharmony_ci zram_set_flag(zram, index, ZRAM_FAULT); 4008c2ecf20Sopenharmony_ci zram_slot_unlock(zram, index); 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci hpio = hyperhold_io_get(eid, GFP_NOIO, REQ_OP_READ); 4038c2ecf20Sopenharmony_ci if (!hpio) { 4048c2ecf20Sopenharmony_ci ret = -ENOMEM; 4058c2ecf20Sopenharmony_ci goto out; 4068c2ecf20Sopenharmony_ci } 4078c2ecf20Sopenharmony_ci ret = hyperhold_read_async(hpio, sync_read_endio, NULL); 4088c2ecf20Sopenharmony_ci /* io submit error */ 4098c2ecf20Sopenharmony_ci if (ret && ret != -EAGAIN) 4108c2ecf20Sopenharmony_ci goto out; 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci hyperhold_io_wait(hpio); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci /* if not reset to zero, will return err sometimes and cause SIG_BUS error */ 4158c2ecf20Sopenharmony_ci ret = 0; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci /* get a write io, data is ready, copy the pages even write failed */ 4188c2ecf20Sopenharmony_ci if (op_is_write(hyperhold_io_operate(hpio))) 4198c2ecf20Sopenharmony_ci goto move; 4208c2ecf20Sopenharmony_ci /* read io failed, return -EIO */ 4218c2ecf20Sopenharmony_ci if (!hyperhold_io_success(hpio)) { 4228c2ecf20Sopenharmony_ci ret = -EIO; 4238c2ecf20Sopenharmony_ci goto out; 4248c2ecf20Sopenharmony_ci } 4258c2ecf20Sopenharmony_ci /* success, copy the data and free extent */ 4268c2ecf20Sopenharmony_cimove: 4278c2ecf20Sopenharmony_ci if (move_extent_from_hpio(zram, hpio)) { 4288c2ecf20Sopenharmony_ci zgrp_ext_delete(zram->zgrp, eid, gid); 4298c2ecf20Sopenharmony_ci hyperhold_should_free_extent(eid); 4308c2ecf20Sopenharmony_ci } 4318c2ecf20Sopenharmony_ci move_obj_from_hpio(zram, index, hpio); 4328c2ecf20Sopenharmony_ciout: 4338c2ecf20Sopenharmony_ci hyperhold_io_put(hpio); 4348c2ecf20Sopenharmony_ci zram_slot_lock(zram, index); 4358c2ecf20Sopenharmony_ci zram_clear_flag(zram, index, ZRAM_FAULT); 4368c2ecf20Sopenharmony_ci wake_up(&zram->zgrp->wbgrp.fault_wq); 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci return ret; 4398c2ecf20Sopenharmony_ci} 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ciu64 read_group_objs(struct zram *zram, u16 gid, u64 req_size) 4428c2ecf20Sopenharmony_ci{ 4438c2ecf20Sopenharmony_ci u32 eid; 4448c2ecf20Sopenharmony_ci u64 read_size = 0; 4458c2ecf20Sopenharmony_ci u32 nr; 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci if (!(zram->zgrp)) { 4488c2ecf20Sopenharmony_ci pr_debug("zram group is not enable!\n"); 4498c2ecf20Sopenharmony_ci return 0; 4508c2ecf20Sopenharmony_ci } 4518c2ecf20Sopenharmony_ci if (!CHECK_BOUND(gid, 1, zram->zgrp->nr_grp - 1)) 4528c2ecf20Sopenharmony_ci return 0; 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci pr_debug("read %llu data of group %u.\n", req_size, gid); 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci while (!req_size || req_size > read_size) { 4578c2ecf20Sopenharmony_ci nr = zgrp_isolate_exts(zram->zgrp, gid, &eid, 1, NULL); 4588c2ecf20Sopenharmony_ci if (!nr) 4598c2ecf20Sopenharmony_ci break; 4608c2ecf20Sopenharmony_ci read_size += read_one_extent(zram, eid, gid); 4618c2ecf20Sopenharmony_ci } 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci return read_size; 4648c2ecf20Sopenharmony_ci} 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ciu64 write_group_objs(struct zram *zram, u16 gid, u64 req_size) 4678c2ecf20Sopenharmony_ci{ 4688c2ecf20Sopenharmony_ci u64 write_size = 0; 4698c2ecf20Sopenharmony_ci u64 size = 0; 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci if (!(zram->zgrp)) { 4728c2ecf20Sopenharmony_ci pr_debug("zram group is not enable!\n"); 4738c2ecf20Sopenharmony_ci return 0; 4748c2ecf20Sopenharmony_ci } 4758c2ecf20Sopenharmony_ci if (!CHECK(zram->zgrp->wbgrp.enable, "zram group writeback is not enable!\n")) 4768c2ecf20Sopenharmony_ci return 0; 4778c2ecf20Sopenharmony_ci if (!CHECK_BOUND(gid, 1, zram->zgrp->nr_grp - 1)) 4788c2ecf20Sopenharmony_ci return 0; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci pr_debug("write %llu data of group %u.\n", req_size, gid); 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci while (!req_size || req_size > write_size) { 4838c2ecf20Sopenharmony_ci size = write_one_extent(zram, gid); 4848c2ecf20Sopenharmony_ci if (!size) 4858c2ecf20Sopenharmony_ci break; 4868c2ecf20Sopenharmony_ci write_size += size; 4878c2ecf20Sopenharmony_ci } 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci atomic64_add(write_size, &zram->zgrp->stats[0].write_size); 4908c2ecf20Sopenharmony_ci atomic64_add(write_size, &zram->zgrp->stats[gid].write_size); 4918c2ecf20Sopenharmony_ci return write_size; 4928c2ecf20Sopenharmony_ci} 4938c2ecf20Sopenharmony_ci#endif 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_GROUP_DEBUG 4968c2ecf20Sopenharmony_ci#include <linux/random.h> 4978c2ecf20Sopenharmony_ci#define ZGRP_TEST_MAX_GRP 101 4988c2ecf20Sopenharmony_ci#endif 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ciint zram_group_fault_obj(struct zram *zram, u32 index) 5018c2ecf20Sopenharmony_ci{ 5028c2ecf20Sopenharmony_ci u16 gid; 5038c2ecf20Sopenharmony_ci u32 size; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci if (!(zram->zgrp)) { 5068c2ecf20Sopenharmony_ci pr_debug("zram group is not enable!\n"); 5078c2ecf20Sopenharmony_ci return 0; 5088c2ecf20Sopenharmony_ci } 5098c2ecf20Sopenharmony_ci if (!CHECK_BOUND(index, 0, zram->zgrp->nr_obj - 1)) 5108c2ecf20Sopenharmony_ci return 0; 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci gid = zram_get_memcg_id(zram, index); 5138c2ecf20Sopenharmony_ci size = zram_get_obj_size(zram, index); 5148c2ecf20Sopenharmony_ci zgrp_fault_stats_inc(zram->zgrp, gid, size); 5158c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_GROUP_WRITEBACK 5168c2ecf20Sopenharmony_ci return read_one_obj_sync(zram, index); 5178c2ecf20Sopenharmony_ci#else 5188c2ecf20Sopenharmony_ci return 0; 5198c2ecf20Sopenharmony_ci#endif 5208c2ecf20Sopenharmony_ci} 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_civoid zram_group_track_obj(struct zram *zram, u32 index, struct mem_cgroup *memcg) 5238c2ecf20Sopenharmony_ci{ 5248c2ecf20Sopenharmony_ci u16 gid; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci if (!(zram->zgrp)) { 5278c2ecf20Sopenharmony_ci pr_debug("zram group is not enable!\n"); 5288c2ecf20Sopenharmony_ci return; 5298c2ecf20Sopenharmony_ci } 5308c2ecf20Sopenharmony_ci if (!CHECK_BOUND(index, 0, zram->zgrp->nr_obj - 1)) 5318c2ecf20Sopenharmony_ci return; 5328c2ecf20Sopenharmony_ci if (!CHECK(memcg || !memcg->id.id, "obj %u has no memcg!\n", index)) 5338c2ecf20Sopenharmony_ci return; 5348c2ecf20Sopenharmony_ci gid = zram_get_memcg_id(zram, index); 5358c2ecf20Sopenharmony_ci if (!CHECK(!gid, "obj %u has gid %u.\n", index, gid)) 5368c2ecf20Sopenharmony_ci BUG(); 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci gid = memcg->id.id; 5398c2ecf20Sopenharmony_ci zram_set_memcg_id(zram, index, gid); 5408c2ecf20Sopenharmony_ci zgrp_obj_insert(zram->zgrp, index, gid); 5418c2ecf20Sopenharmony_ci zgrp_obj_stats_inc(zram->zgrp, gid, zram_get_obj_size(zram, index)); 5428c2ecf20Sopenharmony_ci} 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_civoid zram_group_untrack_obj(struct zram *zram, u32 index) 5458c2ecf20Sopenharmony_ci{ 5468c2ecf20Sopenharmony_ci u16 gid; 5478c2ecf20Sopenharmony_ci u32 size; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci if (!(zram->zgrp)) { 5508c2ecf20Sopenharmony_ci pr_debug("zram group is not enable!\n"); 5518c2ecf20Sopenharmony_ci return; 5528c2ecf20Sopenharmony_ci } 5538c2ecf20Sopenharmony_ci if (!CHECK_BOUND(index, 0, zram->zgrp->nr_obj - 1)) 5548c2ecf20Sopenharmony_ci return; 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_GROUP_WRITEBACK 5578c2ecf20Sopenharmony_cicheck: 5588c2ecf20Sopenharmony_ci if (!zram_test_flag(zram, index, ZRAM_FAULT)) 5598c2ecf20Sopenharmony_ci goto clear; 5608c2ecf20Sopenharmony_ci zram_slot_unlock(zram, index); 5618c2ecf20Sopenharmony_ci wait_event(zram->zgrp->wbgrp.fault_wq, !zram_test_flag(zram, index, ZRAM_FAULT)); 5628c2ecf20Sopenharmony_ci zram_slot_lock(zram, index); 5638c2ecf20Sopenharmony_ci goto check; 5648c2ecf20Sopenharmony_ciclear: 5658c2ecf20Sopenharmony_ci#endif 5668c2ecf20Sopenharmony_ci gid = zram_get_memcg_id(zram, index); 5678c2ecf20Sopenharmony_ci size = zram_get_obj_size(zram, index); 5688c2ecf20Sopenharmony_ci if (!gid) 5698c2ecf20Sopenharmony_ci return; 5708c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_GROUP_WRITEBACK 5718c2ecf20Sopenharmony_ci if (zram_test_flag(zram, index, ZRAM_GWB)) { 5728c2ecf20Sopenharmony_ci u32 eid = hyperhold_addr_extent(zram_get_handle(zram, index)); 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci if (wbgrp_obj_delete(zram->zgrp, index, eid)) { 5758c2ecf20Sopenharmony_ci zgrp_ext_delete(zram->zgrp, eid, gid); 5768c2ecf20Sopenharmony_ci hyperhold_should_free_extent(eid); 5778c2ecf20Sopenharmony_ci } 5788c2ecf20Sopenharmony_ci zram_clear_flag(zram, index, ZRAM_GWB); 5798c2ecf20Sopenharmony_ci zram_set_memcg_id(zram, index, 0); 5808c2ecf20Sopenharmony_ci wbgrp_obj_stats_dec(zram->zgrp, gid, eid, size); 5818c2ecf20Sopenharmony_ci zram_set_handle(zram, index, 0); 5828c2ecf20Sopenharmony_ci return; 5838c2ecf20Sopenharmony_ci } 5848c2ecf20Sopenharmony_ci#endif 5858c2ecf20Sopenharmony_ci zgrp_obj_delete(zram->zgrp, index, gid); 5868c2ecf20Sopenharmony_ci zram_set_memcg_id(zram, index, 0); 5878c2ecf20Sopenharmony_ci zgrp_obj_stats_dec(zram->zgrp, gid, size); 5888c2ecf20Sopenharmony_ci} 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_GROUP_DEBUG 5918c2ecf20Sopenharmony_civoid group_debug(struct zram *zram, u32 op, u32 index, u32 gid) 5928c2ecf20Sopenharmony_ci{ 5938c2ecf20Sopenharmony_ci if (op == 0) 5948c2ecf20Sopenharmony_ci zram_group_dump(zram->zgrp, gid, index); 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_GROUP_WRITEBACK 5978c2ecf20Sopenharmony_ci if (op == 22) 5988c2ecf20Sopenharmony_ci read_group_objs(zram, gid, index); 5998c2ecf20Sopenharmony_ci if (op == 23) 6008c2ecf20Sopenharmony_ci write_group_objs(zram, gid, index); 6018c2ecf20Sopenharmony_ci if (op == 20) { 6028c2ecf20Sopenharmony_ci if (index) 6038c2ecf20Sopenharmony_ci zram_group_apply_writeback(zram->zgrp, hyperhold_nr_extent()); 6048c2ecf20Sopenharmony_ci else 6058c2ecf20Sopenharmony_ci zram_group_remove_writeback(zram->zgrp); 6068c2ecf20Sopenharmony_ci } 6078c2ecf20Sopenharmony_ci#endif 6088c2ecf20Sopenharmony_ci} 6098c2ecf20Sopenharmony_ci#endif 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_cistatic u64 group_obj_stats(struct zram *zram, u16 gid, int type) 6128c2ecf20Sopenharmony_ci{ 6138c2ecf20Sopenharmony_ci if (!(zram->zgrp)) { 6148c2ecf20Sopenharmony_ci pr_debug("zram group is not enable!\n"); 6158c2ecf20Sopenharmony_ci return 0; 6168c2ecf20Sopenharmony_ci } 6178c2ecf20Sopenharmony_ci if (!CHECK_BOUND(gid, 0, zram->zgrp->nr_grp - 1)) 6188c2ecf20Sopenharmony_ci return 0; 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci if (type == CACHE_SIZE) 6218c2ecf20Sopenharmony_ci return atomic64_read(&zram->zgrp->stats[gid].zram_size); 6228c2ecf20Sopenharmony_ci else if (type == CACHE_PAGE) 6238c2ecf20Sopenharmony_ci return atomic_read(&zram->zgrp->stats[gid].zram_pages); 6248c2ecf20Sopenharmony_ci else if (type == CACHE_FAULT) 6258c2ecf20Sopenharmony_ci return atomic64_read(&zram->zgrp->stats[gid].zram_fault); 6268c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_GROUP_WRITEBACK 6278c2ecf20Sopenharmony_ci else if (type == SWAP_SIZE) 6288c2ecf20Sopenharmony_ci return atomic64_read(&zram->zgrp->stats[gid].wb_size); 6298c2ecf20Sopenharmony_ci else if (type == SWAP_PAGE) 6308c2ecf20Sopenharmony_ci return atomic_read(&zram->zgrp->stats[gid].wb_pages); 6318c2ecf20Sopenharmony_ci else if (type == READ_SIZE) 6328c2ecf20Sopenharmony_ci return atomic64_read(&zram->zgrp->stats[gid].read_size); 6338c2ecf20Sopenharmony_ci else if (type == WRITE_SIZE) 6348c2ecf20Sopenharmony_ci return atomic64_read(&zram->zgrp->stats[gid].write_size); 6358c2ecf20Sopenharmony_ci else if (type == SWAP_FAULT) 6368c2ecf20Sopenharmony_ci return atomic64_read(&zram->zgrp->stats[gid].wb_fault); 6378c2ecf20Sopenharmony_ci BUG(); 6388c2ecf20Sopenharmony_ci#endif 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci return 0; 6418c2ecf20Sopenharmony_ci} 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_GROUP_WRITEBACK 6448c2ecf20Sopenharmony_cistatic u64 zram_group_read(u16 gid, u64 req_size, void *priv) 6458c2ecf20Sopenharmony_ci{ 6468c2ecf20Sopenharmony_ci if (!CHECK(priv, "priv is NULL!\n")) 6478c2ecf20Sopenharmony_ci return 0; 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci return read_group_objs((struct zram *)priv, gid, req_size); 6508c2ecf20Sopenharmony_ci} 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_cistatic u64 zram_group_write(u16 gid, u64 req_size, void *priv) 6538c2ecf20Sopenharmony_ci{ 6548c2ecf20Sopenharmony_ci if (!CHECK(priv, "priv is NULL!\n")) 6558c2ecf20Sopenharmony_ci return 0; 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci return write_group_objs((struct zram *)priv, gid, req_size); 6588c2ecf20Sopenharmony_ci} 6598c2ecf20Sopenharmony_ci#else 6608c2ecf20Sopenharmony_cistatic u64 zram_group_read(u16 gid, u64 req_size, void *priv) 6618c2ecf20Sopenharmony_ci{ 6628c2ecf20Sopenharmony_ci return 0; 6638c2ecf20Sopenharmony_ci} 6648c2ecf20Sopenharmony_cistatic u64 zram_group_write(u16 gid, u64 req_size, void *priv) 6658c2ecf20Sopenharmony_ci{ 6668c2ecf20Sopenharmony_ci return 0; 6678c2ecf20Sopenharmony_ci} 6688c2ecf20Sopenharmony_ci#endif 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_cistatic u64 zram_group_data_size(u16 gid, int type, void *priv) 6728c2ecf20Sopenharmony_ci{ 6738c2ecf20Sopenharmony_ci if (!CHECK(priv, "priv is NULL!\n")) 6748c2ecf20Sopenharmony_ci return 0; 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci return group_obj_stats((struct zram *)priv, gid, type); 6778c2ecf20Sopenharmony_ci} 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_cistruct group_swap_ops zram_group_ops = { 6808c2ecf20Sopenharmony_ci .group_read = zram_group_read, 6818c2ecf20Sopenharmony_ci .group_write = zram_group_write, 6828c2ecf20Sopenharmony_ci .group_data_size = zram_group_data_size, 6838c2ecf20Sopenharmony_ci}; 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_cistatic int register_zram_group(struct zram *zram) 6868c2ecf20Sopenharmony_ci{ 6878c2ecf20Sopenharmony_ci if (!CHECK(zram, "zram is NULL!\n")) 6888c2ecf20Sopenharmony_ci return -EINVAL; 6898c2ecf20Sopenharmony_ci if (!(zram->zgrp)) { 6908c2ecf20Sopenharmony_ci pr_debug("zram group is not enable!\n"); 6918c2ecf20Sopenharmony_ci return -EINVAL; 6928c2ecf20Sopenharmony_ci } 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci zram->zgrp->gsdev = register_group_swap(&zram_group_ops, zram); 6958c2ecf20Sopenharmony_ci if (!zram->zgrp->gsdev) { 6968c2ecf20Sopenharmony_ci pr_err("register zram group failed!\n"); 6978c2ecf20Sopenharmony_ci return -ENOMEM; 6988c2ecf20Sopenharmony_ci } 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci return 0; 7018c2ecf20Sopenharmony_ci} 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_cistatic void unregister_zram_group(struct zram *zram) 7048c2ecf20Sopenharmony_ci{ 7058c2ecf20Sopenharmony_ci if (!CHECK(zram, "zram is NULL!\n")) 7068c2ecf20Sopenharmony_ci return; 7078c2ecf20Sopenharmony_ci if (!(zram->zgrp)) { 7088c2ecf20Sopenharmony_ci pr_debug("zram group is not enable!\n"); 7098c2ecf20Sopenharmony_ci return; 7108c2ecf20Sopenharmony_ci } 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci unregister_group_swap(zram->zgrp->gsdev); 7138c2ecf20Sopenharmony_ci zram->zgrp->gsdev = NULL; 7148c2ecf20Sopenharmony_ci} 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_civoid zram_group_init(struct zram *zram, u32 nr_obj) 7178c2ecf20Sopenharmony_ci{ 7188c2ecf20Sopenharmony_ci unsigned int ctrl = zram->zgrp_ctrl; 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci if (ctrl == ZGRP_NONE) 7218c2ecf20Sopenharmony_ci return; 7228c2ecf20Sopenharmony_ci zram->zgrp = zram_group_meta_alloc(nr_obj, ZGRP_MAX_GRP - 1); 7238c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_GROUP_WRITEBACK 7248c2ecf20Sopenharmony_ci if (ctrl == ZGRP_WRITE) 7258c2ecf20Sopenharmony_ci zram_group_apply_writeback(zram->zgrp, hyperhold_nr_extent()); 7268c2ecf20Sopenharmony_ci#endif 7278c2ecf20Sopenharmony_ci register_zram_group(zram); 7288c2ecf20Sopenharmony_ci} 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_civoid zram_group_deinit(struct zram *zram) 7318c2ecf20Sopenharmony_ci{ 7328c2ecf20Sopenharmony_ci unregister_zram_group(zram); 7338c2ecf20Sopenharmony_ci zram_group_meta_free(zram->zgrp); 7348c2ecf20Sopenharmony_ci zram->zgrp = NULL; 7358c2ecf20Sopenharmony_ci} 736