Lines Matching +full:non +full:- +full:overlapping

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * compress.c - NTFS kernel compressed attributes handling.
4 * Part of the Linux-NTFS project.
6 * Copyright (c) 2001-2004 Anton Altaparmakov
22 * ntfs_compression_constants - enum of constants used in the compression code
30 /* Compression sub-block constants. */
45 * ntfs_compression_buffer - one buffer for the decompression engine
50 * ntfs_cb_lock - spinlock which protects ntfs_compression_buffer
55 * allocate_compression_buffers - allocate the decompression buffers
59 * Return 0 on success or -ENOMEM if the allocations failed.
67 return -ENOMEM; in allocate_compression_buffers()
72 * free_compression_buffers - free the decompression buffers
84 * zero_partial_compressed_page - zero out of bounds compressed page region
93 if (((s64)page->index << PAGE_SHIFT) >= initialized_size) { in zero_partial_compressed_page()
98 memset(kp + kp_ofs, 0, PAGE_SIZE - kp_ofs); in zero_partial_compressed_page()
103 * handle_bounds_compressed_page - test for&handle out of bounds compressed page
108 if ((page->index >= (initialized_size >> PAGE_SHIFT)) && in handle_bounds_compressed_page()
115 * ntfs_decompress - decompress a compression block into an array of pages
122 * @xpage: the target page (-1 if none) (IN)
137 * If xpage is -1 or @xpage has not been completed, @xpage_done is not modified.
140 * and @cb_size is the size of @cb_start in bytes (8-64kiB).
142 * Return 0 if success or -EOVERFLOW on error in the compressed stream.
150 * the compression block @cb_start as it is a per-CPU buffer.
160 * and the therein contained sub-blocks (sb). in ntfs_decompress()
170 u8 *dp_sb_start; /* Start of current sub-block in dp. */ in ntfs_decompress()
173 u16 do_sb_start; /* @dest_ofs when starting this sub-block. */ in ntfs_decompress()
183 int err = -EOVERFLOW; in ntfs_decompress()
187 ntfs_debug("Beginning sub-block at offset = 0x%zx in the cb.", in ntfs_decompress()
188 cb - cb_start); in ntfs_decompress()
231 /* Setup offsets for the current sub-block destination. */ in ntfs_decompress()
243 /* Setup the current sub-block source pointers and validate range. */ in ntfs_decompress()
253 /* No page present. Skip decompression of this sub-block. */ in ntfs_decompress()
256 /* Advance destination position to next sub-block. */ in ntfs_decompress()
266 /* Now, we are ready to process the current sub-block (sb). */ in ntfs_decompress()
268 ntfs_debug("Found uncompressed sub-block."); in ntfs_decompress()
275 if (cb_sb_end - cb != NTFS_SB_SIZE) in ntfs_decompress()
282 /* Advance destination position to next sub-block. */ in ntfs_decompress()
296 ntfs_debug("Found compressed sub-block."); in ntfs_decompress()
303 /* Forward to the first tag in the sub-block. */ in ntfs_decompress()
307 /* Check if the decompressed sub-block was not full-length. */ in ntfs_decompress()
309 int nr_bytes = do_sb_end - *dest_ofs; in ntfs_decompress()
311 ntfs_debug("Filling incomplete sub-block with " in ntfs_decompress()
317 /* We have finished the current sub-block. */ in ntfs_decompress()
365 * O(n). We just need an arch-optimized log2() function now. in ntfs_decompress()
368 for (i = *dest_ofs - do_sb_start - 1; i >= 0x10; i >>= 1) in ntfs_decompress()
376 * the destination using the fact that p = (pt >> (12 - lg)) + 1 in ntfs_decompress()
379 dp_back_addr = dp_addr - (pt >> (12 - lg)) - 1; in ntfs_decompress()
391 /* The number of non-overlapping bytes. */ in ntfs_decompress()
392 max_non_overlap = dp_addr - dp_back_addr; in ntfs_decompress()
402 * The byte sequence does overlap, copy non-overlapping in ntfs_decompress()
404 * overlapping part. Also, advance the destination in ntfs_decompress()
410 length -= max_non_overlap; in ntfs_decompress()
411 while (length--) in ntfs_decompress()
423 ntfs_error(NULL, "Failed. Returning -EOVERFLOW."); in ntfs_decompress()
428 * ntfs_read_compressed_block - read a compressed block into the page cache
432 * attribute is known to be non-resident, not encrypted, but compressed.
443 * them with the out-of-date uncompressed data.
448 * moment we would just return -EIO on such a page. This bug will only become
466 struct address_space *mapping = page->mapping; in ntfs_read_compressed_block()
467 ntfs_inode *ni = NTFS_I(mapping->host); in ntfs_read_compressed_block()
468 ntfs_volume *vol = ni->vol; in ntfs_read_compressed_block()
469 struct super_block *sb = vol->sb; in ntfs_read_compressed_block()
471 unsigned long flags, block_size = sb->s_blocksize; in ntfs_read_compressed_block()
472 unsigned char block_size_bits = sb->s_blocksize_bits; in ntfs_read_compressed_block()
475 unsigned long offset, index = page->index; in ntfs_read_compressed_block()
476 u32 cb_size = ni->itype.compressed.block_size; in ntfs_read_compressed_block()
477 u64 cb_size_mask = cb_size - 1UL; in ntfs_read_compressed_block()
482 vol->cluster_size_bits; in ntfs_read_compressed_block()
487 VCN end_vcn = ((((s64)(index + 1UL) << PAGE_SHIFT) + cb_size - 1) in ntfs_read_compressed_block()
488 & ~cb_size_mask) >> vol->cluster_size_bits; in ntfs_read_compressed_block()
490 unsigned int nr_cbs = (end_vcn - start_vcn) << vol->cluster_size_bits in ntfs_read_compressed_block()
491 >> ni->itype.compressed.block_size_bits; in ntfs_read_compressed_block()
494 * compression blocks (cbs) overlapping @page. Due to alignment in ntfs_read_compressed_block()
497 unsigned int nr_pages = (end_vcn - start_vcn) << in ntfs_read_compressed_block()
498 vol->cluster_size_bits >> PAGE_SHIFT; in ntfs_read_compressed_block()
506 ntfs_debug("Entering, page->index = 0x%lx, cb_size = 0x%x, nr_pages = " in ntfs_read_compressed_block()
512 BUG_ON(ni->type != AT_DATA); in ntfs_read_compressed_block()
513 BUG_ON(ni->name_len); in ntfs_read_compressed_block()
527 ntfs_error(vol->sb, "Failed to allocate internal buffers."); in ntfs_read_compressed_block()
528 return -ENOMEM; in ntfs_read_compressed_block()
535 offset = start_vcn << vol->cluster_size_bits >> PAGE_SHIFT; in ntfs_read_compressed_block()
536 xpage = index - offset; in ntfs_read_compressed_block()
540 * cache, alignment guarantees keep all the below much simpler. (-8 in ntfs_read_compressed_block()
542 read_lock_irqsave(&ni->size_lock, flags); in ntfs_read_compressed_block()
544 initialized_size = ni->initialized_size; in ntfs_read_compressed_block()
545 read_unlock_irqrestore(&ni->size_lock, flags); in ntfs_read_compressed_block()
546 max_page = ((i_size + PAGE_SIZE - 1) >> PAGE_SHIFT) - in ntfs_read_compressed_block()
554 ntfs_debug("Compressed read outside i_size - truncated?"); in ntfs_read_compressed_block()
589 cb_clusters = ni->itype.compressed.block_clusters; in ntfs_read_compressed_block()
591 nr_cbs--; in ntfs_read_compressed_block()
602 down_read(&ni->runlist.lock); in ntfs_read_compressed_block()
603 rl = ni->runlist.rl; in ntfs_read_compressed_block()
607 while (rl->length && rl[1].vcn <= vcn) in ntfs_read_compressed_block()
629 up_read(&ni->runlist.lock); in ntfs_read_compressed_block()
634 block = lcn << vol->cluster_size_bits >> block_size_bits; in ntfs_read_compressed_block()
636 max_block = block + (vol->cluster_size >> block_size_bits); in ntfs_read_compressed_block()
647 up_read(&ni->runlist.lock); in ntfs_read_compressed_block()
660 tbh->b_end_io = end_buffer_read_sync; in ntfs_read_compressed_block()
681 ntfs_warning(vol->sb, "Buffer is unlocked but not " in ntfs_read_compressed_block()
689 ntfs_warning(vol->sb, "Buffer is now uptodate. Good."); in ntfs_read_compressed_block()
707 memcpy(cb_pos, bhs[i]->b_data, block_size); in ntfs_read_compressed_block()
730 if (vcn == start_vcn - cb_clusters) { in ntfs_read_compressed_block()
731 /* Sparse cb, zero out page range overlapping the cb. */ in ntfs_read_compressed_block()
736 cb_max_page--; in ntfs_read_compressed_block()
744 PAGE_SIZE - in ntfs_read_compressed_block()
756 cb_pos += PAGE_SIZE - cur_ofs; in ntfs_read_compressed_block()
766 cb_max_ofs - cur_ofs); in ntfs_read_compressed_block()
769 * cb_pos += cb_max_ofs - cur_ofs; in ntfs_read_compressed_block()
787 * Or if we choose not to do the read-ahead/-behind stuff, we in ntfs_read_compressed_block()
792 cb_max_page--; in ntfs_read_compressed_block()
798 PAGE_SIZE - cur_ofs); in ntfs_read_compressed_block()
799 cb_pos += PAGE_SIZE - cur_ofs; in ntfs_read_compressed_block()
809 cb_max_ofs - cur_ofs); in ntfs_read_compressed_block()
810 cb_pos += cb_max_ofs - cur_ofs; in ntfs_read_compressed_block()
835 cb_pos2 += PAGE_SIZE - cur_ofs2; in ntfs_read_compressed_block()
847 &xpage_done, cb_pos, cb_size - (cb_pos - cb), in ntfs_read_compressed_block()
854 ntfs_error(vol->sb, "ntfs_decompress() failed in inode " in ntfs_read_compressed_block()
857 ni->mft_no, -err); in ntfs_read_compressed_block()
888 ntfs_error(vol->sb, "Still have pages left! " in ntfs_read_compressed_block()
891 "0x%lx.", ni->mft_no, page->index); in ntfs_read_compressed_block()
909 ntfs_debug("Failed. Returning error code %s.", err == -EOVERFLOW ? in ntfs_read_compressed_block()
911 return err < 0 ? err : -EIO; in ntfs_read_compressed_block()
914 ntfs_error(vol->sb, "IO error while reading compressed data."); in ntfs_read_compressed_block()
921 ntfs_error(vol->sb, "ntfs_map_runlist() failed. Cannot read " in ntfs_read_compressed_block()
926 up_read(&ni->runlist.lock); in ntfs_read_compressed_block()
927 ntfs_error(vol->sb, "ntfs_rl_vcn_to_lcn() failed. Cannot read " in ntfs_read_compressed_block()
932 up_read(&ni->runlist.lock); in ntfs_read_compressed_block()
933 ntfs_error(vol->sb, "getblk() failed. Cannot read compression block."); in ntfs_read_compressed_block()
949 return -EIO; in ntfs_read_compressed_block()