Blame view

fs/squashfs/zlib_wrapper.c 3.47 KB
e6a6d3795   Phillip Lougher   Squashfs: move zl...
1
2
3
4
  /*
   * Squashfs - a compressed read only filesystem for Linux
   *
   * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
d7f2ff671   Phillip Lougher   Squashfs: update ...
5
   * Phillip Lougher <phillip@squashfs.org.uk>
e6a6d3795   Phillip Lougher   Squashfs: move zl...
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2,
   * or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   *
   * zlib_wrapper.c
   */
  
  
  #include <linux/mutex.h>
  #include <linux/buffer_head.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
27
  #include <linux/slab.h>
e6a6d3795   Phillip Lougher   Squashfs: move zl...
28
  #include <linux/zlib.h>
117a91e0f   Phillip Lougher   Squashfs: Use vma...
29
  #include <linux/vmalloc.h>
e6a6d3795   Phillip Lougher   Squashfs: move zl...
30
31
32
  
  #include "squashfs_fs.h"
  #include "squashfs_fs_sb.h"
e6a6d3795   Phillip Lougher   Squashfs: move zl...
33
  #include "squashfs.h"
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
34
  #include "decompressor.h"
e6a6d3795   Phillip Lougher   Squashfs: move zl...
35

b7fc0ff09   Phillip Lougher   Squashfs: extend ...
36
  static void *zlib_init(struct squashfs_sb_info *dummy, void *buff, int len)
f1a40359f   Phillip Lougher   Squashfs: factor ...
37
38
39
40
  {
  	z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
  	if (stream == NULL)
  		goto failed;
117a91e0f   Phillip Lougher   Squashfs: Use vma...
41
  	stream->workspace = vmalloc(zlib_inflate_workspacesize());
f1a40359f   Phillip Lougher   Squashfs: factor ...
42
43
44
45
46
47
48
49
50
  	if (stream->workspace == NULL)
  		goto failed;
  
  	return stream;
  
  failed:
  	ERROR("Failed to allocate zlib workspace
  ");
  	kfree(stream);
b7fc0ff09   Phillip Lougher   Squashfs: extend ...
51
  	return ERR_PTR(-ENOMEM);
f1a40359f   Phillip Lougher   Squashfs: factor ...
52
  }
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
53
  static void zlib_free(void *strm)
f1a40359f   Phillip Lougher   Squashfs: factor ...
54
55
56
57
  {
  	z_stream *stream = strm;
  
  	if (stream)
117a91e0f   Phillip Lougher   Squashfs: Use vma...
58
  		vfree(stream->workspace);
f1a40359f   Phillip Lougher   Squashfs: factor ...
59
60
  	kfree(stream);
  }
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
61
  static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
e6a6d3795   Phillip Lougher   Squashfs: move zl...
62
63
64
  	struct buffer_head **bh, int b, int offset, int length, int srclength,
  	int pages)
  {
170cf0216   Phillip Lougher   Squashfs: remove ...
65
66
  	int zlib_err, zlib_init = 0;
  	int k = 0, page = 0;
f1a40359f   Phillip Lougher   Squashfs: factor ...
67
  	z_stream *stream = msblk->stream;
e6a6d3795   Phillip Lougher   Squashfs: move zl...
68
69
  
  	mutex_lock(&msblk->read_data_mutex);
f1a40359f   Phillip Lougher   Squashfs: factor ...
70
71
  	stream->avail_out = 0;
  	stream->avail_in = 0;
e6a6d3795   Phillip Lougher   Squashfs: move zl...
72

e6a6d3795   Phillip Lougher   Squashfs: move zl...
73
  	do {
f1a40359f   Phillip Lougher   Squashfs: factor ...
74
  		if (stream->avail_in == 0 && k < b) {
170cf0216   Phillip Lougher   Squashfs: remove ...
75
76
  			int avail = min(length, msblk->devblksize - offset);
  			length -= avail;
e6a6d3795   Phillip Lougher   Squashfs: move zl...
77
78
79
  			wait_on_buffer(bh[k]);
  			if (!buffer_uptodate(bh[k]))
  				goto release_mutex;
f1a40359f   Phillip Lougher   Squashfs: factor ...
80
81
  			stream->next_in = bh[k]->b_data + offset;
  			stream->avail_in = avail;
e6a6d3795   Phillip Lougher   Squashfs: move zl...
82
83
  			offset = 0;
  		}
f1a40359f   Phillip Lougher   Squashfs: factor ...
84
85
86
  		if (stream->avail_out == 0 && page < pages) {
  			stream->next_out = buffer[page++];
  			stream->avail_out = PAGE_CACHE_SIZE;
e6a6d3795   Phillip Lougher   Squashfs: move zl...
87
88
89
  		}
  
  		if (!zlib_init) {
f1a40359f   Phillip Lougher   Squashfs: factor ...
90
  			zlib_err = zlib_inflateInit(stream);
e6a6d3795   Phillip Lougher   Squashfs: move zl...
91
92
93
94
95
96
97
98
99
  			if (zlib_err != Z_OK) {
  				ERROR("zlib_inflateInit returned unexpected "
  					"result 0x%x, srclength %d
  ",
  					zlib_err, srclength);
  				goto release_mutex;
  			}
  			zlib_init = 1;
  		}
f1a40359f   Phillip Lougher   Squashfs: factor ...
100
  		zlib_err = zlib_inflate(stream, Z_SYNC_FLUSH);
e6a6d3795   Phillip Lougher   Squashfs: move zl...
101

f1a40359f   Phillip Lougher   Squashfs: factor ...
102
  		if (stream->avail_in == 0 && k < b)
e6a6d3795   Phillip Lougher   Squashfs: move zl...
103
104
105
106
107
108
109
110
  			put_bh(bh[k++]);
  	} while (zlib_err == Z_OK);
  
  	if (zlib_err != Z_STREAM_END) {
  		ERROR("zlib_inflate error, data probably corrupt
  ");
  		goto release_mutex;
  	}
f1a40359f   Phillip Lougher   Squashfs: factor ...
111
  	zlib_err = zlib_inflateEnd(stream);
e6a6d3795   Phillip Lougher   Squashfs: move zl...
112
113
114
115
116
  	if (zlib_err != Z_OK) {
  		ERROR("zlib_inflate error, data probably corrupt
  ");
  		goto release_mutex;
  	}
e7ee11f0e   Phillip Lougher   Squashfs: add mis...
117
118
119
120
121
  	if (k < b) {
  		ERROR("zlib_uncompress error, data remaining
  ");
  		goto release_mutex;
  	}
792590c72   Phillip Lougher   squashfs: fix loc...
122
  	length = stream->total_out;
e6a6d3795   Phillip Lougher   Squashfs: move zl...
123
  	mutex_unlock(&msblk->read_data_mutex);
792590c72   Phillip Lougher   squashfs: fix loc...
124
  	return length;
e6a6d3795   Phillip Lougher   Squashfs: move zl...
125
126
127
128
129
130
131
132
133
  
  release_mutex:
  	mutex_unlock(&msblk->read_data_mutex);
  
  	for (; k < b; k++)
  		put_bh(bh[k]);
  
  	return -EIO;
  }
4c0f0bb23   Phillip Lougher   Squashfs: add a d...
134
135
136
137
138
139
140
141
142
  
  const struct squashfs_decompressor squashfs_zlib_comp_ops = {
  	.init = zlib_init,
  	.free = zlib_free,
  	.decompress = zlib_uncompress,
  	.id = ZLIB_COMPRESSION,
  	.name = "zlib",
  	.supported = 1
  };