aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/zram/zcomp.c115
-rw-r--r--drivers/block/zram/zcomp.h58
-rw-r--r--drivers/block/zram/zcomp_lzo.c47
-rw-r--r--drivers/block/zram/zcomp_lzo.h17
4 files changed, 237 insertions, 0 deletions
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
new file mode 100644
index 000000000000..22f4ae235660
--- /dev/null
+++ b/drivers/block/zram/zcomp.c
@@ -0,0 +1,115 @@
1/*
2 * Copyright (C) 2014 Sergey Senozhatsky.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include <linux/kernel.h>
11#include <linux/string.h>
12#include <linux/slab.h>
13#include <linux/wait.h>
14#include <linux/sched.h>
15
16#include "zcomp.h"
17#include "zcomp_lzo.h"
18
19static struct zcomp_backend *find_backend(const char *compress)
20{
21 if (strncmp(compress, "lzo", 3) == 0)
22 return &zcomp_lzo;
23 return NULL;
24}
25
26static void zcomp_strm_free(struct zcomp *comp, struct zcomp_strm *zstrm)
27{
28 if (zstrm->private)
29 comp->backend->destroy(zstrm->private);
30 free_pages((unsigned long)zstrm->buffer, 1);
31 kfree(zstrm);
32}
33
34/*
35 * allocate new zcomp_strm structure with ->private initialized by
36 * backend, return NULL on error
37 */
38static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp)
39{
40 struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_KERNEL);
41 if (!zstrm)
42 return NULL;
43
44 zstrm->private = comp->backend->create();
45 /*
46 * allocate 2 pages. 1 for compressed data, plus 1 extra for the
47 * case when compressed size is larger than the original one
48 */
49 zstrm->buffer = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
50 if (!zstrm->private || !zstrm->buffer) {
51 zcomp_strm_free(comp, zstrm);
52 zstrm = NULL;
53 }
54 return zstrm;
55}
56
57struct zcomp_strm *zcomp_strm_find(struct zcomp *comp)
58{
59 mutex_lock(&comp->strm_lock);
60 return comp->zstrm;
61}
62
63void zcomp_strm_release(struct zcomp *comp, struct zcomp_strm *zstrm)
64{
65 mutex_unlock(&comp->strm_lock);
66}
67
68int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
69 const unsigned char *src, size_t *dst_len)
70{
71 return comp->backend->compress(src, zstrm->buffer, dst_len,
72 zstrm->private);
73}
74
75int zcomp_decompress(struct zcomp *comp, const unsigned char *src,
76 size_t src_len, unsigned char *dst)
77{
78 return comp->backend->decompress(src, src_len, dst);
79}
80
81void zcomp_destroy(struct zcomp *comp)
82{
83 zcomp_strm_free(comp, comp->zstrm);
84 kfree(comp);
85}
86
87/*
88 * search available compressors for requested algorithm.
89 * allocate new zcomp and initialize it. return NULL
90 * if requested algorithm is not supported or in case
91 * of init error
92 */
93struct zcomp *zcomp_create(const char *compress)
94{
95 struct zcomp *comp;
96 struct zcomp_backend *backend;
97
98 backend = find_backend(compress);
99 if (!backend)
100 return NULL;
101
102 comp = kzalloc(sizeof(struct zcomp), GFP_KERNEL);
103 if (!comp)
104 return NULL;
105
106 comp->backend = backend;
107 mutex_init(&comp->strm_lock);
108
109 comp->zstrm = zcomp_strm_alloc(comp);
110 if (!comp->zstrm) {
111 kfree(comp);
112 return NULL;
113 }
114 return comp;
115}
diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h
new file mode 100644
index 000000000000..c9a98e1317fe
--- /dev/null
+++ b/drivers/block/zram/zcomp.h
@@ -0,0 +1,58 @@
1/*
2 * Copyright (C) 2014 Sergey Senozhatsky.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#ifndef _ZCOMP_H_
11#define _ZCOMP_H_
12
13#include <linux/mutex.h>
14
15struct zcomp_strm {
16 /* compression/decompression buffer */
17 void *buffer;
18 /*
19 * The private data of the compression stream, only compression
20 * stream backend can touch this (e.g. compression algorithm
21 * working memory)
22 */
23 void *private;
24};
25
26/* static compression backend */
27struct zcomp_backend {
28 int (*compress)(const unsigned char *src, unsigned char *dst,
29 size_t *dst_len, void *private);
30
31 int (*decompress)(const unsigned char *src, size_t src_len,
32 unsigned char *dst);
33
34 void *(*create)(void);
35 void (*destroy)(void *private);
36
37 const char *name;
38};
39
40/* dynamic per-device compression frontend */
41struct zcomp {
42 struct mutex strm_lock;
43 struct zcomp_strm *zstrm;
44 struct zcomp_backend *backend;
45};
46
47struct zcomp *zcomp_create(const char *comp);
48void zcomp_destroy(struct zcomp *comp);
49
50struct zcomp_strm *zcomp_strm_find(struct zcomp *comp);
51void zcomp_strm_release(struct zcomp *comp, struct zcomp_strm *zstrm);
52
53int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm,
54 const unsigned char *src, size_t *dst_len);
55
56int zcomp_decompress(struct zcomp *comp, const unsigned char *src,
57 size_t src_len, unsigned char *dst);
58#endif /* _ZCOMP_H_ */
diff --git a/drivers/block/zram/zcomp_lzo.c b/drivers/block/zram/zcomp_lzo.c
new file mode 100644
index 000000000000..da1bc47d588e
--- /dev/null
+++ b/drivers/block/zram/zcomp_lzo.c
@@ -0,0 +1,47 @@
1/*
2 * Copyright (C) 2014 Sergey Senozhatsky.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include <linux/kernel.h>
11#include <linux/slab.h>
12#include <linux/lzo.h>
13
14#include "zcomp_lzo.h"
15
16static void *lzo_create(void)
17{
18 return kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
19}
20
21static void lzo_destroy(void *private)
22{
23 kfree(private);
24}
25
26static int lzo_compress(const unsigned char *src, unsigned char *dst,
27 size_t *dst_len, void *private)
28{
29 int ret = lzo1x_1_compress(src, PAGE_SIZE, dst, dst_len, private);
30 return ret == LZO_E_OK ? 0 : ret;
31}
32
33static int lzo_decompress(const unsigned char *src, size_t src_len,
34 unsigned char *dst)
35{
36 size_t dst_len = PAGE_SIZE;
37 int ret = lzo1x_decompress_safe(src, src_len, dst, &dst_len);
38 return ret == LZO_E_OK ? 0 : ret;
39}
40
41struct zcomp_backend zcomp_lzo = {
42 .compress = lzo_compress,
43 .decompress = lzo_decompress,
44 .create = lzo_create,
45 .destroy = lzo_destroy,
46 .name = "lzo",
47};
diff --git a/drivers/block/zram/zcomp_lzo.h b/drivers/block/zram/zcomp_lzo.h
new file mode 100644
index 000000000000..128c5807fa14
--- /dev/null
+++ b/drivers/block/zram/zcomp_lzo.h
@@ -0,0 +1,17 @@
1/*
2 * Copyright (C) 2014 Sergey Senozhatsky.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#ifndef _ZCOMP_LZO_H_
11#define _ZCOMP_LZO_H_
12
13#include "zcomp.h"
14
15extern struct zcomp_backend zcomp_lzo;
16
17#endif /* _ZCOMP_LZO_H_ */