11e9ea7e0SNamjae Jeon // SPDX-License-Identifier: GPL-2.0-or-later 21e9ea7e0SNamjae Jeon /* 3495e90faSNamjae Jeon * NTFS kernel compressed attributes handling. 41e9ea7e0SNamjae Jeon * 51e9ea7e0SNamjae Jeon * Copyright (c) 2001-2004 Anton Altaparmakov 61e9ea7e0SNamjae Jeon * Copyright (c) 2002 Richard Russon 7495e90faSNamjae Jeon * Copyright (c) 2025 LG Electronics Co., Ltd. 8495e90faSNamjae Jeon * 9495e90faSNamjae Jeon * Part of this file is based on code from the NTFS-3G. 10495e90faSNamjae Jeon * and is copyrighted by the respective authors below: 11495e90faSNamjae Jeon * Copyright (c) 2004-2005 Anton Altaparmakov 12495e90faSNamjae Jeon * Copyright (c) 2004-2006 Szabolcs Szakacsits 13495e90faSNamjae Jeon * Copyright (c) 2005 Yura Pakhuchiy 14495e90faSNamjae Jeon * Copyright (c) 2009-2014 Jean-Pierre Andre 15495e90faSNamjae Jeon * Copyright (c) 2014 Eric Biggers 161e9ea7e0SNamjae Jeon */ 171e9ea7e0SNamjae Jeon 181e9ea7e0SNamjae Jeon #include <linux/fs.h> 191e9ea7e0SNamjae Jeon #include <linux/blkdev.h> 201e9ea7e0SNamjae Jeon #include <linux/vmalloc.h> 211e9ea7e0SNamjae Jeon #include <linux/slab.h> 221e9ea7e0SNamjae Jeon 231e9ea7e0SNamjae Jeon #include "attrib.h" 241e9ea7e0SNamjae Jeon #include "inode.h" 251e9ea7e0SNamjae Jeon #include "debug.h" 261e9ea7e0SNamjae Jeon #include "ntfs.h" 27495e90faSNamjae Jeon #include "lcnalloc.h" 28495e90faSNamjae Jeon #include "mft.h" 291e9ea7e0SNamjae Jeon 30495e90faSNamjae Jeon /* 31495e90faSNamjae Jeon * Constants used in the compression code 321e9ea7e0SNamjae Jeon */ 33495e90faSNamjae Jeon enum { 341e9ea7e0SNamjae Jeon /* Token types and access mask. */ 351e9ea7e0SNamjae Jeon NTFS_SYMBOL_TOKEN = 0, 361e9ea7e0SNamjae Jeon NTFS_PHRASE_TOKEN = 1, 371e9ea7e0SNamjae Jeon NTFS_TOKEN_MASK = 1, 381e9ea7e0SNamjae Jeon 391e9ea7e0SNamjae Jeon /* Compression sub-block constants. */ 401e9ea7e0SNamjae Jeon NTFS_SB_SIZE_MASK = 0x0fff, 411e9ea7e0SNamjae Jeon NTFS_SB_SIZE = 0x1000, 421e9ea7e0SNamjae Jeon NTFS_SB_IS_COMPRESSED = 0x8000, 431e9ea7e0SNamjae Jeon 441e9ea7e0SNamjae Jeon /* 451e9ea7e0SNamjae Jeon * The maximum compression block size is by definition 16 * the cluster 461e9ea7e0SNamjae Jeon * size, with the maximum supported cluster size being 4kiB. Thus the 471e9ea7e0SNamjae Jeon * maximum compression buffer size is 64kiB, so we use this when 481e9ea7e0SNamjae Jeon * initializing the compression buffer. 491e9ea7e0SNamjae Jeon */ 501e9ea7e0SNamjae Jeon NTFS_MAX_CB_SIZE = 64 * 1024, 51495e90faSNamjae Jeon }; 521e9ea7e0SNamjae Jeon 531e9ea7e0SNamjae Jeon /* 541e9ea7e0SNamjae Jeon * ntfs_compression_buffer - one buffer for the decompression engine 551e9ea7e0SNamjae Jeon */ 561e9ea7e0SNamjae Jeon static u8 *ntfs_compression_buffer; 571e9ea7e0SNamjae Jeon 581e9ea7e0SNamjae Jeon /* 59495e90faSNamjae Jeon * ntfs_cb_lock - mutex lock which protects ntfs_compression_buffer 601e9ea7e0SNamjae Jeon */ 61495e90faSNamjae Jeon static DEFINE_MUTEX(ntfs_cb_lock); 621e9ea7e0SNamjae Jeon 63495e90faSNamjae Jeon /* 641e9ea7e0SNamjae Jeon * allocate_compression_buffers - allocate the decompression buffers 651e9ea7e0SNamjae Jeon * 661e9ea7e0SNamjae Jeon * Caller has to hold the ntfs_lock mutex. 671e9ea7e0SNamjae Jeon * 681e9ea7e0SNamjae Jeon * Return 0 on success or -ENOMEM if the allocations failed. 691e9ea7e0SNamjae Jeon */ 701e9ea7e0SNamjae Jeon int allocate_compression_buffers(void) 711e9ea7e0SNamjae Jeon { 72495e90faSNamjae Jeon if (ntfs_compression_buffer) 73495e90faSNamjae Jeon return 0; 741e9ea7e0SNamjae Jeon 751e9ea7e0SNamjae Jeon ntfs_compression_buffer = vmalloc(NTFS_MAX_CB_SIZE); 761e9ea7e0SNamjae Jeon if (!ntfs_compression_buffer) 771e9ea7e0SNamjae Jeon return -ENOMEM; 781e9ea7e0SNamjae Jeon return 0; 791e9ea7e0SNamjae Jeon } 801e9ea7e0SNamjae Jeon 81495e90faSNamjae Jeon /* 821e9ea7e0SNamjae Jeon * free_compression_buffers - free the decompression buffers 831e9ea7e0SNamjae Jeon * 841e9ea7e0SNamjae Jeon * Caller has to hold the ntfs_lock mutex. 851e9ea7e0SNamjae Jeon */ 861e9ea7e0SNamjae Jeon void free_compression_buffers(void) 871e9ea7e0SNamjae Jeon { 88495e90faSNamjae Jeon mutex_lock(&ntfs_cb_lock); 89495e90faSNamjae Jeon if (!ntfs_compression_buffer) { 90495e90faSNamjae Jeon mutex_unlock(&ntfs_cb_lock); 91495e90faSNamjae Jeon return; 921e9ea7e0SNamjae Jeon } 931e9ea7e0SNamjae Jeon 94495e90faSNamjae Jeon vfree(ntfs_compression_buffer); 95495e90faSNamjae Jeon ntfs_compression_buffer = NULL; 96495e90faSNamjae Jeon mutex_unlock(&ntfs_cb_lock); 97495e90faSNamjae Jeon } 98495e90faSNamjae Jeon 99495e90faSNamjae Jeon /* 1001e9ea7e0SNamjae Jeon * zero_partial_compressed_page - zero out of bounds compressed page region 101495e90faSNamjae Jeon * @page: page to zero 102495e90faSNamjae Jeon * @initialized_size: initialized size of the attribute 1031e9ea7e0SNamjae Jeon */ 1041e9ea7e0SNamjae Jeon static void zero_partial_compressed_page(struct page *page, 1051e9ea7e0SNamjae Jeon const s64 initialized_size) 1061e9ea7e0SNamjae Jeon { 1071e9ea7e0SNamjae Jeon u8 *kp = page_address(page); 1081e9ea7e0SNamjae Jeon unsigned int kp_ofs; 1091e9ea7e0SNamjae Jeon 1101e9ea7e0SNamjae Jeon ntfs_debug("Zeroing page region outside initialized size."); 111495e90faSNamjae Jeon if (((s64)page->__folio_index << PAGE_SHIFT) >= initialized_size) { 1121e9ea7e0SNamjae Jeon clear_page(kp); 1131e9ea7e0SNamjae Jeon return; 1141e9ea7e0SNamjae Jeon } 1151e9ea7e0SNamjae Jeon kp_ofs = initialized_size & ~PAGE_MASK; 1161e9ea7e0SNamjae Jeon memset(kp + kp_ofs, 0, PAGE_SIZE - kp_ofs); 1171e9ea7e0SNamjae Jeon } 1181e9ea7e0SNamjae Jeon 119495e90faSNamjae Jeon /* 1201e9ea7e0SNamjae Jeon * handle_bounds_compressed_page - test for&handle out of bounds compressed page 121495e90faSNamjae Jeon * @page: page to check and handle 122495e90faSNamjae Jeon * @i_size: file size 123495e90faSNamjae Jeon * @initialized_size: initialized size of the attribute 1241e9ea7e0SNamjae Jeon */ 1251e9ea7e0SNamjae Jeon static inline void handle_bounds_compressed_page(struct page *page, 1261e9ea7e0SNamjae Jeon const loff_t i_size, const s64 initialized_size) 1271e9ea7e0SNamjae Jeon { 128495e90faSNamjae Jeon if ((page->__folio_index >= (initialized_size >> PAGE_SHIFT)) && 1291e9ea7e0SNamjae Jeon (initialized_size < i_size)) 1301e9ea7e0SNamjae Jeon zero_partial_compressed_page(page, initialized_size); 1311e9ea7e0SNamjae Jeon } 1321e9ea7e0SNamjae Jeon 133495e90faSNamjae Jeon /* 1341e9ea7e0SNamjae Jeon * ntfs_decompress - decompress a compression block into an array of pages 1351e9ea7e0SNamjae Jeon * @dest_pages: destination array of pages 1361e9ea7e0SNamjae Jeon * @completed_pages: scratch space to track completed pages 1371e9ea7e0SNamjae Jeon * @dest_index: current index into @dest_pages (IN/OUT) 1381e9ea7e0SNamjae Jeon * @dest_ofs: current offset within @dest_pages[@dest_index] (IN/OUT) 1391e9ea7e0SNamjae Jeon * @dest_max_index: maximum index into @dest_pages (IN) 1401e9ea7e0SNamjae Jeon * @dest_max_ofs: maximum offset within @dest_pages[@dest_max_index] (IN) 1411e9ea7e0SNamjae Jeon * @xpage: the target page (-1 if none) (IN) 1421e9ea7e0SNamjae Jeon * @xpage_done: set to 1 if xpage was completed successfully (IN/OUT) 1431e9ea7e0SNamjae Jeon * @cb_start: compression block to decompress (IN) 1441e9ea7e0SNamjae Jeon * @cb_size: size of compression block @cb_start in bytes (IN) 1451e9ea7e0SNamjae Jeon * @i_size: file size when we started the read (IN) 1461e9ea7e0SNamjae Jeon * @initialized_size: initialized file size when we started the read (IN) 1471e9ea7e0SNamjae Jeon * 1481e9ea7e0SNamjae Jeon * The caller must have disabled preemption. ntfs_decompress() reenables it when 1491e9ea7e0SNamjae Jeon * the critical section is finished. 1501e9ea7e0SNamjae Jeon * 1511e9ea7e0SNamjae Jeon * This decompresses the compression block @cb_start into the array of 1521e9ea7e0SNamjae Jeon * destination pages @dest_pages starting at index @dest_index into @dest_pages 1531e9ea7e0SNamjae Jeon * and at offset @dest_pos into the page @dest_pages[@dest_index]. 1541e9ea7e0SNamjae Jeon * 1551e9ea7e0SNamjae Jeon * When the page @dest_pages[@xpage] is completed, @xpage_done is set to 1. 1561e9ea7e0SNamjae Jeon * If xpage is -1 or @xpage has not been completed, @xpage_done is not modified. 1571e9ea7e0SNamjae Jeon * 1581e9ea7e0SNamjae Jeon * @cb_start is a pointer to the compression block which needs decompressing 1591e9ea7e0SNamjae Jeon * and @cb_size is the size of @cb_start in bytes (8-64kiB). 1601e9ea7e0SNamjae Jeon * 1611e9ea7e0SNamjae Jeon * Return 0 if success or -EOVERFLOW on error in the compressed stream. 1621e9ea7e0SNamjae Jeon * @xpage_done indicates whether the target page (@dest_pages[@xpage]) was 1631e9ea7e0SNamjae Jeon * completed during the decompression of the compression block (@cb_start). 1641e9ea7e0SNamjae Jeon * 1651e9ea7e0SNamjae Jeon * Warning: This function *REQUIRES* PAGE_SIZE >= 4096 or it will blow up 1661e9ea7e0SNamjae Jeon * unpredicatbly! You have been warned! 1671e9ea7e0SNamjae Jeon * 1681e9ea7e0SNamjae Jeon * Note to hackers: This function may not sleep until it has finished accessing 1691e9ea7e0SNamjae Jeon * the compression block @cb_start as it is a per-CPU buffer. 1701e9ea7e0SNamjae Jeon */ 1711e9ea7e0SNamjae Jeon static int ntfs_decompress(struct page *dest_pages[], int completed_pages[], 1721e9ea7e0SNamjae Jeon int *dest_index, int *dest_ofs, const int dest_max_index, 1731e9ea7e0SNamjae Jeon const int dest_max_ofs, const int xpage, char *xpage_done, 1741e9ea7e0SNamjae Jeon u8 *const cb_start, const u32 cb_size, const loff_t i_size, 1751e9ea7e0SNamjae Jeon const s64 initialized_size) 1761e9ea7e0SNamjae Jeon { 1771e9ea7e0SNamjae Jeon /* 1781e9ea7e0SNamjae Jeon * Pointers into the compressed data, i.e. the compression block (cb), 1791e9ea7e0SNamjae Jeon * and the therein contained sub-blocks (sb). 1801e9ea7e0SNamjae Jeon */ 1811e9ea7e0SNamjae Jeon u8 *cb_end = cb_start + cb_size; /* End of cb. */ 1821e9ea7e0SNamjae Jeon u8 *cb = cb_start; /* Current position in cb. */ 183495e90faSNamjae Jeon u8 *cb_sb_start = cb; /* Beginning of the current sb in the cb. */ 1841e9ea7e0SNamjae Jeon u8 *cb_sb_end; /* End of current sb / beginning of next sb. */ 1851e9ea7e0SNamjae Jeon 1861e9ea7e0SNamjae Jeon /* Variables for uncompressed data / destination. */ 1871e9ea7e0SNamjae Jeon struct page *dp; /* Current destination page being worked on. */ 1881e9ea7e0SNamjae Jeon u8 *dp_addr; /* Current pointer into dp. */ 1891e9ea7e0SNamjae Jeon u8 *dp_sb_start; /* Start of current sub-block in dp. */ 190495e90faSNamjae Jeon u8 *dp_sb_end; /* End of current sb in dp (dp_sb_start + NTFS_SB_SIZE). */ 1911e9ea7e0SNamjae Jeon u16 do_sb_start; /* @dest_ofs when starting this sub-block. */ 192495e90faSNamjae Jeon u16 do_sb_end; /* @dest_ofs of end of this sb (do_sb_start + NTFS_SB_SIZE). */ 1931e9ea7e0SNamjae Jeon 1941e9ea7e0SNamjae Jeon /* Variables for tag and token parsing. */ 1951e9ea7e0SNamjae Jeon u8 tag; /* Current tag. */ 1961e9ea7e0SNamjae Jeon int token; /* Loop counter for the eight tokens in tag. */ 1971e9ea7e0SNamjae Jeon int nr_completed_pages = 0; 1981e9ea7e0SNamjae Jeon 1991e9ea7e0SNamjae Jeon /* Default error code. */ 2001e9ea7e0SNamjae Jeon int err = -EOVERFLOW; 2011e9ea7e0SNamjae Jeon 2021e9ea7e0SNamjae Jeon ntfs_debug("Entering, cb_size = 0x%x.", cb_size); 2031e9ea7e0SNamjae Jeon do_next_sb: 2041e9ea7e0SNamjae Jeon ntfs_debug("Beginning sub-block at offset = 0x%zx in the cb.", 2051e9ea7e0SNamjae Jeon cb - cb_start); 2061e9ea7e0SNamjae Jeon /* 2071e9ea7e0SNamjae Jeon * Have we reached the end of the compression block or the end of the 2081e9ea7e0SNamjae Jeon * decompressed data? The latter can happen for example if the current 2091e9ea7e0SNamjae Jeon * position in the compression block is one byte before its end so the 2101e9ea7e0SNamjae Jeon * first two checks do not detect it. 2111e9ea7e0SNamjae Jeon */ 212495e90faSNamjae Jeon if (cb == cb_end || !le16_to_cpup((__le16 *)cb) || 2131e9ea7e0SNamjae Jeon (*dest_index == dest_max_index && 2141e9ea7e0SNamjae Jeon *dest_ofs == dest_max_ofs)) { 2151e9ea7e0SNamjae Jeon int i; 2161e9ea7e0SNamjae Jeon 2171e9ea7e0SNamjae Jeon ntfs_debug("Completed. Returning success (0)."); 2181e9ea7e0SNamjae Jeon err = 0; 2191e9ea7e0SNamjae Jeon return_error: 2201e9ea7e0SNamjae Jeon /* We can sleep from now on, so we drop lock. */ 221495e90faSNamjae Jeon mutex_unlock(&ntfs_cb_lock); 2221e9ea7e0SNamjae Jeon /* Second stage: finalize completed pages. */ 2231e9ea7e0SNamjae Jeon if (nr_completed_pages > 0) { 2241e9ea7e0SNamjae Jeon for (i = 0; i < nr_completed_pages; i++) { 2251e9ea7e0SNamjae Jeon int di = completed_pages[i]; 2261e9ea7e0SNamjae Jeon 2271e9ea7e0SNamjae Jeon dp = dest_pages[di]; 2281e9ea7e0SNamjae Jeon /* 2291e9ea7e0SNamjae Jeon * If we are outside the initialized size, zero 2301e9ea7e0SNamjae Jeon * the out of bounds page range. 2311e9ea7e0SNamjae Jeon */ 2321e9ea7e0SNamjae Jeon handle_bounds_compressed_page(dp, i_size, 2331e9ea7e0SNamjae Jeon initialized_size); 2341e9ea7e0SNamjae Jeon flush_dcache_page(dp); 235495e90faSNamjae Jeon kunmap_local(page_address(dp)); 2361e9ea7e0SNamjae Jeon SetPageUptodate(dp); 2371e9ea7e0SNamjae Jeon unlock_page(dp); 2381e9ea7e0SNamjae Jeon if (di == xpage) 2391e9ea7e0SNamjae Jeon *xpage_done = 1; 2401e9ea7e0SNamjae Jeon else 2411e9ea7e0SNamjae Jeon put_page(dp); 2421e9ea7e0SNamjae Jeon dest_pages[di] = NULL; 2431e9ea7e0SNamjae Jeon } 2441e9ea7e0SNamjae Jeon } 2451e9ea7e0SNamjae Jeon return err; 2461e9ea7e0SNamjae Jeon } 2471e9ea7e0SNamjae Jeon 2481e9ea7e0SNamjae Jeon /* Setup offsets for the current sub-block destination. */ 2491e9ea7e0SNamjae Jeon do_sb_start = *dest_ofs; 2501e9ea7e0SNamjae Jeon do_sb_end = do_sb_start + NTFS_SB_SIZE; 2511e9ea7e0SNamjae Jeon 2521e9ea7e0SNamjae Jeon /* Check that we are still within allowed boundaries. */ 2531e9ea7e0SNamjae Jeon if (*dest_index == dest_max_index && do_sb_end > dest_max_ofs) 2541e9ea7e0SNamjae Jeon goto return_overflow; 2551e9ea7e0SNamjae Jeon 2561e9ea7e0SNamjae Jeon /* Does the minimum size of a compressed sb overflow valid range? */ 2571e9ea7e0SNamjae Jeon if (cb + 6 > cb_end) 2581e9ea7e0SNamjae Jeon goto return_overflow; 2591e9ea7e0SNamjae Jeon 2601e9ea7e0SNamjae Jeon /* Setup the current sub-block source pointers and validate range. */ 2611e9ea7e0SNamjae Jeon cb_sb_start = cb; 262495e90faSNamjae Jeon cb_sb_end = cb_sb_start + (le16_to_cpup((__le16 *)cb) & NTFS_SB_SIZE_MASK) 2631e9ea7e0SNamjae Jeon + 3; 2641e9ea7e0SNamjae Jeon if (cb_sb_end > cb_end) 2651e9ea7e0SNamjae Jeon goto return_overflow; 2661e9ea7e0SNamjae Jeon 2671e9ea7e0SNamjae Jeon /* Get the current destination page. */ 2681e9ea7e0SNamjae Jeon dp = dest_pages[*dest_index]; 2691e9ea7e0SNamjae Jeon if (!dp) { 2701e9ea7e0SNamjae Jeon /* No page present. Skip decompression of this sub-block. */ 2711e9ea7e0SNamjae Jeon cb = cb_sb_end; 2721e9ea7e0SNamjae Jeon 2731e9ea7e0SNamjae Jeon /* Advance destination position to next sub-block. */ 2741e9ea7e0SNamjae Jeon *dest_ofs = (*dest_ofs + NTFS_SB_SIZE) & ~PAGE_MASK; 2751e9ea7e0SNamjae Jeon if (!*dest_ofs && (++*dest_index > dest_max_index)) 2761e9ea7e0SNamjae Jeon goto return_overflow; 2771e9ea7e0SNamjae Jeon goto do_next_sb; 2781e9ea7e0SNamjae Jeon } 2791e9ea7e0SNamjae Jeon 2801e9ea7e0SNamjae Jeon /* We have a valid destination page. Setup the destination pointers. */ 2811e9ea7e0SNamjae Jeon dp_addr = (u8 *)page_address(dp) + do_sb_start; 2821e9ea7e0SNamjae Jeon 2831e9ea7e0SNamjae Jeon /* Now, we are ready to process the current sub-block (sb). */ 284495e90faSNamjae Jeon if (!(le16_to_cpup((__le16 *)cb) & NTFS_SB_IS_COMPRESSED)) { 2851e9ea7e0SNamjae Jeon ntfs_debug("Found uncompressed sub-block."); 2861e9ea7e0SNamjae Jeon /* This sb is not compressed, just copy it into destination. */ 2871e9ea7e0SNamjae Jeon 2881e9ea7e0SNamjae Jeon /* Advance source position to first data byte. */ 2891e9ea7e0SNamjae Jeon cb += 2; 2901e9ea7e0SNamjae Jeon 2911e9ea7e0SNamjae Jeon /* An uncompressed sb must be full size. */ 2921e9ea7e0SNamjae Jeon if (cb_sb_end - cb != NTFS_SB_SIZE) 2931e9ea7e0SNamjae Jeon goto return_overflow; 2941e9ea7e0SNamjae Jeon 2951e9ea7e0SNamjae Jeon /* Copy the block and advance the source position. */ 2961e9ea7e0SNamjae Jeon memcpy(dp_addr, cb, NTFS_SB_SIZE); 2971e9ea7e0SNamjae Jeon cb += NTFS_SB_SIZE; 2981e9ea7e0SNamjae Jeon 2991e9ea7e0SNamjae Jeon /* Advance destination position to next sub-block. */ 3001e9ea7e0SNamjae Jeon *dest_ofs += NTFS_SB_SIZE; 301495e90faSNamjae Jeon *dest_ofs &= ~PAGE_MASK; 302495e90faSNamjae Jeon if (!(*dest_ofs)) { 3031e9ea7e0SNamjae Jeon finalize_page: 3041e9ea7e0SNamjae Jeon /* 3051e9ea7e0SNamjae Jeon * First stage: add current page index to array of 3061e9ea7e0SNamjae Jeon * completed pages. 3071e9ea7e0SNamjae Jeon */ 3081e9ea7e0SNamjae Jeon completed_pages[nr_completed_pages++] = *dest_index; 3091e9ea7e0SNamjae Jeon if (++*dest_index > dest_max_index) 3101e9ea7e0SNamjae Jeon goto return_overflow; 3111e9ea7e0SNamjae Jeon } 3121e9ea7e0SNamjae Jeon goto do_next_sb; 3131e9ea7e0SNamjae Jeon } 3141e9ea7e0SNamjae Jeon ntfs_debug("Found compressed sub-block."); 3151e9ea7e0SNamjae Jeon /* This sb is compressed, decompress it into destination. */ 3161e9ea7e0SNamjae Jeon 3171e9ea7e0SNamjae Jeon /* Setup destination pointers. */ 3181e9ea7e0SNamjae Jeon dp_sb_start = dp_addr; 3191e9ea7e0SNamjae Jeon dp_sb_end = dp_sb_start + NTFS_SB_SIZE; 3201e9ea7e0SNamjae Jeon 3211e9ea7e0SNamjae Jeon /* Forward to the first tag in the sub-block. */ 3221e9ea7e0SNamjae Jeon cb += 2; 3231e9ea7e0SNamjae Jeon do_next_tag: 3241e9ea7e0SNamjae Jeon if (cb == cb_sb_end) { 3251e9ea7e0SNamjae Jeon /* Check if the decompressed sub-block was not full-length. */ 3261e9ea7e0SNamjae Jeon if (dp_addr < dp_sb_end) { 3271e9ea7e0SNamjae Jeon int nr_bytes = do_sb_end - *dest_ofs; 3281e9ea7e0SNamjae Jeon 329495e90faSNamjae Jeon ntfs_debug("Filling incomplete sub-block with zeroes."); 3301e9ea7e0SNamjae Jeon /* Zero remainder and update destination position. */ 3311e9ea7e0SNamjae Jeon memset(dp_addr, 0, nr_bytes); 3321e9ea7e0SNamjae Jeon *dest_ofs += nr_bytes; 3331e9ea7e0SNamjae Jeon } 3341e9ea7e0SNamjae Jeon /* We have finished the current sub-block. */ 335495e90faSNamjae Jeon *dest_ofs &= ~PAGE_MASK; 336495e90faSNamjae Jeon if (!(*dest_ofs)) 3371e9ea7e0SNamjae Jeon goto finalize_page; 3381e9ea7e0SNamjae Jeon goto do_next_sb; 3391e9ea7e0SNamjae Jeon } 3401e9ea7e0SNamjae Jeon 3411e9ea7e0SNamjae Jeon /* Check we are still in range. */ 3421e9ea7e0SNamjae Jeon if (cb > cb_sb_end || dp_addr > dp_sb_end) 3431e9ea7e0SNamjae Jeon goto return_overflow; 3441e9ea7e0SNamjae Jeon 3451e9ea7e0SNamjae Jeon /* Get the next tag and advance to first token. */ 3461e9ea7e0SNamjae Jeon tag = *cb++; 3471e9ea7e0SNamjae Jeon 3481e9ea7e0SNamjae Jeon /* Parse the eight tokens described by the tag. */ 3491e9ea7e0SNamjae Jeon for (token = 0; token < 8; token++, tag >>= 1) { 3501e9ea7e0SNamjae Jeon register u16 i; 351495e90faSNamjae Jeon u16 lg, pt, length, max_non_overlap; 3521e9ea7e0SNamjae Jeon u8 *dp_back_addr; 3531e9ea7e0SNamjae Jeon 3541e9ea7e0SNamjae Jeon /* Check if we are done / still in range. */ 3551e9ea7e0SNamjae Jeon if (cb >= cb_sb_end || dp_addr > dp_sb_end) 3561e9ea7e0SNamjae Jeon break; 3571e9ea7e0SNamjae Jeon 3581e9ea7e0SNamjae Jeon /* Determine token type and parse appropriately.*/ 3591e9ea7e0SNamjae Jeon if ((tag & NTFS_TOKEN_MASK) == NTFS_SYMBOL_TOKEN) { 3601e9ea7e0SNamjae Jeon /* 3611e9ea7e0SNamjae Jeon * We have a symbol token, copy the symbol across, and 3621e9ea7e0SNamjae Jeon * advance the source and destination positions. 3631e9ea7e0SNamjae Jeon */ 3641e9ea7e0SNamjae Jeon *dp_addr++ = *cb++; 3651e9ea7e0SNamjae Jeon ++*dest_ofs; 3661e9ea7e0SNamjae Jeon 3671e9ea7e0SNamjae Jeon /* Continue with the next token. */ 3681e9ea7e0SNamjae Jeon continue; 3691e9ea7e0SNamjae Jeon } 3701e9ea7e0SNamjae Jeon 3711e9ea7e0SNamjae Jeon /* 3721e9ea7e0SNamjae Jeon * We have a phrase token. Make sure it is not the first tag in 3731e9ea7e0SNamjae Jeon * the sb as this is illegal and would confuse the code below. 3741e9ea7e0SNamjae Jeon */ 3751e9ea7e0SNamjae Jeon if (dp_addr == dp_sb_start) 3761e9ea7e0SNamjae Jeon goto return_overflow; 3771e9ea7e0SNamjae Jeon 3781e9ea7e0SNamjae Jeon /* 3791e9ea7e0SNamjae Jeon * Determine the number of bytes to go back (p) and the number 3801e9ea7e0SNamjae Jeon * of bytes to copy (l). We use an optimized algorithm in which 3811e9ea7e0SNamjae Jeon * we first calculate log2(current destination position in sb), 3821e9ea7e0SNamjae Jeon * which allows determination of l and p in O(1) rather than 3831e9ea7e0SNamjae Jeon * O(n). We just need an arch-optimized log2() function now. 3841e9ea7e0SNamjae Jeon */ 3851e9ea7e0SNamjae Jeon lg = 0; 3861e9ea7e0SNamjae Jeon for (i = *dest_ofs - do_sb_start - 1; i >= 0x10; i >>= 1) 3871e9ea7e0SNamjae Jeon lg++; 3881e9ea7e0SNamjae Jeon 3891e9ea7e0SNamjae Jeon /* Get the phrase token into i. */ 390495e90faSNamjae Jeon pt = le16_to_cpup((__le16 *)cb); 3911e9ea7e0SNamjae Jeon 3921e9ea7e0SNamjae Jeon /* 3931e9ea7e0SNamjae Jeon * Calculate starting position of the byte sequence in 3941e9ea7e0SNamjae Jeon * the destination using the fact that p = (pt >> (12 - lg)) + 1 3951e9ea7e0SNamjae Jeon * and make sure we don't go too far back. 3961e9ea7e0SNamjae Jeon */ 3971e9ea7e0SNamjae Jeon dp_back_addr = dp_addr - (pt >> (12 - lg)) - 1; 3981e9ea7e0SNamjae Jeon if (dp_back_addr < dp_sb_start) 3991e9ea7e0SNamjae Jeon goto return_overflow; 4001e9ea7e0SNamjae Jeon 4011e9ea7e0SNamjae Jeon /* Now calculate the length of the byte sequence. */ 4021e9ea7e0SNamjae Jeon length = (pt & (0xfff >> lg)) + 3; 4031e9ea7e0SNamjae Jeon 4041e9ea7e0SNamjae Jeon /* Advance destination position and verify it is in range. */ 4051e9ea7e0SNamjae Jeon *dest_ofs += length; 4061e9ea7e0SNamjae Jeon if (*dest_ofs > do_sb_end) 4071e9ea7e0SNamjae Jeon goto return_overflow; 4081e9ea7e0SNamjae Jeon 4091e9ea7e0SNamjae Jeon /* The number of non-overlapping bytes. */ 4101e9ea7e0SNamjae Jeon max_non_overlap = dp_addr - dp_back_addr; 4111e9ea7e0SNamjae Jeon 4121e9ea7e0SNamjae Jeon if (length <= max_non_overlap) { 4131e9ea7e0SNamjae Jeon /* The byte sequence doesn't overlap, just copy it. */ 4141e9ea7e0SNamjae Jeon memcpy(dp_addr, dp_back_addr, length); 4151e9ea7e0SNamjae Jeon 4161e9ea7e0SNamjae Jeon /* Advance destination pointer. */ 4171e9ea7e0SNamjae Jeon dp_addr += length; 4181e9ea7e0SNamjae Jeon } else { 4191e9ea7e0SNamjae Jeon /* 4201e9ea7e0SNamjae Jeon * The byte sequence does overlap, copy non-overlapping 4211e9ea7e0SNamjae Jeon * part and then do a slow byte by byte copy for the 4221e9ea7e0SNamjae Jeon * overlapping part. Also, advance the destination 4231e9ea7e0SNamjae Jeon * pointer. 4241e9ea7e0SNamjae Jeon */ 4251e9ea7e0SNamjae Jeon memcpy(dp_addr, dp_back_addr, max_non_overlap); 4261e9ea7e0SNamjae Jeon dp_addr += max_non_overlap; 4271e9ea7e0SNamjae Jeon dp_back_addr += max_non_overlap; 4281e9ea7e0SNamjae Jeon length -= max_non_overlap; 4291e9ea7e0SNamjae Jeon while (length--) 4301e9ea7e0SNamjae Jeon *dp_addr++ = *dp_back_addr++; 4311e9ea7e0SNamjae Jeon } 4321e9ea7e0SNamjae Jeon 4331e9ea7e0SNamjae Jeon /* Advance source position and continue with the next token. */ 4341e9ea7e0SNamjae Jeon cb += 2; 4351e9ea7e0SNamjae Jeon } 4361e9ea7e0SNamjae Jeon 4371e9ea7e0SNamjae Jeon /* No tokens left in the current tag. Continue with the next tag. */ 4381e9ea7e0SNamjae Jeon goto do_next_tag; 4391e9ea7e0SNamjae Jeon 4401e9ea7e0SNamjae Jeon return_overflow: 4411e9ea7e0SNamjae Jeon ntfs_error(NULL, "Failed. Returning -EOVERFLOW."); 4421e9ea7e0SNamjae Jeon goto return_error; 4431e9ea7e0SNamjae Jeon } 4441e9ea7e0SNamjae Jeon 445495e90faSNamjae Jeon /* 4461e9ea7e0SNamjae Jeon * ntfs_read_compressed_block - read a compressed block into the page cache 447495e90faSNamjae Jeon * @folio: locked folio in the compression block(s) we need to read 4481e9ea7e0SNamjae Jeon * 4491e9ea7e0SNamjae Jeon * When we are called the page has already been verified to be locked and the 4501e9ea7e0SNamjae Jeon * attribute is known to be non-resident, not encrypted, but compressed. 4511e9ea7e0SNamjae Jeon * 4521e9ea7e0SNamjae Jeon * 1. Determine which compression block(s) @page is in. 4531e9ea7e0SNamjae Jeon * 2. Get hold of all pages corresponding to this/these compression block(s). 4541e9ea7e0SNamjae Jeon * 3. Read the (first) compression block. 4551e9ea7e0SNamjae Jeon * 4. Decompress it into the corresponding pages. 4561e9ea7e0SNamjae Jeon * 5. Throw the compressed data away and proceed to 3. for the next compression 4571e9ea7e0SNamjae Jeon * block or return success if no more compression blocks left. 4581e9ea7e0SNamjae Jeon * 4591e9ea7e0SNamjae Jeon * Warning: We have to be careful what we do about existing pages. They might 4601e9ea7e0SNamjae Jeon * have been written to so that we would lose data if we were to just overwrite 4611e9ea7e0SNamjae Jeon * them with the out-of-date uncompressed data. 4621e9ea7e0SNamjae Jeon */ 463495e90faSNamjae Jeon int ntfs_read_compressed_block(struct folio *folio) 4641e9ea7e0SNamjae Jeon { 465495e90faSNamjae Jeon struct page *page = &folio->page; 4661e9ea7e0SNamjae Jeon loff_t i_size; 4671e9ea7e0SNamjae Jeon s64 initialized_size; 4681e9ea7e0SNamjae Jeon struct address_space *mapping = page->mapping; 469495e90faSNamjae Jeon struct ntfs_inode *ni = NTFS_I(mapping->host); 470495e90faSNamjae Jeon struct ntfs_volume *vol = ni->vol; 4711e9ea7e0SNamjae Jeon struct super_block *sb = vol->sb; 472495e90faSNamjae Jeon struct runlist_element *rl; 473495e90faSNamjae Jeon unsigned long flags; 4741e9ea7e0SNamjae Jeon u8 *cb, *cb_pos, *cb_end; 475495e90faSNamjae Jeon unsigned long offset, index = page->__folio_index; 4761e9ea7e0SNamjae Jeon u32 cb_size = ni->itype.compressed.block_size; 4771e9ea7e0SNamjae Jeon u64 cb_size_mask = cb_size - 1UL; 478495e90faSNamjae Jeon s64 vcn; 479495e90faSNamjae Jeon s64 lcn; 4801e9ea7e0SNamjae Jeon /* The first wanted vcn (minimum alignment is PAGE_SIZE). */ 481495e90faSNamjae Jeon s64 start_vcn = (((s64)index << PAGE_SHIFT) & ~cb_size_mask) >> 4821e9ea7e0SNamjae Jeon vol->cluster_size_bits; 4831e9ea7e0SNamjae Jeon /* 4841e9ea7e0SNamjae Jeon * The first vcn after the last wanted vcn (minimum alignment is again 4851e9ea7e0SNamjae Jeon * PAGE_SIZE. 4861e9ea7e0SNamjae Jeon */ 487495e90faSNamjae Jeon s64 end_vcn = ((((s64)(index + 1UL) << PAGE_SHIFT) + cb_size - 1) 4881e9ea7e0SNamjae Jeon & ~cb_size_mask) >> vol->cluster_size_bits; 4891e9ea7e0SNamjae Jeon /* Number of compression blocks (cbs) in the wanted vcn range. */ 490495e90faSNamjae Jeon unsigned int nr_cbs = ntfs_cluster_to_bytes(vol, end_vcn - start_vcn) >> 491495e90faSNamjae Jeon ni->itype.compressed.block_size_bits; 4921e9ea7e0SNamjae Jeon /* 4931e9ea7e0SNamjae Jeon * Number of pages required to store the uncompressed data from all 4941e9ea7e0SNamjae Jeon * compression blocks (cbs) overlapping @page. Due to alignment 4951e9ea7e0SNamjae Jeon * guarantees of start_vcn and end_vcn, no need to round up here. 4961e9ea7e0SNamjae Jeon */ 497495e90faSNamjae Jeon unsigned int nr_pages = ntfs_cluster_to_pidx(vol, end_vcn - start_vcn); 498495e90faSNamjae Jeon unsigned int xpage, max_page, cur_page, cur_ofs, i, page_ofs, page_index; 4991e9ea7e0SNamjae Jeon unsigned int cb_clusters, cb_max_ofs; 500495e90faSNamjae Jeon int cb_max_page, err = 0; 5011e9ea7e0SNamjae Jeon struct page **pages; 5021e9ea7e0SNamjae Jeon int *completed_pages; 5031e9ea7e0SNamjae Jeon unsigned char xpage_done = 0; 504495e90faSNamjae Jeon struct page *lpage; 5051e9ea7e0SNamjae Jeon 506495e90faSNamjae Jeon ntfs_debug("Entering, page->index = 0x%lx, cb_size = 0x%x, nr_pages = %i.", 507495e90faSNamjae Jeon index, cb_size, nr_pages); 5081e9ea7e0SNamjae Jeon /* 5091e9ea7e0SNamjae Jeon * Bad things happen if we get here for anything that is not an 5101e9ea7e0SNamjae Jeon * unnamed $DATA attribute. 5111e9ea7e0SNamjae Jeon */ 512495e90faSNamjae Jeon if (ni->type != AT_DATA || ni->name_len) { 513495e90faSNamjae Jeon unlock_page(page); 514495e90faSNamjae Jeon return -EIO; 515495e90faSNamjae Jeon } 5161e9ea7e0SNamjae Jeon 5171e9ea7e0SNamjae Jeon pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_NOFS); 5181e9ea7e0SNamjae Jeon completed_pages = kmalloc_array(nr_pages + 1, sizeof(int), GFP_NOFS); 5191e9ea7e0SNamjae Jeon 520495e90faSNamjae Jeon if (unlikely(!pages || !completed_pages)) { 5211e9ea7e0SNamjae Jeon kfree(pages); 5221e9ea7e0SNamjae Jeon kfree(completed_pages); 5231e9ea7e0SNamjae Jeon unlock_page(page); 5241e9ea7e0SNamjae Jeon ntfs_error(vol->sb, "Failed to allocate internal buffers."); 5251e9ea7e0SNamjae Jeon return -ENOMEM; 5261e9ea7e0SNamjae Jeon } 5271e9ea7e0SNamjae Jeon 5281e9ea7e0SNamjae Jeon /* 5291e9ea7e0SNamjae Jeon * We have already been given one page, this is the one we must do. 5301e9ea7e0SNamjae Jeon * Once again, the alignment guarantees keep it simple. 5311e9ea7e0SNamjae Jeon */ 532495e90faSNamjae Jeon offset = ntfs_cluster_to_pidx(vol, start_vcn); 5331e9ea7e0SNamjae Jeon xpage = index - offset; 5341e9ea7e0SNamjae Jeon pages[xpage] = page; 5351e9ea7e0SNamjae Jeon /* 5361e9ea7e0SNamjae Jeon * The remaining pages need to be allocated and inserted into the page 5371e9ea7e0SNamjae Jeon * cache, alignment guarantees keep all the below much simpler. (-8 5381e9ea7e0SNamjae Jeon */ 5391e9ea7e0SNamjae Jeon read_lock_irqsave(&ni->size_lock, flags); 5401e9ea7e0SNamjae Jeon i_size = i_size_read(VFS_I(ni)); 5411e9ea7e0SNamjae Jeon initialized_size = ni->initialized_size; 5421e9ea7e0SNamjae Jeon read_unlock_irqrestore(&ni->size_lock, flags); 5431e9ea7e0SNamjae Jeon max_page = ((i_size + PAGE_SIZE - 1) >> PAGE_SHIFT) - 5441e9ea7e0SNamjae Jeon offset; 5451e9ea7e0SNamjae Jeon /* Is the page fully outside i_size? (truncate in progress) */ 5461e9ea7e0SNamjae Jeon if (xpage >= max_page) { 5471e9ea7e0SNamjae Jeon kfree(pages); 5481e9ea7e0SNamjae Jeon kfree(completed_pages); 549495e90faSNamjae Jeon zero_user_segments(page, 0, PAGE_SIZE, 0, 0); 5501e9ea7e0SNamjae Jeon ntfs_debug("Compressed read outside i_size - truncated?"); 5511e9ea7e0SNamjae Jeon SetPageUptodate(page); 5521e9ea7e0SNamjae Jeon unlock_page(page); 5531e9ea7e0SNamjae Jeon return 0; 5541e9ea7e0SNamjae Jeon } 5551e9ea7e0SNamjae Jeon if (nr_pages < max_page) 5561e9ea7e0SNamjae Jeon max_page = nr_pages; 557495e90faSNamjae Jeon 5581e9ea7e0SNamjae Jeon for (i = 0; i < max_page; i++, offset++) { 5591e9ea7e0SNamjae Jeon if (i != xpage) 5601e9ea7e0SNamjae Jeon pages[i] = grab_cache_page_nowait(mapping, offset); 5611e9ea7e0SNamjae Jeon page = pages[i]; 5621e9ea7e0SNamjae Jeon if (page) { 5631e9ea7e0SNamjae Jeon /* 5641e9ea7e0SNamjae Jeon * We only (re)read the page if it isn't already read 5651e9ea7e0SNamjae Jeon * in and/or dirty or we would be losing data or at 5661e9ea7e0SNamjae Jeon * least wasting our time. 5671e9ea7e0SNamjae Jeon */ 568495e90faSNamjae Jeon if (!PageDirty(page) && (!PageUptodate(page))) { 569495e90faSNamjae Jeon kmap_local_page(page); 5701e9ea7e0SNamjae Jeon continue; 5711e9ea7e0SNamjae Jeon } 5721e9ea7e0SNamjae Jeon unlock_page(page); 5731e9ea7e0SNamjae Jeon put_page(page); 5741e9ea7e0SNamjae Jeon pages[i] = NULL; 5751e9ea7e0SNamjae Jeon } 5761e9ea7e0SNamjae Jeon } 5771e9ea7e0SNamjae Jeon 5781e9ea7e0SNamjae Jeon /* 5791e9ea7e0SNamjae Jeon * We have the runlist, and all the destination pages we need to fill. 5801e9ea7e0SNamjae Jeon * Now read the first compression block. 5811e9ea7e0SNamjae Jeon */ 5821e9ea7e0SNamjae Jeon cur_page = 0; 5831e9ea7e0SNamjae Jeon cur_ofs = 0; 5841e9ea7e0SNamjae Jeon cb_clusters = ni->itype.compressed.block_clusters; 5851e9ea7e0SNamjae Jeon do_next_cb: 5861e9ea7e0SNamjae Jeon nr_cbs--; 5871e9ea7e0SNamjae Jeon 588495e90faSNamjae Jeon mutex_lock(&ntfs_cb_lock); 589495e90faSNamjae Jeon if (!ntfs_compression_buffer) 590495e90faSNamjae Jeon if (allocate_compression_buffers()) { 591495e90faSNamjae Jeon mutex_unlock(&ntfs_cb_lock); 592495e90faSNamjae Jeon goto err_out; 593495e90faSNamjae Jeon } 594495e90faSNamjae Jeon 595495e90faSNamjae Jeon 596495e90faSNamjae Jeon cb = ntfs_compression_buffer; 597495e90faSNamjae Jeon cb_pos = cb; 598495e90faSNamjae Jeon cb_end = cb + cb_size; 599495e90faSNamjae Jeon 6001e9ea7e0SNamjae Jeon rl = NULL; 6011e9ea7e0SNamjae Jeon for (vcn = start_vcn, start_vcn += cb_clusters; vcn < start_vcn; 6021e9ea7e0SNamjae Jeon vcn++) { 6031e9ea7e0SNamjae Jeon bool is_retry = false; 6041e9ea7e0SNamjae Jeon 6051e9ea7e0SNamjae Jeon if (!rl) { 6061e9ea7e0SNamjae Jeon lock_retry_remap: 6071e9ea7e0SNamjae Jeon down_read(&ni->runlist.lock); 6081e9ea7e0SNamjae Jeon rl = ni->runlist.rl; 6091e9ea7e0SNamjae Jeon } 6101e9ea7e0SNamjae Jeon if (likely(rl != NULL)) { 6111e9ea7e0SNamjae Jeon /* Seek to element containing target vcn. */ 6121e9ea7e0SNamjae Jeon while (rl->length && rl[1].vcn <= vcn) 6131e9ea7e0SNamjae Jeon rl++; 6141e9ea7e0SNamjae Jeon lcn = ntfs_rl_vcn_to_lcn(rl, vcn); 6151e9ea7e0SNamjae Jeon } else 6161e9ea7e0SNamjae Jeon lcn = LCN_RL_NOT_MAPPED; 6171e9ea7e0SNamjae Jeon ntfs_debug("Reading vcn = 0x%llx, lcn = 0x%llx.", 6181e9ea7e0SNamjae Jeon (unsigned long long)vcn, 6191e9ea7e0SNamjae Jeon (unsigned long long)lcn); 6201e9ea7e0SNamjae Jeon if (lcn < 0) { 6211e9ea7e0SNamjae Jeon /* 6221e9ea7e0SNamjae Jeon * When we reach the first sparse cluster we have 6231e9ea7e0SNamjae Jeon * finished with the cb. 6241e9ea7e0SNamjae Jeon */ 6251e9ea7e0SNamjae Jeon if (lcn == LCN_HOLE) 6261e9ea7e0SNamjae Jeon break; 627495e90faSNamjae Jeon if (is_retry || lcn != LCN_RL_NOT_MAPPED) { 628495e90faSNamjae Jeon mutex_unlock(&ntfs_cb_lock); 6291e9ea7e0SNamjae Jeon goto rl_err; 630495e90faSNamjae Jeon } 6311e9ea7e0SNamjae Jeon is_retry = true; 6321e9ea7e0SNamjae Jeon /* 6331e9ea7e0SNamjae Jeon * Attempt to map runlist, dropping lock for the 6341e9ea7e0SNamjae Jeon * duration. 6351e9ea7e0SNamjae Jeon */ 6361e9ea7e0SNamjae Jeon up_read(&ni->runlist.lock); 6371e9ea7e0SNamjae Jeon if (!ntfs_map_runlist(ni, vcn)) 6381e9ea7e0SNamjae Jeon goto lock_retry_remap; 639495e90faSNamjae Jeon mutex_unlock(&ntfs_cb_lock); 6401e9ea7e0SNamjae Jeon goto map_rl_err; 6411e9ea7e0SNamjae Jeon } 642495e90faSNamjae Jeon 643495e90faSNamjae Jeon page_ofs = ntfs_cluster_to_poff(vol, lcn); 644495e90faSNamjae Jeon page_index = ntfs_cluster_to_pidx(vol, lcn); 645495e90faSNamjae Jeon 646495e90faSNamjae Jeon lpage = read_mapping_page(sb->s_bdev->bd_mapping, 647495e90faSNamjae Jeon page_index, NULL); 648495e90faSNamjae Jeon if (IS_ERR(lpage)) { 649495e90faSNamjae Jeon err = PTR_ERR(lpage); 650495e90faSNamjae Jeon mutex_unlock(&ntfs_cb_lock); 651495e90faSNamjae Jeon goto read_err; 652495e90faSNamjae Jeon } 653495e90faSNamjae Jeon 654495e90faSNamjae Jeon lock_page(lpage); 655495e90faSNamjae Jeon memcpy(cb_pos, page_address(lpage) + page_ofs, 656495e90faSNamjae Jeon vol->cluster_size); 657495e90faSNamjae Jeon unlock_page(lpage); 658495e90faSNamjae Jeon put_page(lpage); 659495e90faSNamjae Jeon cb_pos += vol->cluster_size; 6601e9ea7e0SNamjae Jeon } 6611e9ea7e0SNamjae Jeon 6621e9ea7e0SNamjae Jeon /* Release the lock if we took it. */ 6631e9ea7e0SNamjae Jeon if (rl) 6641e9ea7e0SNamjae Jeon up_read(&ni->runlist.lock); 6651e9ea7e0SNamjae Jeon 6661e9ea7e0SNamjae Jeon /* Just a precaution. */ 6671e9ea7e0SNamjae Jeon if (cb_pos + 2 <= cb + cb_size) 6681e9ea7e0SNamjae Jeon *(u16 *)cb_pos = 0; 6691e9ea7e0SNamjae Jeon 6701e9ea7e0SNamjae Jeon /* Reset cb_pos back to the beginning. */ 6711e9ea7e0SNamjae Jeon cb_pos = cb; 6721e9ea7e0SNamjae Jeon 6731e9ea7e0SNamjae Jeon /* We now have both source (if present) and destination. */ 6741e9ea7e0SNamjae Jeon ntfs_debug("Successfully read the compression block."); 6751e9ea7e0SNamjae Jeon 6761e9ea7e0SNamjae Jeon /* The last page and maximum offset within it for the current cb. */ 6771e9ea7e0SNamjae Jeon cb_max_page = (cur_page << PAGE_SHIFT) + cur_ofs + cb_size; 6781e9ea7e0SNamjae Jeon cb_max_ofs = cb_max_page & ~PAGE_MASK; 6791e9ea7e0SNamjae Jeon cb_max_page >>= PAGE_SHIFT; 6801e9ea7e0SNamjae Jeon 6811e9ea7e0SNamjae Jeon /* Catch end of file inside a compression block. */ 6821e9ea7e0SNamjae Jeon if (cb_max_page > max_page) 6831e9ea7e0SNamjae Jeon cb_max_page = max_page; 6841e9ea7e0SNamjae Jeon 6851e9ea7e0SNamjae Jeon if (vcn == start_vcn - cb_clusters) { 6861e9ea7e0SNamjae Jeon /* Sparse cb, zero out page range overlapping the cb. */ 6871e9ea7e0SNamjae Jeon ntfs_debug("Found sparse compression block."); 6881e9ea7e0SNamjae Jeon /* We can sleep from now on, so we drop lock. */ 689495e90faSNamjae Jeon mutex_unlock(&ntfs_cb_lock); 6901e9ea7e0SNamjae Jeon if (cb_max_ofs) 6911e9ea7e0SNamjae Jeon cb_max_page--; 6921e9ea7e0SNamjae Jeon for (; cur_page < cb_max_page; cur_page++) { 6931e9ea7e0SNamjae Jeon page = pages[cur_page]; 6941e9ea7e0SNamjae Jeon if (page) { 6951e9ea7e0SNamjae Jeon if (likely(!cur_ofs)) 6961e9ea7e0SNamjae Jeon clear_page(page_address(page)); 6971e9ea7e0SNamjae Jeon else 6981e9ea7e0SNamjae Jeon memset(page_address(page) + cur_ofs, 0, 6991e9ea7e0SNamjae Jeon PAGE_SIZE - 7001e9ea7e0SNamjae Jeon cur_ofs); 7011e9ea7e0SNamjae Jeon flush_dcache_page(page); 702495e90faSNamjae Jeon kunmap_local(page_address(page)); 7031e9ea7e0SNamjae Jeon SetPageUptodate(page); 7041e9ea7e0SNamjae Jeon unlock_page(page); 7051e9ea7e0SNamjae Jeon if (cur_page == xpage) 7061e9ea7e0SNamjae Jeon xpage_done = 1; 7071e9ea7e0SNamjae Jeon else 7081e9ea7e0SNamjae Jeon put_page(page); 7091e9ea7e0SNamjae Jeon pages[cur_page] = NULL; 7101e9ea7e0SNamjae Jeon } 7111e9ea7e0SNamjae Jeon cb_pos += PAGE_SIZE - cur_ofs; 7121e9ea7e0SNamjae Jeon cur_ofs = 0; 7131e9ea7e0SNamjae Jeon if (cb_pos >= cb_end) 7141e9ea7e0SNamjae Jeon break; 7151e9ea7e0SNamjae Jeon } 7161e9ea7e0SNamjae Jeon /* If we have a partial final page, deal with it now. */ 7171e9ea7e0SNamjae Jeon if (cb_max_ofs && cb_pos < cb_end) { 7181e9ea7e0SNamjae Jeon page = pages[cur_page]; 7191e9ea7e0SNamjae Jeon if (page) 7201e9ea7e0SNamjae Jeon memset(page_address(page) + cur_ofs, 0, 7211e9ea7e0SNamjae Jeon cb_max_ofs - cur_ofs); 7221e9ea7e0SNamjae Jeon /* 7231e9ea7e0SNamjae Jeon * No need to update cb_pos at this stage: 7241e9ea7e0SNamjae Jeon * cb_pos += cb_max_ofs - cur_ofs; 7251e9ea7e0SNamjae Jeon */ 7261e9ea7e0SNamjae Jeon cur_ofs = cb_max_ofs; 7271e9ea7e0SNamjae Jeon } 7281e9ea7e0SNamjae Jeon } else if (vcn == start_vcn) { 7291e9ea7e0SNamjae Jeon /* We can't sleep so we need two stages. */ 7301e9ea7e0SNamjae Jeon unsigned int cur2_page = cur_page; 7311e9ea7e0SNamjae Jeon unsigned int cur_ofs2 = cur_ofs; 7321e9ea7e0SNamjae Jeon u8 *cb_pos2 = cb_pos; 7331e9ea7e0SNamjae Jeon 7341e9ea7e0SNamjae Jeon ntfs_debug("Found uncompressed compression block."); 7351e9ea7e0SNamjae Jeon /* Uncompressed cb, copy it to the destination pages. */ 7361e9ea7e0SNamjae Jeon if (cb_max_ofs) 7371e9ea7e0SNamjae Jeon cb_max_page--; 7381e9ea7e0SNamjae Jeon /* First stage: copy data into destination pages. */ 7391e9ea7e0SNamjae Jeon for (; cur_page < cb_max_page; cur_page++) { 7401e9ea7e0SNamjae Jeon page = pages[cur_page]; 7411e9ea7e0SNamjae Jeon if (page) 7421e9ea7e0SNamjae Jeon memcpy(page_address(page) + cur_ofs, cb_pos, 7431e9ea7e0SNamjae Jeon PAGE_SIZE - cur_ofs); 7441e9ea7e0SNamjae Jeon cb_pos += PAGE_SIZE - cur_ofs; 7451e9ea7e0SNamjae Jeon cur_ofs = 0; 7461e9ea7e0SNamjae Jeon if (cb_pos >= cb_end) 7471e9ea7e0SNamjae Jeon break; 7481e9ea7e0SNamjae Jeon } 7491e9ea7e0SNamjae Jeon /* If we have a partial final page, deal with it now. */ 7501e9ea7e0SNamjae Jeon if (cb_max_ofs && cb_pos < cb_end) { 7511e9ea7e0SNamjae Jeon page = pages[cur_page]; 7521e9ea7e0SNamjae Jeon if (page) 7531e9ea7e0SNamjae Jeon memcpy(page_address(page) + cur_ofs, cb_pos, 7541e9ea7e0SNamjae Jeon cb_max_ofs - cur_ofs); 7551e9ea7e0SNamjae Jeon cb_pos += cb_max_ofs - cur_ofs; 7561e9ea7e0SNamjae Jeon cur_ofs = cb_max_ofs; 7571e9ea7e0SNamjae Jeon } 7581e9ea7e0SNamjae Jeon /* We can sleep from now on, so drop lock. */ 759495e90faSNamjae Jeon mutex_unlock(&ntfs_cb_lock); 7601e9ea7e0SNamjae Jeon /* Second stage: finalize pages. */ 7611e9ea7e0SNamjae Jeon for (; cur2_page < cb_max_page; cur2_page++) { 7621e9ea7e0SNamjae Jeon page = pages[cur2_page]; 7631e9ea7e0SNamjae Jeon if (page) { 7641e9ea7e0SNamjae Jeon /* 7651e9ea7e0SNamjae Jeon * If we are outside the initialized size, zero 7661e9ea7e0SNamjae Jeon * the out of bounds page range. 7671e9ea7e0SNamjae Jeon */ 7681e9ea7e0SNamjae Jeon handle_bounds_compressed_page(page, i_size, 7691e9ea7e0SNamjae Jeon initialized_size); 7701e9ea7e0SNamjae Jeon flush_dcache_page(page); 771495e90faSNamjae Jeon kunmap_local(page_address(page)); 7721e9ea7e0SNamjae Jeon SetPageUptodate(page); 7731e9ea7e0SNamjae Jeon unlock_page(page); 7741e9ea7e0SNamjae Jeon if (cur2_page == xpage) 7751e9ea7e0SNamjae Jeon xpage_done = 1; 7761e9ea7e0SNamjae Jeon else 7771e9ea7e0SNamjae Jeon put_page(page); 7781e9ea7e0SNamjae Jeon pages[cur2_page] = NULL; 7791e9ea7e0SNamjae Jeon } 7801e9ea7e0SNamjae Jeon cb_pos2 += PAGE_SIZE - cur_ofs2; 7811e9ea7e0SNamjae Jeon cur_ofs2 = 0; 7821e9ea7e0SNamjae Jeon if (cb_pos2 >= cb_end) 7831e9ea7e0SNamjae Jeon break; 7841e9ea7e0SNamjae Jeon } 7851e9ea7e0SNamjae Jeon } else { 7861e9ea7e0SNamjae Jeon /* Compressed cb, decompress it into the destination page(s). */ 7871e9ea7e0SNamjae Jeon unsigned int prev_cur_page = cur_page; 7881e9ea7e0SNamjae Jeon 7891e9ea7e0SNamjae Jeon ntfs_debug("Found compressed compression block."); 7901e9ea7e0SNamjae Jeon err = ntfs_decompress(pages, completed_pages, &cur_page, 7911e9ea7e0SNamjae Jeon &cur_ofs, cb_max_page, cb_max_ofs, xpage, 7921e9ea7e0SNamjae Jeon &xpage_done, cb_pos, cb_size - (cb_pos - cb), 7931e9ea7e0SNamjae Jeon i_size, initialized_size); 7941e9ea7e0SNamjae Jeon /* 7951e9ea7e0SNamjae Jeon * We can sleep from now on, lock already dropped by 7961e9ea7e0SNamjae Jeon * ntfs_decompress(). 7971e9ea7e0SNamjae Jeon */ 7981e9ea7e0SNamjae Jeon if (err) { 799495e90faSNamjae Jeon ntfs_error(vol->sb, 800*d9038d99SNamjae Jeon "ntfs_decompress() failed in inode 0x%llx with error code %i. Skipping this compression block.", 8011e9ea7e0SNamjae Jeon ni->mft_no, -err); 8021e9ea7e0SNamjae Jeon /* Release the unfinished pages. */ 8031e9ea7e0SNamjae Jeon for (; prev_cur_page < cur_page; prev_cur_page++) { 8041e9ea7e0SNamjae Jeon page = pages[prev_cur_page]; 8051e9ea7e0SNamjae Jeon if (page) { 8061e9ea7e0SNamjae Jeon flush_dcache_page(page); 807495e90faSNamjae Jeon kunmap_local(page_address(page)); 8081e9ea7e0SNamjae Jeon unlock_page(page); 8091e9ea7e0SNamjae Jeon if (prev_cur_page != xpage) 8101e9ea7e0SNamjae Jeon put_page(page); 8111e9ea7e0SNamjae Jeon pages[prev_cur_page] = NULL; 8121e9ea7e0SNamjae Jeon } 8131e9ea7e0SNamjae Jeon } 8141e9ea7e0SNamjae Jeon } 8151e9ea7e0SNamjae Jeon } 8161e9ea7e0SNamjae Jeon 8171e9ea7e0SNamjae Jeon /* Do we have more work to do? */ 8181e9ea7e0SNamjae Jeon if (nr_cbs) 8191e9ea7e0SNamjae Jeon goto do_next_cb; 8201e9ea7e0SNamjae Jeon 8211e9ea7e0SNamjae Jeon /* Clean up if we have any pages left. Should never happen. */ 8221e9ea7e0SNamjae Jeon for (cur_page = 0; cur_page < max_page; cur_page++) { 8231e9ea7e0SNamjae Jeon page = pages[cur_page]; 8241e9ea7e0SNamjae Jeon if (page) { 825495e90faSNamjae Jeon ntfs_error(vol->sb, 826*d9038d99SNamjae Jeon "Still have pages left! Terminating them with extreme prejudice. Inode 0x%llx, page index 0x%lx.", 827495e90faSNamjae Jeon ni->mft_no, page->__folio_index); 8281e9ea7e0SNamjae Jeon flush_dcache_page(page); 829495e90faSNamjae Jeon kunmap_local(page_address(page)); 8301e9ea7e0SNamjae Jeon unlock_page(page); 8311e9ea7e0SNamjae Jeon if (cur_page != xpage) 8321e9ea7e0SNamjae Jeon put_page(page); 8331e9ea7e0SNamjae Jeon pages[cur_page] = NULL; 8341e9ea7e0SNamjae Jeon } 8351e9ea7e0SNamjae Jeon } 8361e9ea7e0SNamjae Jeon 8371e9ea7e0SNamjae Jeon /* We no longer need the list of pages. */ 8381e9ea7e0SNamjae Jeon kfree(pages); 8391e9ea7e0SNamjae Jeon kfree(completed_pages); 8401e9ea7e0SNamjae Jeon 8411e9ea7e0SNamjae Jeon /* If we have completed the requested page, we return success. */ 8421e9ea7e0SNamjae Jeon if (likely(xpage_done)) 8431e9ea7e0SNamjae Jeon return 0; 8441e9ea7e0SNamjae Jeon 8451e9ea7e0SNamjae Jeon ntfs_debug("Failed. Returning error code %s.", err == -EOVERFLOW ? 8461e9ea7e0SNamjae Jeon "EOVERFLOW" : (!err ? "EIO" : "unknown error")); 8471e9ea7e0SNamjae Jeon return err < 0 ? err : -EIO; 8481e9ea7e0SNamjae Jeon 8491e9ea7e0SNamjae Jeon map_rl_err: 850495e90faSNamjae Jeon ntfs_error(vol->sb, "ntfs_map_runlist() failed. Cannot read compression block."); 8511e9ea7e0SNamjae Jeon goto err_out; 8521e9ea7e0SNamjae Jeon 8531e9ea7e0SNamjae Jeon rl_err: 8541e9ea7e0SNamjae Jeon up_read(&ni->runlist.lock); 855495e90faSNamjae Jeon ntfs_error(vol->sb, "ntfs_rl_vcn_to_lcn() failed. Cannot read compression block."); 8561e9ea7e0SNamjae Jeon goto err_out; 8571e9ea7e0SNamjae Jeon 858495e90faSNamjae Jeon read_err: 8591e9ea7e0SNamjae Jeon up_read(&ni->runlist.lock); 860495e90faSNamjae Jeon ntfs_error(vol->sb, "IO error while reading compressed data."); 8611e9ea7e0SNamjae Jeon 8621e9ea7e0SNamjae Jeon err_out: 8631e9ea7e0SNamjae Jeon for (i = cur_page; i < max_page; i++) { 8641e9ea7e0SNamjae Jeon page = pages[i]; 8651e9ea7e0SNamjae Jeon if (page) { 8661e9ea7e0SNamjae Jeon flush_dcache_page(page); 867495e90faSNamjae Jeon kunmap_local(page_address(page)); 8681e9ea7e0SNamjae Jeon unlock_page(page); 8691e9ea7e0SNamjae Jeon if (i != xpage) 8701e9ea7e0SNamjae Jeon put_page(page); 8711e9ea7e0SNamjae Jeon } 8721e9ea7e0SNamjae Jeon } 8731e9ea7e0SNamjae Jeon kfree(pages); 8741e9ea7e0SNamjae Jeon kfree(completed_pages); 8751e9ea7e0SNamjae Jeon return -EIO; 8761e9ea7e0SNamjae Jeon } 877495e90faSNamjae Jeon 878495e90faSNamjae Jeon /* 879495e90faSNamjae Jeon * Match length at or above which ntfs_best_match() will stop searching for 880495e90faSNamjae Jeon * longer matches. 881495e90faSNamjae Jeon */ 882495e90faSNamjae Jeon #define NICE_MATCH_LEN 18 883495e90faSNamjae Jeon 884495e90faSNamjae Jeon /* 885495e90faSNamjae Jeon * Maximum number of potential matches that ntfs_best_match() will consider at 886495e90faSNamjae Jeon * each position. 887495e90faSNamjae Jeon */ 888495e90faSNamjae Jeon #define MAX_SEARCH_DEPTH 24 889495e90faSNamjae Jeon 890495e90faSNamjae Jeon /* log base 2 of the number of entries in the hash table for match-finding. */ 891495e90faSNamjae Jeon #define HASH_SHIFT 14 892495e90faSNamjae Jeon 893495e90faSNamjae Jeon /* 894495e90faSNamjae Jeon * Constant for the multiplicative hash function. These hashing constants 895495e90faSNamjae Jeon * are used solely for the match-finding algorithm during compression. 896495e90faSNamjae Jeon * They are NOT part of the on-disk format. The decompressor does not 897495e90faSNamjae Jeon * utilize this hash. 898495e90faSNamjae Jeon */ 899495e90faSNamjae Jeon #define HASH_MULTIPLIER 0x1E35A7BD 900495e90faSNamjae Jeon 901495e90faSNamjae Jeon struct compress_context { 902495e90faSNamjae Jeon const unsigned char *inbuf; 903495e90faSNamjae Jeon int bufsize; 904495e90faSNamjae Jeon int size; 905495e90faSNamjae Jeon int rel; 906495e90faSNamjae Jeon int mxsz; 907495e90faSNamjae Jeon s16 head[1 << HASH_SHIFT]; 908495e90faSNamjae Jeon s16 prev[NTFS_SB_SIZE]; 909495e90faSNamjae Jeon }; 910495e90faSNamjae Jeon 911495e90faSNamjae Jeon /* 912495e90faSNamjae Jeon * Hash the next 3-byte sequence in the input buffer 913495e90faSNamjae Jeon */ 914495e90faSNamjae Jeon static inline unsigned int ntfs_hash(const u8 *p) 915495e90faSNamjae Jeon { 916495e90faSNamjae Jeon u32 str; 917495e90faSNamjae Jeon u32 hash; 918495e90faSNamjae Jeon 919495e90faSNamjae Jeon /* 920495e90faSNamjae Jeon * Unaligned access allowed, and little endian CPU. 921495e90faSNamjae Jeon * Callers ensure that at least 4 (not 3) bytes are remaining. 922495e90faSNamjae Jeon */ 923495e90faSNamjae Jeon str = *(const u32 *)p & 0xFFFFFF; 924495e90faSNamjae Jeon hash = str * HASH_MULTIPLIER; 925495e90faSNamjae Jeon 926495e90faSNamjae Jeon /* High bits are more random than the low bits. */ 927495e90faSNamjae Jeon return hash >> (32 - HASH_SHIFT); 928495e90faSNamjae Jeon } 929495e90faSNamjae Jeon 930495e90faSNamjae Jeon /* 931495e90faSNamjae Jeon * Search for the longest sequence matching current position 932495e90faSNamjae Jeon * 933495e90faSNamjae Jeon * A hash table, each entry of which points to a chain of sequence 934495e90faSNamjae Jeon * positions sharing the corresponding hash code, is maintained to speed up 935495e90faSNamjae Jeon * searching for matches. To maintain the hash table, either 936495e90faSNamjae Jeon * ntfs_best_match() or ntfs_skip_position() has to be called for each 937495e90faSNamjae Jeon * consecutive position. 938495e90faSNamjae Jeon * 939495e90faSNamjae Jeon * This function is heavily used; it has to be optimized carefully. 940495e90faSNamjae Jeon * 941495e90faSNamjae Jeon * This function sets pctx->size and pctx->rel to the length and offset, 942495e90faSNamjae Jeon * respectively, of the longest match found. 943495e90faSNamjae Jeon * 944495e90faSNamjae Jeon * The minimum match length is assumed to be 3, and the maximum match 945495e90faSNamjae Jeon * length is assumed to be pctx->mxsz. If this function produces 946495e90faSNamjae Jeon * pctx->size < 3, then no match was found. 947495e90faSNamjae Jeon * 948495e90faSNamjae Jeon * Note: for the following reasons, this function is not guaranteed to find 949495e90faSNamjae Jeon * *the* longest match up to pctx->mxsz: 950495e90faSNamjae Jeon * 951495e90faSNamjae Jeon * (1) If this function finds a match of NICE_MATCH_LEN bytes or greater, 952495e90faSNamjae Jeon * it ends early because a match this long is good enough and it's not 953495e90faSNamjae Jeon * worth spending more time searching. 954495e90faSNamjae Jeon * 955495e90faSNamjae Jeon * (2) If this function considers MAX_SEARCH_DEPTH matches with a single 956495e90faSNamjae Jeon * position, it ends early and returns the longest match found so far. 957495e90faSNamjae Jeon * This saves a lot of time on degenerate inputs. 958495e90faSNamjae Jeon */ 959495e90faSNamjae Jeon static void ntfs_best_match(struct compress_context *pctx, const int i, 960495e90faSNamjae Jeon int best_len) 961495e90faSNamjae Jeon { 962495e90faSNamjae Jeon const u8 * const inbuf = pctx->inbuf; 963495e90faSNamjae Jeon const u8 * const strptr = &inbuf[i]; /* String we're matching against */ 964495e90faSNamjae Jeon s16 * const prev = pctx->prev; 965495e90faSNamjae Jeon const int max_len = min(pctx->bufsize - i, pctx->mxsz); 966495e90faSNamjae Jeon const int nice_len = min(NICE_MATCH_LEN, max_len); 967495e90faSNamjae Jeon int depth_remaining = MAX_SEARCH_DEPTH; 968495e90faSNamjae Jeon const u8 *best_matchptr = strptr; 969495e90faSNamjae Jeon unsigned int hash; 970495e90faSNamjae Jeon s16 cur_match; 971495e90faSNamjae Jeon const u8 *matchptr; 972495e90faSNamjae Jeon int len; 973495e90faSNamjae Jeon 974495e90faSNamjae Jeon if (max_len < 4) 975495e90faSNamjae Jeon goto out; 976495e90faSNamjae Jeon 977495e90faSNamjae Jeon /* Insert the current sequence into the appropriate hash chain. */ 978495e90faSNamjae Jeon hash = ntfs_hash(strptr); 979495e90faSNamjae Jeon cur_match = pctx->head[hash]; 980495e90faSNamjae Jeon prev[i] = cur_match; 981495e90faSNamjae Jeon pctx->head[hash] = i; 982495e90faSNamjae Jeon 983495e90faSNamjae Jeon if (best_len >= max_len) { 984495e90faSNamjae Jeon /* 985495e90faSNamjae Jeon * Lazy match is being attempted, but there aren't enough length 986495e90faSNamjae Jeon * bits remaining to code a longer match. 987495e90faSNamjae Jeon */ 988495e90faSNamjae Jeon goto out; 989495e90faSNamjae Jeon } 990495e90faSNamjae Jeon 991495e90faSNamjae Jeon /* Search the appropriate hash chain for matches. */ 992495e90faSNamjae Jeon 993495e90faSNamjae Jeon for (; cur_match >= 0 && depth_remaining--; cur_match = prev[cur_match]) { 994495e90faSNamjae Jeon matchptr = &inbuf[cur_match]; 995495e90faSNamjae Jeon 996495e90faSNamjae Jeon /* 997495e90faSNamjae Jeon * Considering the potential match at 'matchptr': is it longer 998495e90faSNamjae Jeon * than 'best_len'? 999495e90faSNamjae Jeon * 1000495e90faSNamjae Jeon * The bytes at index 'best_len' are the most likely to differ, 1001495e90faSNamjae Jeon * so check them first. 1002495e90faSNamjae Jeon * 1003495e90faSNamjae Jeon * The bytes at indices 'best_len - 1' and '0' are less 1004495e90faSNamjae Jeon * important to check separately. But doing so still gives a 1005495e90faSNamjae Jeon * slight performance improvement, at least on x86_64, probably 1006495e90faSNamjae Jeon * because they create separate branches for the CPU to predict 1007495e90faSNamjae Jeon * independently of the branches in the main comparison loops. 1008495e90faSNamjae Jeon */ 1009495e90faSNamjae Jeon if (matchptr[best_len] != strptr[best_len] || 1010495e90faSNamjae Jeon matchptr[best_len - 1] != strptr[best_len - 1] || 1011495e90faSNamjae Jeon matchptr[0] != strptr[0]) 1012495e90faSNamjae Jeon goto next_match; 1013495e90faSNamjae Jeon 1014495e90faSNamjae Jeon for (len = 1; len < best_len - 1; len++) 1015495e90faSNamjae Jeon if (matchptr[len] != strptr[len]) 1016495e90faSNamjae Jeon goto next_match; 1017495e90faSNamjae Jeon 1018495e90faSNamjae Jeon /* 1019495e90faSNamjae Jeon * The match is the longest found so far --- 1020495e90faSNamjae Jeon * at least 'best_len' + 1 bytes. Continue extending it. 1021495e90faSNamjae Jeon */ 1022495e90faSNamjae Jeon 1023495e90faSNamjae Jeon best_matchptr = matchptr; 1024495e90faSNamjae Jeon 1025495e90faSNamjae Jeon do { 1026495e90faSNamjae Jeon if (++best_len >= nice_len) { 1027495e90faSNamjae Jeon /* 1028495e90faSNamjae Jeon * 'nice_len' reached; don't waste time 1029495e90faSNamjae Jeon * searching for longer matches. Extend the 1030495e90faSNamjae Jeon * match as far as possible and terminate the 1031495e90faSNamjae Jeon * search. 1032495e90faSNamjae Jeon */ 1033495e90faSNamjae Jeon while (best_len < max_len && 1034495e90faSNamjae Jeon (best_matchptr[best_len] == 1035495e90faSNamjae Jeon strptr[best_len])) 1036495e90faSNamjae Jeon best_len++; 1037495e90faSNamjae Jeon goto out; 1038495e90faSNamjae Jeon } 1039495e90faSNamjae Jeon } while (best_matchptr[best_len] == strptr[best_len]); 1040495e90faSNamjae Jeon 1041495e90faSNamjae Jeon /* Found a longer match, but 'nice_len' not yet reached. */ 1042495e90faSNamjae Jeon 1043495e90faSNamjae Jeon next_match: 1044495e90faSNamjae Jeon /* Continue to next match in the chain. */ 1045495e90faSNamjae Jeon ; 1046495e90faSNamjae Jeon } 1047495e90faSNamjae Jeon 1048495e90faSNamjae Jeon /* 1049495e90faSNamjae Jeon * Reached end of chain, or ended early due to reaching the maximum 1050495e90faSNamjae Jeon * search depth. 1051495e90faSNamjae Jeon */ 1052495e90faSNamjae Jeon 1053495e90faSNamjae Jeon out: 1054495e90faSNamjae Jeon /* Return the longest match we were able to find. */ 1055495e90faSNamjae Jeon pctx->size = best_len; 1056495e90faSNamjae Jeon pctx->rel = best_matchptr - strptr; /* given as a negative number! */ 1057495e90faSNamjae Jeon } 1058495e90faSNamjae Jeon 1059495e90faSNamjae Jeon /* 1060495e90faSNamjae Jeon * Advance the match-finder, but don't search for matches. 1061495e90faSNamjae Jeon */ 1062495e90faSNamjae Jeon static void ntfs_skip_position(struct compress_context *pctx, const int i) 1063495e90faSNamjae Jeon { 1064495e90faSNamjae Jeon unsigned int hash; 1065495e90faSNamjae Jeon 1066495e90faSNamjae Jeon if (pctx->bufsize - i < 4) 1067495e90faSNamjae Jeon return; 1068495e90faSNamjae Jeon 1069495e90faSNamjae Jeon /* Insert the current sequence into the appropriate hash chain. */ 1070495e90faSNamjae Jeon hash = ntfs_hash(pctx->inbuf + i); 1071495e90faSNamjae Jeon pctx->prev[i] = pctx->head[hash]; 1072495e90faSNamjae Jeon pctx->head[hash] = i; 1073495e90faSNamjae Jeon } 1074495e90faSNamjae Jeon 1075495e90faSNamjae Jeon /* 1076495e90faSNamjae Jeon * Compress a 4096-byte block 1077495e90faSNamjae Jeon * 1078495e90faSNamjae Jeon * Returns a header of two bytes followed by the compressed data. 1079495e90faSNamjae Jeon * If compression is not effective, the header and an uncompressed 1080495e90faSNamjae Jeon * block is returned. 1081495e90faSNamjae Jeon * 1082495e90faSNamjae Jeon * Note : two bytes may be output before output buffer overflow 1083495e90faSNamjae Jeon * is detected, so a 4100-bytes output buffer must be reserved. 1084495e90faSNamjae Jeon * 1085495e90faSNamjae Jeon * Returns the size of the compressed block, including the 1086495e90faSNamjae Jeon * header (minimal size is 2, maximum size is 4098) 1087495e90faSNamjae Jeon * 0 if an error has been met. 1088495e90faSNamjae Jeon */ 1089495e90faSNamjae Jeon static unsigned int ntfs_compress_block(const char *inbuf, const int bufsize, 1090495e90faSNamjae Jeon char *outbuf) 1091495e90faSNamjae Jeon { 1092495e90faSNamjae Jeon struct compress_context *pctx; 1093495e90faSNamjae Jeon int i; /* current position */ 1094495e90faSNamjae Jeon int j; /* end of best match from current position */ 1095495e90faSNamjae Jeon int k; /* end of best match from next position */ 1096495e90faSNamjae Jeon int offs; /* offset to best match */ 1097495e90faSNamjae Jeon int bp; /* bits to store offset */ 1098495e90faSNamjae Jeon int bp_cur; /* saved bits to store offset at current position */ 1099495e90faSNamjae Jeon int mxoff; /* max match offset : 1 << bp */ 1100495e90faSNamjae Jeon unsigned int xout; 1101495e90faSNamjae Jeon unsigned int q; /* aggregated offset and size */ 1102495e90faSNamjae Jeon int have_match; /* do we have a match at the current position? */ 1103495e90faSNamjae Jeon char *ptag; /* location reserved for a tag */ 1104495e90faSNamjae Jeon int tag; /* current value of tag */ 1105495e90faSNamjae Jeon int ntag; /* count of bits still undefined in tag */ 1106495e90faSNamjae Jeon 1107495e90faSNamjae Jeon pctx = kvzalloc(sizeof(struct compress_context), GFP_NOFS); 1108495e90faSNamjae Jeon if (!pctx) 1109495e90faSNamjae Jeon return -ENOMEM; 1110495e90faSNamjae Jeon 1111495e90faSNamjae Jeon /* 1112495e90faSNamjae Jeon * All hash chains start as empty. The special value '-1' indicates the 1113495e90faSNamjae Jeon * end of each hash chain. 1114495e90faSNamjae Jeon */ 1115495e90faSNamjae Jeon memset(pctx->head, 0xFF, sizeof(pctx->head)); 1116495e90faSNamjae Jeon 1117495e90faSNamjae Jeon pctx->inbuf = (const unsigned char *)inbuf; 1118495e90faSNamjae Jeon pctx->bufsize = bufsize; 1119495e90faSNamjae Jeon xout = 2; 1120495e90faSNamjae Jeon i = 0; 1121495e90faSNamjae Jeon bp = 4; 1122495e90faSNamjae Jeon mxoff = 1 << bp; 1123495e90faSNamjae Jeon pctx->mxsz = (1 << (16 - bp)) + 2; 1124495e90faSNamjae Jeon have_match = 0; 1125495e90faSNamjae Jeon tag = 0; 1126495e90faSNamjae Jeon ntag = 8; 1127495e90faSNamjae Jeon ptag = &outbuf[xout++]; 1128495e90faSNamjae Jeon 1129495e90faSNamjae Jeon while ((i < bufsize) && (xout < (NTFS_SB_SIZE + 2))) { 1130495e90faSNamjae Jeon 1131495e90faSNamjae Jeon /* 1132495e90faSNamjae Jeon * This implementation uses "lazy" parsing: it always chooses 1133495e90faSNamjae Jeon * the longest match, unless the match at the next position is 1134495e90faSNamjae Jeon * longer. This is the same strategy used by the high 1135495e90faSNamjae Jeon * compression modes of zlib. 1136495e90faSNamjae Jeon */ 1137495e90faSNamjae Jeon if (!have_match) { 1138495e90faSNamjae Jeon /* 1139495e90faSNamjae Jeon * Find the longest match at the current position. But 1140495e90faSNamjae Jeon * first adjust the maximum match length if needed. 1141495e90faSNamjae Jeon * (This loop might need to run more than one time in 1142495e90faSNamjae Jeon * the case that we just output a long match.) 1143495e90faSNamjae Jeon */ 1144495e90faSNamjae Jeon while (mxoff < i) { 1145495e90faSNamjae Jeon bp++; 1146495e90faSNamjae Jeon mxoff <<= 1; 1147495e90faSNamjae Jeon pctx->mxsz = (pctx->mxsz + 2) >> 1; 1148495e90faSNamjae Jeon } 1149495e90faSNamjae Jeon ntfs_best_match(pctx, i, 2); 1150495e90faSNamjae Jeon } 1151495e90faSNamjae Jeon 1152495e90faSNamjae Jeon if (pctx->size >= 3) { 1153495e90faSNamjae Jeon /* Found a match at the current position. */ 1154495e90faSNamjae Jeon j = i + pctx->size; 1155495e90faSNamjae Jeon bp_cur = bp; 1156495e90faSNamjae Jeon offs = pctx->rel; 1157495e90faSNamjae Jeon 1158495e90faSNamjae Jeon if (pctx->size >= NICE_MATCH_LEN) { 1159495e90faSNamjae Jeon /* Choose long matches immediately. */ 1160495e90faSNamjae Jeon q = (~offs << (16 - bp_cur)) + (j - i - 3); 1161495e90faSNamjae Jeon outbuf[xout++] = q & 255; 1162495e90faSNamjae Jeon outbuf[xout++] = (q >> 8) & 255; 1163495e90faSNamjae Jeon tag |= (1 << (8 - ntag)); 1164495e90faSNamjae Jeon 1165495e90faSNamjae Jeon if (j == bufsize) { 1166495e90faSNamjae Jeon /* 1167495e90faSNamjae Jeon * Shortcut if the match extends to the 1168495e90faSNamjae Jeon * end of the buffer. 1169495e90faSNamjae Jeon */ 1170495e90faSNamjae Jeon i = j; 1171495e90faSNamjae Jeon --ntag; 1172495e90faSNamjae Jeon break; 1173495e90faSNamjae Jeon } 1174495e90faSNamjae Jeon i += 1; 1175495e90faSNamjae Jeon do { 1176495e90faSNamjae Jeon ntfs_skip_position(pctx, i); 1177495e90faSNamjae Jeon } while (++i != j); 1178495e90faSNamjae Jeon have_match = 0; 1179495e90faSNamjae Jeon } else { 1180495e90faSNamjae Jeon /* 1181495e90faSNamjae Jeon * Check for a longer match at the next 1182495e90faSNamjae Jeon * position. 1183495e90faSNamjae Jeon */ 1184495e90faSNamjae Jeon 1185495e90faSNamjae Jeon /* 1186495e90faSNamjae Jeon * Doesn't need to be while() since we just 1187495e90faSNamjae Jeon * adjusted the maximum match length at the 1188495e90faSNamjae Jeon * previous position. 1189495e90faSNamjae Jeon */ 1190495e90faSNamjae Jeon if (mxoff < i + 1) { 1191495e90faSNamjae Jeon bp++; 1192495e90faSNamjae Jeon mxoff <<= 1; 1193495e90faSNamjae Jeon pctx->mxsz = (pctx->mxsz + 2) >> 1; 1194495e90faSNamjae Jeon } 1195495e90faSNamjae Jeon ntfs_best_match(pctx, i + 1, pctx->size); 1196495e90faSNamjae Jeon k = i + 1 + pctx->size; 1197495e90faSNamjae Jeon 1198495e90faSNamjae Jeon if (k > (j + 1)) { 1199495e90faSNamjae Jeon /* 1200495e90faSNamjae Jeon * Next match is longer. 1201495e90faSNamjae Jeon * Output a literal. 1202495e90faSNamjae Jeon */ 1203495e90faSNamjae Jeon outbuf[xout++] = inbuf[i++]; 1204495e90faSNamjae Jeon have_match = 1; 1205495e90faSNamjae Jeon } else { 1206495e90faSNamjae Jeon /* 1207495e90faSNamjae Jeon * Next match isn't longer. 1208495e90faSNamjae Jeon * Output the current match. 1209495e90faSNamjae Jeon */ 1210495e90faSNamjae Jeon q = (~offs << (16 - bp_cur)) + 1211495e90faSNamjae Jeon (j - i - 3); 1212495e90faSNamjae Jeon outbuf[xout++] = q & 255; 1213495e90faSNamjae Jeon outbuf[xout++] = (q >> 8) & 255; 1214495e90faSNamjae Jeon tag |= (1 << (8 - ntag)); 1215495e90faSNamjae Jeon 1216495e90faSNamjae Jeon /* 1217495e90faSNamjae Jeon * The minimum match length is 3, and 1218495e90faSNamjae Jeon * we've run two bytes through the 1219495e90faSNamjae Jeon * matchfinder already. So the minimum 1220495e90faSNamjae Jeon * number of positions we need to skip 1221495e90faSNamjae Jeon * is 1. 1222495e90faSNamjae Jeon */ 1223495e90faSNamjae Jeon i += 2; 1224495e90faSNamjae Jeon do { 1225495e90faSNamjae Jeon ntfs_skip_position(pctx, i); 1226495e90faSNamjae Jeon } while (++i != j); 1227495e90faSNamjae Jeon have_match = 0; 1228495e90faSNamjae Jeon } 1229495e90faSNamjae Jeon } 1230495e90faSNamjae Jeon } else { 1231495e90faSNamjae Jeon /* No match at current position. Output a literal. */ 1232495e90faSNamjae Jeon outbuf[xout++] = inbuf[i++]; 1233495e90faSNamjae Jeon have_match = 0; 1234495e90faSNamjae Jeon } 1235495e90faSNamjae Jeon 1236495e90faSNamjae Jeon /* Store the tag if fully used. */ 1237495e90faSNamjae Jeon if (!--ntag) { 1238495e90faSNamjae Jeon *ptag = tag; 1239495e90faSNamjae Jeon ntag = 8; 1240495e90faSNamjae Jeon ptag = &outbuf[xout++]; 1241495e90faSNamjae Jeon tag = 0; 1242495e90faSNamjae Jeon } 1243495e90faSNamjae Jeon } 1244495e90faSNamjae Jeon 1245495e90faSNamjae Jeon /* Store the last tag if partially used. */ 1246495e90faSNamjae Jeon if (ntag == 8) 1247495e90faSNamjae Jeon xout--; 1248495e90faSNamjae Jeon else 1249495e90faSNamjae Jeon *ptag = tag; 1250495e90faSNamjae Jeon 1251495e90faSNamjae Jeon /* Determine whether to store the data compressed or uncompressed. */ 1252495e90faSNamjae Jeon if ((i >= bufsize) && (xout < (NTFS_SB_SIZE + 2))) { 1253495e90faSNamjae Jeon /* Compressed. */ 1254495e90faSNamjae Jeon outbuf[0] = (xout - 3) & 255; 1255495e90faSNamjae Jeon outbuf[1] = 0xb0 + (((xout - 3) >> 8) & 15); 1256495e90faSNamjae Jeon } else { 1257495e90faSNamjae Jeon /* Uncompressed. */ 1258495e90faSNamjae Jeon memcpy(&outbuf[2], inbuf, bufsize); 1259495e90faSNamjae Jeon if (bufsize < NTFS_SB_SIZE) 1260495e90faSNamjae Jeon memset(&outbuf[bufsize + 2], 0, NTFS_SB_SIZE - bufsize); 1261495e90faSNamjae Jeon outbuf[0] = 0xff; 1262495e90faSNamjae Jeon outbuf[1] = 0x3f; 1263495e90faSNamjae Jeon xout = NTFS_SB_SIZE + 2; 1264495e90faSNamjae Jeon } 1265495e90faSNamjae Jeon 1266495e90faSNamjae Jeon /* 1267495e90faSNamjae Jeon * Free the compression context and return the total number of bytes 1268495e90faSNamjae Jeon * written to 'outbuf'. 1269495e90faSNamjae Jeon */ 1270495e90faSNamjae Jeon kvfree(pctx); 1271495e90faSNamjae Jeon return xout; 1272495e90faSNamjae Jeon } 1273495e90faSNamjae Jeon 1274495e90faSNamjae Jeon static int ntfs_write_cb(struct ntfs_inode *ni, loff_t pos, struct page **pages, 1275495e90faSNamjae Jeon int pages_per_cb) 1276495e90faSNamjae Jeon { 1277495e90faSNamjae Jeon struct ntfs_volume *vol = ni->vol; 1278495e90faSNamjae Jeon char *outbuf = NULL, *pbuf, *inbuf; 1279495e90faSNamjae Jeon u32 compsz, p, insz = pages_per_cb << PAGE_SHIFT; 1280495e90faSNamjae Jeon s32 rounded, bio_size; 1281495e90faSNamjae Jeon unsigned int sz, bsz; 1282495e90faSNamjae Jeon bool fail = false, allzeroes; 1283495e90faSNamjae Jeon /* a single compressed zero */ 1284495e90faSNamjae Jeon static char onezero[] = {0x01, 0xb0, 0x00, 0x00}; 1285495e90faSNamjae Jeon /* a couple of compressed zeroes */ 1286495e90faSNamjae Jeon static char twozeroes[] = {0x02, 0xb0, 0x00, 0x00, 0x00}; 1287495e90faSNamjae Jeon /* more compressed zeroes, to be followed by some count */ 1288495e90faSNamjae Jeon static char morezeroes[] = {0x03, 0xb0, 0x02, 0x00}; 1289495e90faSNamjae Jeon struct page **pages_disk = NULL, *pg; 1290495e90faSNamjae Jeon s64 bio_lcn; 1291495e90faSNamjae Jeon struct runlist_element *rlc, *rl; 1292495e90faSNamjae Jeon int i, err; 1293495e90faSNamjae Jeon int pages_count = (round_up(ni->itype.compressed.block_size + 2 * 1294495e90faSNamjae Jeon (ni->itype.compressed.block_size / NTFS_SB_SIZE) + 2, PAGE_SIZE)) / PAGE_SIZE; 1295495e90faSNamjae Jeon size_t new_rl_count; 1296495e90faSNamjae Jeon struct bio *bio = NULL; 1297495e90faSNamjae Jeon loff_t new_length; 1298495e90faSNamjae Jeon s64 new_vcn; 1299495e90faSNamjae Jeon 1300495e90faSNamjae Jeon inbuf = vmap(pages, pages_per_cb, VM_MAP, PAGE_KERNEL_RO); 1301495e90faSNamjae Jeon if (!inbuf) 1302495e90faSNamjae Jeon return -ENOMEM; 1303495e90faSNamjae Jeon 1304495e90faSNamjae Jeon /* may need 2 extra bytes per block and 2 more bytes */ 1305495e90faSNamjae Jeon pages_disk = kcalloc(pages_count, sizeof(struct page *), GFP_NOFS); 1306495e90faSNamjae Jeon if (!pages_disk) { 1307495e90faSNamjae Jeon vunmap(inbuf); 1308495e90faSNamjae Jeon return -ENOMEM; 1309495e90faSNamjae Jeon } 1310495e90faSNamjae Jeon 1311495e90faSNamjae Jeon for (i = 0; i < pages_count; i++) { 1312495e90faSNamjae Jeon pg = alloc_page(GFP_KERNEL); 1313495e90faSNamjae Jeon if (!pg) { 1314495e90faSNamjae Jeon err = -ENOMEM; 1315495e90faSNamjae Jeon goto out; 1316495e90faSNamjae Jeon } 1317495e90faSNamjae Jeon pages_disk[i] = pg; 1318495e90faSNamjae Jeon lock_page(pg); 1319495e90faSNamjae Jeon kmap_local_page(pg); 1320495e90faSNamjae Jeon } 1321495e90faSNamjae Jeon 1322495e90faSNamjae Jeon outbuf = vmap(pages_disk, pages_count, VM_MAP, PAGE_KERNEL); 1323495e90faSNamjae Jeon if (!outbuf) { 1324495e90faSNamjae Jeon err = -ENOMEM; 1325495e90faSNamjae Jeon goto out; 1326495e90faSNamjae Jeon } 1327495e90faSNamjae Jeon 1328495e90faSNamjae Jeon compsz = 0; 1329495e90faSNamjae Jeon allzeroes = true; 1330495e90faSNamjae Jeon for (p = 0; (p < insz) && !fail; p += NTFS_SB_SIZE) { 1331495e90faSNamjae Jeon if ((p + NTFS_SB_SIZE) < insz) 1332495e90faSNamjae Jeon bsz = NTFS_SB_SIZE; 1333495e90faSNamjae Jeon else 1334495e90faSNamjae Jeon bsz = insz - p; 1335495e90faSNamjae Jeon pbuf = &outbuf[compsz]; 1336495e90faSNamjae Jeon sz = ntfs_compress_block(&inbuf[p], bsz, pbuf); 1337495e90faSNamjae Jeon /* fail if all the clusters (or more) are needed */ 1338495e90faSNamjae Jeon if (!sz || ((compsz + sz + vol->cluster_size + 2) > 1339495e90faSNamjae Jeon ni->itype.compressed.block_size)) 1340495e90faSNamjae Jeon fail = true; 1341495e90faSNamjae Jeon else { 1342495e90faSNamjae Jeon if (allzeroes) { 1343495e90faSNamjae Jeon /* check whether this is all zeroes */ 1344495e90faSNamjae Jeon switch (sz) { 1345495e90faSNamjae Jeon case 4: 1346495e90faSNamjae Jeon allzeroes = !memcmp(pbuf, onezero, 4); 1347495e90faSNamjae Jeon break; 1348495e90faSNamjae Jeon case 5: 1349495e90faSNamjae Jeon allzeroes = !memcmp(pbuf, twozeroes, 5); 1350495e90faSNamjae Jeon break; 1351495e90faSNamjae Jeon case 6: 1352495e90faSNamjae Jeon allzeroes = !memcmp(pbuf, morezeroes, 4); 1353495e90faSNamjae Jeon break; 1354495e90faSNamjae Jeon default: 1355495e90faSNamjae Jeon allzeroes = false; 1356495e90faSNamjae Jeon break; 1357495e90faSNamjae Jeon } 1358495e90faSNamjae Jeon } 1359495e90faSNamjae Jeon compsz += sz; 1360495e90faSNamjae Jeon } 1361495e90faSNamjae Jeon } 1362495e90faSNamjae Jeon 1363495e90faSNamjae Jeon if (!fail && !allzeroes) { 1364495e90faSNamjae Jeon outbuf[compsz++] = 0; 1365495e90faSNamjae Jeon outbuf[compsz++] = 0; 1366495e90faSNamjae Jeon rounded = ((compsz - 1) | (vol->cluster_size - 1)) + 1; 1367495e90faSNamjae Jeon memset(&outbuf[compsz], 0, rounded - compsz); 1368495e90faSNamjae Jeon bio_size = rounded; 1369495e90faSNamjae Jeon pages = pages_disk; 1370495e90faSNamjae Jeon } else if (allzeroes) { 1371495e90faSNamjae Jeon err = 0; 1372495e90faSNamjae Jeon goto out; 1373495e90faSNamjae Jeon } else { 1374495e90faSNamjae Jeon bio_size = insz; 1375495e90faSNamjae Jeon } 1376495e90faSNamjae Jeon 1377495e90faSNamjae Jeon new_vcn = ntfs_bytes_to_cluster(vol, pos & ~(ni->itype.compressed.block_size - 1)); 1378495e90faSNamjae Jeon new_length = ntfs_bytes_to_cluster(vol, round_up(bio_size, vol->cluster_size)); 1379495e90faSNamjae Jeon 1380495e90faSNamjae Jeon err = ntfs_non_resident_attr_punch_hole(ni, new_vcn, ni->itype.compressed.block_clusters); 1381495e90faSNamjae Jeon if (err < 0) 1382495e90faSNamjae Jeon goto out; 1383495e90faSNamjae Jeon 1384495e90faSNamjae Jeon rlc = ntfs_cluster_alloc(vol, new_vcn, new_length, -1, DATA_ZONE, 1385495e90faSNamjae Jeon false, true, true); 1386495e90faSNamjae Jeon if (IS_ERR(rlc)) { 1387495e90faSNamjae Jeon err = PTR_ERR(rlc); 1388495e90faSNamjae Jeon goto out; 1389495e90faSNamjae Jeon } 1390495e90faSNamjae Jeon 1391495e90faSNamjae Jeon bio_lcn = rlc->lcn; 1392495e90faSNamjae Jeon down_write(&ni->runlist.lock); 1393495e90faSNamjae Jeon rl = ntfs_runlists_merge(&ni->runlist, rlc, 0, &new_rl_count); 1394495e90faSNamjae Jeon if (IS_ERR(rl)) { 1395495e90faSNamjae Jeon up_write(&ni->runlist.lock); 1396495e90faSNamjae Jeon ntfs_error(vol->sb, "Failed to merge runlists"); 1397495e90faSNamjae Jeon err = PTR_ERR(rl); 1398495e90faSNamjae Jeon if (ntfs_cluster_free_from_rl(vol, rlc)) 1399495e90faSNamjae Jeon ntfs_error(vol->sb, "Failed to free hot clusters."); 1400495e90faSNamjae Jeon kvfree(rlc); 1401495e90faSNamjae Jeon goto out; 1402495e90faSNamjae Jeon } 1403495e90faSNamjae Jeon 1404495e90faSNamjae Jeon ni->runlist.count = new_rl_count; 1405495e90faSNamjae Jeon ni->runlist.rl = rl; 1406495e90faSNamjae Jeon 1407495e90faSNamjae Jeon err = ntfs_attr_update_mapping_pairs(ni, 0); 1408495e90faSNamjae Jeon up_write(&ni->runlist.lock); 1409495e90faSNamjae Jeon if (err) { 1410495e90faSNamjae Jeon err = -EIO; 1411495e90faSNamjae Jeon goto out; 1412495e90faSNamjae Jeon } 1413495e90faSNamjae Jeon 1414495e90faSNamjae Jeon i = 0; 1415495e90faSNamjae Jeon while (bio_size > 0) { 1416495e90faSNamjae Jeon int page_size; 1417495e90faSNamjae Jeon 1418495e90faSNamjae Jeon if (bio_size >= PAGE_SIZE) { 1419495e90faSNamjae Jeon page_size = PAGE_SIZE; 1420495e90faSNamjae Jeon bio_size -= PAGE_SIZE; 1421495e90faSNamjae Jeon } else { 1422495e90faSNamjae Jeon page_size = bio_size; 1423495e90faSNamjae Jeon bio_size = 0; 1424495e90faSNamjae Jeon } 1425495e90faSNamjae Jeon 1426495e90faSNamjae Jeon setup_bio: 1427495e90faSNamjae Jeon if (!bio) { 1428495e90faSNamjae Jeon bio = bio_alloc(vol->sb->s_bdev, 1, REQ_OP_WRITE, 1429495e90faSNamjae Jeon GFP_NOIO); 1430495e90faSNamjae Jeon bio->bi_iter.bi_sector = 1431495e90faSNamjae Jeon ntfs_bytes_to_sector(vol, 1432495e90faSNamjae Jeon ntfs_cluster_to_bytes(vol, bio_lcn + i)); 1433495e90faSNamjae Jeon } 1434495e90faSNamjae Jeon 1435495e90faSNamjae Jeon if (!bio_add_page(bio, pages[i], page_size, 0)) { 1436495e90faSNamjae Jeon err = submit_bio_wait(bio); 1437495e90faSNamjae Jeon bio_put(bio); 1438495e90faSNamjae Jeon if (err) 1439495e90faSNamjae Jeon goto out; 1440495e90faSNamjae Jeon bio = NULL; 1441495e90faSNamjae Jeon goto setup_bio; 1442495e90faSNamjae Jeon } 1443495e90faSNamjae Jeon i++; 1444495e90faSNamjae Jeon } 1445495e90faSNamjae Jeon 1446495e90faSNamjae Jeon err = submit_bio_wait(bio); 1447495e90faSNamjae Jeon bio_put(bio); 1448495e90faSNamjae Jeon out: 1449495e90faSNamjae Jeon vunmap(outbuf); 1450495e90faSNamjae Jeon for (i = 0; i < pages_count; i++) { 1451495e90faSNamjae Jeon pg = pages_disk[i]; 1452495e90faSNamjae Jeon if (pg) { 1453495e90faSNamjae Jeon kunmap_local(page_address(pg)); 1454495e90faSNamjae Jeon unlock_page(pg); 1455495e90faSNamjae Jeon put_page(pg); 1456495e90faSNamjae Jeon } 1457495e90faSNamjae Jeon } 1458495e90faSNamjae Jeon kfree(pages_disk); 1459495e90faSNamjae Jeon vunmap(inbuf); 1460495e90faSNamjae Jeon NInoSetFileNameDirty(ni); 1461495e90faSNamjae Jeon mark_mft_record_dirty(ni); 1462495e90faSNamjae Jeon 1463495e90faSNamjae Jeon return err; 1464495e90faSNamjae Jeon } 1465495e90faSNamjae Jeon 1466495e90faSNamjae Jeon int ntfs_compress_write(struct ntfs_inode *ni, loff_t pos, size_t count, 1467495e90faSNamjae Jeon struct iov_iter *from) 1468495e90faSNamjae Jeon { 1469495e90faSNamjae Jeon struct folio *folio; 1470495e90faSNamjae Jeon struct page **pages = NULL, *page; 1471495e90faSNamjae Jeon int pages_per_cb = ni->itype.compressed.block_size >> PAGE_SHIFT; 1472495e90faSNamjae Jeon int cb_size = ni->itype.compressed.block_size, cb_off, err = 0; 1473495e90faSNamjae Jeon int i, ip; 1474495e90faSNamjae Jeon size_t written = 0; 1475495e90faSNamjae Jeon struct address_space *mapping = VFS_I(ni)->i_mapping; 1476495e90faSNamjae Jeon 1477495e90faSNamjae Jeon if (NInoCompressed(ni) && pos + count > ni->allocated_size) { 1478495e90faSNamjae Jeon int err; 1479495e90faSNamjae Jeon loff_t end = pos + count; 1480495e90faSNamjae Jeon 1481495e90faSNamjae Jeon err = ntfs_attr_expand(ni, end, 1482495e90faSNamjae Jeon round_up(end, ni->itype.compressed.block_size)); 1483495e90faSNamjae Jeon if (err) 1484495e90faSNamjae Jeon return err; 1485495e90faSNamjae Jeon } 1486495e90faSNamjae Jeon 1487495e90faSNamjae Jeon pages = kmalloc_array(pages_per_cb, sizeof(struct page *), GFP_NOFS); 1488495e90faSNamjae Jeon if (!pages) 1489495e90faSNamjae Jeon return -ENOMEM; 1490495e90faSNamjae Jeon 1491495e90faSNamjae Jeon while (count) { 1492495e90faSNamjae Jeon pgoff_t index; 1493495e90faSNamjae Jeon size_t copied, bytes; 1494495e90faSNamjae Jeon int off; 1495495e90faSNamjae Jeon 1496495e90faSNamjae Jeon off = pos & (cb_size - 1); 1497495e90faSNamjae Jeon bytes = cb_size - off; 1498495e90faSNamjae Jeon if (bytes > count) 1499495e90faSNamjae Jeon bytes = count; 1500495e90faSNamjae Jeon 1501495e90faSNamjae Jeon cb_off = pos & ~(cb_size - 1); 1502495e90faSNamjae Jeon index = cb_off >> PAGE_SHIFT; 1503495e90faSNamjae Jeon 1504495e90faSNamjae Jeon if (unlikely(fault_in_iov_iter_readable(from, bytes))) { 1505495e90faSNamjae Jeon err = -EFAULT; 1506495e90faSNamjae Jeon goto out; 1507495e90faSNamjae Jeon } 1508495e90faSNamjae Jeon 1509495e90faSNamjae Jeon for (i = 0; i < pages_per_cb; i++) { 1510495e90faSNamjae Jeon folio = read_mapping_folio(mapping, index + i, NULL); 1511495e90faSNamjae Jeon if (IS_ERR(folio)) { 1512495e90faSNamjae Jeon for (ip = 0; ip < i; ip++) { 1513495e90faSNamjae Jeon folio_unlock(page_folio(pages[ip])); 1514495e90faSNamjae Jeon folio_put(page_folio(pages[ip])); 1515495e90faSNamjae Jeon } 1516495e90faSNamjae Jeon err = PTR_ERR(folio); 1517495e90faSNamjae Jeon goto out; 1518495e90faSNamjae Jeon } 1519495e90faSNamjae Jeon 1520495e90faSNamjae Jeon folio_lock(folio); 1521495e90faSNamjae Jeon pages[i] = folio_page(folio, 0); 1522495e90faSNamjae Jeon } 1523495e90faSNamjae Jeon 1524495e90faSNamjae Jeon WARN_ON(!bytes); 1525495e90faSNamjae Jeon copied = 0; 1526495e90faSNamjae Jeon ip = off >> PAGE_SHIFT; 1527495e90faSNamjae Jeon off = offset_in_page(pos); 1528495e90faSNamjae Jeon 1529495e90faSNamjae Jeon for (;;) { 1530495e90faSNamjae Jeon size_t cp, tail = PAGE_SIZE - off; 1531495e90faSNamjae Jeon 1532495e90faSNamjae Jeon page = pages[ip]; 1533495e90faSNamjae Jeon cp = copy_folio_from_iter_atomic(page_folio(page), off, 1534495e90faSNamjae Jeon min(tail, bytes), from); 1535495e90faSNamjae Jeon flush_dcache_page(page); 1536495e90faSNamjae Jeon 1537495e90faSNamjae Jeon copied += cp; 1538495e90faSNamjae Jeon bytes -= cp; 1539495e90faSNamjae Jeon if (!bytes || !cp) 1540495e90faSNamjae Jeon break; 1541495e90faSNamjae Jeon 1542495e90faSNamjae Jeon if (cp < tail) { 1543495e90faSNamjae Jeon off += cp; 1544495e90faSNamjae Jeon } else { 1545495e90faSNamjae Jeon ip++; 1546495e90faSNamjae Jeon off = 0; 1547495e90faSNamjae Jeon } 1548495e90faSNamjae Jeon } 1549495e90faSNamjae Jeon 1550495e90faSNamjae Jeon err = ntfs_write_cb(ni, pos, pages, pages_per_cb); 1551495e90faSNamjae Jeon 1552495e90faSNamjae Jeon for (i = 0; i < pages_per_cb; i++) { 1553495e90faSNamjae Jeon folio = page_folio(pages[i]); 1554495e90faSNamjae Jeon if (i < ip) { 1555495e90faSNamjae Jeon folio_clear_dirty(folio); 1556495e90faSNamjae Jeon folio_mark_uptodate(folio); 1557495e90faSNamjae Jeon } 1558495e90faSNamjae Jeon folio_unlock(folio); 1559495e90faSNamjae Jeon folio_put(folio); 1560495e90faSNamjae Jeon } 1561495e90faSNamjae Jeon 1562495e90faSNamjae Jeon if (err) 1563495e90faSNamjae Jeon goto out; 1564495e90faSNamjae Jeon 1565495e90faSNamjae Jeon cond_resched(); 1566495e90faSNamjae Jeon pos += copied; 1567495e90faSNamjae Jeon written += copied; 1568495e90faSNamjae Jeon count = iov_iter_count(from); 1569495e90faSNamjae Jeon } 1570495e90faSNamjae Jeon 1571495e90faSNamjae Jeon out: 1572495e90faSNamjae Jeon kfree(pages); 1573495e90faSNamjae Jeon if (err < 0) 1574495e90faSNamjae Jeon written = err; 1575495e90faSNamjae Jeon 1576495e90faSNamjae Jeon return written; 1577495e90faSNamjae Jeon } 1578