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