1cd67e10aSMinchan Kim /* 2cd67e10aSMinchan Kim * Compressed RAM block device 3cd67e10aSMinchan Kim * 4cd67e10aSMinchan Kim * Copyright (C) 2008, 2009, 2010 Nitin Gupta 57bfb3de8SMinchan Kim * 2012, 2013 Minchan Kim 6cd67e10aSMinchan Kim * 7cd67e10aSMinchan Kim * This code is released using a dual license strategy: BSD/GPL 8cd67e10aSMinchan Kim * You can choose the licence that better fits your requirements. 9cd67e10aSMinchan Kim * 10cd67e10aSMinchan Kim * Released under the terms of 3-clause BSD License 11cd67e10aSMinchan Kim * Released under the terms of GNU General Public License Version 2.0 12cd67e10aSMinchan Kim * 13cd67e10aSMinchan Kim */ 14cd67e10aSMinchan Kim 15cd67e10aSMinchan Kim #define KMSG_COMPONENT "zram" 16cd67e10aSMinchan Kim #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 17cd67e10aSMinchan Kim 18cd67e10aSMinchan Kim #include <linux/module.h> 19cd67e10aSMinchan Kim #include <linux/kernel.h> 20cd67e10aSMinchan Kim #include <linux/bio.h> 21cd67e10aSMinchan Kim #include <linux/bitops.h> 22cd67e10aSMinchan Kim #include <linux/blkdev.h> 23cd67e10aSMinchan Kim #include <linux/buffer_head.h> 24cd67e10aSMinchan Kim #include <linux/device.h> 25cd67e10aSMinchan Kim #include <linux/genhd.h> 26cd67e10aSMinchan Kim #include <linux/highmem.h> 27cd67e10aSMinchan Kim #include <linux/slab.h> 28b09ab054SMinchan Kim #include <linux/backing-dev.h> 29cd67e10aSMinchan Kim #include <linux/string.h> 30cd67e10aSMinchan Kim #include <linux/vmalloc.h> 31fcfa8d95SSergey Senozhatsky #include <linux/err.h> 3285508ec6SSergey Senozhatsky #include <linux/idr.h> 336566d1a3SSergey Senozhatsky #include <linux/sysfs.h> 34c0265342SMinchan Kim #include <linux/debugfs.h> 351dd6c834SAnna-Maria Gleixner #include <linux/cpuhotplug.h> 36c6a564ffSChristoph Hellwig #include <linux/part_stat.h> 37cd67e10aSMinchan Kim 38cd67e10aSMinchan Kim #include "zram_drv.h" 39cd67e10aSMinchan Kim 4085508ec6SSergey Senozhatsky static DEFINE_IDR(zram_index_idr); 416566d1a3SSergey Senozhatsky /* idr index must be protected */ 426566d1a3SSergey Senozhatsky static DEFINE_MUTEX(zram_index_mutex); 436566d1a3SSergey Senozhatsky 44cd67e10aSMinchan Kim static int zram_major; 453d711a38SRui Salvaterra static const char *default_compressor = CONFIG_ZRAM_DEF_COMP; 46cd67e10aSMinchan Kim 47cd67e10aSMinchan Kim /* Module params (documentation at end) */ 48cd67e10aSMinchan Kim static unsigned int num_devices = 1; 4960f5921aSSergey Senozhatsky /* 5060f5921aSSergey Senozhatsky * Pages that compress to sizes equals or greater than this are stored 5160f5921aSSergey Senozhatsky * uncompressed in memory. 5260f5921aSSergey Senozhatsky */ 5360f5921aSSergey Senozhatsky static size_t huge_class_size; 54cd67e10aSMinchan Kim 55a8b456d0SChristoph Hellwig static const struct block_device_operations zram_devops; 56a8b456d0SChristoph Hellwig static const struct block_device_operations zram_wb_devops; 57a8b456d0SChristoph Hellwig 581f7319c7SMinchan Kim static void zram_free_page(struct zram *zram, size_t index); 59a939888eSMinchan Kim static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, 60a939888eSMinchan Kim u32 index, int offset, struct bio *bio); 61a939888eSMinchan Kim 621f7319c7SMinchan Kim 633c9959e0SMinchan Kim static int zram_slot_trylock(struct zram *zram, u32 index) 643c9959e0SMinchan Kim { 657e529283SMinchan Kim return bit_spin_trylock(ZRAM_LOCK, &zram->table[index].flags); 663c9959e0SMinchan Kim } 673c9959e0SMinchan Kim 68c4d6c4ccSMinchan Kim static void zram_slot_lock(struct zram *zram, u32 index) 69c4d6c4ccSMinchan Kim { 707e529283SMinchan Kim bit_spin_lock(ZRAM_LOCK, &zram->table[index].flags); 71c4d6c4ccSMinchan Kim } 72c4d6c4ccSMinchan Kim 73c4d6c4ccSMinchan Kim static void zram_slot_unlock(struct zram *zram, u32 index) 74c4d6c4ccSMinchan Kim { 757e529283SMinchan Kim bit_spin_unlock(ZRAM_LOCK, &zram->table[index].flags); 76c4d6c4ccSMinchan Kim } 77c4d6c4ccSMinchan Kim 7808eee69fSMinchan Kim static inline bool init_done(struct zram *zram) 79be2d1d56SSergey Senozhatsky { 8008eee69fSMinchan Kim return zram->disksize; 81be2d1d56SSergey Senozhatsky } 82be2d1d56SSergey Senozhatsky 83cd67e10aSMinchan Kim static inline struct zram *dev_to_zram(struct device *dev) 84cd67e10aSMinchan Kim { 85cd67e10aSMinchan Kim return (struct zram *)dev_to_disk(dev)->private_data; 86cd67e10aSMinchan Kim } 87cd67e10aSMinchan Kim 88643ae61dSMinchan Kim static unsigned long zram_get_handle(struct zram *zram, u32 index) 89643ae61dSMinchan Kim { 90643ae61dSMinchan Kim return zram->table[index].handle; 91643ae61dSMinchan Kim } 92643ae61dSMinchan Kim 93643ae61dSMinchan Kim static void zram_set_handle(struct zram *zram, u32 index, unsigned long handle) 94643ae61dSMinchan Kim { 95643ae61dSMinchan Kim zram->table[index].handle = handle; 96643ae61dSMinchan Kim } 97643ae61dSMinchan Kim 98b31177f2SSergey Senozhatsky /* flag operations require table entry bit_spin_lock() being held */ 99c0265342SMinchan Kim static bool zram_test_flag(struct zram *zram, u32 index, 100522698d7SSergey Senozhatsky enum zram_pageflags flag) 10199ebbd30SAndrew Morton { 1027e529283SMinchan Kim return zram->table[index].flags & BIT(flag); 10399ebbd30SAndrew Morton } 10499ebbd30SAndrew Morton 105beb6602cSMinchan Kim static void zram_set_flag(struct zram *zram, u32 index, 106522698d7SSergey Senozhatsky enum zram_pageflags flag) 107522698d7SSergey Senozhatsky { 1087e529283SMinchan Kim zram->table[index].flags |= BIT(flag); 10999ebbd30SAndrew Morton } 11099ebbd30SAndrew Morton 111beb6602cSMinchan Kim static void zram_clear_flag(struct zram *zram, u32 index, 112522698d7SSergey Senozhatsky enum zram_pageflags flag) 113cd67e10aSMinchan Kim { 1147e529283SMinchan Kim zram->table[index].flags &= ~BIT(flag); 115522698d7SSergey Senozhatsky } 116cd67e10aSMinchan Kim 117beb6602cSMinchan Kim static inline void zram_set_element(struct zram *zram, u32 index, 1188e19d540Szhouxianrong unsigned long element) 1198e19d540Szhouxianrong { 120beb6602cSMinchan Kim zram->table[index].element = element; 1218e19d540Szhouxianrong } 1228e19d540Szhouxianrong 123643ae61dSMinchan Kim static unsigned long zram_get_element(struct zram *zram, u32 index) 1248e19d540Szhouxianrong { 125643ae61dSMinchan Kim return zram->table[index].element; 1268e19d540Szhouxianrong } 1278e19d540Szhouxianrong 128beb6602cSMinchan Kim static size_t zram_get_obj_size(struct zram *zram, u32 index) 129522698d7SSergey Senozhatsky { 1307e529283SMinchan Kim return zram->table[index].flags & (BIT(ZRAM_FLAG_SHIFT) - 1); 131522698d7SSergey Senozhatsky } 132522698d7SSergey Senozhatsky 133beb6602cSMinchan Kim static void zram_set_obj_size(struct zram *zram, 134522698d7SSergey Senozhatsky u32 index, size_t size) 135522698d7SSergey Senozhatsky { 1367e529283SMinchan Kim unsigned long flags = zram->table[index].flags >> ZRAM_FLAG_SHIFT; 137522698d7SSergey Senozhatsky 1387e529283SMinchan Kim zram->table[index].flags = (flags << ZRAM_FLAG_SHIFT) | size; 139522698d7SSergey Senozhatsky } 140522698d7SSergey Senozhatsky 141a939888eSMinchan Kim static inline bool zram_allocated(struct zram *zram, u32 index) 142a939888eSMinchan Kim { 143a939888eSMinchan Kim return zram_get_obj_size(zram, index) || 144a939888eSMinchan Kim zram_test_flag(zram, index, ZRAM_SAME) || 145a939888eSMinchan Kim zram_test_flag(zram, index, ZRAM_WB); 146a939888eSMinchan Kim } 147a939888eSMinchan Kim 1481f7319c7SMinchan Kim #if PAGE_SIZE != 4096 1491c53e0d2SGeliang Tang static inline bool is_partial_io(struct bio_vec *bvec) 150522698d7SSergey Senozhatsky { 151522698d7SSergey Senozhatsky return bvec->bv_len != PAGE_SIZE; 152522698d7SSergey Senozhatsky } 1531f7319c7SMinchan Kim #else 1541f7319c7SMinchan Kim static inline bool is_partial_io(struct bio_vec *bvec) 1551f7319c7SMinchan Kim { 1561f7319c7SMinchan Kim return false; 1571f7319c7SMinchan Kim } 1581f7319c7SMinchan Kim #endif 159522698d7SSergey Senozhatsky 160522698d7SSergey Senozhatsky /* 161522698d7SSergey Senozhatsky * Check if request is within bounds and aligned on zram logical blocks. 162522698d7SSergey Senozhatsky */ 1631c53e0d2SGeliang Tang static inline bool valid_io_request(struct zram *zram, 164522698d7SSergey Senozhatsky sector_t start, unsigned int size) 165522698d7SSergey Senozhatsky { 166522698d7SSergey Senozhatsky u64 end, bound; 167522698d7SSergey Senozhatsky 168522698d7SSergey Senozhatsky /* unaligned request */ 169522698d7SSergey Senozhatsky if (unlikely(start & (ZRAM_SECTOR_PER_LOGICAL_BLOCK - 1))) 1701c53e0d2SGeliang Tang return false; 171522698d7SSergey Senozhatsky if (unlikely(size & (ZRAM_LOGICAL_BLOCK_SIZE - 1))) 1721c53e0d2SGeliang Tang return false; 173522698d7SSergey Senozhatsky 174522698d7SSergey Senozhatsky end = start + (size >> SECTOR_SHIFT); 175522698d7SSergey Senozhatsky bound = zram->disksize >> SECTOR_SHIFT; 176522698d7SSergey Senozhatsky /* out of range range */ 177522698d7SSergey Senozhatsky if (unlikely(start >= bound || end > bound || start > end)) 1781c53e0d2SGeliang Tang return false; 179522698d7SSergey Senozhatsky 180522698d7SSergey Senozhatsky /* I/O request is valid */ 1811c53e0d2SGeliang Tang return true; 182522698d7SSergey Senozhatsky } 183522698d7SSergey Senozhatsky 184522698d7SSergey Senozhatsky static void update_position(u32 *index, int *offset, struct bio_vec *bvec) 185522698d7SSergey Senozhatsky { 186e86942c7SMinchan Kim *index += (*offset + bvec->bv_len) / PAGE_SIZE; 187522698d7SSergey Senozhatsky *offset = (*offset + bvec->bv_len) % PAGE_SIZE; 188522698d7SSergey Senozhatsky } 189522698d7SSergey Senozhatsky 190522698d7SSergey Senozhatsky static inline void update_used_max(struct zram *zram, 191522698d7SSergey Senozhatsky const unsigned long pages) 192522698d7SSergey Senozhatsky { 193522698d7SSergey Senozhatsky unsigned long old_max, cur_max; 194522698d7SSergey Senozhatsky 195522698d7SSergey Senozhatsky old_max = atomic_long_read(&zram->stats.max_used_pages); 196522698d7SSergey Senozhatsky 197522698d7SSergey Senozhatsky do { 198522698d7SSergey Senozhatsky cur_max = old_max; 199522698d7SSergey Senozhatsky if (pages > cur_max) 200522698d7SSergey Senozhatsky old_max = atomic_long_cmpxchg( 201522698d7SSergey Senozhatsky &zram->stats.max_used_pages, cur_max, pages); 202522698d7SSergey Senozhatsky } while (old_max != cur_max); 203522698d7SSergey Senozhatsky } 204522698d7SSergey Senozhatsky 20548ad1abeSMatthew Wilcox static inline void zram_fill_page(void *ptr, unsigned long len, 2068e19d540Szhouxianrong unsigned long value) 2078e19d540Szhouxianrong { 2088e19d540Szhouxianrong WARN_ON_ONCE(!IS_ALIGNED(len, sizeof(unsigned long))); 20948ad1abeSMatthew Wilcox memset_l(ptr, value, len / sizeof(unsigned long)); 2108e19d540Szhouxianrong } 2118e19d540Szhouxianrong 2128e19d540Szhouxianrong static bool page_same_filled(void *ptr, unsigned long *element) 213522698d7SSergey Senozhatsky { 214522698d7SSergey Senozhatsky unsigned long *page; 215f0fe9984SSangwoo Park unsigned long val; 21690f82cbfSTaejoon Song unsigned int pos, last_pos = PAGE_SIZE / sizeof(*page) - 1; 217522698d7SSergey Senozhatsky 218522698d7SSergey Senozhatsky page = (unsigned long *)ptr; 219f0fe9984SSangwoo Park val = page[0]; 220522698d7SSergey Senozhatsky 22190f82cbfSTaejoon Song if (val != page[last_pos]) 22290f82cbfSTaejoon Song return false; 22390f82cbfSTaejoon Song 22490f82cbfSTaejoon Song for (pos = 1; pos < last_pos; pos++) { 225f0fe9984SSangwoo Park if (val != page[pos]) 2261c53e0d2SGeliang Tang return false; 227522698d7SSergey Senozhatsky } 228522698d7SSergey Senozhatsky 229f0fe9984SSangwoo Park *element = val; 2308e19d540Szhouxianrong 2311c53e0d2SGeliang Tang return true; 232522698d7SSergey Senozhatsky } 233522698d7SSergey Senozhatsky 234cd67e10aSMinchan Kim static ssize_t initstate_show(struct device *dev, 235cd67e10aSMinchan Kim struct device_attribute *attr, char *buf) 236cd67e10aSMinchan Kim { 237a68eb3b6SSergey Senozhatsky u32 val; 238cd67e10aSMinchan Kim struct zram *zram = dev_to_zram(dev); 239cd67e10aSMinchan Kim 240a68eb3b6SSergey Senozhatsky down_read(&zram->init_lock); 241a68eb3b6SSergey Senozhatsky val = init_done(zram); 242a68eb3b6SSergey Senozhatsky up_read(&zram->init_lock); 243cd67e10aSMinchan Kim 24456b4e8cbSSergey Senozhatsky return scnprintf(buf, PAGE_SIZE, "%u\n", val); 245cd67e10aSMinchan Kim } 246cd67e10aSMinchan Kim 247522698d7SSergey Senozhatsky static ssize_t disksize_show(struct device *dev, 248522698d7SSergey Senozhatsky struct device_attribute *attr, char *buf) 249522698d7SSergey Senozhatsky { 250522698d7SSergey Senozhatsky struct zram *zram = dev_to_zram(dev); 251522698d7SSergey Senozhatsky 252522698d7SSergey Senozhatsky return scnprintf(buf, PAGE_SIZE, "%llu\n", zram->disksize); 253522698d7SSergey Senozhatsky } 254522698d7SSergey Senozhatsky 2559ada9da9SMinchan Kim static ssize_t mem_limit_store(struct device *dev, 2569ada9da9SMinchan Kim struct device_attribute *attr, const char *buf, size_t len) 2579ada9da9SMinchan Kim { 2589ada9da9SMinchan Kim u64 limit; 2599ada9da9SMinchan Kim char *tmp; 2609ada9da9SMinchan Kim struct zram *zram = dev_to_zram(dev); 2619ada9da9SMinchan Kim 2629ada9da9SMinchan Kim limit = memparse(buf, &tmp); 2639ada9da9SMinchan Kim if (buf == tmp) /* no chars parsed, invalid input */ 2649ada9da9SMinchan Kim return -EINVAL; 2659ada9da9SMinchan Kim 2669ada9da9SMinchan Kim down_write(&zram->init_lock); 2679ada9da9SMinchan Kim zram->limit_pages = PAGE_ALIGN(limit) >> PAGE_SHIFT; 2689ada9da9SMinchan Kim up_write(&zram->init_lock); 2699ada9da9SMinchan Kim 2709ada9da9SMinchan Kim return len; 2719ada9da9SMinchan Kim } 2729ada9da9SMinchan Kim 273461a8eeeSMinchan Kim static ssize_t mem_used_max_store(struct device *dev, 274461a8eeeSMinchan Kim struct device_attribute *attr, const char *buf, size_t len) 275461a8eeeSMinchan Kim { 276461a8eeeSMinchan Kim int err; 277461a8eeeSMinchan Kim unsigned long val; 278461a8eeeSMinchan Kim struct zram *zram = dev_to_zram(dev); 279461a8eeeSMinchan Kim 280461a8eeeSMinchan Kim err = kstrtoul(buf, 10, &val); 281461a8eeeSMinchan Kim if (err || val != 0) 282461a8eeeSMinchan Kim return -EINVAL; 283461a8eeeSMinchan Kim 284461a8eeeSMinchan Kim down_read(&zram->init_lock); 2855a99e95bSWeijie Yang if (init_done(zram)) { 286461a8eeeSMinchan Kim atomic_long_set(&zram->stats.max_used_pages, 287beb6602cSMinchan Kim zs_get_total_pages(zram->mem_pool)); 2885a99e95bSWeijie Yang } 289461a8eeeSMinchan Kim up_read(&zram->init_lock); 290461a8eeeSMinchan Kim 291461a8eeeSMinchan Kim return len; 292461a8eeeSMinchan Kim } 293461a8eeeSMinchan Kim 294e82592c4SMinchan Kim static ssize_t idle_store(struct device *dev, 295e82592c4SMinchan Kim struct device_attribute *attr, const char *buf, size_t len) 296e82592c4SMinchan Kim { 297e82592c4SMinchan Kim struct zram *zram = dev_to_zram(dev); 298e82592c4SMinchan Kim unsigned long nr_pages = zram->disksize >> PAGE_SHIFT; 299e82592c4SMinchan Kim int index; 300e82592c4SMinchan Kim 3010bc9f5d1SMinchan Kim if (!sysfs_streq(buf, "all")) 302e82592c4SMinchan Kim return -EINVAL; 303e82592c4SMinchan Kim 304e82592c4SMinchan Kim down_read(&zram->init_lock); 305e82592c4SMinchan Kim if (!init_done(zram)) { 306e82592c4SMinchan Kim up_read(&zram->init_lock); 307e82592c4SMinchan Kim return -EINVAL; 308e82592c4SMinchan Kim } 309e82592c4SMinchan Kim 310e82592c4SMinchan Kim for (index = 0; index < nr_pages; index++) { 311a939888eSMinchan Kim /* 312a939888eSMinchan Kim * Do not mark ZRAM_UNDER_WB slot as ZRAM_IDLE to close race. 313a939888eSMinchan Kim * See the comment in writeback_store. 314a939888eSMinchan Kim */ 315e82592c4SMinchan Kim zram_slot_lock(zram, index); 3161d69a3f8SMinchan Kim if (zram_allocated(zram, index) && 3171d69a3f8SMinchan Kim !zram_test_flag(zram, index, ZRAM_UNDER_WB)) 318e82592c4SMinchan Kim zram_set_flag(zram, index, ZRAM_IDLE); 319e82592c4SMinchan Kim zram_slot_unlock(zram, index); 320e82592c4SMinchan Kim } 321e82592c4SMinchan Kim 322e82592c4SMinchan Kim up_read(&zram->init_lock); 323e82592c4SMinchan Kim 324e82592c4SMinchan Kim return len; 325e82592c4SMinchan Kim } 326e82592c4SMinchan Kim 327013bf95aSMinchan Kim #ifdef CONFIG_ZRAM_WRITEBACK 3281d69a3f8SMinchan Kim static ssize_t writeback_limit_enable_store(struct device *dev, 3291d69a3f8SMinchan Kim struct device_attribute *attr, const char *buf, size_t len) 3301d69a3f8SMinchan Kim { 3311d69a3f8SMinchan Kim struct zram *zram = dev_to_zram(dev); 3321d69a3f8SMinchan Kim u64 val; 3331d69a3f8SMinchan Kim ssize_t ret = -EINVAL; 3341d69a3f8SMinchan Kim 3351d69a3f8SMinchan Kim if (kstrtoull(buf, 10, &val)) 3361d69a3f8SMinchan Kim return ret; 3371d69a3f8SMinchan Kim 3381d69a3f8SMinchan Kim down_read(&zram->init_lock); 3391d69a3f8SMinchan Kim spin_lock(&zram->wb_limit_lock); 3401d69a3f8SMinchan Kim zram->wb_limit_enable = val; 3411d69a3f8SMinchan Kim spin_unlock(&zram->wb_limit_lock); 3421d69a3f8SMinchan Kim up_read(&zram->init_lock); 3431d69a3f8SMinchan Kim ret = len; 3441d69a3f8SMinchan Kim 3451d69a3f8SMinchan Kim return ret; 3461d69a3f8SMinchan Kim } 3471d69a3f8SMinchan Kim 3481d69a3f8SMinchan Kim static ssize_t writeback_limit_enable_show(struct device *dev, 3491d69a3f8SMinchan Kim struct device_attribute *attr, char *buf) 3501d69a3f8SMinchan Kim { 3511d69a3f8SMinchan Kim bool val; 3521d69a3f8SMinchan Kim struct zram *zram = dev_to_zram(dev); 3531d69a3f8SMinchan Kim 3541d69a3f8SMinchan Kim down_read(&zram->init_lock); 3551d69a3f8SMinchan Kim spin_lock(&zram->wb_limit_lock); 3561d69a3f8SMinchan Kim val = zram->wb_limit_enable; 3571d69a3f8SMinchan Kim spin_unlock(&zram->wb_limit_lock); 3581d69a3f8SMinchan Kim up_read(&zram->init_lock); 3591d69a3f8SMinchan Kim 3601d69a3f8SMinchan Kim return scnprintf(buf, PAGE_SIZE, "%d\n", val); 3611d69a3f8SMinchan Kim } 3621d69a3f8SMinchan Kim 363bb416d18SMinchan Kim static ssize_t writeback_limit_store(struct device *dev, 364bb416d18SMinchan Kim struct device_attribute *attr, const char *buf, size_t len) 365bb416d18SMinchan Kim { 366bb416d18SMinchan Kim struct zram *zram = dev_to_zram(dev); 367bb416d18SMinchan Kim u64 val; 368bb416d18SMinchan Kim ssize_t ret = -EINVAL; 369bb416d18SMinchan Kim 370bb416d18SMinchan Kim if (kstrtoull(buf, 10, &val)) 371bb416d18SMinchan Kim return ret; 372bb416d18SMinchan Kim 373bb416d18SMinchan Kim down_read(&zram->init_lock); 3741d69a3f8SMinchan Kim spin_lock(&zram->wb_limit_lock); 3751d69a3f8SMinchan Kim zram->bd_wb_limit = val; 3761d69a3f8SMinchan Kim spin_unlock(&zram->wb_limit_lock); 377bb416d18SMinchan Kim up_read(&zram->init_lock); 378bb416d18SMinchan Kim ret = len; 379bb416d18SMinchan Kim 380bb416d18SMinchan Kim return ret; 381bb416d18SMinchan Kim } 382bb416d18SMinchan Kim 383bb416d18SMinchan Kim static ssize_t writeback_limit_show(struct device *dev, 384bb416d18SMinchan Kim struct device_attribute *attr, char *buf) 385bb416d18SMinchan Kim { 386bb416d18SMinchan Kim u64 val; 387bb416d18SMinchan Kim struct zram *zram = dev_to_zram(dev); 388bb416d18SMinchan Kim 389bb416d18SMinchan Kim down_read(&zram->init_lock); 3901d69a3f8SMinchan Kim spin_lock(&zram->wb_limit_lock); 3911d69a3f8SMinchan Kim val = zram->bd_wb_limit; 3921d69a3f8SMinchan Kim spin_unlock(&zram->wb_limit_lock); 393bb416d18SMinchan Kim up_read(&zram->init_lock); 394bb416d18SMinchan Kim 395bb416d18SMinchan Kim return scnprintf(buf, PAGE_SIZE, "%llu\n", val); 396bb416d18SMinchan Kim } 397bb416d18SMinchan Kim 398013bf95aSMinchan Kim static void reset_bdev(struct zram *zram) 399013bf95aSMinchan Kim { 400013bf95aSMinchan Kim struct block_device *bdev; 401013bf95aSMinchan Kim 4027e529283SMinchan Kim if (!zram->backing_dev) 403013bf95aSMinchan Kim return; 404013bf95aSMinchan Kim 405013bf95aSMinchan Kim bdev = zram->bdev; 406013bf95aSMinchan Kim blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); 407013bf95aSMinchan Kim /* hope filp_close flush all of IO */ 408013bf95aSMinchan Kim filp_close(zram->backing_dev, NULL); 409013bf95aSMinchan Kim zram->backing_dev = NULL; 410013bf95aSMinchan Kim zram->bdev = NULL; 411a8b456d0SChristoph Hellwig zram->disk->fops = &zram_devops; 4121363d466SMinchan Kim kvfree(zram->bitmap); 4131363d466SMinchan Kim zram->bitmap = NULL; 414013bf95aSMinchan Kim } 415013bf95aSMinchan Kim 416013bf95aSMinchan Kim static ssize_t backing_dev_show(struct device *dev, 417013bf95aSMinchan Kim struct device_attribute *attr, char *buf) 418013bf95aSMinchan Kim { 419f7daefe4SChenwandun struct file *file; 420013bf95aSMinchan Kim struct zram *zram = dev_to_zram(dev); 421013bf95aSMinchan Kim char *p; 422013bf95aSMinchan Kim ssize_t ret; 423013bf95aSMinchan Kim 424013bf95aSMinchan Kim down_read(&zram->init_lock); 425f7daefe4SChenwandun file = zram->backing_dev; 426f7daefe4SChenwandun if (!file) { 427013bf95aSMinchan Kim memcpy(buf, "none\n", 5); 428013bf95aSMinchan Kim up_read(&zram->init_lock); 429013bf95aSMinchan Kim return 5; 430013bf95aSMinchan Kim } 431013bf95aSMinchan Kim 432013bf95aSMinchan Kim p = file_path(file, buf, PAGE_SIZE - 1); 433013bf95aSMinchan Kim if (IS_ERR(p)) { 434013bf95aSMinchan Kim ret = PTR_ERR(p); 435013bf95aSMinchan Kim goto out; 436013bf95aSMinchan Kim } 437013bf95aSMinchan Kim 438013bf95aSMinchan Kim ret = strlen(p); 439013bf95aSMinchan Kim memmove(buf, p, ret); 440013bf95aSMinchan Kim buf[ret++] = '\n'; 441013bf95aSMinchan Kim out: 442013bf95aSMinchan Kim up_read(&zram->init_lock); 443013bf95aSMinchan Kim return ret; 444013bf95aSMinchan Kim } 445013bf95aSMinchan Kim 446013bf95aSMinchan Kim static ssize_t backing_dev_store(struct device *dev, 447013bf95aSMinchan Kim struct device_attribute *attr, const char *buf, size_t len) 448013bf95aSMinchan Kim { 449013bf95aSMinchan Kim char *file_name; 450c8bd134aSPeter Kalauskas size_t sz; 451013bf95aSMinchan Kim struct file *backing_dev = NULL; 452013bf95aSMinchan Kim struct inode *inode; 453013bf95aSMinchan Kim struct address_space *mapping; 454ee763e21SChristoph Hellwig unsigned int bitmap_sz; 4551363d466SMinchan Kim unsigned long nr_pages, *bitmap = NULL; 456013bf95aSMinchan Kim struct block_device *bdev = NULL; 457013bf95aSMinchan Kim int err; 458013bf95aSMinchan Kim struct zram *zram = dev_to_zram(dev); 459013bf95aSMinchan Kim 460013bf95aSMinchan Kim file_name = kmalloc(PATH_MAX, GFP_KERNEL); 461013bf95aSMinchan Kim if (!file_name) 462013bf95aSMinchan Kim return -ENOMEM; 463013bf95aSMinchan Kim 464013bf95aSMinchan Kim down_write(&zram->init_lock); 465013bf95aSMinchan Kim if (init_done(zram)) { 466013bf95aSMinchan Kim pr_info("Can't setup backing device for initialized device\n"); 467013bf95aSMinchan Kim err = -EBUSY; 468013bf95aSMinchan Kim goto out; 469013bf95aSMinchan Kim } 470013bf95aSMinchan Kim 471c8bd134aSPeter Kalauskas strlcpy(file_name, buf, PATH_MAX); 472c8bd134aSPeter Kalauskas /* ignore trailing newline */ 473c8bd134aSPeter Kalauskas sz = strlen(file_name); 474c8bd134aSPeter Kalauskas if (sz > 0 && file_name[sz - 1] == '\n') 475c8bd134aSPeter Kalauskas file_name[sz - 1] = 0x00; 476013bf95aSMinchan Kim 477013bf95aSMinchan Kim backing_dev = filp_open(file_name, O_RDWR|O_LARGEFILE, 0); 478013bf95aSMinchan Kim if (IS_ERR(backing_dev)) { 479013bf95aSMinchan Kim err = PTR_ERR(backing_dev); 480013bf95aSMinchan Kim backing_dev = NULL; 481013bf95aSMinchan Kim goto out; 482013bf95aSMinchan Kim } 483013bf95aSMinchan Kim 484013bf95aSMinchan Kim mapping = backing_dev->f_mapping; 485013bf95aSMinchan Kim inode = mapping->host; 486013bf95aSMinchan Kim 487013bf95aSMinchan Kim /* Support only block device in this moment */ 488013bf95aSMinchan Kim if (!S_ISBLK(inode->i_mode)) { 489013bf95aSMinchan Kim err = -ENOTBLK; 490013bf95aSMinchan Kim goto out; 491013bf95aSMinchan Kim } 492013bf95aSMinchan Kim 4930fc66c9dSChristoph Hellwig bdev = blkdev_get_by_dev(inode->i_rdev, 4940fc66c9dSChristoph Hellwig FMODE_READ | FMODE_WRITE | FMODE_EXCL, zram); 4950fc66c9dSChristoph Hellwig if (IS_ERR(bdev)) { 4960fc66c9dSChristoph Hellwig err = PTR_ERR(bdev); 4975547932dSMinchan Kim bdev = NULL; 498013bf95aSMinchan Kim goto out; 4995547932dSMinchan Kim } 500013bf95aSMinchan Kim 5011363d466SMinchan Kim nr_pages = i_size_read(inode) >> PAGE_SHIFT; 5021363d466SMinchan Kim bitmap_sz = BITS_TO_LONGS(nr_pages) * sizeof(long); 5031363d466SMinchan Kim bitmap = kvzalloc(bitmap_sz, GFP_KERNEL); 5041363d466SMinchan Kim if (!bitmap) { 5051363d466SMinchan Kim err = -ENOMEM; 5061363d466SMinchan Kim goto out; 5071363d466SMinchan Kim } 5081363d466SMinchan Kim 509013bf95aSMinchan Kim reset_bdev(zram); 510013bf95aSMinchan Kim 511013bf95aSMinchan Kim zram->bdev = bdev; 512013bf95aSMinchan Kim zram->backing_dev = backing_dev; 5131363d466SMinchan Kim zram->bitmap = bitmap; 5141363d466SMinchan Kim zram->nr_pages = nr_pages; 5154f7a7beaSMinchan Kim /* 5164f7a7beaSMinchan Kim * With writeback feature, zram does asynchronous IO so it's no longer 5174f7a7beaSMinchan Kim * synchronous device so let's remove synchronous io flag. Othewise, 5184f7a7beaSMinchan Kim * upper layer(e.g., swap) could wait IO completion rather than 5194f7a7beaSMinchan Kim * (submit and return), which will cause system sluggish. 5204f7a7beaSMinchan Kim * Furthermore, when the IO function returns(e.g., swap_readpage), 5214f7a7beaSMinchan Kim * upper layer expects IO was done so it could deallocate the page 5224f7a7beaSMinchan Kim * freely but in fact, IO is going on so finally could cause 5234f7a7beaSMinchan Kim * use-after-free when the IO is really done. 5244f7a7beaSMinchan Kim */ 525a8b456d0SChristoph Hellwig zram->disk->fops = &zram_wb_devops; 526013bf95aSMinchan Kim up_write(&zram->init_lock); 527013bf95aSMinchan Kim 528013bf95aSMinchan Kim pr_info("setup backing device %s\n", file_name); 529013bf95aSMinchan Kim kfree(file_name); 530013bf95aSMinchan Kim 531013bf95aSMinchan Kim return len; 532013bf95aSMinchan Kim out: 5331363d466SMinchan Kim kvfree(bitmap); 5341363d466SMinchan Kim 535013bf95aSMinchan Kim if (bdev) 536013bf95aSMinchan Kim blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL); 537013bf95aSMinchan Kim 538013bf95aSMinchan Kim if (backing_dev) 539013bf95aSMinchan Kim filp_close(backing_dev, NULL); 540013bf95aSMinchan Kim 541013bf95aSMinchan Kim up_write(&zram->init_lock); 542013bf95aSMinchan Kim 543013bf95aSMinchan Kim kfree(file_name); 544013bf95aSMinchan Kim 545013bf95aSMinchan Kim return err; 546013bf95aSMinchan Kim } 547013bf95aSMinchan Kim 5487e529283SMinchan Kim static unsigned long alloc_block_bdev(struct zram *zram) 5491363d466SMinchan Kim { 5503c9959e0SMinchan Kim unsigned long blk_idx = 1; 5513c9959e0SMinchan Kim retry: 5521363d466SMinchan Kim /* skip 0 bit to confuse zram.handle = 0 */ 5533c9959e0SMinchan Kim blk_idx = find_next_zero_bit(zram->bitmap, zram->nr_pages, blk_idx); 5543c9959e0SMinchan Kim if (blk_idx == zram->nr_pages) 5551363d466SMinchan Kim return 0; 5561363d466SMinchan Kim 5573c9959e0SMinchan Kim if (test_and_set_bit(blk_idx, zram->bitmap)) 5583c9959e0SMinchan Kim goto retry; 5591363d466SMinchan Kim 56023eddf39SMinchan Kim atomic64_inc(&zram->stats.bd_count); 5613c9959e0SMinchan Kim return blk_idx; 5621363d466SMinchan Kim } 5631363d466SMinchan Kim 5647e529283SMinchan Kim static void free_block_bdev(struct zram *zram, unsigned long blk_idx) 5651363d466SMinchan Kim { 5661363d466SMinchan Kim int was_set; 5671363d466SMinchan Kim 5687e529283SMinchan Kim was_set = test_and_clear_bit(blk_idx, zram->bitmap); 5691363d466SMinchan Kim WARN_ON_ONCE(!was_set); 57023eddf39SMinchan Kim atomic64_dec(&zram->stats.bd_count); 5711363d466SMinchan Kim } 5721363d466SMinchan Kim 573384bc41fSColin Ian King static void zram_page_end_io(struct bio *bio) 574db8ffbd4SMinchan Kim { 575263663cdSMing Lei struct page *page = bio_first_page_all(bio); 576db8ffbd4SMinchan Kim 577db8ffbd4SMinchan Kim page_endio(page, op_is_write(bio_op(bio)), 578db8ffbd4SMinchan Kim blk_status_to_errno(bio->bi_status)); 579db8ffbd4SMinchan Kim bio_put(bio); 580db8ffbd4SMinchan Kim } 581db8ffbd4SMinchan Kim 5828e654f8fSMinchan Kim /* 5838e654f8fSMinchan Kim * Returns 1 if the submission is successful. 5848e654f8fSMinchan Kim */ 5858e654f8fSMinchan Kim static int read_from_bdev_async(struct zram *zram, struct bio_vec *bvec, 5868e654f8fSMinchan Kim unsigned long entry, struct bio *parent) 5878e654f8fSMinchan Kim { 5888e654f8fSMinchan Kim struct bio *bio; 5898e654f8fSMinchan Kim 5908e654f8fSMinchan Kim bio = bio_alloc(GFP_ATOMIC, 1); 5918e654f8fSMinchan Kim if (!bio) 5928e654f8fSMinchan Kim return -ENOMEM; 5938e654f8fSMinchan Kim 5948e654f8fSMinchan Kim bio->bi_iter.bi_sector = entry * (PAGE_SIZE >> 9); 595a0725ab0SLinus Torvalds bio_set_dev(bio, zram->bdev); 5968e654f8fSMinchan Kim if (!bio_add_page(bio, bvec->bv_page, bvec->bv_len, bvec->bv_offset)) { 5978e654f8fSMinchan Kim bio_put(bio); 5988e654f8fSMinchan Kim return -EIO; 5998e654f8fSMinchan Kim } 6008e654f8fSMinchan Kim 6018e654f8fSMinchan Kim if (!parent) { 6028e654f8fSMinchan Kim bio->bi_opf = REQ_OP_READ; 6038e654f8fSMinchan Kim bio->bi_end_io = zram_page_end_io; 6048e654f8fSMinchan Kim } else { 6058e654f8fSMinchan Kim bio->bi_opf = parent->bi_opf; 6068e654f8fSMinchan Kim bio_chain(bio, parent); 6078e654f8fSMinchan Kim } 6088e654f8fSMinchan Kim 6098e654f8fSMinchan Kim submit_bio(bio); 6108e654f8fSMinchan Kim return 1; 6118e654f8fSMinchan Kim } 6128e654f8fSMinchan Kim 6130d835962SMinchan Kim #define PAGE_WB_SIG "page_index=" 6140d835962SMinchan Kim 6150d835962SMinchan Kim #define PAGE_WRITEBACK 0 6161d69a3f8SMinchan Kim #define HUGE_WRITEBACK 1 6171d69a3f8SMinchan Kim #define IDLE_WRITEBACK 2 618a939888eSMinchan Kim 6190d835962SMinchan Kim 620a939888eSMinchan Kim static ssize_t writeback_store(struct device *dev, 621a939888eSMinchan Kim struct device_attribute *attr, const char *buf, size_t len) 622a939888eSMinchan Kim { 623a939888eSMinchan Kim struct zram *zram = dev_to_zram(dev); 624a939888eSMinchan Kim unsigned long nr_pages = zram->disksize >> PAGE_SHIFT; 6250d835962SMinchan Kim unsigned long index = 0; 626a939888eSMinchan Kim struct bio bio; 627a939888eSMinchan Kim struct bio_vec bio_vec; 628a939888eSMinchan Kim struct page *page; 6293b82a051SColin Ian King ssize_t ret = len; 63057e0076eSMinchan Kim int mode, err; 631a939888eSMinchan Kim unsigned long blk_idx = 0; 632a939888eSMinchan Kim 6330bc9f5d1SMinchan Kim if (sysfs_streq(buf, "idle")) 634a939888eSMinchan Kim mode = IDLE_WRITEBACK; 6350bc9f5d1SMinchan Kim else if (sysfs_streq(buf, "huge")) 636a939888eSMinchan Kim mode = HUGE_WRITEBACK; 6370d835962SMinchan Kim else { 6380d835962SMinchan Kim if (strncmp(buf, PAGE_WB_SIG, sizeof(PAGE_WB_SIG) - 1)) 639a939888eSMinchan Kim return -EINVAL; 640a939888eSMinchan Kim 6412766f182SMinchan Kim if (kstrtol(buf + sizeof(PAGE_WB_SIG) - 1, 10, &index) || 6422766f182SMinchan Kim index >= nr_pages) 6430d835962SMinchan Kim return -EINVAL; 6440d835962SMinchan Kim 6450d835962SMinchan Kim nr_pages = 1; 6460d835962SMinchan Kim mode = PAGE_WRITEBACK; 6470d835962SMinchan Kim } 6480d835962SMinchan Kim 649a939888eSMinchan Kim down_read(&zram->init_lock); 650a939888eSMinchan Kim if (!init_done(zram)) { 651a939888eSMinchan Kim ret = -EINVAL; 652a939888eSMinchan Kim goto release_init_lock; 653a939888eSMinchan Kim } 654a939888eSMinchan Kim 655a939888eSMinchan Kim if (!zram->backing_dev) { 656a939888eSMinchan Kim ret = -ENODEV; 657a939888eSMinchan Kim goto release_init_lock; 658a939888eSMinchan Kim } 659a939888eSMinchan Kim 660a939888eSMinchan Kim page = alloc_page(GFP_KERNEL); 661a939888eSMinchan Kim if (!page) { 662a939888eSMinchan Kim ret = -ENOMEM; 663a939888eSMinchan Kim goto release_init_lock; 664a939888eSMinchan Kim } 665a939888eSMinchan Kim 6662766f182SMinchan Kim for (; nr_pages != 0; index++, nr_pages--) { 667a939888eSMinchan Kim struct bio_vec bvec; 668a939888eSMinchan Kim 669a939888eSMinchan Kim bvec.bv_page = page; 670a939888eSMinchan Kim bvec.bv_len = PAGE_SIZE; 671a939888eSMinchan Kim bvec.bv_offset = 0; 672a939888eSMinchan Kim 6731d69a3f8SMinchan Kim spin_lock(&zram->wb_limit_lock); 6741d69a3f8SMinchan Kim if (zram->wb_limit_enable && !zram->bd_wb_limit) { 6751d69a3f8SMinchan Kim spin_unlock(&zram->wb_limit_lock); 676bb416d18SMinchan Kim ret = -EIO; 677bb416d18SMinchan Kim break; 678bb416d18SMinchan Kim } 6791d69a3f8SMinchan Kim spin_unlock(&zram->wb_limit_lock); 680bb416d18SMinchan Kim 681a939888eSMinchan Kim if (!blk_idx) { 682a939888eSMinchan Kim blk_idx = alloc_block_bdev(zram); 683a939888eSMinchan Kim if (!blk_idx) { 684a939888eSMinchan Kim ret = -ENOSPC; 685a939888eSMinchan Kim break; 686a939888eSMinchan Kim } 687a939888eSMinchan Kim } 688a939888eSMinchan Kim 689a939888eSMinchan Kim zram_slot_lock(zram, index); 690a939888eSMinchan Kim if (!zram_allocated(zram, index)) 691a939888eSMinchan Kim goto next; 692a939888eSMinchan Kim 693a939888eSMinchan Kim if (zram_test_flag(zram, index, ZRAM_WB) || 694a939888eSMinchan Kim zram_test_flag(zram, index, ZRAM_SAME) || 695a939888eSMinchan Kim zram_test_flag(zram, index, ZRAM_UNDER_WB)) 696a939888eSMinchan Kim goto next; 697a939888eSMinchan Kim 6981d69a3f8SMinchan Kim if (mode == IDLE_WRITEBACK && 6991d69a3f8SMinchan Kim !zram_test_flag(zram, index, ZRAM_IDLE)) 7001d69a3f8SMinchan Kim goto next; 7011d69a3f8SMinchan Kim if (mode == HUGE_WRITEBACK && 7021d69a3f8SMinchan Kim !zram_test_flag(zram, index, ZRAM_HUGE)) 703a939888eSMinchan Kim goto next; 704a939888eSMinchan Kim /* 705a939888eSMinchan Kim * Clearing ZRAM_UNDER_WB is duty of caller. 706a939888eSMinchan Kim * IOW, zram_free_page never clear it. 707a939888eSMinchan Kim */ 708a939888eSMinchan Kim zram_set_flag(zram, index, ZRAM_UNDER_WB); 709a939888eSMinchan Kim /* Need for hugepage writeback racing */ 710a939888eSMinchan Kim zram_set_flag(zram, index, ZRAM_IDLE); 711a939888eSMinchan Kim zram_slot_unlock(zram, index); 712a939888eSMinchan Kim if (zram_bvec_read(zram, &bvec, index, 0, NULL)) { 713a939888eSMinchan Kim zram_slot_lock(zram, index); 714a939888eSMinchan Kim zram_clear_flag(zram, index, ZRAM_UNDER_WB); 715a939888eSMinchan Kim zram_clear_flag(zram, index, ZRAM_IDLE); 716a939888eSMinchan Kim zram_slot_unlock(zram, index); 717a939888eSMinchan Kim continue; 718a939888eSMinchan Kim } 719a939888eSMinchan Kim 720a939888eSMinchan Kim bio_init(&bio, &bio_vec, 1); 721a939888eSMinchan Kim bio_set_dev(&bio, zram->bdev); 722a939888eSMinchan Kim bio.bi_iter.bi_sector = blk_idx * (PAGE_SIZE >> 9); 723a939888eSMinchan Kim bio.bi_opf = REQ_OP_WRITE | REQ_SYNC; 724a939888eSMinchan Kim 725a939888eSMinchan Kim bio_add_page(&bio, bvec.bv_page, bvec.bv_len, 726a939888eSMinchan Kim bvec.bv_offset); 727a939888eSMinchan Kim /* 728a939888eSMinchan Kim * XXX: A single page IO would be inefficient for write 729a939888eSMinchan Kim * but it would be not bad as starter. 730a939888eSMinchan Kim */ 73157e0076eSMinchan Kim err = submit_bio_wait(&bio); 73257e0076eSMinchan Kim if (err) { 733a939888eSMinchan Kim zram_slot_lock(zram, index); 734a939888eSMinchan Kim zram_clear_flag(zram, index, ZRAM_UNDER_WB); 735a939888eSMinchan Kim zram_clear_flag(zram, index, ZRAM_IDLE); 736a939888eSMinchan Kim zram_slot_unlock(zram, index); 73757e0076eSMinchan Kim /* 73857e0076eSMinchan Kim * Return last IO error unless every IO were 73957e0076eSMinchan Kim * not suceeded. 74057e0076eSMinchan Kim */ 74157e0076eSMinchan Kim ret = err; 742a939888eSMinchan Kim continue; 743a939888eSMinchan Kim } 744a939888eSMinchan Kim 74523eddf39SMinchan Kim atomic64_inc(&zram->stats.bd_writes); 746a939888eSMinchan Kim /* 747a939888eSMinchan Kim * We released zram_slot_lock so need to check if the slot was 748a939888eSMinchan Kim * changed. If there is freeing for the slot, we can catch it 749a939888eSMinchan Kim * easily by zram_allocated. 750a939888eSMinchan Kim * A subtle case is the slot is freed/reallocated/marked as 751a939888eSMinchan Kim * ZRAM_IDLE again. To close the race, idle_store doesn't 752a939888eSMinchan Kim * mark ZRAM_IDLE once it found the slot was ZRAM_UNDER_WB. 753a939888eSMinchan Kim * Thus, we could close the race by checking ZRAM_IDLE bit. 754a939888eSMinchan Kim */ 755a939888eSMinchan Kim zram_slot_lock(zram, index); 756a939888eSMinchan Kim if (!zram_allocated(zram, index) || 757a939888eSMinchan Kim !zram_test_flag(zram, index, ZRAM_IDLE)) { 758a939888eSMinchan Kim zram_clear_flag(zram, index, ZRAM_UNDER_WB); 759a939888eSMinchan Kim zram_clear_flag(zram, index, ZRAM_IDLE); 760a939888eSMinchan Kim goto next; 761a939888eSMinchan Kim } 762a939888eSMinchan Kim 763a939888eSMinchan Kim zram_free_page(zram, index); 764a939888eSMinchan Kim zram_clear_flag(zram, index, ZRAM_UNDER_WB); 765a939888eSMinchan Kim zram_set_flag(zram, index, ZRAM_WB); 766a939888eSMinchan Kim zram_set_element(zram, index, blk_idx); 767a939888eSMinchan Kim blk_idx = 0; 768a939888eSMinchan Kim atomic64_inc(&zram->stats.pages_stored); 7691d69a3f8SMinchan Kim spin_lock(&zram->wb_limit_lock); 7701d69a3f8SMinchan Kim if (zram->wb_limit_enable && zram->bd_wb_limit > 0) 7711d69a3f8SMinchan Kim zram->bd_wb_limit -= 1UL << (PAGE_SHIFT - 12); 7721d69a3f8SMinchan Kim spin_unlock(&zram->wb_limit_lock); 773a939888eSMinchan Kim next: 774a939888eSMinchan Kim zram_slot_unlock(zram, index); 775a939888eSMinchan Kim } 776a939888eSMinchan Kim 777a939888eSMinchan Kim if (blk_idx) 778a939888eSMinchan Kim free_block_bdev(zram, blk_idx); 779a939888eSMinchan Kim __free_page(page); 780a939888eSMinchan Kim release_init_lock: 781a939888eSMinchan Kim up_read(&zram->init_lock); 782a939888eSMinchan Kim 783a939888eSMinchan Kim return ret; 784a939888eSMinchan Kim } 785a939888eSMinchan Kim 7868e654f8fSMinchan Kim struct zram_work { 7878e654f8fSMinchan Kim struct work_struct work; 7888e654f8fSMinchan Kim struct zram *zram; 7898e654f8fSMinchan Kim unsigned long entry; 7908e654f8fSMinchan Kim struct bio *bio; 791e153abc0SJérôme Glisse struct bio_vec bvec; 7928e654f8fSMinchan Kim }; 7938e654f8fSMinchan Kim 7948e654f8fSMinchan Kim #if PAGE_SIZE != 4096 7958e654f8fSMinchan Kim static void zram_sync_read(struct work_struct *work) 7968e654f8fSMinchan Kim { 7978e654f8fSMinchan Kim struct zram_work *zw = container_of(work, struct zram_work, work); 7988e654f8fSMinchan Kim struct zram *zram = zw->zram; 7998e654f8fSMinchan Kim unsigned long entry = zw->entry; 8008e654f8fSMinchan Kim struct bio *bio = zw->bio; 8018e654f8fSMinchan Kim 802e153abc0SJérôme Glisse read_from_bdev_async(zram, &zw->bvec, entry, bio); 8038e654f8fSMinchan Kim } 8048e654f8fSMinchan Kim 8058e654f8fSMinchan Kim /* 806c62b37d9SChristoph Hellwig * Block layer want one ->submit_bio to be active at a time, so if we use 807c62b37d9SChristoph Hellwig * chained IO with parent IO in same context, it's a deadlock. To avoid that, 808c62b37d9SChristoph Hellwig * use a worker thread context. 8098e654f8fSMinchan Kim */ 8108e654f8fSMinchan Kim static int read_from_bdev_sync(struct zram *zram, struct bio_vec *bvec, 8118e654f8fSMinchan Kim unsigned long entry, struct bio *bio) 8128e654f8fSMinchan Kim { 8138e654f8fSMinchan Kim struct zram_work work; 8148e654f8fSMinchan Kim 815e153abc0SJérôme Glisse work.bvec = *bvec; 8168e654f8fSMinchan Kim work.zram = zram; 8178e654f8fSMinchan Kim work.entry = entry; 8188e654f8fSMinchan Kim work.bio = bio; 8198e654f8fSMinchan Kim 8208e654f8fSMinchan Kim INIT_WORK_ONSTACK(&work.work, zram_sync_read); 8218e654f8fSMinchan Kim queue_work(system_unbound_wq, &work.work); 8228e654f8fSMinchan Kim flush_work(&work.work); 8238e654f8fSMinchan Kim destroy_work_on_stack(&work.work); 8248e654f8fSMinchan Kim 8258e654f8fSMinchan Kim return 1; 8268e654f8fSMinchan Kim } 8278e654f8fSMinchan Kim #else 8288e654f8fSMinchan Kim static int read_from_bdev_sync(struct zram *zram, struct bio_vec *bvec, 8298e654f8fSMinchan Kim unsigned long entry, struct bio *bio) 8308e654f8fSMinchan Kim { 8318e654f8fSMinchan Kim WARN_ON(1); 8328e654f8fSMinchan Kim return -EIO; 8338e654f8fSMinchan Kim } 8348e654f8fSMinchan Kim #endif 8358e654f8fSMinchan Kim 8368e654f8fSMinchan Kim static int read_from_bdev(struct zram *zram, struct bio_vec *bvec, 8378e654f8fSMinchan Kim unsigned long entry, struct bio *parent, bool sync) 8388e654f8fSMinchan Kim { 83923eddf39SMinchan Kim atomic64_inc(&zram->stats.bd_reads); 8408e654f8fSMinchan Kim if (sync) 8418e654f8fSMinchan Kim return read_from_bdev_sync(zram, bvec, entry, parent); 8428e654f8fSMinchan Kim else 8438e654f8fSMinchan Kim return read_from_bdev_async(zram, bvec, entry, parent); 8448e654f8fSMinchan Kim } 845013bf95aSMinchan Kim #else 846013bf95aSMinchan Kim static inline void reset_bdev(struct zram *zram) {}; 8478e654f8fSMinchan Kim static int read_from_bdev(struct zram *zram, struct bio_vec *bvec, 8488e654f8fSMinchan Kim unsigned long entry, struct bio *parent, bool sync) 8498e654f8fSMinchan Kim { 8508e654f8fSMinchan Kim return -EIO; 8518e654f8fSMinchan Kim } 8527e529283SMinchan Kim 8537e529283SMinchan Kim static void free_block_bdev(struct zram *zram, unsigned long blk_idx) {}; 854013bf95aSMinchan Kim #endif 855013bf95aSMinchan Kim 856c0265342SMinchan Kim #ifdef CONFIG_ZRAM_MEMORY_TRACKING 857c0265342SMinchan Kim 858c0265342SMinchan Kim static struct dentry *zram_debugfs_root; 859c0265342SMinchan Kim 860c0265342SMinchan Kim static void zram_debugfs_create(void) 861c0265342SMinchan Kim { 862c0265342SMinchan Kim zram_debugfs_root = debugfs_create_dir("zram", NULL); 863c0265342SMinchan Kim } 864c0265342SMinchan Kim 865c0265342SMinchan Kim static void zram_debugfs_destroy(void) 866c0265342SMinchan Kim { 867c0265342SMinchan Kim debugfs_remove_recursive(zram_debugfs_root); 868c0265342SMinchan Kim } 869c0265342SMinchan Kim 870c0265342SMinchan Kim static void zram_accessed(struct zram *zram, u32 index) 871c0265342SMinchan Kim { 872e82592c4SMinchan Kim zram_clear_flag(zram, index, ZRAM_IDLE); 873c0265342SMinchan Kim zram->table[index].ac_time = ktime_get_boottime(); 874c0265342SMinchan Kim } 875c0265342SMinchan Kim 876c0265342SMinchan Kim static ssize_t read_block_state(struct file *file, char __user *buf, 877c0265342SMinchan Kim size_t count, loff_t *ppos) 878c0265342SMinchan Kim { 879c0265342SMinchan Kim char *kbuf; 880c0265342SMinchan Kim ssize_t index, written = 0; 881c0265342SMinchan Kim struct zram *zram = file->private_data; 882c0265342SMinchan Kim unsigned long nr_pages = zram->disksize >> PAGE_SHIFT; 883c0265342SMinchan Kim struct timespec64 ts; 884c0265342SMinchan Kim 885c0265342SMinchan Kim kbuf = kvmalloc(count, GFP_KERNEL); 886c0265342SMinchan Kim if (!kbuf) 887c0265342SMinchan Kim return -ENOMEM; 888c0265342SMinchan Kim 889c0265342SMinchan Kim down_read(&zram->init_lock); 890c0265342SMinchan Kim if (!init_done(zram)) { 891c0265342SMinchan Kim up_read(&zram->init_lock); 892c0265342SMinchan Kim kvfree(kbuf); 893c0265342SMinchan Kim return -EINVAL; 894c0265342SMinchan Kim } 895c0265342SMinchan Kim 896c0265342SMinchan Kim for (index = *ppos; index < nr_pages; index++) { 897c0265342SMinchan Kim int copied; 898c0265342SMinchan Kim 899c0265342SMinchan Kim zram_slot_lock(zram, index); 900c0265342SMinchan Kim if (!zram_allocated(zram, index)) 901c0265342SMinchan Kim goto next; 902c0265342SMinchan Kim 903c0265342SMinchan Kim ts = ktime_to_timespec64(zram->table[index].ac_time); 904c0265342SMinchan Kim copied = snprintf(kbuf + written, count, 905e82592c4SMinchan Kim "%12zd %12lld.%06lu %c%c%c%c\n", 906c0265342SMinchan Kim index, (s64)ts.tv_sec, 907c0265342SMinchan Kim ts.tv_nsec / NSEC_PER_USEC, 908c0265342SMinchan Kim zram_test_flag(zram, index, ZRAM_SAME) ? 's' : '.', 909c0265342SMinchan Kim zram_test_flag(zram, index, ZRAM_WB) ? 'w' : '.', 910e82592c4SMinchan Kim zram_test_flag(zram, index, ZRAM_HUGE) ? 'h' : '.', 911e82592c4SMinchan Kim zram_test_flag(zram, index, ZRAM_IDLE) ? 'i' : '.'); 912c0265342SMinchan Kim 913c0265342SMinchan Kim if (count < copied) { 914c0265342SMinchan Kim zram_slot_unlock(zram, index); 915c0265342SMinchan Kim break; 916c0265342SMinchan Kim } 917c0265342SMinchan Kim written += copied; 918c0265342SMinchan Kim count -= copied; 919c0265342SMinchan Kim next: 920c0265342SMinchan Kim zram_slot_unlock(zram, index); 921c0265342SMinchan Kim *ppos += 1; 922c0265342SMinchan Kim } 923c0265342SMinchan Kim 924c0265342SMinchan Kim up_read(&zram->init_lock); 925c0265342SMinchan Kim if (copy_to_user(buf, kbuf, written)) 926c0265342SMinchan Kim written = -EFAULT; 927c0265342SMinchan Kim kvfree(kbuf); 928c0265342SMinchan Kim 929c0265342SMinchan Kim return written; 930c0265342SMinchan Kim } 931c0265342SMinchan Kim 932c0265342SMinchan Kim static const struct file_operations proc_zram_block_state_op = { 933c0265342SMinchan Kim .open = simple_open, 934c0265342SMinchan Kim .read = read_block_state, 935c0265342SMinchan Kim .llseek = default_llseek, 936c0265342SMinchan Kim }; 937c0265342SMinchan Kim 938c0265342SMinchan Kim static void zram_debugfs_register(struct zram *zram) 939c0265342SMinchan Kim { 940c0265342SMinchan Kim if (!zram_debugfs_root) 941c0265342SMinchan Kim return; 942c0265342SMinchan Kim 943c0265342SMinchan Kim zram->debugfs_dir = debugfs_create_dir(zram->disk->disk_name, 944c0265342SMinchan Kim zram_debugfs_root); 945c0265342SMinchan Kim debugfs_create_file("block_state", 0400, zram->debugfs_dir, 946c0265342SMinchan Kim zram, &proc_zram_block_state_op); 947c0265342SMinchan Kim } 948c0265342SMinchan Kim 949c0265342SMinchan Kim static void zram_debugfs_unregister(struct zram *zram) 950c0265342SMinchan Kim { 951c0265342SMinchan Kim debugfs_remove_recursive(zram->debugfs_dir); 952c0265342SMinchan Kim } 953c0265342SMinchan Kim #else 954c0265342SMinchan Kim static void zram_debugfs_create(void) {}; 955c0265342SMinchan Kim static void zram_debugfs_destroy(void) {}; 956e82592c4SMinchan Kim static void zram_accessed(struct zram *zram, u32 index) 957e82592c4SMinchan Kim { 958e82592c4SMinchan Kim zram_clear_flag(zram, index, ZRAM_IDLE); 959e82592c4SMinchan Kim }; 960c0265342SMinchan Kim static void zram_debugfs_register(struct zram *zram) {}; 961c0265342SMinchan Kim static void zram_debugfs_unregister(struct zram *zram) {}; 962c0265342SMinchan Kim #endif 963013bf95aSMinchan Kim 96443209ea2SSergey Senozhatsky /* 96543209ea2SSergey Senozhatsky * We switched to per-cpu streams and this attr is not needed anymore. 96643209ea2SSergey Senozhatsky * However, we will keep it around for some time, because: 96743209ea2SSergey Senozhatsky * a) we may revert per-cpu streams in the future 96843209ea2SSergey Senozhatsky * b) it's visible to user space and we need to follow our 2 years 96943209ea2SSergey Senozhatsky * retirement rule; but we already have a number of 'soon to be 97043209ea2SSergey Senozhatsky * altered' attrs, so max_comp_streams need to wait for the next 97143209ea2SSergey Senozhatsky * layoff cycle. 97243209ea2SSergey Senozhatsky */ 973522698d7SSergey Senozhatsky static ssize_t max_comp_streams_show(struct device *dev, 974522698d7SSergey Senozhatsky struct device_attribute *attr, char *buf) 975522698d7SSergey Senozhatsky { 97643209ea2SSergey Senozhatsky return scnprintf(buf, PAGE_SIZE, "%d\n", num_online_cpus()); 977522698d7SSergey Senozhatsky } 978522698d7SSergey Senozhatsky 979beca3ec7SSergey Senozhatsky static ssize_t max_comp_streams_store(struct device *dev, 980beca3ec7SSergey Senozhatsky struct device_attribute *attr, const char *buf, size_t len) 981beca3ec7SSergey Senozhatsky { 98243209ea2SSergey Senozhatsky return len; 983beca3ec7SSergey Senozhatsky } 984beca3ec7SSergey Senozhatsky 985e46b8a03SSergey Senozhatsky static ssize_t comp_algorithm_show(struct device *dev, 986e46b8a03SSergey Senozhatsky struct device_attribute *attr, char *buf) 987e46b8a03SSergey Senozhatsky { 988e46b8a03SSergey Senozhatsky size_t sz; 989e46b8a03SSergey Senozhatsky struct zram *zram = dev_to_zram(dev); 990e46b8a03SSergey Senozhatsky 991e46b8a03SSergey Senozhatsky down_read(&zram->init_lock); 992e46b8a03SSergey Senozhatsky sz = zcomp_available_show(zram->compressor, buf); 993e46b8a03SSergey Senozhatsky up_read(&zram->init_lock); 994e46b8a03SSergey Senozhatsky 995e46b8a03SSergey Senozhatsky return sz; 996e46b8a03SSergey Senozhatsky } 997e46b8a03SSergey Senozhatsky 998e46b8a03SSergey Senozhatsky static ssize_t comp_algorithm_store(struct device *dev, 999e46b8a03SSergey Senozhatsky struct device_attribute *attr, const char *buf, size_t len) 1000e46b8a03SSergey Senozhatsky { 1001e46b8a03SSergey Senozhatsky struct zram *zram = dev_to_zram(dev); 1002f357e345SMatthias Kaehlcke char compressor[ARRAY_SIZE(zram->compressor)]; 10034bbacd51SSergey Senozhatsky size_t sz; 10044bbacd51SSergey Senozhatsky 1005415403beSSergey Senozhatsky strlcpy(compressor, buf, sizeof(compressor)); 1006415403beSSergey Senozhatsky /* ignore trailing newline */ 1007415403beSSergey Senozhatsky sz = strlen(compressor); 1008415403beSSergey Senozhatsky if (sz > 0 && compressor[sz - 1] == '\n') 1009415403beSSergey Senozhatsky compressor[sz - 1] = 0x00; 1010415403beSSergey Senozhatsky 1011415403beSSergey Senozhatsky if (!zcomp_available_algorithm(compressor)) 10121d5b43bfSLuis Henriques return -EINVAL; 10131d5b43bfSLuis Henriques 1014e46b8a03SSergey Senozhatsky down_write(&zram->init_lock); 1015e46b8a03SSergey Senozhatsky if (init_done(zram)) { 1016e46b8a03SSergey Senozhatsky up_write(&zram->init_lock); 1017e46b8a03SSergey Senozhatsky pr_info("Can't change algorithm for initialized device\n"); 1018e46b8a03SSergey Senozhatsky return -EBUSY; 1019e46b8a03SSergey Senozhatsky } 10204bbacd51SSergey Senozhatsky 1021f357e345SMatthias Kaehlcke strcpy(zram->compressor, compressor); 1022e46b8a03SSergey Senozhatsky up_write(&zram->init_lock); 1023e46b8a03SSergey Senozhatsky return len; 1024e46b8a03SSergey Senozhatsky } 1025e46b8a03SSergey Senozhatsky 1026522698d7SSergey Senozhatsky static ssize_t compact_store(struct device *dev, 1027522698d7SSergey Senozhatsky struct device_attribute *attr, const char *buf, size_t len) 1028cd67e10aSMinchan Kim { 1029522698d7SSergey Senozhatsky struct zram *zram = dev_to_zram(dev); 1030522698d7SSergey Senozhatsky 1031522698d7SSergey Senozhatsky down_read(&zram->init_lock); 1032522698d7SSergey Senozhatsky if (!init_done(zram)) { 1033522698d7SSergey Senozhatsky up_read(&zram->init_lock); 1034522698d7SSergey Senozhatsky return -EINVAL; 1035cd67e10aSMinchan Kim } 1036cd67e10aSMinchan Kim 1037beb6602cSMinchan Kim zs_compact(zram->mem_pool); 1038522698d7SSergey Senozhatsky up_read(&zram->init_lock); 1039522698d7SSergey Senozhatsky 1040522698d7SSergey Senozhatsky return len; 1041cd67e10aSMinchan Kim } 1042cd67e10aSMinchan Kim 1043522698d7SSergey Senozhatsky static ssize_t io_stat_show(struct device *dev, 1044522698d7SSergey Senozhatsky struct device_attribute *attr, char *buf) 1045cd67e10aSMinchan Kim { 1046522698d7SSergey Senozhatsky struct zram *zram = dev_to_zram(dev); 1047522698d7SSergey Senozhatsky ssize_t ret; 1048522698d7SSergey Senozhatsky 1049522698d7SSergey Senozhatsky down_read(&zram->init_lock); 1050522698d7SSergey Senozhatsky ret = scnprintf(buf, PAGE_SIZE, 1051522698d7SSergey Senozhatsky "%8llu %8llu %8llu %8llu\n", 1052522698d7SSergey Senozhatsky (u64)atomic64_read(&zram->stats.failed_reads), 1053522698d7SSergey Senozhatsky (u64)atomic64_read(&zram->stats.failed_writes), 1054522698d7SSergey Senozhatsky (u64)atomic64_read(&zram->stats.invalid_io), 1055522698d7SSergey Senozhatsky (u64)atomic64_read(&zram->stats.notify_free)); 1056522698d7SSergey Senozhatsky up_read(&zram->init_lock); 1057522698d7SSergey Senozhatsky 1058522698d7SSergey Senozhatsky return ret; 1059d2d5e762SWeijie Yang } 1060d2d5e762SWeijie Yang 1061522698d7SSergey Senozhatsky static ssize_t mm_stat_show(struct device *dev, 1062522698d7SSergey Senozhatsky struct device_attribute *attr, char *buf) 1063d2d5e762SWeijie Yang { 1064522698d7SSergey Senozhatsky struct zram *zram = dev_to_zram(dev); 10657d3f3938SSergey Senozhatsky struct zs_pool_stats pool_stats; 1066522698d7SSergey Senozhatsky u64 orig_size, mem_used = 0; 1067522698d7SSergey Senozhatsky long max_used; 1068522698d7SSergey Senozhatsky ssize_t ret; 1069522698d7SSergey Senozhatsky 10707d3f3938SSergey Senozhatsky memset(&pool_stats, 0x00, sizeof(struct zs_pool_stats)); 10717d3f3938SSergey Senozhatsky 1072522698d7SSergey Senozhatsky down_read(&zram->init_lock); 10737d3f3938SSergey Senozhatsky if (init_done(zram)) { 1074beb6602cSMinchan Kim mem_used = zs_get_total_pages(zram->mem_pool); 1075beb6602cSMinchan Kim zs_pool_stats(zram->mem_pool, &pool_stats); 10767d3f3938SSergey Senozhatsky } 1077522698d7SSergey Senozhatsky 1078522698d7SSergey Senozhatsky orig_size = atomic64_read(&zram->stats.pages_stored); 1079522698d7SSergey Senozhatsky max_used = atomic_long_read(&zram->stats.max_used_pages); 1080522698d7SSergey Senozhatsky 1081522698d7SSergey Senozhatsky ret = scnprintf(buf, PAGE_SIZE, 1082194e28daSMinchan Kim "%8llu %8llu %8llu %8lu %8ld %8llu %8lu %8llu %8llu\n", 1083522698d7SSergey Senozhatsky orig_size << PAGE_SHIFT, 1084522698d7SSergey Senozhatsky (u64)atomic64_read(&zram->stats.compr_data_size), 1085522698d7SSergey Senozhatsky mem_used << PAGE_SHIFT, 1086522698d7SSergey Senozhatsky zram->limit_pages << PAGE_SHIFT, 1087522698d7SSergey Senozhatsky max_used << PAGE_SHIFT, 10888e19d540Szhouxianrong (u64)atomic64_read(&zram->stats.same_pages), 108923959281SRokudo Yan atomic_long_read(&pool_stats.pages_compacted), 1090194e28daSMinchan Kim (u64)atomic64_read(&zram->stats.huge_pages), 1091194e28daSMinchan Kim (u64)atomic64_read(&zram->stats.huge_pages_since)); 1092522698d7SSergey Senozhatsky up_read(&zram->init_lock); 1093522698d7SSergey Senozhatsky 1094522698d7SSergey Senozhatsky return ret; 1095d2d5e762SWeijie Yang } 1096d2d5e762SWeijie Yang 109723eddf39SMinchan Kim #ifdef CONFIG_ZRAM_WRITEBACK 1098bb416d18SMinchan Kim #define FOUR_K(x) ((x) * (1 << (PAGE_SHIFT - 12))) 109923eddf39SMinchan Kim static ssize_t bd_stat_show(struct device *dev, 110023eddf39SMinchan Kim struct device_attribute *attr, char *buf) 110123eddf39SMinchan Kim { 110223eddf39SMinchan Kim struct zram *zram = dev_to_zram(dev); 110323eddf39SMinchan Kim ssize_t ret; 110423eddf39SMinchan Kim 110523eddf39SMinchan Kim down_read(&zram->init_lock); 110623eddf39SMinchan Kim ret = scnprintf(buf, PAGE_SIZE, 110723eddf39SMinchan Kim "%8llu %8llu %8llu\n", 1108bb416d18SMinchan Kim FOUR_K((u64)atomic64_read(&zram->stats.bd_count)), 1109bb416d18SMinchan Kim FOUR_K((u64)atomic64_read(&zram->stats.bd_reads)), 1110bb416d18SMinchan Kim FOUR_K((u64)atomic64_read(&zram->stats.bd_writes))); 111123eddf39SMinchan Kim up_read(&zram->init_lock); 111223eddf39SMinchan Kim 111323eddf39SMinchan Kim return ret; 111423eddf39SMinchan Kim } 111523eddf39SMinchan Kim #endif 111623eddf39SMinchan Kim 1117623e47fcSSergey Senozhatsky static ssize_t debug_stat_show(struct device *dev, 1118623e47fcSSergey Senozhatsky struct device_attribute *attr, char *buf) 1119623e47fcSSergey Senozhatsky { 1120623e47fcSSergey Senozhatsky int version = 1; 1121623e47fcSSergey Senozhatsky struct zram *zram = dev_to_zram(dev); 1122623e47fcSSergey Senozhatsky ssize_t ret; 1123623e47fcSSergey Senozhatsky 1124623e47fcSSergey Senozhatsky down_read(&zram->init_lock); 1125623e47fcSSergey Senozhatsky ret = scnprintf(buf, PAGE_SIZE, 11263c9959e0SMinchan Kim "version: %d\n%8llu %8llu\n", 1127623e47fcSSergey Senozhatsky version, 11283c9959e0SMinchan Kim (u64)atomic64_read(&zram->stats.writestall), 11293c9959e0SMinchan Kim (u64)atomic64_read(&zram->stats.miss_free)); 1130623e47fcSSergey Senozhatsky up_read(&zram->init_lock); 1131623e47fcSSergey Senozhatsky 1132623e47fcSSergey Senozhatsky return ret; 1133623e47fcSSergey Senozhatsky } 1134623e47fcSSergey Senozhatsky 1135522698d7SSergey Senozhatsky static DEVICE_ATTR_RO(io_stat); 1136522698d7SSergey Senozhatsky static DEVICE_ATTR_RO(mm_stat); 113723eddf39SMinchan Kim #ifdef CONFIG_ZRAM_WRITEBACK 113823eddf39SMinchan Kim static DEVICE_ATTR_RO(bd_stat); 113923eddf39SMinchan Kim #endif 1140623e47fcSSergey Senozhatsky static DEVICE_ATTR_RO(debug_stat); 1141d2d5e762SWeijie Yang 1142beb6602cSMinchan Kim static void zram_meta_free(struct zram *zram, u64 disksize) 1143cd67e10aSMinchan Kim { 11441fec1172SGanesh Mahendran size_t num_pages = disksize >> PAGE_SHIFT; 11451fec1172SGanesh Mahendran size_t index; 11461fec1172SGanesh Mahendran 11471fec1172SGanesh Mahendran /* Free all pages that are still in this zram device */ 1148302128dcSMinchan Kim for (index = 0; index < num_pages; index++) 1149302128dcSMinchan Kim zram_free_page(zram, index); 11501fec1172SGanesh Mahendran 1151beb6602cSMinchan Kim zs_destroy_pool(zram->mem_pool); 1152beb6602cSMinchan Kim vfree(zram->table); 1153cd67e10aSMinchan Kim } 1154cd67e10aSMinchan Kim 1155beb6602cSMinchan Kim static bool zram_meta_alloc(struct zram *zram, u64 disksize) 1156cd67e10aSMinchan Kim { 1157cd67e10aSMinchan Kim size_t num_pages; 1158cd67e10aSMinchan Kim 1159cd67e10aSMinchan Kim num_pages = disksize >> PAGE_SHIFT; 1160fad953ceSKees Cook zram->table = vzalloc(array_size(num_pages, sizeof(*zram->table))); 1161beb6602cSMinchan Kim if (!zram->table) 1162beb6602cSMinchan Kim return false; 1163beb6602cSMinchan Kim 1164beb6602cSMinchan Kim zram->mem_pool = zs_create_pool(zram->disk->disk_name); 1165beb6602cSMinchan Kim if (!zram->mem_pool) { 1166beb6602cSMinchan Kim vfree(zram->table); 1167beb6602cSMinchan Kim return false; 1168cd67e10aSMinchan Kim } 1169cd67e10aSMinchan Kim 117060f5921aSSergey Senozhatsky if (!huge_class_size) 117160f5921aSSergey Senozhatsky huge_class_size = zs_huge_class_size(zram->mem_pool); 1172beb6602cSMinchan Kim return true; 1173cd67e10aSMinchan Kim } 1174cd67e10aSMinchan Kim 1175d2d5e762SWeijie Yang /* 1176d2d5e762SWeijie Yang * To protect concurrent access to the same index entry, 1177d2d5e762SWeijie Yang * caller should hold this table index entry's bit_spinlock to 1178d2d5e762SWeijie Yang * indicate this index entry is accessing. 1179d2d5e762SWeijie Yang */ 1180cd67e10aSMinchan Kim static void zram_free_page(struct zram *zram, size_t index) 1181cd67e10aSMinchan Kim { 1182db8ffbd4SMinchan Kim unsigned long handle; 1183db8ffbd4SMinchan Kim 11847e529283SMinchan Kim #ifdef CONFIG_ZRAM_MEMORY_TRACKING 11857e529283SMinchan Kim zram->table[index].ac_time = 0; 11867e529283SMinchan Kim #endif 1187e82592c4SMinchan Kim if (zram_test_flag(zram, index, ZRAM_IDLE)) 1188e82592c4SMinchan Kim zram_clear_flag(zram, index, ZRAM_IDLE); 1189e82592c4SMinchan Kim 119089e85bceSMinchan Kim if (zram_test_flag(zram, index, ZRAM_HUGE)) { 119189e85bceSMinchan Kim zram_clear_flag(zram, index, ZRAM_HUGE); 119289e85bceSMinchan Kim atomic64_dec(&zram->stats.huge_pages); 119389e85bceSMinchan Kim } 119489e85bceSMinchan Kim 11957e529283SMinchan Kim if (zram_test_flag(zram, index, ZRAM_WB)) { 11967e529283SMinchan Kim zram_clear_flag(zram, index, ZRAM_WB); 11977e529283SMinchan Kim free_block_bdev(zram, zram_get_element(zram, index)); 11987e529283SMinchan Kim goto out; 1199db8ffbd4SMinchan Kim } 1200cd67e10aSMinchan Kim 1201cd67e10aSMinchan Kim /* 12028e19d540Szhouxianrong * No memory is allocated for same element filled pages. 12038e19d540Szhouxianrong * Simply clear same page flag. 1204cd67e10aSMinchan Kim */ 1205beb6602cSMinchan Kim if (zram_test_flag(zram, index, ZRAM_SAME)) { 1206beb6602cSMinchan Kim zram_clear_flag(zram, index, ZRAM_SAME); 12078e19d540Szhouxianrong atomic64_dec(&zram->stats.same_pages); 12087e529283SMinchan Kim goto out; 1209cd67e10aSMinchan Kim } 1210cd67e10aSMinchan Kim 1211db8ffbd4SMinchan Kim handle = zram_get_handle(zram, index); 12128e19d540Szhouxianrong if (!handle) 12138e19d540Szhouxianrong return; 12148e19d540Szhouxianrong 1215beb6602cSMinchan Kim zs_free(zram->mem_pool, handle); 1216cd67e10aSMinchan Kim 1217beb6602cSMinchan Kim atomic64_sub(zram_get_obj_size(zram, index), 1218d2d5e762SWeijie Yang &zram->stats.compr_data_size); 12197e529283SMinchan Kim out: 122090a7806eSSergey Senozhatsky atomic64_dec(&zram->stats.pages_stored); 1221643ae61dSMinchan Kim zram_set_handle(zram, index, 0); 1222beb6602cSMinchan Kim zram_set_obj_size(zram, index, 0); 1223a939888eSMinchan Kim WARN_ON_ONCE(zram->table[index].flags & 1224a939888eSMinchan Kim ~(1UL << ZRAM_LOCK | 1UL << ZRAM_UNDER_WB)); 1225cd67e10aSMinchan Kim } 1226cd67e10aSMinchan Kim 12278e654f8fSMinchan Kim static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index, 12288e654f8fSMinchan Kim struct bio *bio, bool partial_io) 1229cd67e10aSMinchan Kim { 12300669d2b2SPeter Zijlstra struct zcomp_strm *zstrm; 123192967471SMinchan Kim unsigned long handle; 1232ebaf9ab5SSergey Senozhatsky unsigned int size; 12331f7319c7SMinchan Kim void *src, *dst; 12340669d2b2SPeter Zijlstra int ret; 12351f7319c7SMinchan Kim 12368e654f8fSMinchan Kim zram_slot_lock(zram, index); 12378e654f8fSMinchan Kim if (zram_test_flag(zram, index, ZRAM_WB)) { 12388e654f8fSMinchan Kim struct bio_vec bvec; 12398e654f8fSMinchan Kim 12408e654f8fSMinchan Kim zram_slot_unlock(zram, index); 12418e654f8fSMinchan Kim 12428e654f8fSMinchan Kim bvec.bv_page = page; 12438e654f8fSMinchan Kim bvec.bv_len = PAGE_SIZE; 12448e654f8fSMinchan Kim bvec.bv_offset = 0; 12458e654f8fSMinchan Kim return read_from_bdev(zram, &bvec, 12468e654f8fSMinchan Kim zram_get_element(zram, index), 12478e654f8fSMinchan Kim bio, partial_io); 12488e654f8fSMinchan Kim } 12498e654f8fSMinchan Kim 1250643ae61dSMinchan Kim handle = zram_get_handle(zram, index); 1251ae94264eSMinchan Kim if (!handle || zram_test_flag(zram, index, ZRAM_SAME)) { 1252ae94264eSMinchan Kim unsigned long value; 1253ae94264eSMinchan Kim void *mem; 1254ae94264eSMinchan Kim 1255ae94264eSMinchan Kim value = handle ? zram_get_element(zram, index) : 0; 1256ae94264eSMinchan Kim mem = kmap_atomic(page); 1257ae94264eSMinchan Kim zram_fill_page(mem, PAGE_SIZE, value); 1258ae94264eSMinchan Kim kunmap_atomic(mem); 1259ae94264eSMinchan Kim zram_slot_unlock(zram, index); 1260ae94264eSMinchan Kim return 0; 1261ae94264eSMinchan Kim } 1262ae94264eSMinchan Kim 1263beb6602cSMinchan Kim size = zram_get_obj_size(zram, index); 1264cd67e10aSMinchan Kim 12650669d2b2SPeter Zijlstra if (size != PAGE_SIZE) 12660669d2b2SPeter Zijlstra zstrm = zcomp_stream_get(zram->comp); 12670669d2b2SPeter Zijlstra 1268beb6602cSMinchan Kim src = zs_map_object(zram->mem_pool, handle, ZS_MM_RO); 1269ebaf9ab5SSergey Senozhatsky if (size == PAGE_SIZE) { 12701f7319c7SMinchan Kim dst = kmap_atomic(page); 12711f7319c7SMinchan Kim memcpy(dst, src, PAGE_SIZE); 12721f7319c7SMinchan Kim kunmap_atomic(dst); 12731f7319c7SMinchan Kim ret = 0; 1274ebaf9ab5SSergey Senozhatsky } else { 12751f7319c7SMinchan Kim dst = kmap_atomic(page); 12761f7319c7SMinchan Kim ret = zcomp_decompress(zstrm, src, size, dst); 12771f7319c7SMinchan Kim kunmap_atomic(dst); 1278ebaf9ab5SSergey Senozhatsky zcomp_stream_put(zram->comp); 1279ebaf9ab5SSergey Senozhatsky } 1280beb6602cSMinchan Kim zs_unmap_object(zram->mem_pool, handle); 128186c49814SMinchan Kim zram_slot_unlock(zram, index); 1282cd67e10aSMinchan Kim 1283cd67e10aSMinchan Kim /* Should NEVER happen. Return bio error if it does. */ 12844e79603bSDouglas Anderson if (WARN_ON(ret)) 1285cd67e10aSMinchan Kim pr_err("Decompression failed! err=%d, page=%u\n", ret, index); 1286cd67e10aSMinchan Kim 12871f7319c7SMinchan Kim return ret; 1288cd67e10aSMinchan Kim } 1289cd67e10aSMinchan Kim 1290cd67e10aSMinchan Kim static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, 12918e654f8fSMinchan Kim u32 index, int offset, struct bio *bio) 1292cd67e10aSMinchan Kim { 1293cd67e10aSMinchan Kim int ret; 1294cd67e10aSMinchan Kim struct page *page; 12951f7319c7SMinchan Kim 1296cd67e10aSMinchan Kim page = bvec->bv_page; 12971f7319c7SMinchan Kim if (is_partial_io(bvec)) { 1298cd67e10aSMinchan Kim /* Use a temporary buffer to decompress the page */ 12991f7319c7SMinchan Kim page = alloc_page(GFP_NOIO|__GFP_HIGHMEM); 13001f7319c7SMinchan Kim if (!page) 13011f7319c7SMinchan Kim return -ENOMEM; 1302cd67e10aSMinchan Kim } 1303cd67e10aSMinchan Kim 13048e654f8fSMinchan Kim ret = __zram_bvec_read(zram, page, index, bio, is_partial_io(bvec)); 1305b7ca232eSSergey Senozhatsky if (unlikely(ret)) 13061f7319c7SMinchan Kim goto out; 1307cd67e10aSMinchan Kim 13081f7319c7SMinchan Kim if (is_partial_io(bvec)) { 13091f7319c7SMinchan Kim void *dst = kmap_atomic(bvec->bv_page); 13101f7319c7SMinchan Kim void *src = kmap_atomic(page); 1311cd67e10aSMinchan Kim 13121f7319c7SMinchan Kim memcpy(dst + bvec->bv_offset, src + offset, bvec->bv_len); 13131f7319c7SMinchan Kim kunmap_atomic(src); 13141f7319c7SMinchan Kim kunmap_atomic(dst); 13151f7319c7SMinchan Kim } 13161f7319c7SMinchan Kim out: 1317cd67e10aSMinchan Kim if (is_partial_io(bvec)) 13181f7319c7SMinchan Kim __free_page(page); 13191f7319c7SMinchan Kim 1320cd67e10aSMinchan Kim return ret; 1321cd67e10aSMinchan Kim } 1322cd67e10aSMinchan Kim 1323db8ffbd4SMinchan Kim static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec, 1324db8ffbd4SMinchan Kim u32 index, struct bio *bio) 1325cd67e10aSMinchan Kim { 1326ae85a807SMinchan Kim int ret = 0; 1327461a8eeeSMinchan Kim unsigned long alloced_pages; 13281f7319c7SMinchan Kim unsigned long handle = 0; 132997ec7c8bSMinchan Kim unsigned int comp_len = 0; 133097ec7c8bSMinchan Kim void *src, *dst, *mem; 133197ec7c8bSMinchan Kim struct zcomp_strm *zstrm; 133297ec7c8bSMinchan Kim struct page *page = bvec->bv_page; 133397ec7c8bSMinchan Kim unsigned long element = 0; 133497ec7c8bSMinchan Kim enum zram_pageflags flags = 0; 133597ec7c8bSMinchan Kim 133697ec7c8bSMinchan Kim mem = kmap_atomic(page); 133797ec7c8bSMinchan Kim if (page_same_filled(mem, &element)) { 133897ec7c8bSMinchan Kim kunmap_atomic(mem); 133997ec7c8bSMinchan Kim /* Free memory associated with this sector now. */ 134097ec7c8bSMinchan Kim flags = ZRAM_SAME; 134197ec7c8bSMinchan Kim atomic64_inc(&zram->stats.same_pages); 134297ec7c8bSMinchan Kim goto out; 134397ec7c8bSMinchan Kim } 134497ec7c8bSMinchan Kim kunmap_atomic(mem); 1345cd67e10aSMinchan Kim 1346da9556a2SSergey Senozhatsky compress_again: 134797ec7c8bSMinchan Kim zstrm = zcomp_stream_get(zram->comp); 13481f7319c7SMinchan Kim src = kmap_atomic(page); 134997ec7c8bSMinchan Kim ret = zcomp_compress(zstrm, src, &comp_len); 13501f7319c7SMinchan Kim kunmap_atomic(src); 1351cd67e10aSMinchan Kim 1352b7ca232eSSergey Senozhatsky if (unlikely(ret)) { 135397ec7c8bSMinchan Kim zcomp_stream_put(zram->comp); 1354cd67e10aSMinchan Kim pr_err("Compression failed! err=%d\n", ret); 1355beb6602cSMinchan Kim zs_free(zram->mem_pool, handle); 13561f7319c7SMinchan Kim return ret; 1357cd67e10aSMinchan Kim } 1358da9556a2SSergey Senozhatsky 1359a939888eSMinchan Kim if (comp_len >= huge_class_size) 136089e85bceSMinchan Kim comp_len = PAGE_SIZE; 1361da9556a2SSergey Senozhatsky /* 1362da9556a2SSergey Senozhatsky * handle allocation has 2 paths: 1363da9556a2SSergey Senozhatsky * a) fast path is executed with preemption disabled (for 1364da9556a2SSergey Senozhatsky * per-cpu streams) and has __GFP_DIRECT_RECLAIM bit clear, 1365da9556a2SSergey Senozhatsky * since we can't sleep; 1366da9556a2SSergey Senozhatsky * b) slow path enables preemption and attempts to allocate 1367da9556a2SSergey Senozhatsky * the page with __GFP_DIRECT_RECLAIM bit set. we have to 1368da9556a2SSergey Senozhatsky * put per-cpu compression stream and, thus, to re-do 1369da9556a2SSergey Senozhatsky * the compression once handle is allocated. 1370da9556a2SSergey Senozhatsky * 1371da9556a2SSergey Senozhatsky * if we have a 'non-null' handle here then we are coming 1372da9556a2SSergey Senozhatsky * from the slow path and handle has already been allocated. 1373da9556a2SSergey Senozhatsky */ 1374da9556a2SSergey Senozhatsky if (!handle) 1375beb6602cSMinchan Kim handle = zs_malloc(zram->mem_pool, comp_len, 1376da9556a2SSergey Senozhatsky __GFP_KSWAPD_RECLAIM | 1377da9556a2SSergey Senozhatsky __GFP_NOWARN | 13789bc482d3SMinchan Kim __GFP_HIGHMEM | 13799bc482d3SMinchan Kim __GFP_MOVABLE); 1380cd67e10aSMinchan Kim if (!handle) { 13812aea8493SSergey Senozhatsky zcomp_stream_put(zram->comp); 1382623e47fcSSergey Senozhatsky atomic64_inc(&zram->stats.writestall); 1383beb6602cSMinchan Kim handle = zs_malloc(zram->mem_pool, comp_len, 13849bc482d3SMinchan Kim GFP_NOIO | __GFP_HIGHMEM | 13859bc482d3SMinchan Kim __GFP_MOVABLE); 1386da9556a2SSergey Senozhatsky if (handle) 1387da9556a2SSergey Senozhatsky goto compress_again; 13881f7319c7SMinchan Kim return -ENOMEM; 1389cd67e10aSMinchan Kim } 13909ada9da9SMinchan Kim 1391beb6602cSMinchan Kim alloced_pages = zs_get_total_pages(zram->mem_pool); 139212372755SSergey SENOZHATSKY update_used_max(zram, alloced_pages); 139312372755SSergey SENOZHATSKY 1394461a8eeeSMinchan Kim if (zram->limit_pages && alloced_pages > zram->limit_pages) { 139597ec7c8bSMinchan Kim zcomp_stream_put(zram->comp); 1396beb6602cSMinchan Kim zs_free(zram->mem_pool, handle); 13971f7319c7SMinchan Kim return -ENOMEM; 13989ada9da9SMinchan Kim } 13999ada9da9SMinchan Kim 1400beb6602cSMinchan Kim dst = zs_map_object(zram->mem_pool, handle, ZS_MM_WO); 14011f7319c7SMinchan Kim 14021f7319c7SMinchan Kim src = zstrm->buffer; 14031f7319c7SMinchan Kim if (comp_len == PAGE_SIZE) 1404cd67e10aSMinchan Kim src = kmap_atomic(page); 14051f7319c7SMinchan Kim memcpy(dst, src, comp_len); 14061f7319c7SMinchan Kim if (comp_len == PAGE_SIZE) 1407cd67e10aSMinchan Kim kunmap_atomic(src); 1408cd67e10aSMinchan Kim 14092aea8493SSergey Senozhatsky zcomp_stream_put(zram->comp); 1410beb6602cSMinchan Kim zs_unmap_object(zram->mem_pool, handle); 14114ebbe7f7SMinchan Kim atomic64_add(comp_len, &zram->stats.compr_data_size); 14124ebbe7f7SMinchan Kim out: 1413cd67e10aSMinchan Kim /* 1414cd67e10aSMinchan Kim * Free memory associated with this sector 1415cd67e10aSMinchan Kim * before overwriting unused sectors. 1416cd67e10aSMinchan Kim */ 141786c49814SMinchan Kim zram_slot_lock(zram, index); 1418cd67e10aSMinchan Kim zram_free_page(zram, index); 1419db8ffbd4SMinchan Kim 142089e85bceSMinchan Kim if (comp_len == PAGE_SIZE) { 142189e85bceSMinchan Kim zram_set_flag(zram, index, ZRAM_HUGE); 142289e85bceSMinchan Kim atomic64_inc(&zram->stats.huge_pages); 1423194e28daSMinchan Kim atomic64_inc(&zram->stats.huge_pages_since); 142489e85bceSMinchan Kim } 142589e85bceSMinchan Kim 1426db8ffbd4SMinchan Kim if (flags) { 1427db8ffbd4SMinchan Kim zram_set_flag(zram, index, flags); 14284ebbe7f7SMinchan Kim zram_set_element(zram, index, element); 14294ebbe7f7SMinchan Kim } else { 1430643ae61dSMinchan Kim zram_set_handle(zram, index, handle); 1431beb6602cSMinchan Kim zram_set_obj_size(zram, index, comp_len); 14324ebbe7f7SMinchan Kim } 143386c49814SMinchan Kim zram_slot_unlock(zram, index); 1434cd67e10aSMinchan Kim 1435cd67e10aSMinchan Kim /* Update stats */ 143690a7806eSSergey Senozhatsky atomic64_inc(&zram->stats.pages_stored); 1437ae85a807SMinchan Kim return ret; 14381f7319c7SMinchan Kim } 14391f7319c7SMinchan Kim 14401f7319c7SMinchan Kim static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, 1441db8ffbd4SMinchan Kim u32 index, int offset, struct bio *bio) 14421f7319c7SMinchan Kim { 14431f7319c7SMinchan Kim int ret; 14441f7319c7SMinchan Kim struct page *page = NULL; 14451f7319c7SMinchan Kim void *src; 14461f7319c7SMinchan Kim struct bio_vec vec; 14471f7319c7SMinchan Kim 14481f7319c7SMinchan Kim vec = *bvec; 14491f7319c7SMinchan Kim if (is_partial_io(bvec)) { 14501f7319c7SMinchan Kim void *dst; 14511f7319c7SMinchan Kim /* 14521f7319c7SMinchan Kim * This is a partial IO. We need to read the full page 14531f7319c7SMinchan Kim * before to write the changes. 14541f7319c7SMinchan Kim */ 14551f7319c7SMinchan Kim page = alloc_page(GFP_NOIO|__GFP_HIGHMEM); 14561f7319c7SMinchan Kim if (!page) 14571f7319c7SMinchan Kim return -ENOMEM; 14581f7319c7SMinchan Kim 14598e654f8fSMinchan Kim ret = __zram_bvec_read(zram, page, index, bio, true); 14601f7319c7SMinchan Kim if (ret) 14611f7319c7SMinchan Kim goto out; 14621f7319c7SMinchan Kim 14631f7319c7SMinchan Kim src = kmap_atomic(bvec->bv_page); 14641f7319c7SMinchan Kim dst = kmap_atomic(page); 14651f7319c7SMinchan Kim memcpy(dst + offset, src + bvec->bv_offset, bvec->bv_len); 14661f7319c7SMinchan Kim kunmap_atomic(dst); 14671f7319c7SMinchan Kim kunmap_atomic(src); 14681f7319c7SMinchan Kim 14691f7319c7SMinchan Kim vec.bv_page = page; 14701f7319c7SMinchan Kim vec.bv_len = PAGE_SIZE; 14711f7319c7SMinchan Kim vec.bv_offset = 0; 14721f7319c7SMinchan Kim } 14731f7319c7SMinchan Kim 1474db8ffbd4SMinchan Kim ret = __zram_bvec_write(zram, &vec, index, bio); 1475cd67e10aSMinchan Kim out: 1476cd67e10aSMinchan Kim if (is_partial_io(bvec)) 14771f7319c7SMinchan Kim __free_page(page); 1478cd67e10aSMinchan Kim return ret; 1479cd67e10aSMinchan Kim } 1480cd67e10aSMinchan Kim 1481f4659d8eSJoonsoo Kim /* 1482f4659d8eSJoonsoo Kim * zram_bio_discard - handler on discard request 1483f4659d8eSJoonsoo Kim * @index: physical block index in PAGE_SIZE units 1484f4659d8eSJoonsoo Kim * @offset: byte offset within physical block 1485f4659d8eSJoonsoo Kim */ 1486f4659d8eSJoonsoo Kim static void zram_bio_discard(struct zram *zram, u32 index, 1487f4659d8eSJoonsoo Kim int offset, struct bio *bio) 1488f4659d8eSJoonsoo Kim { 1489f4659d8eSJoonsoo Kim size_t n = bio->bi_iter.bi_size; 1490f4659d8eSJoonsoo Kim 1491f4659d8eSJoonsoo Kim /* 1492f4659d8eSJoonsoo Kim * zram manages data in physical block size units. Because logical block 1493f4659d8eSJoonsoo Kim * size isn't identical with physical block size on some arch, we 1494f4659d8eSJoonsoo Kim * could get a discard request pointing to a specific offset within a 1495f4659d8eSJoonsoo Kim * certain physical block. Although we can handle this request by 1496f4659d8eSJoonsoo Kim * reading that physiclal block and decompressing and partially zeroing 1497f4659d8eSJoonsoo Kim * and re-compressing and then re-storing it, this isn't reasonable 1498f4659d8eSJoonsoo Kim * because our intent with a discard request is to save memory. So 1499f4659d8eSJoonsoo Kim * skipping this logical block is appropriate here. 1500f4659d8eSJoonsoo Kim */ 1501f4659d8eSJoonsoo Kim if (offset) { 150238515c73SWeijie Yang if (n <= (PAGE_SIZE - offset)) 1503f4659d8eSJoonsoo Kim return; 1504f4659d8eSJoonsoo Kim 150538515c73SWeijie Yang n -= (PAGE_SIZE - offset); 1506f4659d8eSJoonsoo Kim index++; 1507f4659d8eSJoonsoo Kim } 1508f4659d8eSJoonsoo Kim 1509f4659d8eSJoonsoo Kim while (n >= PAGE_SIZE) { 151086c49814SMinchan Kim zram_slot_lock(zram, index); 1511f4659d8eSJoonsoo Kim zram_free_page(zram, index); 151286c49814SMinchan Kim zram_slot_unlock(zram, index); 1513015254daSSergey Senozhatsky atomic64_inc(&zram->stats.notify_free); 1514f4659d8eSJoonsoo Kim index++; 1515f4659d8eSJoonsoo Kim n -= PAGE_SIZE; 1516f4659d8eSJoonsoo Kim } 1517f4659d8eSJoonsoo Kim } 1518f4659d8eSJoonsoo Kim 1519ae85a807SMinchan Kim /* 1520ae85a807SMinchan Kim * Returns errno if it has some problem. Otherwise return 0 or 1. 1521ae85a807SMinchan Kim * Returns 0 if IO request was done synchronously 1522ae85a807SMinchan Kim * Returns 1 if IO request was successfully submitted. 1523ae85a807SMinchan Kim */ 1524522698d7SSergey Senozhatsky static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index, 15253f289dcbSTejun Heo int offset, unsigned int op, struct bio *bio) 1526522698d7SSergey Senozhatsky { 1527522698d7SSergey Senozhatsky int ret; 1528522698d7SSergey Senozhatsky 15293f289dcbSTejun Heo if (!op_is_write(op)) { 1530522698d7SSergey Senozhatsky atomic64_inc(&zram->stats.num_reads); 15318e654f8fSMinchan Kim ret = zram_bvec_read(zram, bvec, index, offset, bio); 15321f7319c7SMinchan Kim flush_dcache_page(bvec->bv_page); 1533522698d7SSergey Senozhatsky } else { 1534522698d7SSergey Senozhatsky atomic64_inc(&zram->stats.num_writes); 1535db8ffbd4SMinchan Kim ret = zram_bvec_write(zram, bvec, index, offset, bio); 1536522698d7SSergey Senozhatsky } 1537522698d7SSergey Senozhatsky 1538d7eac6b6SMinchan Kim zram_slot_lock(zram, index); 1539d7eac6b6SMinchan Kim zram_accessed(zram, index); 1540d7eac6b6SMinchan Kim zram_slot_unlock(zram, index); 1541d7eac6b6SMinchan Kim 1542ae85a807SMinchan Kim if (unlikely(ret < 0)) { 15433f289dcbSTejun Heo if (!op_is_write(op)) 1544522698d7SSergey Senozhatsky atomic64_inc(&zram->stats.failed_reads); 1545522698d7SSergey Senozhatsky else 1546522698d7SSergey Senozhatsky atomic64_inc(&zram->stats.failed_writes); 1547522698d7SSergey Senozhatsky } 1548522698d7SSergey Senozhatsky 1549522698d7SSergey Senozhatsky return ret; 1550522698d7SSergey Senozhatsky } 1551522698d7SSergey Senozhatsky 1552522698d7SSergey Senozhatsky static void __zram_make_request(struct zram *zram, struct bio *bio) 1553522698d7SSergey Senozhatsky { 1554abf54548SMike Christie int offset; 1555522698d7SSergey Senozhatsky u32 index; 1556522698d7SSergey Senozhatsky struct bio_vec bvec; 1557522698d7SSergey Senozhatsky struct bvec_iter iter; 1558d7614e44SChristoph Hellwig unsigned long start_time; 1559522698d7SSergey Senozhatsky 1560522698d7SSergey Senozhatsky index = bio->bi_iter.bi_sector >> SECTORS_PER_PAGE_SHIFT; 1561522698d7SSergey Senozhatsky offset = (bio->bi_iter.bi_sector & 1562522698d7SSergey Senozhatsky (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT; 1563522698d7SSergey Senozhatsky 156431edeacdSChristoph Hellwig switch (bio_op(bio)) { 156531edeacdSChristoph Hellwig case REQ_OP_DISCARD: 156631edeacdSChristoph Hellwig case REQ_OP_WRITE_ZEROES: 1567522698d7SSergey Senozhatsky zram_bio_discard(zram, index, offset, bio); 15684246a0b6SChristoph Hellwig bio_endio(bio); 1569522698d7SSergey Senozhatsky return; 157031edeacdSChristoph Hellwig default: 157131edeacdSChristoph Hellwig break; 1572522698d7SSergey Senozhatsky } 1573522698d7SSergey Senozhatsky 1574d7614e44SChristoph Hellwig start_time = bio_start_io_acct(bio); 1575522698d7SSergey Senozhatsky bio_for_each_segment(bvec, bio, iter) { 1576e86942c7SMinchan Kim struct bio_vec bv = bvec; 1577e86942c7SMinchan Kim unsigned int unwritten = bvec.bv_len; 1578522698d7SSergey Senozhatsky 1579e86942c7SMinchan Kim do { 1580e86942c7SMinchan Kim bv.bv_len = min_t(unsigned int, PAGE_SIZE - offset, 1581e86942c7SMinchan Kim unwritten); 1582abf54548SMike Christie if (zram_bvec_rw(zram, &bv, index, offset, 1583d7614e44SChristoph Hellwig bio_op(bio), bio) < 0) { 1584d7614e44SChristoph Hellwig bio->bi_status = BLK_STS_IOERR; 1585d7614e44SChristoph Hellwig break; 1586d7614e44SChristoph Hellwig } 1587522698d7SSergey Senozhatsky 1588e86942c7SMinchan Kim bv.bv_offset += bv.bv_len; 1589e86942c7SMinchan Kim unwritten -= bv.bv_len; 1590522698d7SSergey Senozhatsky 1591e86942c7SMinchan Kim update_position(&index, &offset, &bv); 1592e86942c7SMinchan Kim } while (unwritten); 1593522698d7SSergey Senozhatsky } 1594d7614e44SChristoph Hellwig bio_end_io_acct(bio, start_time); 15954246a0b6SChristoph Hellwig bio_endio(bio); 1596522698d7SSergey Senozhatsky } 1597522698d7SSergey Senozhatsky 1598522698d7SSergey Senozhatsky /* 1599522698d7SSergey Senozhatsky * Handler function for all zram I/O requests. 1600522698d7SSergey Senozhatsky */ 16013e08773cSChristoph Hellwig static void zram_submit_bio(struct bio *bio) 1602522698d7SSergey Senozhatsky { 1603309dca30SChristoph Hellwig struct zram *zram = bio->bi_bdev->bd_disk->private_data; 1604522698d7SSergey Senozhatsky 1605522698d7SSergey Senozhatsky if (!valid_io_request(zram, bio->bi_iter.bi_sector, 1606522698d7SSergey Senozhatsky bio->bi_iter.bi_size)) { 1607522698d7SSergey Senozhatsky atomic64_inc(&zram->stats.invalid_io); 16083e08773cSChristoph Hellwig bio_io_error(bio); 16093e08773cSChristoph Hellwig return; 1610522698d7SSergey Senozhatsky } 1611522698d7SSergey Senozhatsky 1612522698d7SSergey Senozhatsky __zram_make_request(zram, bio); 1613522698d7SSergey Senozhatsky } 1614522698d7SSergey Senozhatsky 1615522698d7SSergey Senozhatsky static void zram_slot_free_notify(struct block_device *bdev, 1616522698d7SSergey Senozhatsky unsigned long index) 1617522698d7SSergey Senozhatsky { 1618522698d7SSergey Senozhatsky struct zram *zram; 1619522698d7SSergey Senozhatsky 1620522698d7SSergey Senozhatsky zram = bdev->bd_disk->private_data; 1621522698d7SSergey Senozhatsky 16223c9959e0SMinchan Kim atomic64_inc(&zram->stats.notify_free); 16233c9959e0SMinchan Kim if (!zram_slot_trylock(zram, index)) { 16243c9959e0SMinchan Kim atomic64_inc(&zram->stats.miss_free); 16253c9959e0SMinchan Kim return; 16263c9959e0SMinchan Kim } 16273c9959e0SMinchan Kim 1628522698d7SSergey Senozhatsky zram_free_page(zram, index); 162986c49814SMinchan Kim zram_slot_unlock(zram, index); 1630522698d7SSergey Senozhatsky } 1631522698d7SSergey Senozhatsky 1632522698d7SSergey Senozhatsky static int zram_rw_page(struct block_device *bdev, sector_t sector, 16333f289dcbSTejun Heo struct page *page, unsigned int op) 1634522698d7SSergey Senozhatsky { 1635ae85a807SMinchan Kim int offset, ret; 1636522698d7SSergey Senozhatsky u32 index; 1637522698d7SSergey Senozhatsky struct zram *zram; 1638522698d7SSergey Senozhatsky struct bio_vec bv; 1639d7614e44SChristoph Hellwig unsigned long start_time; 1640522698d7SSergey Senozhatsky 164198cc093cSHuang Ying if (PageTransHuge(page)) 164298cc093cSHuang Ying return -ENOTSUPP; 1643522698d7SSergey Senozhatsky zram = bdev->bd_disk->private_data; 1644522698d7SSergey Senozhatsky 1645522698d7SSergey Senozhatsky if (!valid_io_request(zram, sector, PAGE_SIZE)) { 1646522698d7SSergey Senozhatsky atomic64_inc(&zram->stats.invalid_io); 1647ae85a807SMinchan Kim ret = -EINVAL; 1648a09759acSMinchan Kim goto out; 1649522698d7SSergey Senozhatsky } 1650522698d7SSergey Senozhatsky 1651522698d7SSergey Senozhatsky index = sector >> SECTORS_PER_PAGE_SHIFT; 16524ca82dabSMinchan Kim offset = (sector & (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT; 1653522698d7SSergey Senozhatsky 1654522698d7SSergey Senozhatsky bv.bv_page = page; 1655522698d7SSergey Senozhatsky bv.bv_len = PAGE_SIZE; 1656522698d7SSergey Senozhatsky bv.bv_offset = 0; 1657522698d7SSergey Senozhatsky 1658d7614e44SChristoph Hellwig start_time = disk_start_io_acct(bdev->bd_disk, SECTORS_PER_PAGE, op); 16593f289dcbSTejun Heo ret = zram_bvec_rw(zram, &bv, index, offset, op, NULL); 1660d7614e44SChristoph Hellwig disk_end_io_acct(bdev->bd_disk, op, start_time); 1661522698d7SSergey Senozhatsky out: 1662522698d7SSergey Senozhatsky /* 1663522698d7SSergey Senozhatsky * If I/O fails, just return error(ie, non-zero) without 1664522698d7SSergey Senozhatsky * calling page_endio. 1665522698d7SSergey Senozhatsky * It causes resubmit the I/O with bio request by upper functions 1666522698d7SSergey Senozhatsky * of rw_page(e.g., swap_readpage, __swap_writepage) and 1667522698d7SSergey Senozhatsky * bio->bi_end_io does things to handle the error 1668522698d7SSergey Senozhatsky * (e.g., SetPageError, set_page_dirty and extra works). 1669522698d7SSergey Senozhatsky */ 1670ae85a807SMinchan Kim if (unlikely(ret < 0)) 1671ae85a807SMinchan Kim return ret; 1672ae85a807SMinchan Kim 1673ae85a807SMinchan Kim switch (ret) { 1674ae85a807SMinchan Kim case 0: 16753f289dcbSTejun Heo page_endio(page, op_is_write(op), 0); 1676ae85a807SMinchan Kim break; 1677ae85a807SMinchan Kim case 1: 1678ae85a807SMinchan Kim ret = 0; 1679ae85a807SMinchan Kim break; 1680ae85a807SMinchan Kim default: 1681ae85a807SMinchan Kim WARN_ON(1); 1682ae85a807SMinchan Kim } 1683ae85a807SMinchan Kim return ret; 1684522698d7SSergey Senozhatsky } 1685522698d7SSergey Senozhatsky 1686ba6b17d6SSergey Senozhatsky static void zram_reset_device(struct zram *zram) 1687cd67e10aSMinchan Kim { 168808eee69fSMinchan Kim struct zcomp *comp; 168908eee69fSMinchan Kim u64 disksize; 169008eee69fSMinchan Kim 1691cd67e10aSMinchan Kim down_write(&zram->init_lock); 16929ada9da9SMinchan Kim 16939ada9da9SMinchan Kim zram->limit_pages = 0; 16949ada9da9SMinchan Kim 1695be2d1d56SSergey Senozhatsky if (!init_done(zram)) { 1696cd67e10aSMinchan Kim up_write(&zram->init_lock); 1697cd67e10aSMinchan Kim return; 1698cd67e10aSMinchan Kim } 1699cd67e10aSMinchan Kim 170008eee69fSMinchan Kim comp = zram->comp; 170108eee69fSMinchan Kim disksize = zram->disksize; 1702cd67e10aSMinchan Kim zram->disksize = 0; 1703d7ad41a1SWeijie Yang 17046e017a39SChristoph Hellwig set_capacity_and_notify(zram->disk, 0); 17058446fe92SChristoph Hellwig part_stat_set_all(zram->disk->part0, 0); 1706a096cafcSSergey Senozhatsky 170708eee69fSMinchan Kim /* I/O operation under all of CPU are done so let's free */ 1708beb6602cSMinchan Kim zram_meta_free(zram, disksize); 1709302128dcSMinchan Kim memset(&zram->stats, 0, sizeof(zram->stats)); 171008eee69fSMinchan Kim zcomp_destroy(comp); 1711013bf95aSMinchan Kim reset_bdev(zram); 17126f163779SMing Lei 17136f163779SMing Lei up_write(&zram->init_lock); 1714cd67e10aSMinchan Kim } 1715cd67e10aSMinchan Kim 1716cd67e10aSMinchan Kim static ssize_t disksize_store(struct device *dev, 1717cd67e10aSMinchan Kim struct device_attribute *attr, const char *buf, size_t len) 1718cd67e10aSMinchan Kim { 1719cd67e10aSMinchan Kim u64 disksize; 1720d61f98c7SSergey Senozhatsky struct zcomp *comp; 1721cd67e10aSMinchan Kim struct zram *zram = dev_to_zram(dev); 1722fcfa8d95SSergey Senozhatsky int err; 1723cd67e10aSMinchan Kim 1724cd67e10aSMinchan Kim disksize = memparse(buf, NULL); 1725cd67e10aSMinchan Kim if (!disksize) 1726cd67e10aSMinchan Kim return -EINVAL; 1727cd67e10aSMinchan Kim 1728beb6602cSMinchan Kim down_write(&zram->init_lock); 1729beb6602cSMinchan Kim if (init_done(zram)) { 1730beb6602cSMinchan Kim pr_info("Cannot change disksize for initialized device\n"); 1731beb6602cSMinchan Kim err = -EBUSY; 1732beb6602cSMinchan Kim goto out_unlock; 1733beb6602cSMinchan Kim } 1734beb6602cSMinchan Kim 1735cd67e10aSMinchan Kim disksize = PAGE_ALIGN(disksize); 1736beb6602cSMinchan Kim if (!zram_meta_alloc(zram, disksize)) { 1737beb6602cSMinchan Kim err = -ENOMEM; 1738beb6602cSMinchan Kim goto out_unlock; 1739beb6602cSMinchan Kim } 1740b67d1ec1SSergey Senozhatsky 1741da9556a2SSergey Senozhatsky comp = zcomp_create(zram->compressor); 1742fcfa8d95SSergey Senozhatsky if (IS_ERR(comp)) { 174370864969SSergey Senozhatsky pr_err("Cannot initialise %s compressing backend\n", 1744e46b8a03SSergey Senozhatsky zram->compressor); 1745fcfa8d95SSergey Senozhatsky err = PTR_ERR(comp); 1746fcfa8d95SSergey Senozhatsky goto out_free_meta; 1747d61f98c7SSergey Senozhatsky } 1748d61f98c7SSergey Senozhatsky 1749d61f98c7SSergey Senozhatsky zram->comp = comp; 1750cd67e10aSMinchan Kim zram->disksize = disksize; 17516e017a39SChristoph Hellwig set_capacity_and_notify(zram->disk, zram->disksize >> SECTOR_SHIFT); 1752e7ccfc4cSMinchan Kim up_write(&zram->init_lock); 1753b4c5c609SMinchan Kim 1754cd67e10aSMinchan Kim return len; 1755b7ca232eSSergey Senozhatsky 1756fcfa8d95SSergey Senozhatsky out_free_meta: 1757beb6602cSMinchan Kim zram_meta_free(zram, disksize); 1758beb6602cSMinchan Kim out_unlock: 1759beb6602cSMinchan Kim up_write(&zram->init_lock); 1760b7ca232eSSergey Senozhatsky return err; 1761cd67e10aSMinchan Kim } 1762cd67e10aSMinchan Kim 1763cd67e10aSMinchan Kim static ssize_t reset_store(struct device *dev, 1764cd67e10aSMinchan Kim struct device_attribute *attr, const char *buf, size_t len) 1765cd67e10aSMinchan Kim { 1766cd67e10aSMinchan Kim int ret; 1767cd67e10aSMinchan Kim unsigned short do_reset; 1768cd67e10aSMinchan Kim struct zram *zram; 1769cd67e10aSMinchan Kim struct block_device *bdev; 1770cd67e10aSMinchan Kim 1771f405c445SSergey Senozhatsky ret = kstrtou16(buf, 10, &do_reset); 1772f405c445SSergey Senozhatsky if (ret) 1773f405c445SSergey Senozhatsky return ret; 1774f405c445SSergey Senozhatsky 1775f405c445SSergey Senozhatsky if (!do_reset) 1776f405c445SSergey Senozhatsky return -EINVAL; 1777f405c445SSergey Senozhatsky 1778cd67e10aSMinchan Kim zram = dev_to_zram(dev); 1779977115c0SChristoph Hellwig bdev = zram->disk->part0; 1780cd67e10aSMinchan Kim 1781a8698707SChristoph Hellwig mutex_lock(&bdev->bd_disk->open_mutex); 1782f405c445SSergey Senozhatsky /* Do not reset an active device or claimed device */ 1783f405c445SSergey Senozhatsky if (bdev->bd_openers || zram->claim) { 1784a8698707SChristoph Hellwig mutex_unlock(&bdev->bd_disk->open_mutex); 1785f405c445SSergey Senozhatsky return -EBUSY; 1786cd67e10aSMinchan Kim } 1787cd67e10aSMinchan Kim 1788f405c445SSergey Senozhatsky /* From now on, anyone can't open /dev/zram[0-9] */ 1789f405c445SSergey Senozhatsky zram->claim = true; 1790a8698707SChristoph Hellwig mutex_unlock(&bdev->bd_disk->open_mutex); 1791cd67e10aSMinchan Kim 1792f405c445SSergey Senozhatsky /* Make sure all the pending I/O are finished */ 1793cd67e10aSMinchan Kim fsync_bdev(bdev); 1794ba6b17d6SSergey Senozhatsky zram_reset_device(zram); 1795cd67e10aSMinchan Kim 1796a8698707SChristoph Hellwig mutex_lock(&bdev->bd_disk->open_mutex); 1797f405c445SSergey Senozhatsky zram->claim = false; 1798a8698707SChristoph Hellwig mutex_unlock(&bdev->bd_disk->open_mutex); 1799f405c445SSergey Senozhatsky 1800f405c445SSergey Senozhatsky return len; 1801f405c445SSergey Senozhatsky } 1802f405c445SSergey Senozhatsky 1803f405c445SSergey Senozhatsky static int zram_open(struct block_device *bdev, fmode_t mode) 1804f405c445SSergey Senozhatsky { 1805f405c445SSergey Senozhatsky int ret = 0; 1806f405c445SSergey Senozhatsky struct zram *zram; 1807f405c445SSergey Senozhatsky 1808a8698707SChristoph Hellwig WARN_ON(!mutex_is_locked(&bdev->bd_disk->open_mutex)); 1809f405c445SSergey Senozhatsky 1810f405c445SSergey Senozhatsky zram = bdev->bd_disk->private_data; 1811f405c445SSergey Senozhatsky /* zram was claimed to reset so open request fails */ 1812f405c445SSergey Senozhatsky if (zram->claim) 1813f405c445SSergey Senozhatsky ret = -EBUSY; 1814f405c445SSergey Senozhatsky 1815cd67e10aSMinchan Kim return ret; 1816cd67e10aSMinchan Kim } 1817cd67e10aSMinchan Kim 1818cd67e10aSMinchan Kim static const struct block_device_operations zram_devops = { 1819f405c445SSergey Senozhatsky .open = zram_open, 1820c62b37d9SChristoph Hellwig .submit_bio = zram_submit_bio, 1821cd67e10aSMinchan Kim .swap_slot_free_notify = zram_slot_free_notify, 18228c7f0102Skaram.lee .rw_page = zram_rw_page, 1823cd67e10aSMinchan Kim .owner = THIS_MODULE 1824cd67e10aSMinchan Kim }; 1825cd67e10aSMinchan Kim 1826a8b456d0SChristoph Hellwig static const struct block_device_operations zram_wb_devops = { 1827a8b456d0SChristoph Hellwig .open = zram_open, 1828a8b456d0SChristoph Hellwig .submit_bio = zram_submit_bio, 1829a8b456d0SChristoph Hellwig .swap_slot_free_notify = zram_slot_free_notify, 1830a8b456d0SChristoph Hellwig .owner = THIS_MODULE 1831a8b456d0SChristoph Hellwig }; 1832a8b456d0SChristoph Hellwig 183399ebbd30SAndrew Morton static DEVICE_ATTR_WO(compact); 1834083914eaSGanesh Mahendran static DEVICE_ATTR_RW(disksize); 1835083914eaSGanesh Mahendran static DEVICE_ATTR_RO(initstate); 1836083914eaSGanesh Mahendran static DEVICE_ATTR_WO(reset); 1837c87d1655SSergey Senozhatsky static DEVICE_ATTR_WO(mem_limit); 1838c87d1655SSergey Senozhatsky static DEVICE_ATTR_WO(mem_used_max); 1839e82592c4SMinchan Kim static DEVICE_ATTR_WO(idle); 1840083914eaSGanesh Mahendran static DEVICE_ATTR_RW(max_comp_streams); 1841083914eaSGanesh Mahendran static DEVICE_ATTR_RW(comp_algorithm); 1842013bf95aSMinchan Kim #ifdef CONFIG_ZRAM_WRITEBACK 1843013bf95aSMinchan Kim static DEVICE_ATTR_RW(backing_dev); 1844a939888eSMinchan Kim static DEVICE_ATTR_WO(writeback); 1845bb416d18SMinchan Kim static DEVICE_ATTR_RW(writeback_limit); 18461d69a3f8SMinchan Kim static DEVICE_ATTR_RW(writeback_limit_enable); 1847013bf95aSMinchan Kim #endif 1848cd67e10aSMinchan Kim 1849cd67e10aSMinchan Kim static struct attribute *zram_disk_attrs[] = { 1850cd67e10aSMinchan Kim &dev_attr_disksize.attr, 1851cd67e10aSMinchan Kim &dev_attr_initstate.attr, 1852cd67e10aSMinchan Kim &dev_attr_reset.attr, 185399ebbd30SAndrew Morton &dev_attr_compact.attr, 18549ada9da9SMinchan Kim &dev_attr_mem_limit.attr, 1855461a8eeeSMinchan Kim &dev_attr_mem_used_max.attr, 1856e82592c4SMinchan Kim &dev_attr_idle.attr, 1857beca3ec7SSergey Senozhatsky &dev_attr_max_comp_streams.attr, 1858e46b8a03SSergey Senozhatsky &dev_attr_comp_algorithm.attr, 1859013bf95aSMinchan Kim #ifdef CONFIG_ZRAM_WRITEBACK 1860013bf95aSMinchan Kim &dev_attr_backing_dev.attr, 1861a939888eSMinchan Kim &dev_attr_writeback.attr, 1862bb416d18SMinchan Kim &dev_attr_writeback_limit.attr, 18631d69a3f8SMinchan Kim &dev_attr_writeback_limit_enable.attr, 1864013bf95aSMinchan Kim #endif 18652f6a3bedSSergey Senozhatsky &dev_attr_io_stat.attr, 18664f2109f6SSergey Senozhatsky &dev_attr_mm_stat.attr, 186723eddf39SMinchan Kim #ifdef CONFIG_ZRAM_WRITEBACK 186823eddf39SMinchan Kim &dev_attr_bd_stat.attr, 186923eddf39SMinchan Kim #endif 1870623e47fcSSergey Senozhatsky &dev_attr_debug_stat.attr, 1871cd67e10aSMinchan Kim NULL, 1872cd67e10aSMinchan Kim }; 1873cd67e10aSMinchan Kim 1874bc1bb362SArvind Yadav static const struct attribute_group zram_disk_attr_group = { 1875cd67e10aSMinchan Kim .attrs = zram_disk_attrs, 1876cd67e10aSMinchan Kim }; 1877cd67e10aSMinchan Kim 187898af4d4dSHannes Reinecke static const struct attribute_group *zram_disk_attr_groups[] = { 187998af4d4dSHannes Reinecke &zram_disk_attr_group, 188098af4d4dSHannes Reinecke NULL, 188198af4d4dSHannes Reinecke }; 188298af4d4dSHannes Reinecke 188392ff1528SSergey Senozhatsky /* 188492ff1528SSergey Senozhatsky * Allocate and initialize new zram device. the function returns 188592ff1528SSergey Senozhatsky * '>= 0' device_id upon success, and negative value otherwise. 188692ff1528SSergey Senozhatsky */ 188792ff1528SSergey Senozhatsky static int zram_add(void) 1888cd67e10aSMinchan Kim { 188985508ec6SSergey Senozhatsky struct zram *zram; 189092ff1528SSergey Senozhatsky int ret, device_id; 189185508ec6SSergey Senozhatsky 189285508ec6SSergey Senozhatsky zram = kzalloc(sizeof(struct zram), GFP_KERNEL); 189385508ec6SSergey Senozhatsky if (!zram) 189485508ec6SSergey Senozhatsky return -ENOMEM; 189585508ec6SSergey Senozhatsky 189692ff1528SSergey Senozhatsky ret = idr_alloc(&zram_index_idr, zram, 0, 0, GFP_KERNEL); 189785508ec6SSergey Senozhatsky if (ret < 0) 189885508ec6SSergey Senozhatsky goto out_free_dev; 189992ff1528SSergey Senozhatsky device_id = ret; 1900cd67e10aSMinchan Kim 1901cd67e10aSMinchan Kim init_rwsem(&zram->init_lock); 19021d69a3f8SMinchan Kim #ifdef CONFIG_ZRAM_WRITEBACK 19031d69a3f8SMinchan Kim spin_lock_init(&zram->wb_limit_lock); 19041d69a3f8SMinchan Kim #endif 19057681750bSChristoph Hellwig 19067681750bSChristoph Hellwig /* gendisk structure */ 19077681750bSChristoph Hellwig zram->disk = blk_alloc_disk(NUMA_NO_NODE); 19087681750bSChristoph Hellwig if (!zram->disk) { 19097681750bSChristoph Hellwig pr_err("Error allocating disk structure for device %d\n", 1910cd67e10aSMinchan Kim device_id); 191185508ec6SSergey Senozhatsky ret = -ENOMEM; 191285508ec6SSergey Senozhatsky goto out_free_idr; 1913cd67e10aSMinchan Kim } 1914cd67e10aSMinchan Kim 1915cd67e10aSMinchan Kim zram->disk->major = zram_major; 1916cd67e10aSMinchan Kim zram->disk->first_minor = device_id; 19177681750bSChristoph Hellwig zram->disk->minors = 1; 1918cd67e10aSMinchan Kim zram->disk->fops = &zram_devops; 1919cd67e10aSMinchan Kim zram->disk->private_data = zram; 1920cd67e10aSMinchan Kim snprintf(zram->disk->disk_name, 16, "zram%d", device_id); 1921cd67e10aSMinchan Kim 1922cd67e10aSMinchan Kim /* Actual capacity set using syfs (/sys/block/zram<id>/disksize */ 1923cd67e10aSMinchan Kim set_capacity(zram->disk, 0); 1924b67d1ec1SSergey Senozhatsky /* zram devices sort of resembles non-rotational disks */ 19258b904b5bSBart Van Assche blk_queue_flag_set(QUEUE_FLAG_NONROT, zram->disk->queue); 19268b904b5bSBart Van Assche blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, zram->disk->queue); 1927e447a015SMinchan Kim 1928cd67e10aSMinchan Kim /* 1929cd67e10aSMinchan Kim * To ensure that we always get PAGE_SIZE aligned 1930cd67e10aSMinchan Kim * and n*PAGE_SIZED sized I/O requests. 1931cd67e10aSMinchan Kim */ 1932cd67e10aSMinchan Kim blk_queue_physical_block_size(zram->disk->queue, PAGE_SIZE); 1933cd67e10aSMinchan Kim blk_queue_logical_block_size(zram->disk->queue, 1934cd67e10aSMinchan Kim ZRAM_LOGICAL_BLOCK_SIZE); 1935cd67e10aSMinchan Kim blk_queue_io_min(zram->disk->queue, PAGE_SIZE); 1936cd67e10aSMinchan Kim blk_queue_io_opt(zram->disk->queue, PAGE_SIZE); 1937f4659d8eSJoonsoo Kim zram->disk->queue->limits.discard_granularity = PAGE_SIZE; 19382bb4cd5cSJens Axboe blk_queue_max_discard_sectors(zram->disk->queue, UINT_MAX); 19398b904b5bSBart Van Assche blk_queue_flag_set(QUEUE_FLAG_DISCARD, zram->disk->queue); 194031edeacdSChristoph Hellwig 1941f4659d8eSJoonsoo Kim /* 1942f4659d8eSJoonsoo Kim * zram_bio_discard() will clear all logical blocks if logical block 1943f4659d8eSJoonsoo Kim * size is identical with physical block size(PAGE_SIZE). But if it is 1944f4659d8eSJoonsoo Kim * different, we will skip discarding some parts of logical blocks in 1945f4659d8eSJoonsoo Kim * the part of the request range which isn't aligned to physical block 1946f4659d8eSJoonsoo Kim * size. So we can't ensure that all discarded logical blocks are 1947f4659d8eSJoonsoo Kim * zeroed. 1948f4659d8eSJoonsoo Kim */ 1949f4659d8eSJoonsoo Kim if (ZRAM_LOGICAL_BLOCK_SIZE == PAGE_SIZE) 195031edeacdSChristoph Hellwig blk_queue_max_write_zeroes_sectors(zram->disk->queue, UINT_MAX); 1951cd67e10aSMinchan Kim 19521cb039f3SChristoph Hellwig blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, zram->disk->queue); 19535e2e1cc4SLuis Chamberlain ret = device_add_disk(NULL, zram->disk, zram_disk_attr_groups); 19545e2e1cc4SLuis Chamberlain if (ret) 19555e2e1cc4SLuis Chamberlain goto out_cleanup_disk; 1956cd67e10aSMinchan Kim 1957e46b8a03SSergey Senozhatsky strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor)); 1958d12b63c9SSergey Senozhatsky 1959c0265342SMinchan Kim zram_debugfs_register(zram); 1960d12b63c9SSergey Senozhatsky pr_info("Added device: %s\n", zram->disk->disk_name); 196192ff1528SSergey Senozhatsky return device_id; 1962cd67e10aSMinchan Kim 19635e2e1cc4SLuis Chamberlain out_cleanup_disk: 19645e2e1cc4SLuis Chamberlain blk_cleanup_disk(zram->disk); 196585508ec6SSergey Senozhatsky out_free_idr: 196685508ec6SSergey Senozhatsky idr_remove(&zram_index_idr, device_id); 196785508ec6SSergey Senozhatsky out_free_dev: 196885508ec6SSergey Senozhatsky kfree(zram); 1969cd67e10aSMinchan Kim return ret; 1970cd67e10aSMinchan Kim } 1971cd67e10aSMinchan Kim 19726566d1a3SSergey Senozhatsky static int zram_remove(struct zram *zram) 1973cd67e10aSMinchan Kim { 1974977115c0SChristoph Hellwig struct block_device *bdev = zram->disk->part0; 19758c54499aSMing Lei bool claimed; 19766566d1a3SSergey Senozhatsky 1977a8698707SChristoph Hellwig mutex_lock(&bdev->bd_disk->open_mutex); 19788c54499aSMing Lei if (bdev->bd_openers) { 1979a8698707SChristoph Hellwig mutex_unlock(&bdev->bd_disk->open_mutex); 19806566d1a3SSergey Senozhatsky return -EBUSY; 19816566d1a3SSergey Senozhatsky } 19826566d1a3SSergey Senozhatsky 19838c54499aSMing Lei claimed = zram->claim; 19848c54499aSMing Lei if (!claimed) 19856566d1a3SSergey Senozhatsky zram->claim = true; 1986a8698707SChristoph Hellwig mutex_unlock(&bdev->bd_disk->open_mutex); 19876566d1a3SSergey Senozhatsky 1988c0265342SMinchan Kim zram_debugfs_unregister(zram); 1989cd67e10aSMinchan Kim 19908c54499aSMing Lei if (claimed) { 19918c54499aSMing Lei /* 19928c54499aSMing Lei * If we were claimed by reset_store(), del_gendisk() will 19938c54499aSMing Lei * wait until reset_store() is done, so nothing need to do. 19948c54499aSMing Lei */ 19958c54499aSMing Lei ; 19968c54499aSMing Lei } else { 19976566d1a3SSergey Senozhatsky /* Make sure all the pending I/O are finished */ 19986566d1a3SSergey Senozhatsky fsync_bdev(bdev); 1999a096cafcSSergey Senozhatsky zram_reset_device(zram); 20008c54499aSMing Lei } 20016566d1a3SSergey Senozhatsky 20026566d1a3SSergey Senozhatsky pr_info("Removed device: %s\n", zram->disk->disk_name); 20036566d1a3SSergey Senozhatsky 2004cd67e10aSMinchan Kim del_gendisk(zram->disk); 20058c54499aSMing Lei 20068c54499aSMing Lei /* del_gendisk drains pending reset_store */ 20078c54499aSMing Lei WARN_ON_ONCE(claimed && zram->claim); 20088c54499aSMing Lei 2009*5a4b6536SMing Lei /* 2010*5a4b6536SMing Lei * disksize_store() may be called in between zram_reset_device() 2011*5a4b6536SMing Lei * and del_gendisk(), so run the last reset to avoid leaking 2012*5a4b6536SMing Lei * anything allocated with disksize_store() 2013*5a4b6536SMing Lei */ 2014*5a4b6536SMing Lei zram_reset_device(zram); 2015*5a4b6536SMing Lei 20167681750bSChristoph Hellwig blk_cleanup_disk(zram->disk); 201785508ec6SSergey Senozhatsky kfree(zram); 20186566d1a3SSergey Senozhatsky return 0; 2019cd67e10aSMinchan Kim } 2020cd67e10aSMinchan Kim 20216566d1a3SSergey Senozhatsky /* zram-control sysfs attributes */ 202227104a53SGreg Kroah-Hartman 202327104a53SGreg Kroah-Hartman /* 202427104a53SGreg Kroah-Hartman * NOTE: hot_add attribute is not the usual read-only sysfs attribute. In a 202527104a53SGreg Kroah-Hartman * sense that reading from this file does alter the state of your system -- it 202627104a53SGreg Kroah-Hartman * creates a new un-initialized zram device and returns back this device's 202727104a53SGreg Kroah-Hartman * device_id (or an error code if it fails to create a new device). 202827104a53SGreg Kroah-Hartman */ 20296566d1a3SSergey Senozhatsky static ssize_t hot_add_show(struct class *class, 20306566d1a3SSergey Senozhatsky struct class_attribute *attr, 20316566d1a3SSergey Senozhatsky char *buf) 20326566d1a3SSergey Senozhatsky { 20336566d1a3SSergey Senozhatsky int ret; 20346566d1a3SSergey Senozhatsky 20356566d1a3SSergey Senozhatsky mutex_lock(&zram_index_mutex); 20366566d1a3SSergey Senozhatsky ret = zram_add(); 20376566d1a3SSergey Senozhatsky mutex_unlock(&zram_index_mutex); 20386566d1a3SSergey Senozhatsky 20396566d1a3SSergey Senozhatsky if (ret < 0) 20406566d1a3SSergey Senozhatsky return ret; 20416566d1a3SSergey Senozhatsky return scnprintf(buf, PAGE_SIZE, "%d\n", ret); 20426566d1a3SSergey Senozhatsky } 2043853eab68SWade Mealing static struct class_attribute class_attr_hot_add = 2044853eab68SWade Mealing __ATTR(hot_add, 0400, hot_add_show, NULL); 20456566d1a3SSergey Senozhatsky 20466566d1a3SSergey Senozhatsky static ssize_t hot_remove_store(struct class *class, 20476566d1a3SSergey Senozhatsky struct class_attribute *attr, 20486566d1a3SSergey Senozhatsky const char *buf, 20496566d1a3SSergey Senozhatsky size_t count) 20506566d1a3SSergey Senozhatsky { 20516566d1a3SSergey Senozhatsky struct zram *zram; 20526566d1a3SSergey Senozhatsky int ret, dev_id; 20536566d1a3SSergey Senozhatsky 20546566d1a3SSergey Senozhatsky /* dev_id is gendisk->first_minor, which is `int' */ 20556566d1a3SSergey Senozhatsky ret = kstrtoint(buf, 10, &dev_id); 20566566d1a3SSergey Senozhatsky if (ret) 20576566d1a3SSergey Senozhatsky return ret; 20586566d1a3SSergey Senozhatsky if (dev_id < 0) 20596566d1a3SSergey Senozhatsky return -EINVAL; 20606566d1a3SSergey Senozhatsky 20616566d1a3SSergey Senozhatsky mutex_lock(&zram_index_mutex); 20626566d1a3SSergey Senozhatsky 20636566d1a3SSergey Senozhatsky zram = idr_find(&zram_index_idr, dev_id); 206417ec4cd9SJerome Marchand if (zram) { 20656566d1a3SSergey Senozhatsky ret = zram_remove(zram); 2066529e71e1STakashi Iwai if (!ret) 206717ec4cd9SJerome Marchand idr_remove(&zram_index_idr, dev_id); 206817ec4cd9SJerome Marchand } else { 20696566d1a3SSergey Senozhatsky ret = -ENODEV; 207017ec4cd9SJerome Marchand } 20716566d1a3SSergey Senozhatsky 20726566d1a3SSergey Senozhatsky mutex_unlock(&zram_index_mutex); 20736566d1a3SSergey Senozhatsky return ret ? ret : count; 20746566d1a3SSergey Senozhatsky } 207527104a53SGreg Kroah-Hartman static CLASS_ATTR_WO(hot_remove); 20766566d1a3SSergey Senozhatsky 207727104a53SGreg Kroah-Hartman static struct attribute *zram_control_class_attrs[] = { 207827104a53SGreg Kroah-Hartman &class_attr_hot_add.attr, 207927104a53SGreg Kroah-Hartman &class_attr_hot_remove.attr, 208027104a53SGreg Kroah-Hartman NULL, 20816566d1a3SSergey Senozhatsky }; 208227104a53SGreg Kroah-Hartman ATTRIBUTE_GROUPS(zram_control_class); 20836566d1a3SSergey Senozhatsky 20846566d1a3SSergey Senozhatsky static struct class zram_control_class = { 20856566d1a3SSergey Senozhatsky .name = "zram-control", 20866566d1a3SSergey Senozhatsky .owner = THIS_MODULE, 208727104a53SGreg Kroah-Hartman .class_groups = zram_control_class_groups, 20886566d1a3SSergey Senozhatsky }; 20896566d1a3SSergey Senozhatsky 209085508ec6SSergey Senozhatsky static int zram_remove_cb(int id, void *ptr, void *data) 209185508ec6SSergey Senozhatsky { 20928c54499aSMing Lei WARN_ON_ONCE(zram_remove(ptr)); 209385508ec6SSergey Senozhatsky return 0; 209485508ec6SSergey Senozhatsky } 209585508ec6SSergey Senozhatsky 209685508ec6SSergey Senozhatsky static void destroy_devices(void) 209785508ec6SSergey Senozhatsky { 20986566d1a3SSergey Senozhatsky class_unregister(&zram_control_class); 209985508ec6SSergey Senozhatsky idr_for_each(&zram_index_idr, &zram_remove_cb, NULL); 2100c0265342SMinchan Kim zram_debugfs_destroy(); 210185508ec6SSergey Senozhatsky idr_destroy(&zram_index_idr); 2102a096cafcSSergey Senozhatsky unregister_blkdev(zram_major, "zram"); 21031dd6c834SAnna-Maria Gleixner cpuhp_remove_multi_state(CPUHP_ZCOMP_PREPARE); 2104a096cafcSSergey Senozhatsky } 2105a096cafcSSergey Senozhatsky 2106cd67e10aSMinchan Kim static int __init zram_init(void) 2107cd67e10aSMinchan Kim { 210892ff1528SSergey Senozhatsky int ret; 2109cd67e10aSMinchan Kim 21101dd6c834SAnna-Maria Gleixner ret = cpuhp_setup_state_multi(CPUHP_ZCOMP_PREPARE, "block/zram:prepare", 21111dd6c834SAnna-Maria Gleixner zcomp_cpu_up_prepare, zcomp_cpu_dead); 21121dd6c834SAnna-Maria Gleixner if (ret < 0) 21131dd6c834SAnna-Maria Gleixner return ret; 21141dd6c834SAnna-Maria Gleixner 21156566d1a3SSergey Senozhatsky ret = class_register(&zram_control_class); 21166566d1a3SSergey Senozhatsky if (ret) { 211770864969SSergey Senozhatsky pr_err("Unable to register zram-control class\n"); 21181dd6c834SAnna-Maria Gleixner cpuhp_remove_multi_state(CPUHP_ZCOMP_PREPARE); 21196566d1a3SSergey Senozhatsky return ret; 21206566d1a3SSergey Senozhatsky } 21216566d1a3SSergey Senozhatsky 2122c0265342SMinchan Kim zram_debugfs_create(); 2123cd67e10aSMinchan Kim zram_major = register_blkdev(0, "zram"); 2124cd67e10aSMinchan Kim if (zram_major <= 0) { 212570864969SSergey Senozhatsky pr_err("Unable to get major number\n"); 21266566d1a3SSergey Senozhatsky class_unregister(&zram_control_class); 21271dd6c834SAnna-Maria Gleixner cpuhp_remove_multi_state(CPUHP_ZCOMP_PREPARE); 2128a096cafcSSergey Senozhatsky return -EBUSY; 2129cd67e10aSMinchan Kim } 2130cd67e10aSMinchan Kim 213192ff1528SSergey Senozhatsky while (num_devices != 0) { 21326566d1a3SSergey Senozhatsky mutex_lock(&zram_index_mutex); 213392ff1528SSergey Senozhatsky ret = zram_add(); 21346566d1a3SSergey Senozhatsky mutex_unlock(&zram_index_mutex); 213592ff1528SSergey Senozhatsky if (ret < 0) 2136a096cafcSSergey Senozhatsky goto out_error; 213792ff1528SSergey Senozhatsky num_devices--; 2138cd67e10aSMinchan Kim } 2139cd67e10aSMinchan Kim 2140cd67e10aSMinchan Kim return 0; 2141cd67e10aSMinchan Kim 2142a096cafcSSergey Senozhatsky out_error: 214385508ec6SSergey Senozhatsky destroy_devices(); 2144cd67e10aSMinchan Kim return ret; 2145cd67e10aSMinchan Kim } 2146cd67e10aSMinchan Kim 2147cd67e10aSMinchan Kim static void __exit zram_exit(void) 2148cd67e10aSMinchan Kim { 214985508ec6SSergey Senozhatsky destroy_devices(); 2150cd67e10aSMinchan Kim } 2151cd67e10aSMinchan Kim 2152cd67e10aSMinchan Kim module_init(zram_init); 2153cd67e10aSMinchan Kim module_exit(zram_exit); 2154cd67e10aSMinchan Kim 2155cd67e10aSMinchan Kim module_param(num_devices, uint, 0); 2156c3cdb40eSSergey Senozhatsky MODULE_PARM_DESC(num_devices, "Number of pre-created zram devices"); 2157cd67e10aSMinchan Kim 2158cd67e10aSMinchan Kim MODULE_LICENSE("Dual BSD/GPL"); 2159cd67e10aSMinchan Kim MODULE_AUTHOR("Nitin Gupta <ngupta@vflare.org>"); 2160cd67e10aSMinchan Kim MODULE_DESCRIPTION("Compressed RAM Block Device"); 2161