18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Compressed RAM block device 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2008, 2009, 2010 Nitin Gupta 58c2ecf20Sopenharmony_ci * 2012, 2013 Minchan Kim 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * This code is released using a dual license strategy: BSD/GPL 88c2ecf20Sopenharmony_ci * You can choose the licence that better fits your requirements. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Released under the terms of 3-clause BSD License 118c2ecf20Sopenharmony_ci * Released under the terms of GNU General Public License Version 2.0 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#ifndef _ZRAM_DRV_H_ 168c2ecf20Sopenharmony_ci#define _ZRAM_DRV_H_ 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <linux/rwsem.h> 198c2ecf20Sopenharmony_ci#include <linux/zsmalloc.h> 208c2ecf20Sopenharmony_ci#include <linux/crypto.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include "zcomp.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_GROUP 258c2ecf20Sopenharmony_ci#include "zram_group.h" 268c2ecf20Sopenharmony_ci#endif 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define SECTORS_PER_PAGE_SHIFT (PAGE_SHIFT - SECTOR_SHIFT) 298c2ecf20Sopenharmony_ci#define SECTORS_PER_PAGE (1 << SECTORS_PER_PAGE_SHIFT) 308c2ecf20Sopenharmony_ci#define ZRAM_LOGICAL_BLOCK_SHIFT 12 318c2ecf20Sopenharmony_ci#define ZRAM_LOGICAL_BLOCK_SIZE (1 << ZRAM_LOGICAL_BLOCK_SHIFT) 328c2ecf20Sopenharmony_ci#define ZRAM_SECTOR_PER_LOGICAL_BLOCK \ 338c2ecf20Sopenharmony_ci (1 << (ZRAM_LOGICAL_BLOCK_SHIFT - SECTOR_SHIFT)) 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci/* 378c2ecf20Sopenharmony_ci * The lower ZRAM_FLAG_SHIFT bits of table.flags is for 388c2ecf20Sopenharmony_ci * object size (excluding header), the higher bits is for 398c2ecf20Sopenharmony_ci * zram_pageflags. 408c2ecf20Sopenharmony_ci * 418c2ecf20Sopenharmony_ci * zram is mainly used for memory efficiency so we want to keep memory 428c2ecf20Sopenharmony_ci * footprint small so we can squeeze size and flags into a field. 438c2ecf20Sopenharmony_ci * The lower ZRAM_FLAG_SHIFT bits is for object size (excluding header), 448c2ecf20Sopenharmony_ci * the higher bits is for zram_pageflags. 458c2ecf20Sopenharmony_ci */ 468c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_GROUP 478c2ecf20Sopenharmony_ci/* reserve 16 bits for group id */ 488c2ecf20Sopenharmony_ci#define ZRAM_SIZE_SHIFT 24 498c2ecf20Sopenharmony_ci#define ZRAM_GRPID_SHIFT 16 508c2ecf20Sopenharmony_ci#define ZRAM_GRPID_MASK (((1UL << ZRAM_GRPID_SHIFT) - 1) << ZRAM_SIZE_SHIFT) 518c2ecf20Sopenharmony_ci#define ZRAM_FLAG_SHIFT (ZRAM_SIZE_SHIFT + ZRAM_GRPID_SHIFT) 528c2ecf20Sopenharmony_ci#else 538c2ecf20Sopenharmony_ci#define ZRAM_FLAG_SHIFT 24 548c2ecf20Sopenharmony_ci#endif 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/* Flags for zram pages (table[page_no].flags) */ 578c2ecf20Sopenharmony_cienum zram_pageflags { 588c2ecf20Sopenharmony_ci /* zram slot is locked */ 598c2ecf20Sopenharmony_ci ZRAM_LOCK = ZRAM_FLAG_SHIFT, 608c2ecf20Sopenharmony_ci ZRAM_SAME, /* Page consists the same element */ 618c2ecf20Sopenharmony_ci ZRAM_WB, /* page is stored on backing_device */ 628c2ecf20Sopenharmony_ci ZRAM_UNDER_WB, /* page is under writeback */ 638c2ecf20Sopenharmony_ci ZRAM_HUGE, /* Incompressible page */ 648c2ecf20Sopenharmony_ci ZRAM_IDLE, /* not accessed page since last idle marking */ 658c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_GROUP_WRITEBACK 668c2ecf20Sopenharmony_ci ZRAM_GWB, /* obj is group writeback*/ 678c2ecf20Sopenharmony_ci ZRAM_FAULT, /* obj is needed by a pagefault req */ 688c2ecf20Sopenharmony_ci#endif 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci __NR_ZRAM_PAGEFLAGS, 718c2ecf20Sopenharmony_ci}; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci/*-- Data structures */ 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci/* Allocated for each disk page */ 768c2ecf20Sopenharmony_cistruct zram_table_entry { 778c2ecf20Sopenharmony_ci union { 788c2ecf20Sopenharmony_ci unsigned long handle; 798c2ecf20Sopenharmony_ci unsigned long element; 808c2ecf20Sopenharmony_ci }; 818c2ecf20Sopenharmony_ci unsigned long flags; 828c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_MEMORY_TRACKING 838c2ecf20Sopenharmony_ci ktime_t ac_time; 848c2ecf20Sopenharmony_ci#endif 858c2ecf20Sopenharmony_ci}; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistruct zram_stats { 888c2ecf20Sopenharmony_ci atomic64_t compr_data_size; /* compressed size of pages stored */ 898c2ecf20Sopenharmony_ci atomic64_t num_reads; /* failed + successful */ 908c2ecf20Sopenharmony_ci atomic64_t num_writes; /* --do-- */ 918c2ecf20Sopenharmony_ci atomic64_t failed_reads; /* can happen when memory is too low */ 928c2ecf20Sopenharmony_ci atomic64_t failed_writes; /* can happen when memory is too low */ 938c2ecf20Sopenharmony_ci atomic64_t invalid_io; /* non-page-aligned I/O requests */ 948c2ecf20Sopenharmony_ci atomic64_t notify_free; /* no. of swap slot free notifications */ 958c2ecf20Sopenharmony_ci atomic64_t same_pages; /* no. of same element filled pages */ 968c2ecf20Sopenharmony_ci atomic64_t huge_pages; /* no. of huge pages */ 978c2ecf20Sopenharmony_ci atomic64_t pages_stored; /* no. of pages currently stored */ 988c2ecf20Sopenharmony_ci atomic_long_t max_used_pages; /* no. of maximum pages stored */ 998c2ecf20Sopenharmony_ci atomic64_t writestall; /* no. of write slow paths */ 1008c2ecf20Sopenharmony_ci atomic64_t miss_free; /* no. of missed free */ 1018c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_WRITEBACK 1028c2ecf20Sopenharmony_ci atomic64_t bd_count; /* no. of pages in backing device */ 1038c2ecf20Sopenharmony_ci atomic64_t bd_reads; /* no. of reads from backing device */ 1048c2ecf20Sopenharmony_ci atomic64_t bd_writes; /* no. of writes from backing device */ 1058c2ecf20Sopenharmony_ci#endif 1068c2ecf20Sopenharmony_ci}; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistruct zram { 1098c2ecf20Sopenharmony_ci struct zram_table_entry *table; 1108c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_GROUP 1118c2ecf20Sopenharmony_ci struct zram_group *zgrp; 1128c2ecf20Sopenharmony_ci unsigned int zgrp_ctrl; 1138c2ecf20Sopenharmony_ci#endif 1148c2ecf20Sopenharmony_ci struct zs_pool *mem_pool; 1158c2ecf20Sopenharmony_ci struct zcomp *comp; 1168c2ecf20Sopenharmony_ci struct gendisk *disk; 1178c2ecf20Sopenharmony_ci /* Prevent concurrent execution of device init */ 1188c2ecf20Sopenharmony_ci struct rw_semaphore init_lock; 1198c2ecf20Sopenharmony_ci /* 1208c2ecf20Sopenharmony_ci * the number of pages zram can consume for storing compressed data 1218c2ecf20Sopenharmony_ci */ 1228c2ecf20Sopenharmony_ci unsigned long limit_pages; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci struct zram_stats stats; 1258c2ecf20Sopenharmony_ci /* 1268c2ecf20Sopenharmony_ci * This is the limit on amount of *uncompressed* worth of data 1278c2ecf20Sopenharmony_ci * we can store in a disk. 1288c2ecf20Sopenharmony_ci */ 1298c2ecf20Sopenharmony_ci u64 disksize; /* bytes */ 1308c2ecf20Sopenharmony_ci char compressor[CRYPTO_MAX_ALG_NAME]; 1318c2ecf20Sopenharmony_ci /* 1328c2ecf20Sopenharmony_ci * zram is claimed so open request will be failed 1338c2ecf20Sopenharmony_ci */ 1348c2ecf20Sopenharmony_ci bool claim; /* Protected by bdev->bd_mutex */ 1358c2ecf20Sopenharmony_ci struct file *backing_dev; 1368c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_WRITEBACK 1378c2ecf20Sopenharmony_ci spinlock_t wb_limit_lock; 1388c2ecf20Sopenharmony_ci bool wb_limit_enable; 1398c2ecf20Sopenharmony_ci u64 bd_wb_limit; 1408c2ecf20Sopenharmony_ci struct block_device *bdev; 1418c2ecf20Sopenharmony_ci unsigned int old_block_size; 1428c2ecf20Sopenharmony_ci unsigned long *bitmap; 1438c2ecf20Sopenharmony_ci unsigned long nr_pages; 1448c2ecf20Sopenharmony_ci#endif 1458c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_MEMORY_TRACKING 1468c2ecf20Sopenharmony_ci struct dentry *debugfs_dir; 1478c2ecf20Sopenharmony_ci#endif 1488c2ecf20Sopenharmony_ci}; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_cistatic inline int zram_slot_trylock(struct zram *zram, u32 index) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci return bit_spin_trylock(ZRAM_LOCK, &zram->table[index].flags); 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic inline void zram_slot_lock(struct zram *zram, u32 index) 1568c2ecf20Sopenharmony_ci{ 1578c2ecf20Sopenharmony_ci bit_spin_lock(ZRAM_LOCK, &zram->table[index].flags); 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_cistatic inline void zram_slot_unlock(struct zram *zram, u32 index) 1618c2ecf20Sopenharmony_ci{ 1628c2ecf20Sopenharmony_ci bit_spin_unlock(ZRAM_LOCK, &zram->table[index].flags); 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistatic inline unsigned long zram_get_handle(struct zram *zram, u32 index) 1668c2ecf20Sopenharmony_ci{ 1678c2ecf20Sopenharmony_ci return zram->table[index].handle; 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistatic inline void zram_set_handle(struct zram *zram, u32 index, unsigned long handle) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci zram->table[index].handle = handle; 1738c2ecf20Sopenharmony_ci} 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci/* flag operations require table entry bit_spin_lock() being held */ 1768c2ecf20Sopenharmony_cistatic inline bool zram_test_flag(struct zram *zram, u32 index, 1778c2ecf20Sopenharmony_ci enum zram_pageflags flag) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci return zram->table[index].flags & BIT(flag); 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic inline void zram_set_flag(struct zram *zram, u32 index, 1838c2ecf20Sopenharmony_ci enum zram_pageflags flag) 1848c2ecf20Sopenharmony_ci{ 1858c2ecf20Sopenharmony_ci zram->table[index].flags |= BIT(flag); 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic inline void zram_clear_flag(struct zram *zram, u32 index, 1898c2ecf20Sopenharmony_ci enum zram_pageflags flag) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci zram->table[index].flags &= ~BIT(flag); 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_GROUP 1948c2ecf20Sopenharmony_cistatic inline size_t zram_get_obj_size(struct zram *zram, u32 index) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci return zram->table[index].flags & (BIT(ZRAM_SIZE_SHIFT) - 1); 1978c2ecf20Sopenharmony_ci} 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_cistatic inline void zram_set_obj_size(struct zram *zram, u32 index, size_t size) 2008c2ecf20Sopenharmony_ci{ 2018c2ecf20Sopenharmony_ci unsigned long flags = zram->table[index].flags >> ZRAM_SIZE_SHIFT; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci zram->table[index].flags = (flags << ZRAM_SIZE_SHIFT) | size; 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_civoid zram_group_init(struct zram *zram, u32 nr_obj); 2078c2ecf20Sopenharmony_civoid zram_group_deinit(struct zram *zram); 2088c2ecf20Sopenharmony_civoid zram_group_track_obj(struct zram *zram, u32 index, struct mem_cgroup *memcg); 2098c2ecf20Sopenharmony_civoid zram_group_untrack_obj(struct zram *zram, u32 index); 2108c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_GROUP_WRITEBACK 2118c2ecf20Sopenharmony_ciint zram_group_fault_obj(struct zram *zram, u32 index); 2128c2ecf20Sopenharmony_ci#endif 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci#ifdef CONFIG_ZRAM_GROUP_DEBUG 2158c2ecf20Sopenharmony_civoid group_debug(struct zram *zram, u32 op, u32 index, u32 gid); 2168c2ecf20Sopenharmony_ci#endif 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci#else 2198c2ecf20Sopenharmony_cistatic inline size_t zram_get_obj_size(struct zram *zram, u32 index) 2208c2ecf20Sopenharmony_ci{ 2218c2ecf20Sopenharmony_ci return zram->table[index].flags & (BIT(ZRAM_FLAG_SHIFT) - 1); 2228c2ecf20Sopenharmony_ci} 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_cistatic inline void zram_set_obj_size(struct zram *zram, u32 index, size_t size) 2258c2ecf20Sopenharmony_ci{ 2268c2ecf20Sopenharmony_ci unsigned long flags = zram->table[index].flags >> ZRAM_FLAG_SHIFT; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci zram->table[index].flags = (flags << ZRAM_FLAG_SHIFT) | size; 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci#endif 2318c2ecf20Sopenharmony_ci#endif 232