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/time.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/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>
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
= 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
;
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] = NULL
;
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(*(__le32
*)(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(*(__le32
*)(bh
->b_data
+ (blockendptr
& bufmask
)));
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. */
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
);
168 if ( fpage
== xpage
)
169 err
= 0; /* The critical page */
171 page_cache_release(page
);
175 /* This data block is compressed. */
177 int bail
= 0, left_out
= -1;
179 int needblocks
= (csize
+ (cstart
& bufmask
) + bufmask
) >> bufshift
;
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
);
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
);
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
)
216 printk(KERN_DEBUG
"zisofs: zisofs_inflateInit returned %d\n",
221 while ( !bail
&& fpage
< maxpage
) {
224 stream
.next_out
= page_address(page
);
226 stream
.next_out
= (void *)&zisofs_sink_page
;
227 stream
.avail_out
= PAGE_CACHE_SIZE
;
229 while ( stream
.avail_out
) {
231 if ( stream
.avail_in
== 0 && left_out
) {
233 printk(KERN_WARNING
"zisofs: ZF read beyond end of input\n");
239 (wait_on_buffer(bh
), !buffer_uptodate(bh
)) ) {
241 printk(KERN_DEBUG
"zisofs: Hit null buffer, fpage = %d, xpage = %d, csize = %ld\n",
242 fpage
, xpage
, csize
);
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 )
257 if ( zerr
!= Z_OK
) {
258 /* EOF, error, or trying to read beyond end of input */
259 if ( err
&& zerr
== Z_MEM_ERROR
)
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
,
265 stream
.avail_in
, stream
.avail_out
,
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 */
282 flush_dcache_page(page
);
283 SetPageUptodate(page
);
286 if ( fpage
== xpage
)
287 err
= 0; /* The critical page */
289 page_cache_release(page
);
294 zlib_inflateEnd(&stream
);
297 up(&zisofs_zlib_semaphore
);
300 for ( i
= 0 ; i
< haveblocks
; i
++ ) {
308 /* Release any residual pages, do not SetPageUptodate */
309 while ( fpage
< maxpage
) {
312 flush_dcache_page(page
);
313 if ( fpage
== xpage
)
317 if ( fpage
!= xpage
)
318 page_cache_release(page
);
323 /* At this point, err contains 0 or -EIO depending on the "critical" page */
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)
338 printk("zisofs_init: called more than once\n");
342 zisofs_zlib_workspace
= vmalloc(zlib_inflate_workspacesize());
343 if ( !zisofs_zlib_workspace
)
345 init_MUTEX(&zisofs_zlib_semaphore
);
351 void zisofs_cleanup(void)
353 if ( !initialized
) {
354 printk("zisofs_cleanup: called without initialization\n");
358 vfree(zisofs_zlib_workspace
);