~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to fs/squashfs/zlib_wrapper.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Squashfs - a compressed read only filesystem for Linux
 
3
 *
 
4
 * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
 
5
 * Phillip Lougher <phillip@squashfs.org.uk>
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU General Public License
 
9
 * as published by the Free Software Foundation; either version 2,
 
10
 * or (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
20
 *
 
21
 * zlib_wrapper.c
 
22
 */
 
23
 
 
24
 
 
25
#include <linux/mutex.h>
 
26
#include <linux/buffer_head.h>
 
27
#include <linux/slab.h>
 
28
#include <linux/zlib.h>
 
29
#include <linux/vmalloc.h>
 
30
 
 
31
#include "squashfs_fs.h"
 
32
#include "squashfs_fs_sb.h"
 
33
#include "squashfs.h"
 
34
#include "decompressor.h"
 
35
 
 
36
static void *zlib_init(struct squashfs_sb_info *dummy, void *buff, int len)
 
37
{
 
38
        z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
 
39
        if (stream == NULL)
 
40
                goto failed;
 
41
        stream->workspace = vmalloc(zlib_inflate_workspacesize());
 
42
        if (stream->workspace == NULL)
 
43
                goto failed;
 
44
 
 
45
        return stream;
 
46
 
 
47
failed:
 
48
        ERROR("Failed to allocate zlib workspace\n");
 
49
        kfree(stream);
 
50
        return ERR_PTR(-ENOMEM);
 
51
}
 
52
 
 
53
 
 
54
static void zlib_free(void *strm)
 
55
{
 
56
        z_stream *stream = strm;
 
57
 
 
58
        if (stream)
 
59
                vfree(stream->workspace);
 
60
        kfree(stream);
 
61
}
 
62
 
 
63
 
 
64
static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
 
65
        struct buffer_head **bh, int b, int offset, int length, int srclength,
 
66
        int pages)
 
67
{
 
68
        int zlib_err, zlib_init = 0;
 
69
        int k = 0, page = 0;
 
70
        z_stream *stream = msblk->stream;
 
71
 
 
72
        mutex_lock(&msblk->read_data_mutex);
 
73
 
 
74
        stream->avail_out = 0;
 
75
        stream->avail_in = 0;
 
76
 
 
77
        do {
 
78
                if (stream->avail_in == 0 && k < b) {
 
79
                        int avail = min(length, msblk->devblksize - offset);
 
80
                        length -= avail;
 
81
                        wait_on_buffer(bh[k]);
 
82
                        if (!buffer_uptodate(bh[k]))
 
83
                                goto release_mutex;
 
84
 
 
85
                        stream->next_in = bh[k]->b_data + offset;
 
86
                        stream->avail_in = avail;
 
87
                        offset = 0;
 
88
                }
 
89
 
 
90
                if (stream->avail_out == 0 && page < pages) {
 
91
                        stream->next_out = buffer[page++];
 
92
                        stream->avail_out = PAGE_CACHE_SIZE;
 
93
                }
 
94
 
 
95
                if (!zlib_init) {
 
96
                        zlib_err = zlib_inflateInit(stream);
 
97
                        if (zlib_err != Z_OK) {
 
98
                                ERROR("zlib_inflateInit returned unexpected "
 
99
                                        "result 0x%x, srclength %d\n",
 
100
                                        zlib_err, srclength);
 
101
                                goto release_mutex;
 
102
                        }
 
103
                        zlib_init = 1;
 
104
                }
 
105
 
 
106
                zlib_err = zlib_inflate(stream, Z_SYNC_FLUSH);
 
107
 
 
108
                if (stream->avail_in == 0 && k < b)
 
109
                        put_bh(bh[k++]);
 
110
        } while (zlib_err == Z_OK);
 
111
 
 
112
        if (zlib_err != Z_STREAM_END) {
 
113
                ERROR("zlib_inflate error, data probably corrupt\n");
 
114
                goto release_mutex;
 
115
        }
 
116
 
 
117
        zlib_err = zlib_inflateEnd(stream);
 
118
        if (zlib_err != Z_OK) {
 
119
                ERROR("zlib_inflate error, data probably corrupt\n");
 
120
                goto release_mutex;
 
121
        }
 
122
 
 
123
        if (k < b) {
 
124
                ERROR("zlib_uncompress error, data remaining\n");
 
125
                goto release_mutex;
 
126
        }
 
127
 
 
128
        length = stream->total_out;
 
129
        mutex_unlock(&msblk->read_data_mutex);
 
130
        return length;
 
131
 
 
132
release_mutex:
 
133
        mutex_unlock(&msblk->read_data_mutex);
 
134
 
 
135
        for (; k < b; k++)
 
136
                put_bh(bh[k]);
 
137
 
 
138
        return -EIO;
 
139
}
 
140
 
 
141
const struct squashfs_decompressor squashfs_zlib_comp_ops = {
 
142
        .init = zlib_init,
 
143
        .free = zlib_free,
 
144
        .decompress = zlib_uncompress,
 
145
        .id = ZLIB_COMPRESSION,
 
146
        .name = "zlib",
 
147
        .supported = 1
 
148
};
 
149