xref: /openbmc/linux/drivers/block/zram/zram_drv.c (revision 8c54499a59b026a3dc2afccf6e1b36d5700d2fef)
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;
1975*8c54499aSMing Lei 	bool claimed;
19766566d1a3SSergey Senozhatsky 
1977a8698707SChristoph Hellwig 	mutex_lock(&bdev->bd_disk->open_mutex);
1978*8c54499aSMing Lei 	if (bdev->bd_openers) {
1979a8698707SChristoph Hellwig 		mutex_unlock(&bdev->bd_disk->open_mutex);
19806566d1a3SSergey Senozhatsky 		return -EBUSY;
19816566d1a3SSergey Senozhatsky 	}
19826566d1a3SSergey Senozhatsky 
1983*8c54499aSMing Lei 	claimed = zram->claim;
1984*8c54499aSMing 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 
1990*8c54499aSMing Lei 	if (claimed) {
1991*8c54499aSMing Lei 		/*
1992*8c54499aSMing Lei 		 * If we were claimed by reset_store(), del_gendisk() will
1993*8c54499aSMing Lei 		 * wait until reset_store() is done, so nothing need to do.
1994*8c54499aSMing Lei 		 */
1995*8c54499aSMing Lei 		;
1996*8c54499aSMing Lei 	} else {
19976566d1a3SSergey Senozhatsky 		/* Make sure all the pending I/O are finished */
19986566d1a3SSergey Senozhatsky 		fsync_bdev(bdev);
1999a096cafcSSergey Senozhatsky 		zram_reset_device(zram);
2000*8c54499aSMing Lei 	}
20016566d1a3SSergey Senozhatsky 
20026566d1a3SSergey Senozhatsky 	pr_info("Removed device: %s\n", zram->disk->disk_name);
20036566d1a3SSergey Senozhatsky 
2004cd67e10aSMinchan Kim 	del_gendisk(zram->disk);
2005*8c54499aSMing Lei 
2006*8c54499aSMing Lei 	/* del_gendisk drains pending reset_store */
2007*8c54499aSMing Lei 	WARN_ON_ONCE(claimed && zram->claim);
2008*8c54499aSMing Lei 
20097681750bSChristoph Hellwig 	blk_cleanup_disk(zram->disk);
201085508ec6SSergey Senozhatsky 	kfree(zram);
20116566d1a3SSergey Senozhatsky 	return 0;
2012cd67e10aSMinchan Kim }
2013cd67e10aSMinchan Kim 
20146566d1a3SSergey Senozhatsky /* zram-control sysfs attributes */
201527104a53SGreg Kroah-Hartman 
201627104a53SGreg Kroah-Hartman /*
201727104a53SGreg Kroah-Hartman  * NOTE: hot_add attribute is not the usual read-only sysfs attribute. In a
201827104a53SGreg Kroah-Hartman  * sense that reading from this file does alter the state of your system -- it
201927104a53SGreg Kroah-Hartman  * creates a new un-initialized zram device and returns back this device's
202027104a53SGreg Kroah-Hartman  * device_id (or an error code if it fails to create a new device).
202127104a53SGreg Kroah-Hartman  */
20226566d1a3SSergey Senozhatsky static ssize_t hot_add_show(struct class *class,
20236566d1a3SSergey Senozhatsky 			struct class_attribute *attr,
20246566d1a3SSergey Senozhatsky 			char *buf)
20256566d1a3SSergey Senozhatsky {
20266566d1a3SSergey Senozhatsky 	int ret;
20276566d1a3SSergey Senozhatsky 
20286566d1a3SSergey Senozhatsky 	mutex_lock(&zram_index_mutex);
20296566d1a3SSergey Senozhatsky 	ret = zram_add();
20306566d1a3SSergey Senozhatsky 	mutex_unlock(&zram_index_mutex);
20316566d1a3SSergey Senozhatsky 
20326566d1a3SSergey Senozhatsky 	if (ret < 0)
20336566d1a3SSergey Senozhatsky 		return ret;
20346566d1a3SSergey Senozhatsky 	return scnprintf(buf, PAGE_SIZE, "%d\n", ret);
20356566d1a3SSergey Senozhatsky }
2036853eab68SWade Mealing static struct class_attribute class_attr_hot_add =
2037853eab68SWade Mealing 	__ATTR(hot_add, 0400, hot_add_show, NULL);
20386566d1a3SSergey Senozhatsky 
20396566d1a3SSergey Senozhatsky static ssize_t hot_remove_store(struct class *class,
20406566d1a3SSergey Senozhatsky 			struct class_attribute *attr,
20416566d1a3SSergey Senozhatsky 			const char *buf,
20426566d1a3SSergey Senozhatsky 			size_t count)
20436566d1a3SSergey Senozhatsky {
20446566d1a3SSergey Senozhatsky 	struct zram *zram;
20456566d1a3SSergey Senozhatsky 	int ret, dev_id;
20466566d1a3SSergey Senozhatsky 
20476566d1a3SSergey Senozhatsky 	/* dev_id is gendisk->first_minor, which is `int' */
20486566d1a3SSergey Senozhatsky 	ret = kstrtoint(buf, 10, &dev_id);
20496566d1a3SSergey Senozhatsky 	if (ret)
20506566d1a3SSergey Senozhatsky 		return ret;
20516566d1a3SSergey Senozhatsky 	if (dev_id < 0)
20526566d1a3SSergey Senozhatsky 		return -EINVAL;
20536566d1a3SSergey Senozhatsky 
20546566d1a3SSergey Senozhatsky 	mutex_lock(&zram_index_mutex);
20556566d1a3SSergey Senozhatsky 
20566566d1a3SSergey Senozhatsky 	zram = idr_find(&zram_index_idr, dev_id);
205717ec4cd9SJerome Marchand 	if (zram) {
20586566d1a3SSergey Senozhatsky 		ret = zram_remove(zram);
2059529e71e1STakashi Iwai 		if (!ret)
206017ec4cd9SJerome Marchand 			idr_remove(&zram_index_idr, dev_id);
206117ec4cd9SJerome Marchand 	} else {
20626566d1a3SSergey Senozhatsky 		ret = -ENODEV;
206317ec4cd9SJerome Marchand 	}
20646566d1a3SSergey Senozhatsky 
20656566d1a3SSergey Senozhatsky 	mutex_unlock(&zram_index_mutex);
20666566d1a3SSergey Senozhatsky 	return ret ? ret : count;
20676566d1a3SSergey Senozhatsky }
206827104a53SGreg Kroah-Hartman static CLASS_ATTR_WO(hot_remove);
20696566d1a3SSergey Senozhatsky 
207027104a53SGreg Kroah-Hartman static struct attribute *zram_control_class_attrs[] = {
207127104a53SGreg Kroah-Hartman 	&class_attr_hot_add.attr,
207227104a53SGreg Kroah-Hartman 	&class_attr_hot_remove.attr,
207327104a53SGreg Kroah-Hartman 	NULL,
20746566d1a3SSergey Senozhatsky };
207527104a53SGreg Kroah-Hartman ATTRIBUTE_GROUPS(zram_control_class);
20766566d1a3SSergey Senozhatsky 
20776566d1a3SSergey Senozhatsky static struct class zram_control_class = {
20786566d1a3SSergey Senozhatsky 	.name		= "zram-control",
20796566d1a3SSergey Senozhatsky 	.owner		= THIS_MODULE,
208027104a53SGreg Kroah-Hartman 	.class_groups	= zram_control_class_groups,
20816566d1a3SSergey Senozhatsky };
20826566d1a3SSergey Senozhatsky 
208385508ec6SSergey Senozhatsky static int zram_remove_cb(int id, void *ptr, void *data)
208485508ec6SSergey Senozhatsky {
2085*8c54499aSMing Lei 	WARN_ON_ONCE(zram_remove(ptr));
208685508ec6SSergey Senozhatsky 	return 0;
208785508ec6SSergey Senozhatsky }
208885508ec6SSergey Senozhatsky 
208985508ec6SSergey Senozhatsky static void destroy_devices(void)
209085508ec6SSergey Senozhatsky {
20916566d1a3SSergey Senozhatsky 	class_unregister(&zram_control_class);
209285508ec6SSergey Senozhatsky 	idr_for_each(&zram_index_idr, &zram_remove_cb, NULL);
2093c0265342SMinchan Kim 	zram_debugfs_destroy();
209485508ec6SSergey Senozhatsky 	idr_destroy(&zram_index_idr);
2095a096cafcSSergey Senozhatsky 	unregister_blkdev(zram_major, "zram");
20961dd6c834SAnna-Maria Gleixner 	cpuhp_remove_multi_state(CPUHP_ZCOMP_PREPARE);
2097a096cafcSSergey Senozhatsky }
2098a096cafcSSergey Senozhatsky 
2099cd67e10aSMinchan Kim static int __init zram_init(void)
2100cd67e10aSMinchan Kim {
210192ff1528SSergey Senozhatsky 	int ret;
2102cd67e10aSMinchan Kim 
21031dd6c834SAnna-Maria Gleixner 	ret = cpuhp_setup_state_multi(CPUHP_ZCOMP_PREPARE, "block/zram:prepare",
21041dd6c834SAnna-Maria Gleixner 				      zcomp_cpu_up_prepare, zcomp_cpu_dead);
21051dd6c834SAnna-Maria Gleixner 	if (ret < 0)
21061dd6c834SAnna-Maria Gleixner 		return ret;
21071dd6c834SAnna-Maria Gleixner 
21086566d1a3SSergey Senozhatsky 	ret = class_register(&zram_control_class);
21096566d1a3SSergey Senozhatsky 	if (ret) {
211070864969SSergey Senozhatsky 		pr_err("Unable to register zram-control class\n");
21111dd6c834SAnna-Maria Gleixner 		cpuhp_remove_multi_state(CPUHP_ZCOMP_PREPARE);
21126566d1a3SSergey Senozhatsky 		return ret;
21136566d1a3SSergey Senozhatsky 	}
21146566d1a3SSergey Senozhatsky 
2115c0265342SMinchan Kim 	zram_debugfs_create();
2116cd67e10aSMinchan Kim 	zram_major = register_blkdev(0, "zram");
2117cd67e10aSMinchan Kim 	if (zram_major <= 0) {
211870864969SSergey Senozhatsky 		pr_err("Unable to get major number\n");
21196566d1a3SSergey Senozhatsky 		class_unregister(&zram_control_class);
21201dd6c834SAnna-Maria Gleixner 		cpuhp_remove_multi_state(CPUHP_ZCOMP_PREPARE);
2121a096cafcSSergey Senozhatsky 		return -EBUSY;
2122cd67e10aSMinchan Kim 	}
2123cd67e10aSMinchan Kim 
212492ff1528SSergey Senozhatsky 	while (num_devices != 0) {
21256566d1a3SSergey Senozhatsky 		mutex_lock(&zram_index_mutex);
212692ff1528SSergey Senozhatsky 		ret = zram_add();
21276566d1a3SSergey Senozhatsky 		mutex_unlock(&zram_index_mutex);
212892ff1528SSergey Senozhatsky 		if (ret < 0)
2129a096cafcSSergey Senozhatsky 			goto out_error;
213092ff1528SSergey Senozhatsky 		num_devices--;
2131cd67e10aSMinchan Kim 	}
2132cd67e10aSMinchan Kim 
2133cd67e10aSMinchan Kim 	return 0;
2134cd67e10aSMinchan Kim 
2135a096cafcSSergey Senozhatsky out_error:
213685508ec6SSergey Senozhatsky 	destroy_devices();
2137cd67e10aSMinchan Kim 	return ret;
2138cd67e10aSMinchan Kim }
2139cd67e10aSMinchan Kim 
2140cd67e10aSMinchan Kim static void __exit zram_exit(void)
2141cd67e10aSMinchan Kim {
214285508ec6SSergey Senozhatsky 	destroy_devices();
2143cd67e10aSMinchan Kim }
2144cd67e10aSMinchan Kim 
2145cd67e10aSMinchan Kim module_init(zram_init);
2146cd67e10aSMinchan Kim module_exit(zram_exit);
2147cd67e10aSMinchan Kim 
2148cd67e10aSMinchan Kim module_param(num_devices, uint, 0);
2149c3cdb40eSSergey Senozhatsky MODULE_PARM_DESC(num_devices, "Number of pre-created zram devices");
2150cd67e10aSMinchan Kim 
2151cd67e10aSMinchan Kim MODULE_LICENSE("Dual BSD/GPL");
2152cd67e10aSMinchan Kim MODULE_AUTHOR("Nitin Gupta <ngupta@vflare.org>");
2153cd67e10aSMinchan Kim MODULE_DESCRIPTION("Compressed RAM Block Device");
2154