Commit | Line | Data |
---|---|---|
33863c21 NG |
1 | /* |
2 | * Compressed RAM block device | |
3 | * | |
4 | * Copyright (C) 2008, 2009, 2010 Nitin Gupta | |
5 | * | |
6 | * This code is released using a dual license strategy: BSD/GPL | |
7 | * You can choose the licence that better fits your requirements. | |
8 | * | |
9 | * Released under the terms of 3-clause BSD License | |
10 | * Released under the terms of GNU General Public License Version 2.0 | |
11 | * | |
12 | * Project home: http://compcache.googlecode.com/ | |
13 | */ | |
14 | ||
15 | #include <linux/device.h> | |
16 | #include <linux/genhd.h> | |
f2da9873 | 17 | #include <linux/mm.h> |
26907840 | 18 | #include <linux/kernel.h> |
33863c21 NG |
19 | |
20 | #include "zram_drv.h" | |
21 | ||
33863c21 NG |
22 | static u64 zram_stat64_read(struct zram *zram, u64 *v) |
23 | { | |
24 | u64 val; | |
25 | ||
26 | spin_lock(&zram->stat64_lock); | |
27 | val = *v; | |
28 | spin_unlock(&zram->stat64_lock); | |
29 | ||
30 | return val; | |
31 | } | |
32 | ||
33 | static struct zram *dev_to_zram(struct device *dev) | |
34 | { | |
35 | int i; | |
36 | struct zram *zram = NULL; | |
37 | ||
5fa5a901 | 38 | for (i = 0; i < zram_get_num_devices(); i++) { |
43801f6e | 39 | zram = &zram_devices[i]; |
33863c21 NG |
40 | if (disk_to_dev(zram->disk) == dev) |
41 | break; | |
42 | } | |
43 | ||
44 | return zram; | |
45 | } | |
46 | ||
47 | static ssize_t disksize_show(struct device *dev, | |
48 | struct device_attribute *attr, char *buf) | |
49 | { | |
50 | struct zram *zram = dev_to_zram(dev); | |
51 | ||
52 | return sprintf(buf, "%llu\n", zram->disksize); | |
53 | } | |
54 | ||
55 | static ssize_t disksize_store(struct device *dev, | |
56 | struct device_attribute *attr, const char *buf, size_t len) | |
57 | { | |
0900beae | 58 | u64 disksize; |
8b3cc3ed | 59 | struct zram_meta *meta; |
33863c21 NG |
60 | struct zram *zram = dev_to_zram(dev); |
61 | ||
26907840 SS |
62 | disksize = memparse(buf, NULL); |
63 | if (!disksize) | |
64 | return -EINVAL; | |
0900beae | 65 | |
8b3cc3ed MK |
66 | disksize = PAGE_ALIGN(disksize); |
67 | meta = zram_meta_alloc(disksize); | |
0900beae | 68 | down_write(&zram->init_lock); |
484875ad | 69 | if (zram->init_done) { |
0900beae | 70 | up_write(&zram->init_lock); |
8b3cc3ed | 71 | zram_meta_free(meta); |
484875ad | 72 | pr_info("Cannot change disksize for initialized device\n"); |
33863c21 | 73 | return -EBUSY; |
484875ad | 74 | } |
33863c21 | 75 | |
8b3cc3ed | 76 | zram->disksize = disksize; |
33863c21 | 77 | set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT); |
8b3cc3ed | 78 | zram_init_device(zram, meta); |
0900beae | 79 | up_write(&zram->init_lock); |
33863c21 NG |
80 | |
81 | return len; | |
82 | } | |
83 | ||
84 | static ssize_t initstate_show(struct device *dev, | |
85 | struct device_attribute *attr, char *buf) | |
86 | { | |
87 | struct zram *zram = dev_to_zram(dev); | |
88 | ||
89 | return sprintf(buf, "%u\n", zram->init_done); | |
90 | } | |
91 | ||
33863c21 NG |
92 | static ssize_t reset_store(struct device *dev, |
93 | struct device_attribute *attr, const char *buf, size_t len) | |
94 | { | |
95 | int ret; | |
04e7bbad | 96 | unsigned short do_reset; |
33863c21 NG |
97 | struct zram *zram; |
98 | struct block_device *bdev; | |
99 | ||
100 | zram = dev_to_zram(dev); | |
101 | bdev = bdget_disk(zram->disk, 0); | |
102 | ||
103 | /* Do not reset an active device! */ | |
104 | if (bdev->bd_holders) | |
105 | return -EBUSY; | |
106 | ||
04e7bbad | 107 | ret = kstrtou16(buf, 10, &do_reset); |
33863c21 NG |
108 | if (ret) |
109 | return ret; | |
110 | ||
111 | if (!do_reset) | |
112 | return -EINVAL; | |
113 | ||
114 | /* Make sure all pending I/O is finished */ | |
115 | if (bdev) | |
116 | fsync_bdev(bdev); | |
117 | ||
0231c403 | 118 | zram_reset_device(zram); |
33863c21 NG |
119 | return len; |
120 | } | |
121 | ||
122 | static ssize_t num_reads_show(struct device *dev, | |
123 | struct device_attribute *attr, char *buf) | |
124 | { | |
125 | struct zram *zram = dev_to_zram(dev); | |
126 | ||
127 | return sprintf(buf, "%llu\n", | |
128 | zram_stat64_read(zram, &zram->stats.num_reads)); | |
129 | } | |
130 | ||
131 | static ssize_t num_writes_show(struct device *dev, | |
132 | struct device_attribute *attr, char *buf) | |
133 | { | |
134 | struct zram *zram = dev_to_zram(dev); | |
135 | ||
136 | return sprintf(buf, "%llu\n", | |
137 | zram_stat64_read(zram, &zram->stats.num_writes)); | |
138 | } | |
139 | ||
140 | static ssize_t invalid_io_show(struct device *dev, | |
141 | struct device_attribute *attr, char *buf) | |
142 | { | |
143 | struct zram *zram = dev_to_zram(dev); | |
144 | ||
145 | return sprintf(buf, "%llu\n", | |
146 | zram_stat64_read(zram, &zram->stats.invalid_io)); | |
147 | } | |
148 | ||
149 | static ssize_t notify_free_show(struct device *dev, | |
150 | struct device_attribute *attr, char *buf) | |
151 | { | |
152 | struct zram *zram = dev_to_zram(dev); | |
153 | ||
154 | return sprintf(buf, "%llu\n", | |
155 | zram_stat64_read(zram, &zram->stats.notify_free)); | |
156 | } | |
157 | ||
158 | static ssize_t zero_pages_show(struct device *dev, | |
159 | struct device_attribute *attr, char *buf) | |
160 | { | |
161 | struct zram *zram = dev_to_zram(dev); | |
162 | ||
163 | return sprintf(buf, "%u\n", zram->stats.pages_zero); | |
164 | } | |
165 | ||
166 | static ssize_t orig_data_size_show(struct device *dev, | |
167 | struct device_attribute *attr, char *buf) | |
168 | { | |
169 | struct zram *zram = dev_to_zram(dev); | |
170 | ||
171 | return sprintf(buf, "%llu\n", | |
172 | (u64)(zram->stats.pages_stored) << PAGE_SHIFT); | |
173 | } | |
174 | ||
175 | static ssize_t compr_data_size_show(struct device *dev, | |
176 | struct device_attribute *attr, char *buf) | |
177 | { | |
178 | struct zram *zram = dev_to_zram(dev); | |
179 | ||
180 | return sprintf(buf, "%llu\n", | |
181 | zram_stat64_read(zram, &zram->stats.compr_size)); | |
182 | } | |
183 | ||
184 | static ssize_t mem_used_total_show(struct device *dev, | |
185 | struct device_attribute *attr, char *buf) | |
186 | { | |
187 | u64 val = 0; | |
188 | struct zram *zram = dev_to_zram(dev); | |
8b3cc3ed | 189 | struct zram_meta *meta = zram->meta; |
33863c21 | 190 | |
130f315a | 191 | if (zram->init_done) |
8b3cc3ed | 192 | val = zs_get_total_size_bytes(meta->mem_pool); |
33863c21 NG |
193 | |
194 | return sprintf(buf, "%llu\n", val); | |
195 | } | |
196 | ||
a3d13107 | 197 | static DEVICE_ATTR(disksize, S_IRUGO | S_IWUSR, |
33863c21 | 198 | disksize_show, disksize_store); |
484875ad | 199 | static DEVICE_ATTR(initstate, S_IRUGO, initstate_show, NULL); |
a3d13107 | 200 | static DEVICE_ATTR(reset, S_IWUSR, NULL, reset_store); |
33863c21 NG |
201 | static DEVICE_ATTR(num_reads, S_IRUGO, num_reads_show, NULL); |
202 | static DEVICE_ATTR(num_writes, S_IRUGO, num_writes_show, NULL); | |
203 | static DEVICE_ATTR(invalid_io, S_IRUGO, invalid_io_show, NULL); | |
204 | static DEVICE_ATTR(notify_free, S_IRUGO, notify_free_show, NULL); | |
205 | static DEVICE_ATTR(zero_pages, S_IRUGO, zero_pages_show, NULL); | |
206 | static DEVICE_ATTR(orig_data_size, S_IRUGO, orig_data_size_show, NULL); | |
207 | static DEVICE_ATTR(compr_data_size, S_IRUGO, compr_data_size_show, NULL); | |
208 | static DEVICE_ATTR(mem_used_total, S_IRUGO, mem_used_total_show, NULL); | |
209 | ||
210 | static struct attribute *zram_disk_attrs[] = { | |
211 | &dev_attr_disksize.attr, | |
212 | &dev_attr_initstate.attr, | |
213 | &dev_attr_reset.attr, | |
214 | &dev_attr_num_reads.attr, | |
215 | &dev_attr_num_writes.attr, | |
216 | &dev_attr_invalid_io.attr, | |
217 | &dev_attr_notify_free.attr, | |
218 | &dev_attr_zero_pages.attr, | |
219 | &dev_attr_orig_data_size.attr, | |
220 | &dev_attr_compr_data_size.attr, | |
221 | &dev_attr_mem_used_total.attr, | |
222 | NULL, | |
223 | }; | |
224 | ||
225 | struct attribute_group zram_disk_attr_group = { | |
226 | .attrs = zram_disk_attrs, | |
227 | }; |