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 memzero_page(pages[i], 0, PAGE_SIZE); 71 SetPageUptodate(pages[i]); 72 } 73 return ((loff_t)pcount) << PAGE_SHIFT; 74 } 75 76 /* Because zlib is not thread-safe, do all the I/O at the top. */ 77 blocknum = block_start >> bufshift; 78 bhs = kcalloc(needblocks + 1, sizeof(*bhs), GFP_KERNEL); 79 if (!bhs) { 80 *errp = -ENOMEM; 81 return 0; 82 } 83 haveblocks = isofs_get_blocks(inode, blocknum, bhs, needblocks); 84 bh_read_batch(haveblocks, bhs); 85 86 curbh = 0; 87 curpage = 0; 88 /* 89 * First block is special since it may be fractional. We also wait for 90 * it before grabbing the zlib mutex; odds are that the subsequent 91 * blocks are going to come in in short order so we don't hold the zlib 92 * mutex longer than necessary. 93 */ 94 95 if (!bhs[0]) 96 goto b_eio; 97 98 wait_on_buffer(bhs[0]); 99 if (!buffer_uptodate(bhs[0])) { 100 *errp = -EIO; 101 goto b_eio; 102 } 103 104 stream.workspace = zisofs_zlib_workspace; 105 mutex_lock(&zisofs_zlib_lock); 106 107 zerr = zlib_inflateInit(&stream); 108 if (zerr != Z_OK) { 109 if (zerr == Z_MEM_ERROR) 110 *errp = -ENOMEM; 111 else 112 *errp = -EIO; 113 printk(KERN_DEBUG "zisofs: zisofs_inflateInit returned %d\n", 114 zerr); 115 goto z_eio; 116 } 117 118 while (curpage < pcount && curbh < haveblocks && 119 zerr != Z_STREAM_END) { 120 if (!stream.avail_out) { 121 if (pages[curpage]) { 122 stream.next_out = kmap_local_page(pages[curpage]) 123 + poffset; 124 stream.avail_out = PAGE_SIZE - poffset; 125 poffset = 0; 126 } else { 127 stream.next_out = (void *)&zisofs_sink_page; 128 stream.avail_out = PAGE_SIZE; 129 } 130 } 131 if (!stream.avail_in) { 132 wait_on_buffer(bhs[curbh]); 133 if (!buffer_uptodate(bhs[curbh])) { 134 *errp = -EIO; 135 break; 136 } 137 stream.next_in = bhs[curbh]->b_data + 138 (block_start & bufmask); 139 stream.avail_in = min_t(unsigned, bufsize - 140 (block_start & bufmask), 141 block_size); 142 block_size -= stream.avail_in; 143 block_start = 0; 144 } 145 146 while (stream.avail_out && stream.avail_in) { 147 zerr = zlib_inflate(&stream, Z_SYNC_FLUSH); 148 if (zerr == Z_BUF_ERROR && stream.avail_in == 0) 149 break; 150 if (zerr == Z_STREAM_END) 151 break; 152 if (zerr != Z_OK) { 153 /* EOF, error, or trying to read beyond end of input */ 154 if (zerr == Z_MEM_ERROR) 155 *errp = -ENOMEM; 156 else { 157 printk(KERN_DEBUG 158 "zisofs: zisofs_inflate returned" 159 " %d, inode = %lu," 160 " page idx = %d, bh idx = %d," 161 " avail_in = %ld," 162 " avail_out = %ld\n", 163 zerr, inode->i_ino, curpage, 164 curbh, stream.avail_in, 165 stream.avail_out); 166 *errp = -EIO; 167 } 168 goto inflate_out; 169 } 170 } 171 172 if (!stream.avail_out) { 173 /* This page completed */ 174 if (pages[curpage]) { 175 flush_dcache_page(pages[curpage]); 176 SetPageUptodate(pages[curpage]); 177 } 178 if (stream.next_out != (unsigned char *)zisofs_sink_page) { 179 kunmap_local(stream.next_out); 180 stream.next_out = NULL; 181 } 182 curpage++; 183 } 184 if (!stream.avail_in) 185 curbh++; 186 } 187 inflate_out: 188 zlib_inflateEnd(&stream); 189 if (stream.next_out && stream.next_out != (unsigned char *)zisofs_sink_page) 190 kunmap_local(stream.next_out); 191 192 z_eio: 193 mutex_unlock(&zisofs_zlib_lock); 194 195 b_eio: 196 for (i = 0; i < haveblocks; i++) 197 brelse(bhs[i]); 198 kfree(bhs); 199 return stream.total_out; 200 } 201 202 /* 203 * Uncompress data so that pages[full_page] is fully uptodate and possibly 204 * fills in other pages if we have data for them. 205 */ 206 static int zisofs_fill_pages(struct inode *inode, int full_page, int pcount, 207 struct page **pages) 208 { 209 loff_t start_off, end_off; 210 loff_t block_start, block_end; 211 unsigned int header_size = ISOFS_I(inode)->i_format_parm[0]; 212 unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1]; 213 unsigned int blockptr; 214 loff_t poffset = 0; 215 blkcnt_t cstart_block, cend_block; 216 struct buffer_head *bh; 217 unsigned int blkbits = ISOFS_BUFFER_BITS(inode); 218 unsigned int blksize = 1 << blkbits; 219 int err; 220 loff_t ret; 221 222 BUG_ON(!pages[full_page]); 223 224 /* 225 * We want to read at least 'full_page' page. Because we have to 226 * uncompress the whole compression block anyway, fill the surrounding 227 * pages with the data we have anyway... 228 */ 229 start_off = page_offset(pages[full_page]); 230 end_off = min_t(loff_t, start_off + PAGE_SIZE, inode->i_size); 231 232 cstart_block = start_off >> zisofs_block_shift; 233 cend_block = (end_off + (1 << zisofs_block_shift) - 1) 234 >> zisofs_block_shift; 235 236 WARN_ON(start_off - (full_page << PAGE_SHIFT) != 237 ((cstart_block << zisofs_block_shift) & PAGE_MASK)); 238 239 /* Find the pointer to this specific chunk */ 240 /* Note: we're not using isonum_731() here because the data is known aligned */ 241 /* Note: header_size is in 32-bit words (4 bytes) */ 242 blockptr = (header_size + cstart_block) << 2; 243 bh = isofs_bread(inode, blockptr >> blkbits); 244 if (!bh) 245 return -EIO; 246 block_start = le32_to_cpu(*(__le32 *) 247 (bh->b_data + (blockptr & (blksize - 1)))); 248 249 while (cstart_block < cend_block && pcount > 0) { 250 /* Load end of the compressed block in the file */ 251 blockptr += 4; 252 /* Traversed to next block? */ 253 if (!(blockptr & (blksize - 1))) { 254 brelse(bh); 255 256 bh = isofs_bread(inode, blockptr >> blkbits); 257 if (!bh) 258 return -EIO; 259 } 260 block_end = le32_to_cpu(*(__le32 *) 261 (bh->b_data + (blockptr & (blksize - 1)))); 262 if (block_start > block_end) { 263 brelse(bh); 264 return -EIO; 265 } 266 err = 0; 267 ret = zisofs_uncompress_block(inode, block_start, block_end, 268 pcount, pages, poffset, &err); 269 poffset += ret; 270 pages += poffset >> PAGE_SHIFT; 271 pcount -= poffset >> PAGE_SHIFT; 272 full_page -= poffset >> PAGE_SHIFT; 273 poffset &= ~PAGE_MASK; 274 275 if (err) { 276 brelse(bh); 277 /* 278 * Did we finish reading the page we really wanted 279 * to read? 280 */ 281 if (full_page < 0) 282 return 0; 283 return err; 284 } 285 286 block_start = block_end; 287 cstart_block++; 288 } 289 290 if (poffset && *pages) { 291 memzero_page(*pages, poffset, PAGE_SIZE - poffset); 292 SetPageUptodate(*pages); 293 } 294 return 0; 295 } 296 297 /* 298 * When decompressing, we typically obtain more than one page 299 * per reference. We inject the additional pages into the page 300 * cache as a form of readahead. 301 */ 302 static int zisofs_read_folio(struct file *file, struct folio *folio) 303 { 304 struct page *page = &folio->page; 305 struct inode *inode = file_inode(file); 306 struct address_space *mapping = inode->i_mapping; 307 int err; 308 int i, pcount, full_page; 309 unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1]; 310 unsigned int zisofs_pages_per_cblock = 311 PAGE_SHIFT <= zisofs_block_shift ? 312 (1 << (zisofs_block_shift - PAGE_SHIFT)) : 0; 313 struct page **pages; 314 pgoff_t index = page->index, end_index; 315 316 end_index = (inode->i_size + PAGE_SIZE - 1) >> PAGE_SHIFT; 317 /* 318 * If this page is wholly outside i_size we just return zero; 319 * do_generic_file_read() will handle this for us 320 */ 321 if (index >= end_index) { 322 SetPageUptodate(page); 323 unlock_page(page); 324 return 0; 325 } 326 327 if (PAGE_SHIFT <= zisofs_block_shift) { 328 /* We have already been given one page, this is the one 329 we must do. */ 330 full_page = index & (zisofs_pages_per_cblock - 1); 331 pcount = min_t(int, zisofs_pages_per_cblock, 332 end_index - (index & ~(zisofs_pages_per_cblock - 1))); 333 index -= full_page; 334 } else { 335 full_page = 0; 336 pcount = 1; 337 } 338 pages = kcalloc(max_t(unsigned int, zisofs_pages_per_cblock, 1), 339 sizeof(*pages), GFP_KERNEL); 340 if (!pages) { 341 unlock_page(page); 342 return -ENOMEM; 343 } 344 pages[full_page] = page; 345 346 for (i = 0; i < pcount; i++, index++) { 347 if (i != full_page) 348 pages[i] = grab_cache_page_nowait(mapping, index); 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 unlock_page(pages[i]); 358 if (i != full_page) 359 put_page(pages[i]); 360 } 361 } 362 363 /* At this point, err contains 0 or -EIO depending on the "critical" page */ 364 kfree(pages); 365 return err; 366 } 367 368 const struct address_space_operations zisofs_aops = { 369 .read_folio = zisofs_read_folio, 370 /* No bmap operation supported */ 371 }; 372 373 int __init zisofs_init(void) 374 { 375 zisofs_zlib_workspace = vmalloc(zlib_inflate_workspacesize()); 376 if ( !zisofs_zlib_workspace ) 377 return -ENOMEM; 378 379 return 0; 380 } 381 382 void zisofs_cleanup(void) 383 { 384 vfree(zisofs_zlib_workspace); 385 } 386
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.