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