[PATCH] Fix bug in saa7146 analog tv i2c-handling
[linux-2.6/history.git] / fs / isofs / compress.c
blob8877508ea039a6c5e61df1b67804ae1169ece5bf
1 /* -*- linux-c -*- ------------------------------------------------------- *
2 *
3 * Copyright 2001 H. Peter Anvin - All Rights Reserved
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
8 * USA; either version 2 of the License, or (at your option) any later
9 * version; incorporated herein by reference.
11 * ----------------------------------------------------------------------- */
14 * linux/fs/isofs/compress.c
16 * Transparent decompression of files on an iso9660 filesystem
19 #include <linux/config.h>
20 #include <linux/module.h>
22 #include <linux/stat.h>
23 #include <linux/time.h>
24 #include <linux/iso_fs.h>
25 #include <linux/kernel.h>
26 #include <linux/major.h>
27 #include <linux/mm.h>
28 #include <linux/string.h>
29 #include <linux/slab.h>
30 #include <linux/errno.h>
31 #include <linux/cdrom.h>
32 #include <linux/init.h>
33 #include <linux/nls.h>
34 #include <linux/ctype.h>
35 #include <linux/smp_lock.h>
36 #include <linux/blkdev.h>
37 #include <linux/vmalloc.h>
38 #include <linux/zlib.h>
39 #include <linux/buffer_head.h>
41 #include <asm/system.h>
42 #include <asm/uaccess.h>
43 #include <asm/semaphore.h>
45 #include "zisofs.h"
47 /* This should probably be global. */
48 static char zisofs_sink_page[PAGE_CACHE_SIZE];
51 * This contains the zlib memory allocation and the mutex for the
52 * allocation; this avoids failures at block-decompression time.
54 static void *zisofs_zlib_workspace;
55 static struct semaphore zisofs_zlib_semaphore;
58 * When decompressing, we typically obtain more than one page
59 * per reference. We inject the additional pages into the page
60 * cache as a form of readahead.
62 static int zisofs_readpage(struct file *file, struct page *page)
64 struct inode *inode = file->f_dentry->d_inode;
65 struct address_space *mapping = inode->i_mapping;
66 unsigned int maxpage, xpage, fpage, blockindex;
67 unsigned long offset;
68 unsigned long blockptr, blockendptr, cstart, cend, csize;
69 struct buffer_head *bh, *ptrbh[2];
70 unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
71 unsigned int bufshift = ISOFS_BUFFER_BITS(inode);
72 unsigned long bufmask = bufsize - 1;
73 int err = -EIO;
74 int i;
75 unsigned int header_size = ISOFS_I(inode)->i_format_parm[0];
76 unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1];
77 /* unsigned long zisofs_block_size = 1UL << zisofs_block_shift; */
78 unsigned int zisofs_block_page_shift = zisofs_block_shift-PAGE_CACHE_SHIFT;
79 unsigned long zisofs_block_pages = 1UL << zisofs_block_page_shift;
80 unsigned long zisofs_block_page_mask = zisofs_block_pages-1;
81 struct page *pages[zisofs_block_pages];
82 unsigned long index = page->index;
83 int indexblocks;
85 /* We have already been given one page, this is the one
86 we must do. */
87 xpage = index & zisofs_block_page_mask;
88 pages[xpage] = page;
90 /* The remaining pages need to be allocated and inserted */
91 offset = index & ~zisofs_block_page_mask;
92 blockindex = offset >> zisofs_block_page_shift;
93 maxpage = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
94 maxpage = min(zisofs_block_pages, maxpage-offset);
96 for ( i = 0 ; i < maxpage ; i++, offset++ ) {
97 if ( i != xpage ) {
98 pages[i] = grab_cache_page_nowait(mapping, offset);
100 page = pages[i];
101 if ( page ) {
102 ClearPageError(page);
103 kmap(page);
107 /* This is the last page filled, plus one; used in case of abort. */
108 fpage = 0;
110 /* Find the pointer to this specific chunk */
111 /* Note: we're not using isonum_731() here because the data is known aligned */
112 /* Note: header_size is in 32-bit words (4 bytes) */
113 blockptr = (header_size + blockindex) << 2;
114 blockendptr = blockptr + 4;
116 indexblocks = ((blockptr^blockendptr) >> bufshift) ? 2 : 1;
117 ptrbh[0] = ptrbh[1] = 0;
119 if ( isofs_get_blocks(inode, blockptr >> bufshift, ptrbh, indexblocks) != indexblocks ) {
120 if ( ptrbh[0] ) brelse(ptrbh[0]);
121 printk(KERN_DEBUG "zisofs: Null buffer on reading block table, inode = %lu, block = %lu\n",
122 inode->i_ino, blockptr >> bufshift);
123 goto eio;
125 ll_rw_block(READ, indexblocks, ptrbh);
127 bh = ptrbh[0];
128 if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
129 printk(KERN_DEBUG "zisofs: Failed to read block table, inode = %lu, block = %lu\n",
130 inode->i_ino, blockptr >> bufshift);
131 if ( ptrbh[1] )
132 brelse(ptrbh[1]);
133 goto eio;
135 cstart = le32_to_cpu(*(u32 *)(bh->b_data + (blockptr & bufmask)));
137 if ( indexblocks == 2 ) {
138 /* We just crossed a block boundary. Switch to the next block */
139 brelse(bh);
140 bh = ptrbh[1];
141 if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
142 printk(KERN_DEBUG "zisofs: Failed to read block table, inode = %lu, block = %lu\n",
143 inode->i_ino, blockendptr >> bufshift);
144 goto eio;
147 cend = le32_to_cpu(*(u32 *)(bh->b_data + (blockendptr & bufmask)));
148 brelse(bh);
150 csize = cend-cstart;
152 /* Now page[] contains an array of pages, any of which can be NULL,
153 and the locks on which we hold. We should now read the data and
154 release the pages. If the pages are NULL the decompressed data
155 for that particular page should be discarded. */
157 if ( csize == 0 ) {
158 /* This data block is empty. */
160 for ( fpage = 0 ; fpage < maxpage ; fpage++ ) {
161 if ( (page = pages[fpage]) != NULL ) {
162 memset(page_address(page), 0, PAGE_CACHE_SIZE);
164 flush_dcache_page(page);
165 SetPageUptodate(page);
166 kunmap(page);
167 unlock_page(page);
168 if ( fpage == xpage )
169 err = 0; /* The critical page */
170 else
171 page_cache_release(page);
174 } else {
175 /* This data block is compressed. */
176 z_stream stream;
177 int bail = 0, left_out = -1;
178 int zerr;
179 int needblocks = (csize + (cstart & bufmask) + bufmask) >> bufshift;
180 int haveblocks;
181 struct buffer_head *bhs[needblocks+1];
182 struct buffer_head **bhptr;
184 /* Because zlib is not thread-safe, do all the I/O at the top. */
186 blockptr = cstart >> bufshift;
187 memset(bhs, 0, (needblocks+1)*sizeof(struct buffer_head *));
188 haveblocks = isofs_get_blocks(inode, blockptr, bhs, needblocks);
189 ll_rw_block(READ, haveblocks, bhs);
191 bhptr = &bhs[0];
192 bh = *bhptr++;
194 /* First block is special since it may be fractional.
195 We also wait for it before grabbing the zlib
196 semaphore; odds are that the subsequent blocks are
197 going to come in in short order so we don't hold
198 the zlib semaphore longer than necessary. */
200 if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
201 printk(KERN_DEBUG "zisofs: Hit null buffer, fpage = %d, xpage = %d, csize = %ld\n",
202 fpage, xpage, csize);
203 goto b_eio;
205 stream.next_in = bh->b_data + (cstart & bufmask);
206 stream.avail_in = min(bufsize-(cstart & bufmask), csize);
207 csize -= stream.avail_in;
209 stream.workspace = zisofs_zlib_workspace;
210 down(&zisofs_zlib_semaphore);
212 zerr = zlib_inflateInit(&stream);
213 if ( zerr != Z_OK ) {
214 if ( err && zerr == Z_MEM_ERROR )
215 err = -ENOMEM;
216 printk(KERN_DEBUG "zisofs: zisofs_inflateInit returned %d\n",
217 zerr);
218 goto z_eio;
221 while ( !bail && fpage < maxpage ) {
222 page = pages[fpage];
223 if ( page )
224 stream.next_out = page_address(page);
225 else
226 stream.next_out = (void *)&zisofs_sink_page;
227 stream.avail_out = PAGE_CACHE_SIZE;
229 while ( stream.avail_out ) {
230 int ao, ai;
231 if ( stream.avail_in == 0 && left_out ) {
232 if ( !csize ) {
233 printk(KERN_WARNING "zisofs: ZF read beyond end of input\n");
234 bail = 1;
235 break;
236 } else {
237 bh = *bhptr++;
238 if ( !bh ||
239 (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
240 /* Reached an EIO */
241 printk(KERN_DEBUG "zisofs: Hit null buffer, fpage = %d, xpage = %d, csize = %ld\n",
242 fpage, xpage, csize);
244 bail = 1;
245 break;
247 stream.next_in = bh->b_data;
248 stream.avail_in = min(csize,bufsize);
249 csize -= stream.avail_in;
252 ao = stream.avail_out; ai = stream.avail_in;
253 zerr = zlib_inflate(&stream, Z_SYNC_FLUSH);
254 left_out = stream.avail_out;
255 if ( zerr == Z_BUF_ERROR && stream.avail_in == 0 )
256 continue;
257 if ( zerr != Z_OK ) {
258 /* EOF, error, or trying to read beyond end of input */
259 if ( err && zerr == Z_MEM_ERROR )
260 err = -ENOMEM;
261 if ( zerr != Z_STREAM_END )
262 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",
263 zerr, inode->i_ino, index,
264 fpage, xpage,
265 stream.avail_in, stream.avail_out,
266 ai, ao);
267 bail = 1;
268 break;
272 if ( stream.avail_out && zerr == Z_STREAM_END ) {
273 /* Fractional page written before EOF. This may
274 be the last page in the file. */
275 memset(stream.next_out, 0, stream.avail_out);
276 stream.avail_out = 0;
279 if ( !stream.avail_out ) {
280 /* This page completed */
281 if ( page ) {
282 flush_dcache_page(page);
283 SetPageUptodate(page);
284 kunmap(page);
285 unlock_page(page);
286 if ( fpage == xpage )
287 err = 0; /* The critical page */
288 else
289 page_cache_release(page);
291 fpage++;
294 zlib_inflateEnd(&stream);
296 z_eio:
297 up(&zisofs_zlib_semaphore);
299 b_eio:
300 for ( i = 0 ; i < haveblocks ; i++ ) {
301 if ( bhs[i] )
302 brelse(bhs[i]);
306 eio:
308 /* Release any residual pages, do not SetPageUptodate */
309 while ( fpage < maxpage ) {
310 page = pages[fpage];
311 if ( page ) {
312 flush_dcache_page(page);
313 if ( fpage == xpage )
314 SetPageError(page);
315 kunmap(page);
316 unlock_page(page);
317 if ( fpage != xpage )
318 page_cache_release(page);
320 fpage++;
323 /* At this point, err contains 0 or -EIO depending on the "critical" page */
324 return err;
327 struct address_space_operations zisofs_aops = {
328 .readpage = zisofs_readpage,
329 /* No sync_page operation supported? */
330 /* No bmap operation supported */
333 static int initialized;
335 int __init zisofs_init(void)
337 if ( initialized ) {
338 printk("zisofs_init: called more than once\n");
339 return 0;
342 zisofs_zlib_workspace = vmalloc(zlib_inflate_workspacesize());
343 if ( !zisofs_zlib_workspace )
344 return -ENOMEM;
345 init_MUTEX(&zisofs_zlib_semaphore);
347 initialized = 1;
348 return 0;
351 void zisofs_cleanup(void)
353 if ( !initialized ) {
354 printk("zisofs_cleanup: called without initialization\n");
355 return;
358 vfree(zisofs_zlib_workspace);
359 initialized = 0;