]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - fs/isofs/compress.c
fs/isofs: logging clean-up
[karo-tx-linux.git] / fs / isofs / compress.c
1 /* -*- linux-c -*- ------------------------------------------------------- *
2  *   
3  *   Copyright 2001 H. Peter Anvin - All Rights Reserved
4  *
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.
10  *
11  * ----------------------------------------------------------------------- */
12
13 /*
14  * linux/fs/isofs/compress.c
15  *
16  * Transparent decompression of files on an iso9660 filesystem
17  */
18 #define DEBUG
19 #define pr_fmt(fmt) "zisofs: " fmt
20
21 #include <linux/module.h>
22 #include <linux/init.h>
23
24 #include <linux/vmalloc.h>
25 #include <linux/zlib.h>
26
27 #include "isofs.h"
28 #include "zisofs.h"
29
30 /* This should probably be global. */
31 static char zisofs_sink_page[PAGE_CACHE_SIZE];
32
33 /*
34  * This contains the zlib memory allocation and the mutex for the
35  * allocation; this avoids failures at block-decompression time.
36  */
37 static void *zisofs_zlib_workspace;
38 static DEFINE_MUTEX(zisofs_zlib_lock);
39
40 /*
41  * Read data of @inode from @block_start to @block_end and uncompress
42  * to one zisofs block. Store the data in the @pages array with @pcount
43  * entries. Start storing at offset @poffset of the first page.
44  */
45 static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
46                                       loff_t block_end, int pcount,
47                                       struct page **pages, unsigned poffset,
48                                       int *errp)
49 {
50         unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1];
51         unsigned int bufsize = ISOFS_BUFFER_SIZE(inode);
52         unsigned int bufshift = ISOFS_BUFFER_BITS(inode);
53         unsigned int bufmask = bufsize - 1;
54         int i, block_size = block_end - block_start;
55         z_stream stream = { .total_out = 0,
56                             .avail_in = 0,
57                             .avail_out = 0, };
58         int zerr;
59         int needblocks = (block_size + (block_start & bufmask) + bufmask)
60                                 >> bufshift;
61         int haveblocks;
62         blkcnt_t blocknum;
63         struct buffer_head *bhs[needblocks + 1];
64         int curbh, curpage;
65
66         if (block_size > deflateBound(1UL << zisofs_block_shift)) {
67                 *errp = -EIO;
68                 return 0;
69         }
70         /* Empty block? */
71         if (block_size == 0) {
72                 for ( i = 0 ; i < pcount ; i++ ) {
73                         if (!pages[i])
74                                 continue;
75                         memset(page_address(pages[i]), 0, PAGE_CACHE_SIZE);
76                         flush_dcache_page(pages[i]);
77                         SetPageUptodate(pages[i]);
78                 }
79                 return ((loff_t)pcount) << PAGE_CACHE_SHIFT;
80         }
81
82         /* Because zlib is not thread-safe, do all the I/O at the top. */
83         blocknum = block_start >> bufshift;
84         memset(bhs, 0, (needblocks + 1) * sizeof(struct buffer_head *));
85         haveblocks = isofs_get_blocks(inode, blocknum, bhs, needblocks);
86         ll_rw_block(READ, haveblocks, bhs);
87
88         curbh = 0;
89         curpage = 0;
90         /*
91          * First block is special since it may be fractional.  We also wait for
92          * it before grabbing the zlib mutex; odds are that the subsequent
93          * blocks are going to come in in short order so we don't hold the zlib
94          * mutex longer than necessary.
95          */
96
97         if (!bhs[0])
98                 goto b_eio;
99
100         wait_on_buffer(bhs[0]);
101         if (!buffer_uptodate(bhs[0])) {
102                 *errp = -EIO;
103                 goto b_eio;
104         }
105
106         stream.workspace = zisofs_zlib_workspace;
107         mutex_lock(&zisofs_zlib_lock);
108                 
109         zerr = zlib_inflateInit(&stream);
110         if (zerr != Z_OK) {
111                 if (zerr == Z_MEM_ERROR)
112                         *errp = -ENOMEM;
113                 else
114                         *errp = -EIO;
115                 pr_debug("zisofs_inflateInit returned %d\n",
116                                zerr);
117                 goto z_eio;
118         }
119
120         while (curpage < pcount && curbh < haveblocks &&
121                zerr != Z_STREAM_END) {
122                 if (!stream.avail_out) {
123                         if (pages[curpage]) {
124                                 stream.next_out = page_address(pages[curpage])
125                                                 + poffset;
126                                 stream.avail_out = PAGE_CACHE_SIZE - poffset;
127                                 poffset = 0;
128                         } else {
129                                 stream.next_out = (void *)&zisofs_sink_page;
130                                 stream.avail_out = PAGE_CACHE_SIZE;
131                         }
132                 }
133                 if (!stream.avail_in) {
134                         wait_on_buffer(bhs[curbh]);
135                         if (!buffer_uptodate(bhs[curbh])) {
136                                 *errp = -EIO;
137                                 break;
138                         }
139                         stream.next_in  = bhs[curbh]->b_data +
140                                                 (block_start & bufmask);
141                         stream.avail_in = min_t(unsigned, bufsize -
142                                                 (block_start & bufmask),
143                                                 block_size);
144                         block_size -= stream.avail_in;
145                         block_start = 0;
146                 }
147
148                 while (stream.avail_out && stream.avail_in) {
149                         zerr = zlib_inflate(&stream, Z_SYNC_FLUSH);
150                         if (zerr == Z_BUF_ERROR && stream.avail_in == 0)
151                                 break;
152                         if (zerr == Z_STREAM_END)
153                                 break;
154                         if (zerr != Z_OK) {
155                                 /* EOF, error, or trying to read beyond end of input */
156                                 if (zerr == Z_MEM_ERROR)
157                                         *errp = -ENOMEM;
158                                 else {
159                                         pr_debug("zisofs_inflate returned %d, inode = %lu, page idx = %d, bh idx = %d, avail_in = %d, avail_out = %d\n",
160                                                  zerr, inode->i_ino, curpage,
161                                                  curbh, stream.avail_in,
162                                                  stream.avail_out);
163                                         *errp = -EIO;
164                                 }
165                                 goto inflate_out;
166                         }
167                 }
168
169                 if (!stream.avail_out) {
170                         /* This page completed */
171                         if (pages[curpage]) {
172                                 flush_dcache_page(pages[curpage]);
173                                 SetPageUptodate(pages[curpage]);
174                         }
175                         curpage++;
176                 }
177                 if (!stream.avail_in)
178                         curbh++;
179         }
180 inflate_out:
181         zlib_inflateEnd(&stream);
182
183 z_eio:
184         mutex_unlock(&zisofs_zlib_lock);
185
186 b_eio:
187         for (i = 0; i < haveblocks; i++)
188                 brelse(bhs[i]);
189         return stream.total_out;
190 }
191
192 /*
193  * Uncompress data so that pages[full_page] is fully uptodate and possibly
194  * fills in other pages if we have data for them.
195  */
196 static int zisofs_fill_pages(struct inode *inode, int full_page, int pcount,
197                              struct page **pages)
198 {
199         loff_t start_off, end_off;
200         loff_t block_start, block_end;
201         unsigned int header_size = ISOFS_I(inode)->i_format_parm[0];
202         unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1];
203         unsigned int blockptr;
204         loff_t poffset = 0;
205         blkcnt_t cstart_block, cend_block;
206         struct buffer_head *bh;
207         unsigned int blkbits = ISOFS_BUFFER_BITS(inode);
208         unsigned int blksize = 1 << blkbits;
209         int err;
210         loff_t ret;
211
212         BUG_ON(!pages[full_page]);
213
214         /*
215          * We want to read at least 'full_page' page. Because we have to
216          * uncompress the whole compression block anyway, fill the surrounding
217          * pages with the data we have anyway...
218          */
219         start_off = page_offset(pages[full_page]);
220         end_off = min_t(loff_t, start_off + PAGE_CACHE_SIZE, inode->i_size);
221
222         cstart_block = start_off >> zisofs_block_shift;
223         cend_block = (end_off + (1 << zisofs_block_shift) - 1)
224                         >> zisofs_block_shift;
225
226         WARN_ON(start_off - (full_page << PAGE_CACHE_SHIFT) !=
227                 ((cstart_block << zisofs_block_shift) & PAGE_CACHE_MASK));
228
229         /* Find the pointer to this specific chunk */
230         /* Note: we're not using isonum_731() here because the data is known aligned */
231         /* Note: header_size is in 32-bit words (4 bytes) */
232         blockptr = (header_size + cstart_block) << 2;
233         bh = isofs_bread(inode, blockptr >> blkbits);
234         if (!bh)
235                 return -EIO;
236         block_start = le32_to_cpu(*(__le32 *)
237                                 (bh->b_data + (blockptr & (blksize - 1))));
238
239         while (cstart_block < cend_block && pcount > 0) {
240                 /* Load end of the compressed block in the file */
241                 blockptr += 4;
242                 /* Traversed to next block? */
243                 if (!(blockptr & (blksize - 1))) {
244                         brelse(bh);
245
246                         bh = isofs_bread(inode, blockptr >> blkbits);
247                         if (!bh)
248                                 return -EIO;
249                 }
250                 block_end = le32_to_cpu(*(__le32 *)
251                                 (bh->b_data + (blockptr & (blksize - 1))));
252                 if (block_start > block_end) {
253                         brelse(bh);
254                         return -EIO;
255                 }
256                 err = 0;
257                 ret = zisofs_uncompress_block(inode, block_start, block_end,
258                                               pcount, pages, poffset, &err);
259                 poffset += ret;
260                 pages += poffset >> PAGE_CACHE_SHIFT;
261                 pcount -= poffset >> PAGE_CACHE_SHIFT;
262                 full_page -= poffset >> PAGE_CACHE_SHIFT;
263                 poffset &= ~PAGE_CACHE_MASK;
264
265                 if (err) {
266                         brelse(bh);
267                         /*
268                          * Did we finish reading the page we really wanted
269                          * to read?
270                          */
271                         if (full_page < 0)
272                                 return 0;
273                         return err;
274                 }
275
276                 block_start = block_end;
277                 cstart_block++;
278         }
279
280         if (poffset && *pages) {
281                 memset(page_address(*pages) + poffset, 0,
282                        PAGE_CACHE_SIZE - poffset);
283                 flush_dcache_page(*pages);
284                 SetPageUptodate(*pages);
285         }
286         return 0;
287 }
288
289 /*
290  * When decompressing, we typically obtain more than one page
291  * per reference.  We inject the additional pages into the page
292  * cache as a form of readahead.
293  */
294 static int zisofs_readpage(struct file *file, struct page *page)
295 {
296         struct inode *inode = file_inode(file);
297         struct address_space *mapping = inode->i_mapping;
298         int err;
299         int i, pcount, full_page;
300         unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1];
301         unsigned int zisofs_pages_per_cblock =
302                 PAGE_CACHE_SHIFT <= zisofs_block_shift ?
303                 (1 << (zisofs_block_shift - PAGE_CACHE_SHIFT)) : 0;
304         struct page *pages[max_t(unsigned, zisofs_pages_per_cblock, 1)];
305         pgoff_t index = page->index, end_index;
306
307         end_index = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
308         /*
309          * If this page is wholly outside i_size we just return zero;
310          * do_generic_file_read() will handle this for us
311          */
312         if (index >= end_index) {
313                 SetPageUptodate(page);
314                 unlock_page(page);
315                 return 0;
316         }
317
318         if (PAGE_CACHE_SHIFT <= zisofs_block_shift) {
319                 /* We have already been given one page, this is the one
320                    we must do. */
321                 full_page = index & (zisofs_pages_per_cblock - 1);
322                 pcount = min_t(int, zisofs_pages_per_cblock,
323                         end_index - (index & ~(zisofs_pages_per_cblock - 1)));
324                 index -= full_page;
325         } else {
326                 full_page = 0;
327                 pcount = 1;
328         }
329         pages[full_page] = page;
330
331         for (i = 0; i < pcount; i++, index++) {
332                 if (i != full_page)
333                         pages[i] = grab_cache_page_nowait(mapping, index);
334                 if (pages[i]) {
335                         ClearPageError(pages[i]);
336                         kmap(pages[i]);
337                 }
338         }
339
340         err = zisofs_fill_pages(inode, full_page, pcount, pages);
341
342         /* Release any residual pages, do not SetPageUptodate */
343         for (i = 0; i < pcount; i++) {
344                 if (pages[i]) {
345                         flush_dcache_page(pages[i]);
346                         if (i == full_page && err)
347                                 SetPageError(pages[i]);
348                         kunmap(pages[i]);
349                         unlock_page(pages[i]);
350                         if (i != full_page)
351                                 page_cache_release(pages[i]);
352                 }
353         }                       
354
355         /* At this point, err contains 0 or -EIO depending on the "critical" page */
356         return err;
357 }
358
359 const struct address_space_operations zisofs_aops = {
360         .readpage = zisofs_readpage,
361         /* No sync_page operation supported? */
362         /* No bmap operation supported */
363 };
364
365 int __init zisofs_init(void)
366 {
367         zisofs_zlib_workspace = vmalloc(zlib_inflate_workspacesize());
368         if ( !zisofs_zlib_workspace )
369                 return -ENOMEM;
370
371         return 0;
372 }
373
374 void zisofs_cleanup(void)
375 {
376         vfree(zisofs_zlib_workspace);
377 }