aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/zram/zcomp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/zram/zcomp.c')
-rw-r--r--drivers/block/zram/zcomp.c115
1 files changed, 115 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}