aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/zram/zcomp.c124
-rw-r--r--drivers/block/zram/zcomp.h4
-rw-r--r--drivers/block/zram/zram_drv.c42
-rw-r--r--drivers/block/zram/zram_drv.h2
4 files changed, 167 insertions, 5 deletions
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index 72e8071f9d73..c06f75f54718 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -24,6 +24,21 @@ struct zcomp_strm_single {
24 struct zcomp_strm *zstrm; 24 struct zcomp_strm *zstrm;
25}; 25};
26 26
27/*
28 * multi zcomp_strm backend
29 */
30struct zcomp_strm_multi {
31 /* protect strm list */
32 spinlock_t strm_lock;
33 /* max possible number of zstrm streams */
34 int max_strm;
35 /* number of available zstrm streams */
36 int avail_strm;
37 /* list of available strms */
38 struct list_head idle_strm;
39 wait_queue_head_t strm_wait;
40};
41
27static struct zcomp_backend *find_backend(const char *compress) 42static struct zcomp_backend *find_backend(const char *compress)
28{ 43{
29 if (strncmp(compress, "lzo", 3) == 0) 44 if (strncmp(compress, "lzo", 3) == 0)
@@ -62,6 +77,107 @@ static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp)
62 return zstrm; 77 return zstrm;
63} 78}
64 79
80/*
81 * get idle zcomp_strm or wait until other process release
82 * (zcomp_strm_release()) one for us
83 */
84static struct zcomp_strm *zcomp_strm_multi_find(struct zcomp *comp)
85{
86 struct zcomp_strm_multi *zs = comp->stream;
87 struct zcomp_strm *zstrm;
88
89 while (1) {
90 spin_lock(&zs->strm_lock);
91 if (!list_empty(&zs->idle_strm)) {
92 zstrm = list_entry(zs->idle_strm.next,
93 struct zcomp_strm, list);
94 list_del(&zstrm->list);
95 spin_unlock(&zs->strm_lock);
96 return zstrm;
97 }
98 /* zstrm streams limit reached, wait for idle stream */
99 if (zs->avail_strm >= zs->max_strm) {
100 spin_unlock(&zs->strm_lock);
101 wait_event(zs->strm_wait, !list_empty(&zs->idle_strm));
102 continue;
103 }
104 /* allocate new zstrm stream */
105 zs->avail_strm++;
106 spin_unlock(&zs->strm_lock);
107
108 zstrm = zcomp_strm_alloc(comp);
109 if (!zstrm) {
110 spin_lock(&zs->strm_lock);
111 zs->avail_strm--;
112 spin_unlock(&zs->strm_lock);
113 wait_event(zs->strm_wait, !list_empty(&zs->idle_strm));
114 continue;
115 }
116 break;
117 }
118 return zstrm;
119}
120
121/* add stream back to idle list and wake up waiter or free the stream */
122static void zcomp_strm_multi_release(struct zcomp *comp, struct zcomp_strm *zstrm)
123{
124 struct zcomp_strm_multi *zs = comp->stream;
125
126 spin_lock(&zs->strm_lock);
127 if (zs->avail_strm <= zs->max_strm) {
128 list_add(&zstrm->list, &zs->idle_strm);
129 spin_unlock(&zs->strm_lock);
130 wake_up(&zs->strm_wait);
131 return;
132 }
133
134 zs->avail_strm--;
135 spin_unlock(&zs->strm_lock);
136 zcomp_strm_free(comp, zstrm);
137}
138
139static void zcomp_strm_multi_destroy(struct zcomp *comp)
140{
141 struct zcomp_strm_multi *zs = comp->stream;
142 struct zcomp_strm *zstrm;
143
144 while (!list_empty(&zs->idle_strm)) {
145 zstrm = list_entry(zs->idle_strm.next,
146 struct zcomp_strm, list);
147 list_del(&zstrm->list);
148 zcomp_strm_free(comp, zstrm);
149 }
150 kfree(zs);
151}
152
153static int zcomp_strm_multi_create(struct zcomp *comp, int max_strm)
154{
155 struct zcomp_strm *zstrm;
156 struct zcomp_strm_multi *zs;
157
158 comp->destroy = zcomp_strm_multi_destroy;
159 comp->strm_find = zcomp_strm_multi_find;
160 comp->strm_release = zcomp_strm_multi_release;
161 zs = kmalloc(sizeof(struct zcomp_strm_multi), GFP_KERNEL);
162 if (!zs)
163 return -ENOMEM;
164
165 comp->stream = zs;
166 spin_lock_init(&zs->strm_lock);
167 INIT_LIST_HEAD(&zs->idle_strm);
168 init_waitqueue_head(&zs->strm_wait);
169 zs->max_strm = max_strm;
170 zs->avail_strm = 1;
171
172 zstrm = zcomp_strm_alloc(comp);
173 if (!zstrm) {
174 kfree(zs);
175 return -ENOMEM;
176 }
177 list_add(&zstrm->list, &zs->idle_strm);
178 return 0;
179}
180
65static struct zcomp_strm *zcomp_strm_single_find(struct zcomp *comp) 181static struct zcomp_strm *zcomp_strm_single_find(struct zcomp *comp)
66{ 182{
67 struct zcomp_strm_single *zs = comp->stream; 183 struct zcomp_strm_single *zs = comp->stream;
@@ -139,7 +255,7 @@ void zcomp_destroy(struct zcomp *comp)
139 * if requested algorithm is not supported or in case 255 * if requested algorithm is not supported or in case
140 * of init error 256 * of init error
141 */ 257 */
142struct zcomp *zcomp_create(const char *compress) 258struct zcomp *zcomp_create(const char *compress, int max_strm)
143{ 259{
144 struct zcomp *comp; 260 struct zcomp *comp;
145 struct zcomp_backend *backend; 261 struct zcomp_backend *backend;
@@ -153,7 +269,11 @@ struct zcomp *zcomp_create(const char *compress)
153 return NULL; 269 return NULL;
154 270
155 comp->backend = backend; 271 comp->backend = backend;
156 if (zcomp_strm_single_create(comp) != 0) { 272 if (max_strm > 1)
273 zcomp_strm_multi_create(comp, max_strm);
274 else
275 zcomp_strm_single_create(comp);
276 if (!comp->stream) {
157 kfree(comp); 277 kfree(comp);
158 return NULL; 278 return NULL;
159 } 279 }
diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h
index dc3500d842a3..2a3684446160 100644
--- a/drivers/block/zram/zcomp.h
+++ b/drivers/block/zram/zcomp.h
@@ -21,6 +21,8 @@ struct zcomp_strm {
21 * working memory) 21 * working memory)
22 */ 22 */
23 void *private; 23 void *private;
24 /* used in multi stream backend, protected by backend strm_lock */
25 struct list_head list;
24}; 26};
25 27
26/* static compression backend */ 28/* static compression backend */
@@ -47,7 +49,7 @@ struct zcomp {
47 void (*destroy)(struct zcomp *comp); 49 void (*destroy)(struct zcomp *comp);
48}; 50};
49 51
50struct zcomp *zcomp_create(const char *comp); 52struct zcomp *zcomp_create(const char *comp, int max_strm);
51void zcomp_destroy(struct zcomp *comp); 53void zcomp_destroy(struct zcomp *comp);
52 54
53struct zcomp_strm *zcomp_strm_find(struct zcomp *comp); 55struct zcomp_strm *zcomp_strm_find(struct zcomp *comp);
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 98823f9ca8b1..bdc7eb8c6df7 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -108,6 +108,40 @@ static ssize_t mem_used_total_show(struct device *dev,
108 return sprintf(buf, "%llu\n", val); 108 return sprintf(buf, "%llu\n", val);
109} 109}
110 110
111static ssize_t max_comp_streams_show(struct device *dev,
112 struct device_attribute *attr, char *buf)
113{
114 int val;
115 struct zram *zram = dev_to_zram(dev);
116
117 down_read(&zram->init_lock);
118 val = zram->max_comp_streams;
119 up_read(&zram->init_lock);
120
121 return sprintf(buf, "%d\n", val);
122}
123
124static ssize_t max_comp_streams_store(struct device *dev,
125 struct device_attribute *attr, const char *buf, size_t len)
126{
127 int num;
128 struct zram *zram = dev_to_zram(dev);
129
130 if (kstrtoint(buf, 0, &num))
131 return -EINVAL;
132 if (num < 1)
133 return -EINVAL;
134 down_write(&zram->init_lock);
135 if (init_done(zram)) {
136 up_write(&zram->init_lock);
137 pr_info("Can't set max_comp_streams for initialized device\n");
138 return -EBUSY;
139 }
140 zram->max_comp_streams = num;
141 up_write(&zram->init_lock);
142 return len;
143}
144
111/* flag operations needs meta->tb_lock */ 145/* flag operations needs meta->tb_lock */
112static int zram_test_flag(struct zram_meta *meta, u32 index, 146static int zram_test_flag(struct zram_meta *meta, u32 index,
113 enum zram_pageflags flag) 147 enum zram_pageflags flag)
@@ -502,6 +536,8 @@ static void zram_reset_device(struct zram *zram, bool reset_capacity)
502 } 536 }
503 537
504 zcomp_destroy(zram->comp); 538 zcomp_destroy(zram->comp);
539 zram->max_comp_streams = 1;
540
505 zram_meta_free(zram->meta); 541 zram_meta_free(zram->meta);
506 zram->meta = NULL; 542 zram->meta = NULL;
507 /* Reset stats */ 543 /* Reset stats */
@@ -537,7 +573,7 @@ static ssize_t disksize_store(struct device *dev,
537 goto out_free_meta; 573 goto out_free_meta;
538 } 574 }
539 575
540 zram->comp = zcomp_create(default_compressor); 576 zram->comp = zcomp_create(default_compressor, zram->max_comp_streams);
541 if (!zram->comp) { 577 if (!zram->comp) {
542 pr_info("Cannot initialise %s compressing backend\n", 578 pr_info("Cannot initialise %s compressing backend\n",
543 default_compressor); 579 default_compressor);
@@ -698,6 +734,8 @@ static DEVICE_ATTR(initstate, S_IRUGO, initstate_show, NULL);
698static DEVICE_ATTR(reset, S_IWUSR, NULL, reset_store); 734static DEVICE_ATTR(reset, S_IWUSR, NULL, reset_store);
699static DEVICE_ATTR(orig_data_size, S_IRUGO, orig_data_size_show, NULL); 735static DEVICE_ATTR(orig_data_size, S_IRUGO, orig_data_size_show, NULL);
700static DEVICE_ATTR(mem_used_total, S_IRUGO, mem_used_total_show, NULL); 736static DEVICE_ATTR(mem_used_total, S_IRUGO, mem_used_total_show, NULL);
737static DEVICE_ATTR(max_comp_streams, S_IRUGO | S_IWUSR,
738 max_comp_streams_show, max_comp_streams_store);
701 739
702ZRAM_ATTR_RO(num_reads); 740ZRAM_ATTR_RO(num_reads);
703ZRAM_ATTR_RO(num_writes); 741ZRAM_ATTR_RO(num_writes);
@@ -722,6 +760,7 @@ static struct attribute *zram_disk_attrs[] = {
722 &dev_attr_orig_data_size.attr, 760 &dev_attr_orig_data_size.attr,
723 &dev_attr_compr_data_size.attr, 761 &dev_attr_compr_data_size.attr,
724 &dev_attr_mem_used_total.attr, 762 &dev_attr_mem_used_total.attr,
763 &dev_attr_max_comp_streams.attr,
725 NULL, 764 NULL,
726}; 765};
727 766
@@ -784,6 +823,7 @@ static int create_device(struct zram *zram, int device_id)
784 } 823 }
785 824
786 zram->meta = NULL; 825 zram->meta = NULL;
826 zram->max_comp_streams = 1;
787 return 0; 827 return 0;
788 828
789out_free_disk: 829out_free_disk:
diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h
index 45e04f7b713f..ccf36d11755a 100644
--- a/drivers/block/zram/zram_drv.h
+++ b/drivers/block/zram/zram_drv.h
@@ -99,7 +99,7 @@ struct zram {
99 * we can store in a disk. 99 * we can store in a disk.
100 */ 100 */
101 u64 disksize; /* bytes */ 101 u64 disksize; /* bytes */
102 102 int max_comp_streams;
103 struct zram_stats stats; 103 struct zram_stats stats;
104}; 104};
105#endif 105#endif