1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <linux/module.h>
20#include <linux/init.h>
21
22#include <linux/vmalloc.h>
23#include <linux/zlib.h>
24
25#include "isofs.h"
26#include "zisofs.h"
27
28
29static char zisofs_sink_page[PAGE_CACHE_SIZE];
30
31
32
33
34
35static void *zisofs_zlib_workspace;
36static DEFINE_MUTEX(zisofs_zlib_lock);
37
38
39
40
41
42
43static int zisofs_readpage(struct file *file, struct page *page)
44{
45 struct inode *inode = file->f_path.dentry->d_inode;
46 struct address_space *mapping = inode->i_mapping;
47 unsigned int maxpage, xpage, fpage, blockindex;
48 unsigned long offset;
49 unsigned long blockptr, blockendptr, cstart, cend, csize;
50 struct buffer_head *bh, *ptrbh[2];
51 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
52 unsigned int bufshift = ISOFS_BUFFER_BITS(inode);
53 unsigned long bufmask = bufsize - 1;
54 int err = -EIO;
55 int i;
56 unsigned int header_size = ISOFS_I(inode)->i_format_parm[0];
57 unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1];
58
59 unsigned int zisofs_block_page_shift = zisofs_block_shift-PAGE_CACHE_SHIFT;
60 unsigned long zisofs_block_pages = 1UL << zisofs_block_page_shift;
61 unsigned long zisofs_block_page_mask = zisofs_block_pages-1;
62 struct page *pages[zisofs_block_pages];
63 unsigned long index = page->index;
64 int indexblocks;
65
66
67
68 xpage = index & zisofs_block_page_mask;
69 pages[xpage] = page;
70
71
72 offset = index & ~zisofs_block_page_mask;
73 blockindex = offset >> zisofs_block_page_shift;
74 maxpage = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
75
76
77
78
79
80 if (page->index >= maxpage) {
81 SetPageUptodate(page);
82 unlock_page(page);
83 return 0;
84 }
85
86 maxpage = min(zisofs_block_pages, maxpage-offset);
87
88 for ( i = 0 ; i < maxpage ; i++, offset++ ) {
89 if ( i != xpage ) {
90 pages[i] = grab_cache_page_nowait(mapping, offset);
91 }
92 page = pages[i];
93 if ( page ) {
94 ClearPageError(page);
95 kmap(page);
96 }
97 }
98
99
100 fpage = 0;
101
102
103
104
105 blockptr = (header_size + blockindex) << 2;
106 blockendptr = blockptr + 4;
107
108 indexblocks = ((blockptr^blockendptr) >> bufshift) ? 2 : 1;
109 ptrbh[0] = ptrbh[1] = NULL;
110
111 if ( isofs_get_blocks(inode, blockptr >> bufshift, ptrbh, indexblocks) != indexblocks ) {
112 if ( ptrbh[0] ) brelse(ptrbh[0]);
113 printk(KERN_DEBUG "zisofs: Null buffer on reading block table, inode = %lu, block = %lu\n",
114 inode->i_ino, blockptr >> bufshift);
115 goto eio;
116 }
117 ll_rw_block(READ, indexblocks, ptrbh);
118
119 bh = ptrbh[0];
120 if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
121 printk(KERN_DEBUG "zisofs: Failed to read block table, inode = %lu, block = %lu\n",
122 inode->i_ino, blockptr >> bufshift);
123 if ( ptrbh[1] )
124 brelse(ptrbh[1]);
125 goto eio;
126 }
127 cstart = le32_to_cpu(*(__le32 *)(bh->b_data + (blockptr & bufmask)));
128
129 if ( indexblocks == 2 ) {
130
131 brelse(bh);
132 bh = ptrbh[1];
133 if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
134 printk(KERN_DEBUG "zisofs: Failed to read block table, inode = %lu, block = %lu\n",
135 inode->i_ino, blockendptr >> bufshift);
136 goto eio;
137 }
138 }
139 cend = le32_to_cpu(*(__le32 *)(bh->b_data + (blockendptr & bufmask)));
140 brelse(bh);
141
142 if (cstart > cend)
143 goto eio;
144
145 csize = cend-cstart;
146
147 if (csize > deflateBound(1UL << zisofs_block_shift))
148 goto eio;
149
150
151
152
153
154
155 if ( csize == 0 ) {
156
157
158 for ( fpage = 0 ; fpage < maxpage ; fpage++ ) {
159 if ( (page = pages[fpage]) != NULL ) {
160 memset(page_address(page), 0, PAGE_CACHE_SIZE);
161
162 flush_dcache_page(page);
163 SetPageUptodate(page);
164 kunmap(page);
165 unlock_page(page);
166 if ( fpage == xpage )
167 err = 0;
168 else
169 page_cache_release(page);
170 }
171 }
172 } else {
173
174 z_stream stream;
175 int bail = 0, left_out = -1;
176 int zerr;
177 int needblocks = (csize + (cstart & bufmask) + bufmask) >> bufshift;
178 int haveblocks;
179 struct buffer_head *bhs[needblocks+1];
180 struct buffer_head **bhptr;
181
182
183
184 blockptr = cstart >> bufshift;
185 memset(bhs, 0, (needblocks+1)*sizeof(struct buffer_head *));
186 haveblocks = isofs_get_blocks(inode, blockptr, bhs, needblocks);
187 ll_rw_block(READ, haveblocks, bhs);
188
189 bhptr = &bhs[0];
190 bh = *bhptr++;
191
192
193
194
195
196
197
198 if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
199 printk(KERN_DEBUG "zisofs: Hit null buffer, fpage = %d, xpage = %d, csize = %ld\n",
200 fpage, xpage, csize);
201 goto b_eio;
202 }
203 stream.next_in = bh->b_data + (cstart & bufmask);
204 stream.avail_in = min(bufsize-(cstart & bufmask), csize);
205 csize -= stream.avail_in;
206
207 stream.workspace = zisofs_zlib_workspace;
208 mutex_lock(&zisofs_zlib_lock);
209
210 zerr = zlib_inflateInit(&stream);
211 if ( zerr != Z_OK ) {
212 if ( err && zerr == Z_MEM_ERROR )
213 err = -ENOMEM;
214 printk(KERN_DEBUG "zisofs: zisofs_inflateInit returned %d\n",
215 zerr);
216 goto z_eio;
217 }
218
219 while ( !bail && fpage < maxpage ) {
220 page = pages[fpage];
221 if ( page )
222 stream.next_out = page_address(page);
223 else
224 stream.next_out = (void *)&zisofs_sink_page;
225 stream.avail_out = PAGE_CACHE_SIZE;
226
227 while ( stream.avail_out ) {
228 int ao, ai;
229 if ( stream.avail_in == 0 && left_out ) {
230 if ( !csize ) {
231 printk(KERN_WARNING "zisofs: ZF read beyond end of input\n");
232 bail = 1;
233 break;
234 } else {
235 bh = *bhptr++;
236 if ( !bh ||
237 (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
238
239 printk(KERN_DEBUG "zisofs: Hit null buffer, fpage = %d, xpage = %d, csize = %ld\n",
240 fpage, xpage, csize);
241
242 bail = 1;
243 break;
244 }
245 stream.next_in = bh->b_data;
246 stream.avail_in = min(csize,bufsize);
247 csize -= stream.avail_in;
248 }
249 }
250 ao = stream.avail_out; ai = stream.avail_in;
251 zerr = zlib_inflate(&stream, Z_SYNC_FLUSH);
252 left_out = stream.avail_out;
253 if ( zerr == Z_BUF_ERROR && stream.avail_in == 0 )
254 continue;
255 if ( zerr != Z_OK ) {
256
257 if ( err && zerr == Z_MEM_ERROR )
258 err = -ENOMEM;
259 if ( zerr != Z_STREAM_END )
260 printk(KERN_DEBUG "zisofs: zisofs_inflate returned %d, inode = %lu, index = %lu, fpage = %d, xpage = %d, avail_in = %d, avail_out = %d, ai = %d, ao = %d\n",
261 zerr, inode->i_ino, index,
262 fpage, xpage,
263 stream.avail_in, stream.avail_out,
264 ai, ao);
265 bail = 1;
266 break;
267 }
268 }
269
270 if ( stream.avail_out && zerr == Z_STREAM_END ) {
271
272
273 memset(stream.next_out, 0, stream.avail_out);
274 stream.avail_out = 0;
275 }
276
277 if ( !stream.avail_out ) {
278
279 if ( page ) {
280 flush_dcache_page(page);
281 SetPageUptodate(page);
282 kunmap(page);
283 unlock_page(page);
284 if ( fpage == xpage )
285 err = 0;
286 else
287 page_cache_release(page);
288 }
289 fpage++;
290 }
291 }
292 zlib_inflateEnd(&stream);
293
294 z_eio:
295 mutex_unlock(&zisofs_zlib_lock);
296
297 b_eio:
298 for ( i = 0 ; i < haveblocks ; i++ ) {
299 if ( bhs[i] )
300 brelse(bhs[i]);
301 }
302 }
303
304eio:
305
306
307 while ( fpage < maxpage ) {
308 page = pages[fpage];
309 if ( page ) {
310 flush_dcache_page(page);
311 if ( fpage == xpage )
312 SetPageError(page);
313 kunmap(page);
314 unlock_page(page);
315 if ( fpage != xpage )
316 page_cache_release(page);
317 }
318 fpage++;
319 }
320
321
322 return err;
323}
324
325const struct address_space_operations zisofs_aops = {
326 .readpage = zisofs_readpage,
327
328
329};
330
331int __init zisofs_init(void)
332{
333 zisofs_zlib_workspace = vmalloc(zlib_inflate_workspacesize());
334 if ( !zisofs_zlib_workspace )
335 return -ENOMEM;
336
337 return 0;
338}
339
340void zisofs_cleanup(void)
341{
342 vfree(zisofs_zlib_workspace);
343}
344