1 /* -*- linux-c -*- ------------------------------------------------------- *
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/sched.h>
24 #include <linux/iso_fs.h>
25 #include <linux/kernel.h>
26 #include <linux/major.h>
28 #include <linux/string.h>
29 #include <linux/locks.h>
30 #include <linux/slab.h>
31 #include <linux/errno.h>
32 #include <linux/cdrom.h>
33 #include <linux/init.h>
34 #include <linux/nls.h>
35 #include <linux/ctype.h>
36 #include <linux/smp_lock.h>
37 #include <linux/blkdev.h>
38 #include <linux/vmalloc.h>
39 #include <linux/zlib.h>
41 #include <asm/system.h>
42 #include <asm/uaccess.h>
43 #include <asm/semaphore.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;
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;
75 unsigned int header_size = inode->u.isofs_i.i_format_parm[0];
76 unsigned int zisofs_block_shift = inode->u.isofs_i.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;
85 /* We have already been given one page, this is the one
87 xpage = index & zisofs_block_page_mask;
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++ ) {
98 pages[i] = grab_cache_page_nowait(mapping, offset);
102 ClearPageError(page);
107 /* This is the last page filled, plus one; used in case of abort. */
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);
125 ll_rw_block(READ, indexblocks, ptrbh);
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);
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 */
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);
147 cend = le32_to_cpu(*(u32 *)(bh->b_data + (blockendptr & bufmask)));
155 if (csize > deflateBound(1UL << zisofs_block_shift))
158 /* Now page[] contains an array of pages, any of which can be NULL,
159 and the locks on which we hold. We should now read the data and
160 release the pages. If the pages are NULL the decompressed data
161 for that particular page should be discarded. */
164 /* This data block is empty. */
166 for ( fpage = 0 ; fpage < maxpage ; fpage++ ) {
167 if ( (page = pages[fpage]) != NULL ) {
168 memset(page_address(page), 0, PAGE_CACHE_SIZE);
170 flush_dcache_page(page);
171 SetPageUptodate(page);
174 if ( fpage == xpage )
175 err = 0; /* The critical page */
177 page_cache_release(page);
181 /* This data block is compressed. */
183 int bail = 0, left_out = -1;
185 int needblocks = (csize + (cstart & bufmask) + bufmask) >> bufshift;
187 struct buffer_head *bhs[needblocks+1];
188 struct buffer_head **bhptr;
190 /* Because zlib is not thread-safe, do all the I/O at the top. */
192 blockptr = cstart >> bufshift;
193 memset(bhs, 0, (needblocks+1)*sizeof(struct buffer_head *));
194 haveblocks = isofs_get_blocks(inode, blockptr, bhs, needblocks);
195 ll_rw_block(READ, haveblocks, bhs);
200 /* First block is special since it may be fractional.
201 We also wait for it before grabbing the zlib
202 semaphore; odds are that the subsequent blocks are
203 going to come in in short order so we don't hold
204 the zlib semaphore longer than necessary. */
206 if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
207 printk(KERN_DEBUG "zisofs: Hit null buffer, fpage = %d, xpage = %d, csize = %ld\n",
208 fpage, xpage, csize);
211 stream.next_in = bh->b_data + (cstart & bufmask);
212 stream.avail_in = min(bufsize-(cstart & bufmask), csize);
213 csize -= stream.avail_in;
215 stream.workspace = zisofs_zlib_workspace;
216 down(&zisofs_zlib_semaphore);
218 zerr = zlib_inflateInit(&stream);
219 if ( zerr != Z_OK ) {
220 if ( err && zerr == Z_MEM_ERROR )
222 printk(KERN_DEBUG "zisofs: zisofs_inflateInit returned %d\n",
227 while ( !bail && fpage < maxpage ) {
230 stream.next_out = page_address(page);
232 stream.next_out = (void *)&zisofs_sink_page;
233 stream.avail_out = PAGE_CACHE_SIZE;
235 while ( stream.avail_out ) {
237 if ( stream.avail_in == 0 && left_out ) {
239 printk(KERN_WARNING "zisofs: ZF read beyond end of input\n");
245 (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
247 printk(KERN_DEBUG "zisofs: Hit null buffer, fpage = %d, xpage = %d, csize = %ld\n",
248 fpage, xpage, csize);
253 stream.next_in = bh->b_data;
254 stream.avail_in = min(csize,bufsize);
255 csize -= stream.avail_in;
258 ao = stream.avail_out; ai = stream.avail_in;
259 zerr = zlib_inflate(&stream, Z_SYNC_FLUSH);
260 left_out = stream.avail_out;
261 if ( zerr == Z_BUF_ERROR && stream.avail_in == 0 )
263 if ( zerr != Z_OK ) {
264 /* EOF, error, or trying to read beyond end of input */
265 if ( err && zerr == Z_MEM_ERROR )
267 if ( zerr != Z_STREAM_END )
268 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",
269 zerr, inode->i_ino, index,
271 stream.avail_in, stream.avail_out,
278 if ( stream.avail_out && zerr == Z_STREAM_END ) {
279 /* Fractional page written before EOF. This may
280 be the last page in the file. */
281 memset(stream.next_out, 0, stream.avail_out);
282 stream.avail_out = 0;
285 if ( !stream.avail_out ) {
286 /* This page completed */
288 flush_dcache_page(page);
289 SetPageUptodate(page);
292 if ( fpage == xpage )
293 err = 0; /* The critical page */
295 page_cache_release(page);
300 zlib_inflateEnd(&stream);
303 up(&zisofs_zlib_semaphore);
306 for ( i = 0 ; i < haveblocks ; i++ ) {
314 /* Release any residual pages, do not SetPageUptodate */
315 while ( fpage < maxpage ) {
318 flush_dcache_page(page);
319 if ( fpage == xpage )
323 if ( fpage != xpage )
324 page_cache_release(page);
329 /* At this point, err contains 0 or -EIO depending on the "critical" page */
333 struct address_space_operations zisofs_aops = {
334 readpage: zisofs_readpage,
335 /* No sync_page operation supported? */
336 /* No bmap operation supported */
339 static int initialized = 0;
341 int __init zisofs_init(void)
344 printk("zisofs_init: called more than once\n");
348 zisofs_zlib_workspace = vmalloc(zlib_inflate_workspacesize());
349 if ( !zisofs_zlib_workspace )
351 init_MUTEX(&zisofs_zlib_semaphore);
357 void __exit zisofs_cleanup(void)
359 if ( !initialized ) {
360 printk("zisofs_cleanup: called without initialization\n");
364 vfree(zisofs_zlib_workspace);