xref: /openbmc/linux/fs/isofs/compress.c (revision 5bb6ce3a)
1a94da204SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /* -*- linux-c -*- ------------------------------------------------------- *
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  *   Copyright 2001 H. Peter Anvin - All Rights Reserved
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * ----------------------------------------------------------------------- */
71da177e4SLinus Torvalds 
81da177e4SLinus Torvalds /*
91da177e4SLinus Torvalds  * linux/fs/isofs/compress.c
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  * Transparent decompression of files on an iso9660 filesystem
121da177e4SLinus Torvalds  */
131da177e4SLinus Torvalds 
141da177e4SLinus Torvalds #include <linux/module.h>
151da177e4SLinus Torvalds #include <linux/init.h>
162f8b5444SChristoph Hellwig #include <linux/bio.h>
1794f2f715SAl Viro 
185ac7c2fdSKyle Spiers #include <linux/slab.h>
191da177e4SLinus Torvalds #include <linux/vmalloc.h>
201da177e4SLinus Torvalds #include <linux/zlib.h>
211da177e4SLinus Torvalds 
2294f2f715SAl Viro #include "isofs.h"
231da177e4SLinus Torvalds #include "zisofs.h"
241da177e4SLinus Torvalds 
251da177e4SLinus Torvalds /* This should probably be global. */
2609cbfeafSKirill A. Shutemov static char zisofs_sink_page[PAGE_SIZE];
271da177e4SLinus Torvalds 
281da177e4SLinus Torvalds /*
291da177e4SLinus Torvalds  * This contains the zlib memory allocation and the mutex for the
301da177e4SLinus Torvalds  * allocation; this avoids failures at block-decompression time.
311da177e4SLinus Torvalds  */
321da177e4SLinus Torvalds static void *zisofs_zlib_workspace;
33a36a151eSDave Young static DEFINE_MUTEX(zisofs_zlib_lock);
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds /*
3659bc0552SJan Kara  * Read data of @inode from @block_start to @block_end and uncompress
3759bc0552SJan Kara  * to one zisofs block. Store the data in the @pages array with @pcount
3859bc0552SJan Kara  * entries. Start storing at offset @poffset of the first page.
3959bc0552SJan Kara  */
zisofs_uncompress_block(struct inode * inode,loff_t block_start,loff_t block_end,int pcount,struct page ** pages,unsigned poffset,int * errp)4059bc0552SJan Kara static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
4159bc0552SJan Kara 				      loff_t block_end, int pcount,
4259bc0552SJan Kara 				      struct page **pages, unsigned poffset,
4359bc0552SJan Kara 				      int *errp)
4459bc0552SJan Kara {
4559bc0552SJan Kara 	unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1];
4659bc0552SJan Kara 	unsigned int bufsize = ISOFS_BUFFER_SIZE(inode);
4759bc0552SJan Kara 	unsigned int bufshift = ISOFS_BUFFER_BITS(inode);
4859bc0552SJan Kara 	unsigned int bufmask = bufsize - 1;
4959bc0552SJan Kara 	int i, block_size = block_end - block_start;
5059bc0552SJan Kara 	z_stream stream = { .total_out = 0,
5159bc0552SJan Kara 			    .avail_in = 0,
5259bc0552SJan Kara 			    .avail_out = 0, };
5359bc0552SJan Kara 	int zerr;
5459bc0552SJan Kara 	int needblocks = (block_size + (block_start & bufmask) + bufmask)
5559bc0552SJan Kara 				>> bufshift;
5659bc0552SJan Kara 	int haveblocks;
5759bc0552SJan Kara 	blkcnt_t blocknum;
585ac7c2fdSKyle Spiers 	struct buffer_head **bhs;
5959bc0552SJan Kara 	int curbh, curpage;
6059bc0552SJan Kara 
6159bc0552SJan Kara 	if (block_size > deflateBound(1UL << zisofs_block_shift)) {
6259bc0552SJan Kara 		*errp = -EIO;
6359bc0552SJan Kara 		return 0;
6459bc0552SJan Kara 	}
6559bc0552SJan Kara 	/* Empty block? */
6659bc0552SJan Kara 	if (block_size == 0) {
6759bc0552SJan Kara 		for ( i = 0 ; i < pcount ; i++ ) {
6859bc0552SJan Kara 			if (!pages[i])
6959bc0552SJan Kara 				continue;
70*5bb6ce3aSFabio M. De Francesco 			memzero_page(pages[i], 0, PAGE_SIZE);
7159bc0552SJan Kara 			SetPageUptodate(pages[i]);
7259bc0552SJan Kara 		}
7309cbfeafSKirill A. Shutemov 		return ((loff_t)pcount) << PAGE_SHIFT;
7459bc0552SJan Kara 	}
7559bc0552SJan Kara 
7659bc0552SJan Kara 	/* Because zlib is not thread-safe, do all the I/O at the top. */
7759bc0552SJan Kara 	blocknum = block_start >> bufshift;
785ac7c2fdSKyle Spiers 	bhs = kcalloc(needblocks + 1, sizeof(*bhs), GFP_KERNEL);
795ac7c2fdSKyle Spiers 	if (!bhs) {
805ac7c2fdSKyle Spiers 		*errp = -ENOMEM;
815ac7c2fdSKyle Spiers 		return 0;
825ac7c2fdSKyle Spiers 	}
8359bc0552SJan Kara 	haveblocks = isofs_get_blocks(inode, blocknum, bhs, needblocks);
841420c4a5SBart Van Assche 	bh_read_batch(haveblocks, bhs);
8559bc0552SJan Kara 
8659bc0552SJan Kara 	curbh = 0;
8759bc0552SJan Kara 	curpage = 0;
8859bc0552SJan Kara 	/*
8959bc0552SJan Kara 	 * First block is special since it may be fractional.  We also wait for
9059bc0552SJan Kara 	 * it before grabbing the zlib mutex; odds are that the subsequent
9159bc0552SJan Kara 	 * blocks are going to come in in short order so we don't hold the zlib
9259bc0552SJan Kara 	 * mutex longer than necessary.
9359bc0552SJan Kara 	 */
9459bc0552SJan Kara 
9559bc0552SJan Kara 	if (!bhs[0])
9659bc0552SJan Kara 		goto b_eio;
9759bc0552SJan Kara 
9859bc0552SJan Kara 	wait_on_buffer(bhs[0]);
9959bc0552SJan Kara 	if (!buffer_uptodate(bhs[0])) {
10059bc0552SJan Kara 		*errp = -EIO;
10159bc0552SJan Kara 		goto b_eio;
10259bc0552SJan Kara 	}
10359bc0552SJan Kara 
10459bc0552SJan Kara 	stream.workspace = zisofs_zlib_workspace;
10559bc0552SJan Kara 	mutex_lock(&zisofs_zlib_lock);
10659bc0552SJan Kara 
10759bc0552SJan Kara 	zerr = zlib_inflateInit(&stream);
10859bc0552SJan Kara 	if (zerr != Z_OK) {
10959bc0552SJan Kara 		if (zerr == Z_MEM_ERROR)
11059bc0552SJan Kara 			*errp = -ENOMEM;
11159bc0552SJan Kara 		else
11259bc0552SJan Kara 			*errp = -EIO;
11359bc0552SJan Kara 		printk(KERN_DEBUG "zisofs: zisofs_inflateInit returned %d\n",
11459bc0552SJan Kara 			       zerr);
11559bc0552SJan Kara 		goto z_eio;
11659bc0552SJan Kara 	}
11759bc0552SJan Kara 
11859bc0552SJan Kara 	while (curpage < pcount && curbh < haveblocks &&
11959bc0552SJan Kara 	       zerr != Z_STREAM_END) {
12059bc0552SJan Kara 		if (!stream.avail_out) {
12159bc0552SJan Kara 			if (pages[curpage]) {
122*5bb6ce3aSFabio M. De Francesco 				stream.next_out = kmap_local_page(pages[curpage])
12359bc0552SJan Kara 						+ poffset;
12409cbfeafSKirill A. Shutemov 				stream.avail_out = PAGE_SIZE - poffset;
12559bc0552SJan Kara 				poffset = 0;
12659bc0552SJan Kara 			} else {
12759bc0552SJan Kara 				stream.next_out = (void *)&zisofs_sink_page;
12809cbfeafSKirill A. Shutemov 				stream.avail_out = PAGE_SIZE;
12959bc0552SJan Kara 			}
13059bc0552SJan Kara 		}
13159bc0552SJan Kara 		if (!stream.avail_in) {
13259bc0552SJan Kara 			wait_on_buffer(bhs[curbh]);
13359bc0552SJan Kara 			if (!buffer_uptodate(bhs[curbh])) {
13459bc0552SJan Kara 				*errp = -EIO;
13559bc0552SJan Kara 				break;
13659bc0552SJan Kara 			}
13759bc0552SJan Kara 			stream.next_in  = bhs[curbh]->b_data +
13859bc0552SJan Kara 						(block_start & bufmask);
13959bc0552SJan Kara 			stream.avail_in = min_t(unsigned, bufsize -
14059bc0552SJan Kara 						(block_start & bufmask),
14159bc0552SJan Kara 						block_size);
14259bc0552SJan Kara 			block_size -= stream.avail_in;
14359bc0552SJan Kara 			block_start = 0;
14459bc0552SJan Kara 		}
14559bc0552SJan Kara 
14659bc0552SJan Kara 		while (stream.avail_out && stream.avail_in) {
14759bc0552SJan Kara 			zerr = zlib_inflate(&stream, Z_SYNC_FLUSH);
14859bc0552SJan Kara 			if (zerr == Z_BUF_ERROR && stream.avail_in == 0)
14959bc0552SJan Kara 				break;
15059bc0552SJan Kara 			if (zerr == Z_STREAM_END)
15159bc0552SJan Kara 				break;
15259bc0552SJan Kara 			if (zerr != Z_OK) {
15359bc0552SJan Kara 				/* EOF, error, or trying to read beyond end of input */
15459bc0552SJan Kara 				if (zerr == Z_MEM_ERROR)
15559bc0552SJan Kara 					*errp = -ENOMEM;
15659bc0552SJan Kara 				else {
15759bc0552SJan Kara 					printk(KERN_DEBUG
15859bc0552SJan Kara 					       "zisofs: zisofs_inflate returned"
15959bc0552SJan Kara 					       " %d, inode = %lu,"
16059bc0552SJan Kara 					       " page idx = %d, bh idx = %d,"
161d97b07c5SYinghai Lu 					       " avail_in = %ld,"
162d97b07c5SYinghai Lu 					       " avail_out = %ld\n",
16359bc0552SJan Kara 					       zerr, inode->i_ino, curpage,
16459bc0552SJan Kara 					       curbh, stream.avail_in,
16559bc0552SJan Kara 					       stream.avail_out);
16659bc0552SJan Kara 					*errp = -EIO;
16759bc0552SJan Kara 				}
16859bc0552SJan Kara 				goto inflate_out;
16959bc0552SJan Kara 			}
17059bc0552SJan Kara 		}
17159bc0552SJan Kara 
17259bc0552SJan Kara 		if (!stream.avail_out) {
17359bc0552SJan Kara 			/* This page completed */
17459bc0552SJan Kara 			if (pages[curpage]) {
17559bc0552SJan Kara 				flush_dcache_page(pages[curpage]);
17659bc0552SJan Kara 				SetPageUptodate(pages[curpage]);
17759bc0552SJan Kara 			}
178*5bb6ce3aSFabio M. De Francesco 			if (stream.next_out != (unsigned char *)zisofs_sink_page) {
179*5bb6ce3aSFabio M. De Francesco 				kunmap_local(stream.next_out);
180*5bb6ce3aSFabio M. De Francesco 				stream.next_out = NULL;
181*5bb6ce3aSFabio M. De Francesco 			}
18259bc0552SJan Kara 			curpage++;
18359bc0552SJan Kara 		}
18459bc0552SJan Kara 		if (!stream.avail_in)
18559bc0552SJan Kara 			curbh++;
18659bc0552SJan Kara 	}
18759bc0552SJan Kara inflate_out:
18859bc0552SJan Kara 	zlib_inflateEnd(&stream);
189*5bb6ce3aSFabio M. De Francesco 	if (stream.next_out && stream.next_out != (unsigned char *)zisofs_sink_page)
190*5bb6ce3aSFabio M. De Francesco 		kunmap_local(stream.next_out);
19159bc0552SJan Kara 
19259bc0552SJan Kara z_eio:
19359bc0552SJan Kara 	mutex_unlock(&zisofs_zlib_lock);
19459bc0552SJan Kara 
19559bc0552SJan Kara b_eio:
19659bc0552SJan Kara 	for (i = 0; i < haveblocks; i++)
19759bc0552SJan Kara 		brelse(bhs[i]);
1985ac7c2fdSKyle Spiers 	kfree(bhs);
19959bc0552SJan Kara 	return stream.total_out;
20059bc0552SJan Kara }
20159bc0552SJan Kara 
20259bc0552SJan Kara /*
20359bc0552SJan Kara  * Uncompress data so that pages[full_page] is fully uptodate and possibly
20459bc0552SJan Kara  * fills in other pages if we have data for them.
20559bc0552SJan Kara  */
zisofs_fill_pages(struct inode * inode,int full_page,int pcount,struct page ** pages)20659bc0552SJan Kara static int zisofs_fill_pages(struct inode *inode, int full_page, int pcount,
20759bc0552SJan Kara 			     struct page **pages)
20859bc0552SJan Kara {
20959bc0552SJan Kara 	loff_t start_off, end_off;
21059bc0552SJan Kara 	loff_t block_start, block_end;
21159bc0552SJan Kara 	unsigned int header_size = ISOFS_I(inode)->i_format_parm[0];
21259bc0552SJan Kara 	unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1];
21359bc0552SJan Kara 	unsigned int blockptr;
21459bc0552SJan Kara 	loff_t poffset = 0;
21559bc0552SJan Kara 	blkcnt_t cstart_block, cend_block;
21659bc0552SJan Kara 	struct buffer_head *bh;
21759bc0552SJan Kara 	unsigned int blkbits = ISOFS_BUFFER_BITS(inode);
21859bc0552SJan Kara 	unsigned int blksize = 1 << blkbits;
21959bc0552SJan Kara 	int err;
22059bc0552SJan Kara 	loff_t ret;
22159bc0552SJan Kara 
22259bc0552SJan Kara 	BUG_ON(!pages[full_page]);
22359bc0552SJan Kara 
22459bc0552SJan Kara 	/*
22559bc0552SJan Kara 	 * We want to read at least 'full_page' page. Because we have to
22659bc0552SJan Kara 	 * uncompress the whole compression block anyway, fill the surrounding
22759bc0552SJan Kara 	 * pages with the data we have anyway...
22859bc0552SJan Kara 	 */
22959bc0552SJan Kara 	start_off = page_offset(pages[full_page]);
23009cbfeafSKirill A. Shutemov 	end_off = min_t(loff_t, start_off + PAGE_SIZE, inode->i_size);
23159bc0552SJan Kara 
23259bc0552SJan Kara 	cstart_block = start_off >> zisofs_block_shift;
23359bc0552SJan Kara 	cend_block = (end_off + (1 << zisofs_block_shift) - 1)
23459bc0552SJan Kara 			>> zisofs_block_shift;
23559bc0552SJan Kara 
23609cbfeafSKirill A. Shutemov 	WARN_ON(start_off - (full_page << PAGE_SHIFT) !=
23709cbfeafSKirill A. Shutemov 		((cstart_block << zisofs_block_shift) & PAGE_MASK));
23859bc0552SJan Kara 
23959bc0552SJan Kara 	/* Find the pointer to this specific chunk */
24059bc0552SJan Kara 	/* Note: we're not using isonum_731() here because the data is known aligned */
24159bc0552SJan Kara 	/* Note: header_size is in 32-bit words (4 bytes) */
24259bc0552SJan Kara 	blockptr = (header_size + cstart_block) << 2;
24359bc0552SJan Kara 	bh = isofs_bread(inode, blockptr >> blkbits);
24459bc0552SJan Kara 	if (!bh)
24559bc0552SJan Kara 		return -EIO;
24659bc0552SJan Kara 	block_start = le32_to_cpu(*(__le32 *)
24759bc0552SJan Kara 				(bh->b_data + (blockptr & (blksize - 1))));
24859bc0552SJan Kara 
24959bc0552SJan Kara 	while (cstart_block < cend_block && pcount > 0) {
25059bc0552SJan Kara 		/* Load end of the compressed block in the file */
25159bc0552SJan Kara 		blockptr += 4;
25259bc0552SJan Kara 		/* Traversed to next block? */
25359bc0552SJan Kara 		if (!(blockptr & (blksize - 1))) {
25459bc0552SJan Kara 			brelse(bh);
25559bc0552SJan Kara 
25659bc0552SJan Kara 			bh = isofs_bread(inode, blockptr >> blkbits);
25759bc0552SJan Kara 			if (!bh)
25859bc0552SJan Kara 				return -EIO;
25959bc0552SJan Kara 		}
26059bc0552SJan Kara 		block_end = le32_to_cpu(*(__le32 *)
26159bc0552SJan Kara 				(bh->b_data + (blockptr & (blksize - 1))));
26259bc0552SJan Kara 		if (block_start > block_end) {
26359bc0552SJan Kara 			brelse(bh);
26459bc0552SJan Kara 			return -EIO;
26559bc0552SJan Kara 		}
26659bc0552SJan Kara 		err = 0;
26759bc0552SJan Kara 		ret = zisofs_uncompress_block(inode, block_start, block_end,
26859bc0552SJan Kara 					      pcount, pages, poffset, &err);
26959bc0552SJan Kara 		poffset += ret;
27009cbfeafSKirill A. Shutemov 		pages += poffset >> PAGE_SHIFT;
27109cbfeafSKirill A. Shutemov 		pcount -= poffset >> PAGE_SHIFT;
27209cbfeafSKirill A. Shutemov 		full_page -= poffset >> PAGE_SHIFT;
27309cbfeafSKirill A. Shutemov 		poffset &= ~PAGE_MASK;
27459bc0552SJan Kara 
27559bc0552SJan Kara 		if (err) {
27659bc0552SJan Kara 			brelse(bh);
27759bc0552SJan Kara 			/*
27859bc0552SJan Kara 			 * Did we finish reading the page we really wanted
27959bc0552SJan Kara 			 * to read?
28059bc0552SJan Kara 			 */
28159bc0552SJan Kara 			if (full_page < 0)
28259bc0552SJan Kara 				return 0;
28359bc0552SJan Kara 			return err;
28459bc0552SJan Kara 		}
28559bc0552SJan Kara 
28659bc0552SJan Kara 		block_start = block_end;
28759bc0552SJan Kara 		cstart_block++;
28859bc0552SJan Kara 	}
28959bc0552SJan Kara 
29059bc0552SJan Kara 	if (poffset && *pages) {
291*5bb6ce3aSFabio M. De Francesco 		memzero_page(*pages, poffset, PAGE_SIZE - poffset);
29259bc0552SJan Kara 		SetPageUptodate(*pages);
29359bc0552SJan Kara 	}
29459bc0552SJan Kara 	return 0;
29559bc0552SJan Kara }
29659bc0552SJan Kara 
29759bc0552SJan Kara /*
2981da177e4SLinus Torvalds  * When decompressing, we typically obtain more than one page
2991da177e4SLinus Torvalds  * per reference.  We inject the additional pages into the page
3001da177e4SLinus Torvalds  * cache as a form of readahead.
3011da177e4SLinus Torvalds  */
zisofs_read_folio(struct file * file,struct folio * folio)302551cb124SMatthew Wilcox (Oracle) static int zisofs_read_folio(struct file *file, struct folio *folio)
3031da177e4SLinus Torvalds {
304551cb124SMatthew Wilcox (Oracle) 	struct page *page = &folio->page;
305496ad9aaSAl Viro 	struct inode *inode = file_inode(file);
3061da177e4SLinus Torvalds 	struct address_space *mapping = inode->i_mapping;
30759bc0552SJan Kara 	int err;
30859bc0552SJan Kara 	int i, pcount, full_page;
3091da177e4SLinus Torvalds 	unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1];
31059bc0552SJan Kara 	unsigned int zisofs_pages_per_cblock =
31109cbfeafSKirill A. Shutemov 		PAGE_SHIFT <= zisofs_block_shift ?
31209cbfeafSKirill A. Shutemov 		(1 << (zisofs_block_shift - PAGE_SHIFT)) : 0;
3135ac7c2fdSKyle Spiers 	struct page **pages;
31459bc0552SJan Kara 	pgoff_t index = page->index, end_index;
3151da177e4SLinus Torvalds 
31609cbfeafSKirill A. Shutemov 	end_index = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
31708ca0db8SDave Young 	/*
31808ca0db8SDave Young 	 * If this page is wholly outside i_size we just return zero;
31908ca0db8SDave Young 	 * do_generic_file_read() will handle this for us
32008ca0db8SDave Young 	 */
32159bc0552SJan Kara 	if (index >= end_index) {
32208ca0db8SDave Young 		SetPageUptodate(page);
32308ca0db8SDave Young 		unlock_page(page);
32408ca0db8SDave Young 		return 0;
32508ca0db8SDave Young 	}
32608ca0db8SDave Young 
32709cbfeafSKirill A. Shutemov 	if (PAGE_SHIFT <= zisofs_block_shift) {
32859bc0552SJan Kara 		/* We have already been given one page, this is the one
32959bc0552SJan Kara 		   we must do. */
33059bc0552SJan Kara 		full_page = index & (zisofs_pages_per_cblock - 1);
33159bc0552SJan Kara 		pcount = min_t(int, zisofs_pages_per_cblock,
33259bc0552SJan Kara 			end_index - (index & ~(zisofs_pages_per_cblock - 1)));
33359bc0552SJan Kara 		index -= full_page;
3341da177e4SLinus Torvalds 	} else {
33559bc0552SJan Kara 		full_page = 0;
33659bc0552SJan Kara 		pcount = 1;
3371da177e4SLinus Torvalds 	}
3385ac7c2fdSKyle Spiers 	pages = kcalloc(max_t(unsigned int, zisofs_pages_per_cblock, 1),
3395ac7c2fdSKyle Spiers 					sizeof(*pages), GFP_KERNEL);
3405ac7c2fdSKyle Spiers 	if (!pages) {
3415ac7c2fdSKyle Spiers 		unlock_page(page);
3425ac7c2fdSKyle Spiers 		return -ENOMEM;
3435ac7c2fdSKyle Spiers 	}
34459bc0552SJan Kara 	pages[full_page] = page;
3451da177e4SLinus Torvalds 
34659bc0552SJan Kara 	for (i = 0; i < pcount; i++, index++) {
34759bc0552SJan Kara 		if (i != full_page)
34859bc0552SJan Kara 			pages[i] = grab_cache_page_nowait(mapping, index);
349*5bb6ce3aSFabio M. De Francesco 		if (pages[i])
35059bc0552SJan Kara 			ClearPageError(pages[i]);
3511da177e4SLinus Torvalds 	}
3521da177e4SLinus Torvalds 
35359bc0552SJan Kara 	err = zisofs_fill_pages(inode, full_page, pcount, pages);
3541da177e4SLinus Torvalds 
3551da177e4SLinus Torvalds 	/* Release any residual pages, do not SetPageUptodate */
35659bc0552SJan Kara 	for (i = 0; i < pcount; i++) {
35759bc0552SJan Kara 		if (pages[i]) {
35859bc0552SJan Kara 			flush_dcache_page(pages[i]);
35959bc0552SJan Kara 			if (i == full_page && err)
36059bc0552SJan Kara 				SetPageError(pages[i]);
36159bc0552SJan Kara 			unlock_page(pages[i]);
36259bc0552SJan Kara 			if (i != full_page)
36309cbfeafSKirill A. Shutemov 				put_page(pages[i]);
3641da177e4SLinus Torvalds 		}
3651da177e4SLinus Torvalds 	}
3661da177e4SLinus Torvalds 
3671da177e4SLinus Torvalds 	/* At this point, err contains 0 or -EIO depending on the "critical" page */
3685ac7c2fdSKyle Spiers 	kfree(pages);
3691da177e4SLinus Torvalds 	return err;
3701da177e4SLinus Torvalds }
3711da177e4SLinus Torvalds 
372f5e54d6eSChristoph Hellwig const struct address_space_operations zisofs_aops = {
373551cb124SMatthew Wilcox (Oracle) 	.read_folio = zisofs_read_folio,
3741da177e4SLinus Torvalds 	/* No bmap operation supported */
3751da177e4SLinus Torvalds };
3761da177e4SLinus Torvalds 
zisofs_init(void)3771da177e4SLinus Torvalds int __init zisofs_init(void)
3781da177e4SLinus Torvalds {
3791da177e4SLinus Torvalds 	zisofs_zlib_workspace = vmalloc(zlib_inflate_workspacesize());
3801da177e4SLinus Torvalds 	if ( !zisofs_zlib_workspace )
3811da177e4SLinus Torvalds 		return -ENOMEM;
3821da177e4SLinus Torvalds 
3831da177e4SLinus Torvalds 	return 0;
3841da177e4SLinus Torvalds }
3851da177e4SLinus Torvalds 
zisofs_cleanup(void)3861da177e4SLinus Torvalds void zisofs_cleanup(void)
3871da177e4SLinus Torvalds {
3881da177e4SLinus Torvalds 	vfree(zisofs_zlib_workspace);
3891da177e4SLinus Torvalds }
390