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