Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ntfs: update runlist handling and cluster allocator

Updates runlist handling and cluster allocation to support
contiguous allocations and filesystem trimming.

Improve the runlist API to handle allocation failures and introduces
discard support.

Acked-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>

+1323 -995
+152 -44
fs/ntfs/bitmap.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 2 /* 3 - * bitmap.c - NTFS kernel bitmap handling. Part of the Linux-NTFS project. 3 + * NTFS kernel bitmap handling. 4 4 * 5 5 * Copyright (c) 2004-2005 Anton Altaparmakov 6 + * Copyright (c) 2025 LG Electronics Co., Ltd. 6 7 */ 7 8 8 - #ifdef NTFS_RW 9 - 10 - #include <linux/pagemap.h> 9 + #include <linux/bitops.h> 10 + #include <linux/blkdev.h> 11 11 12 12 #include "bitmap.h" 13 - #include "debug.h" 14 - #include "aops.h" 15 13 #include "ntfs.h" 16 14 17 - /** 15 + int ntfs_trim_fs(struct ntfs_volume *vol, struct fstrim_range *range) 16 + { 17 + size_t buf_clusters; 18 + pgoff_t index, start_index, end_index; 19 + struct file_ra_state *ra; 20 + struct folio *folio; 21 + unsigned long *bitmap; 22 + char *kaddr; 23 + u64 end, trimmed = 0, start_buf, end_buf, end_cluster; 24 + u64 start_cluster = ntfs_bytes_to_cluster(vol, range->start); 25 + u32 dq = bdev_discard_granularity(vol->sb->s_bdev); 26 + int ret = 0; 27 + 28 + if (!dq) 29 + dq = vol->cluster_size; 30 + 31 + if (start_cluster >= vol->nr_clusters) 32 + return -EINVAL; 33 + 34 + if (range->len == (u64)-1) 35 + end_cluster = vol->nr_clusters; 36 + else { 37 + end_cluster = ntfs_bytes_to_cluster(vol, 38 + (range->start + range->len + vol->cluster_size - 1)); 39 + if (end_cluster > vol->nr_clusters) 40 + end_cluster = vol->nr_clusters; 41 + } 42 + 43 + ra = kzalloc(sizeof(*ra), GFP_NOFS); 44 + if (!ra) 45 + return -ENOMEM; 46 + 47 + buf_clusters = PAGE_SIZE * 8; 48 + start_index = start_cluster >> 15; 49 + end_index = (end_cluster + buf_clusters - 1) >> 15; 50 + 51 + for (index = start_index; index < end_index; index++) { 52 + folio = ntfs_get_locked_folio(vol->lcnbmp_ino->i_mapping, 53 + index, end_index, ra); 54 + if (IS_ERR(folio)) { 55 + ret = PTR_ERR(folio); 56 + goto out_free; 57 + } 58 + 59 + kaddr = kmap_local_folio(folio, 0); 60 + bitmap = (unsigned long *)kaddr; 61 + 62 + start_buf = max_t(u64, index * buf_clusters, start_cluster); 63 + end_buf = min_t(u64, (index + 1) * buf_clusters, end_cluster); 64 + 65 + end = start_buf; 66 + while (end < end_buf) { 67 + u64 aligned_start, aligned_count; 68 + u64 start = find_next_zero_bit(bitmap, end_buf - start_buf, 69 + end - start_buf) + start_buf; 70 + if (start >= end_buf) 71 + break; 72 + 73 + end = find_next_bit(bitmap, end_buf - start_buf, 74 + start - start_buf) + start_buf; 75 + 76 + aligned_start = ALIGN(ntfs_cluster_to_bytes(vol, start), dq); 77 + aligned_count = 78 + ALIGN_DOWN(ntfs_cluster_to_bytes(vol, end - start), dq); 79 + if (aligned_count >= range->minlen) { 80 + ret = blkdev_issue_discard(vol->sb->s_bdev, aligned_start >> 9, 81 + aligned_count >> 9, GFP_NOFS); 82 + if (ret) 83 + goto out_unmap; 84 + trimmed += aligned_count; 85 + } 86 + } 87 + 88 + out_unmap: 89 + kunmap_local(kaddr); 90 + folio_unlock(folio); 91 + folio_put(folio); 92 + 93 + if (ret) 94 + goto out_free; 95 + } 96 + 97 + range->len = trimmed; 98 + 99 + out_free: 100 + kfree(ra); 101 + return ret; 102 + } 103 + 104 + /* 18 105 * __ntfs_bitmap_set_bits_in_run - set a run of bits in a bitmap to a value 19 106 * @vi: vfs inode describing the bitmap 20 107 * @start_bit: first bit to set ··· 123 36 s64 cnt = count; 124 37 pgoff_t index, end_index; 125 38 struct address_space *mapping; 126 - struct page *page; 39 + struct folio *folio; 127 40 u8 *kaddr; 128 41 int pos, len; 129 42 u8 bit; 43 + struct ntfs_inode *ni = NTFS_I(vi); 44 + struct ntfs_volume *vol = ni->vol; 130 45 131 - BUG_ON(!vi); 132 - ntfs_debug("Entering for i_ino 0x%lx, start_bit 0x%llx, count 0x%llx, " 133 - "value %u.%s", vi->i_ino, (unsigned long long)start_bit, 46 + ntfs_debug("Entering for i_ino 0x%lx, start_bit 0x%llx, count 0x%llx, value %u.%s", 47 + vi->i_ino, (unsigned long long)start_bit, 134 48 (unsigned long long)cnt, (unsigned int)value, 135 49 is_rollback ? " (rollback)" : ""); 136 - BUG_ON(start_bit < 0); 137 - BUG_ON(cnt < 0); 138 - BUG_ON(value > 1); 50 + 51 + if (start_bit < 0 || cnt < 0 || value > 1) 52 + return -EINVAL; 53 + 139 54 /* 140 55 * Calculate the indices for the pages containing the first and last 141 56 * bits, i.e. @start_bit and @start_bit + @cnt - 1, respectively. ··· 147 58 148 59 /* Get the page containing the first bit (@start_bit). */ 149 60 mapping = vi->i_mapping; 150 - page = ntfs_map_page(mapping, index); 151 - if (IS_ERR(page)) { 61 + folio = read_mapping_folio(mapping, index, NULL); 62 + if (IS_ERR(folio)) { 152 63 if (!is_rollback) 153 - ntfs_error(vi->i_sb, "Failed to map first page (error " 154 - "%li), aborting.", PTR_ERR(page)); 155 - return PTR_ERR(page); 64 + ntfs_error(vi->i_sb, 65 + "Failed to map first page (error %li), aborting.", 66 + PTR_ERR(folio)); 67 + return PTR_ERR(folio); 156 68 } 157 - kaddr = page_address(page); 69 + 70 + folio_lock(folio); 71 + kaddr = kmap_local_folio(folio, 0); 158 72 159 73 /* Set @pos to the position of the byte containing @start_bit. */ 160 74 pos = (start_bit >> 3) & ~PAGE_MASK; ··· 168 76 /* If the first byte is partial, modify the appropriate bits in it. */ 169 77 if (bit) { 170 78 u8 *byte = kaddr + pos; 79 + 80 + if (ni->mft_no == FILE_Bitmap) 81 + ntfs_set_lcn_empty_bits(vol, index, value, min_t(s64, 8 - bit, cnt)); 171 82 while ((bit & 7) && cnt) { 172 83 cnt--; 173 84 if (value) ··· 192 97 len = min_t(s64, cnt >> 3, PAGE_SIZE - pos); 193 98 memset(kaddr + pos, value ? 0xff : 0, len); 194 99 cnt -= len << 3; 100 + if (ni->mft_no == FILE_Bitmap) 101 + ntfs_set_lcn_empty_bits(vol, index, value, len << 3); 195 102 196 103 /* Update @len to point to the first not-done byte in the page. */ 197 104 if (cnt < 8) ··· 201 104 202 105 /* If we are not in the last page, deal with all subsequent pages. */ 203 106 while (index < end_index) { 204 - BUG_ON(cnt <= 0); 205 - 206 - /* Update @index and get the next page. */ 207 - flush_dcache_page(page); 208 - set_page_dirty(page); 209 - ntfs_unmap_page(page); 210 - page = ntfs_map_page(mapping, ++index); 211 - if (IS_ERR(page)) 107 + if (cnt <= 0) 212 108 goto rollback; 213 - kaddr = page_address(page); 109 + 110 + /* Update @index and get the next folio. */ 111 + folio_mark_dirty(folio); 112 + folio_unlock(folio); 113 + kunmap_local(kaddr); 114 + folio_put(folio); 115 + folio = read_mapping_folio(mapping, ++index, NULL); 116 + if (IS_ERR(folio)) { 117 + ntfs_error(vi->i_sb, 118 + "Failed to map subsequent page (error %li), aborting.", 119 + PTR_ERR(folio)); 120 + goto rollback; 121 + } 122 + 123 + folio_lock(folio); 124 + kaddr = kmap_local_folio(folio, 0); 214 125 /* 215 126 * Depending on @value, modify all remaining whole bytes in the 216 127 * page up to @cnt. ··· 226 121 len = min_t(s64, cnt >> 3, PAGE_SIZE); 227 122 memset(kaddr, value ? 0xff : 0, len); 228 123 cnt -= len << 3; 124 + if (ni->mft_no == FILE_Bitmap) 125 + ntfs_set_lcn_empty_bits(vol, index, value, len << 3); 229 126 } 230 127 /* 231 128 * The currently mapped page is the last one. If the last byte is ··· 237 130 if (cnt) { 238 131 u8 *byte; 239 132 240 - BUG_ON(cnt > 7); 133 + WARN_ON(cnt > 7); 241 134 242 135 bit = cnt; 243 136 byte = kaddr + len; 137 + if (ni->mft_no == FILE_Bitmap) 138 + ntfs_set_lcn_empty_bits(vol, index, value, bit); 244 139 while (bit--) { 245 140 if (value) 246 141 *byte |= 1 << bit; ··· 251 142 } 252 143 } 253 144 done: 254 - /* We are done. Unmap the page and return success. */ 255 - flush_dcache_page(page); 256 - set_page_dirty(page); 257 - ntfs_unmap_page(page); 145 + /* We are done. Unmap the folio and return success. */ 146 + folio_mark_dirty(folio); 147 + folio_unlock(folio); 148 + kunmap_local(kaddr); 149 + folio_put(folio); 258 150 ntfs_debug("Done."); 259 151 return 0; 260 152 rollback: ··· 265 155 * - @count - @cnt is the number of bits that have been modified 266 156 */ 267 157 if (is_rollback) 268 - return PTR_ERR(page); 158 + return PTR_ERR(folio); 269 159 if (count != cnt) 270 160 pos = __ntfs_bitmap_set_bits_in_run(vi, start_bit, count - cnt, 271 161 value ? 0 : 1, true); ··· 273 163 pos = 0; 274 164 if (!pos) { 275 165 /* Rollback was successful. */ 276 - ntfs_error(vi->i_sb, "Failed to map subsequent page (error " 277 - "%li), aborting.", PTR_ERR(page)); 166 + ntfs_error(vi->i_sb, 167 + "Failed to map subsequent page (error %li), aborting.", 168 + PTR_ERR(folio)); 278 169 } else { 279 170 /* Rollback failed. */ 280 - ntfs_error(vi->i_sb, "Failed to map subsequent page (error " 281 - "%li) and rollback failed (error %i). " 282 - "Aborting and leaving inconsistent metadata. " 283 - "Unmount and run chkdsk.", PTR_ERR(page), pos); 171 + ntfs_error(vi->i_sb, 172 + "Failed to map subsequent page (error %li) and rollback failed (error %i). Aborting and leaving inconsistent metadata. Unmount and run chkdsk.", 173 + PTR_ERR(folio), pos); 284 174 NVolSetErrors(NTFS_SB(vi->i_sb)); 285 175 } 286 - return PTR_ERR(page); 176 + return PTR_ERR(folio); 287 177 } 288 - 289 - #endif /* NTFS_RW */
+402 -355
fs/ntfs/lcnalloc.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 2 /* 3 - * lcnalloc.c - Cluster (de)allocation code. Part of the Linux-NTFS project. 3 + * Cluster (de)allocation code. 4 4 * 5 5 * Copyright (c) 2004-2005 Anton Altaparmakov 6 + * Copyright (c) 2025 LG Electronics Co., Ltd. 7 + * 8 + * Part of this file is based on code from the NTFS-3G. 9 + * and is copyrighted by the respective authors below: 10 + * Copyright (c) 2002-2004 Anton Altaparmakov 11 + * Copyright (c) 2004 Yura Pakhuchiy 12 + * Copyright (c) 2004-2008 Szabolcs Szakacsits 13 + * Copyright (c) 2008-2009 Jean-Pierre Andre 6 14 */ 7 15 8 - #ifdef NTFS_RW 9 - 10 - #include <linux/pagemap.h> 16 + #include <linux/blkdev.h> 11 17 12 18 #include "lcnalloc.h" 13 - #include "debug.h" 14 19 #include "bitmap.h" 15 - #include "inode.h" 16 - #include "volume.h" 17 - #include "attrib.h" 18 - #include "malloc.h" 19 - #include "aops.h" 20 20 #include "ntfs.h" 21 21 22 - /** 22 + /* 23 23 * ntfs_cluster_free_from_rl_nolock - free clusters from runlist 24 24 * @vol: mounted ntfs volume on which to free the clusters 25 25 * @rl: runlist describing the clusters to free ··· 33 33 * Locking: - The volume lcn bitmap must be locked for writing on entry and is 34 34 * left locked on return. 35 35 */ 36 - int ntfs_cluster_free_from_rl_nolock(ntfs_volume *vol, 37 - const runlist_element *rl) 36 + int ntfs_cluster_free_from_rl_nolock(struct ntfs_volume *vol, 37 + const struct runlist_element *rl) 38 38 { 39 39 struct inode *lcnbmp_vi = vol->lcnbmp_ino; 40 40 int ret = 0; 41 + s64 nr_freed = 0; 41 42 42 43 ntfs_debug("Entering."); 43 44 if (!rl) 44 45 return 0; 46 + 47 + if (!NVolFreeClusterKnown(vol)) 48 + wait_event(vol->free_waitq, NVolFreeClusterKnown(vol)); 49 + 45 50 for (; rl->length; rl++) { 46 51 int err; 47 52 ··· 55 50 err = ntfs_bitmap_clear_run(lcnbmp_vi, rl->lcn, rl->length); 56 51 if (unlikely(err && (!ret || ret == -ENOMEM) && ret != err)) 57 52 ret = err; 53 + else 54 + nr_freed += rl->length; 58 55 } 56 + ntfs_inc_free_clusters(vol, nr_freed); 59 57 ntfs_debug("Done."); 60 58 return ret; 61 59 } 62 60 63 - /** 61 + static s64 max_empty_bit_range(unsigned char *buf, int size) 62 + { 63 + int i, j, run = 0; 64 + int max_range = 0; 65 + s64 start_pos = -1; 66 + 67 + ntfs_debug("Entering\n"); 68 + 69 + i = 0; 70 + while (i < size) { 71 + switch (*buf) { 72 + case 0: 73 + do { 74 + buf++; 75 + run += 8; 76 + i++; 77 + } while ((i < size) && !*buf); 78 + break; 79 + case 255: 80 + if (run > max_range) { 81 + max_range = run; 82 + start_pos = (s64)i * 8 - run; 83 + } 84 + run = 0; 85 + do { 86 + buf++; 87 + i++; 88 + } while ((i < size) && (*buf == 255)); 89 + break; 90 + default: 91 + for (j = 0; j < 8; j++) { 92 + int bit = *buf & (1 << j); 93 + 94 + if (bit) { 95 + if (run > max_range) { 96 + max_range = run; 97 + start_pos = (s64)i * 8 + (j - run); 98 + } 99 + run = 0; 100 + } else 101 + run++; 102 + } 103 + i++; 104 + buf++; 105 + } 106 + } 107 + 108 + if (run > max_range) 109 + start_pos = (s64)i * 8 - run; 110 + 111 + return start_pos; 112 + } 113 + 114 + /* 64 115 * ntfs_cluster_alloc - allocate clusters on an ntfs volume 65 - * @vol: mounted ntfs volume on which to allocate the clusters 66 - * @start_vcn: vcn to use for the first allocated cluster 67 - * @count: number of clusters to allocate 68 - * @start_lcn: starting lcn at which to allocate the clusters (or -1 if none) 69 - * @zone: zone from which to allocate the clusters 70 - * @is_extension: if 'true', this is an attribute extension 116 + * @vol: mounted ntfs volume on which to allocate clusters 117 + * @start_vcn: vcn of the first allocated cluster 118 + * @count: number of clusters to allocate 119 + * @start_lcn: starting lcn at which to allocate the clusters or -1 if none 120 + * @zone: zone from which to allocate (MFT_ZONE or DATA_ZONE) 121 + * @is_extension: if true, the caller is extending an attribute 122 + * @is_contig: if true, require contiguous allocation 123 + * @is_dealloc: if true, the allocation is for deallocation purposes 71 124 * 72 125 * Allocate @count clusters preferably starting at cluster @start_lcn or at the 73 126 * current allocator position if @start_lcn is -1, on the mounted ntfs volume ··· 172 109 * for speed, but the algorithm is, so further speed improvements are probably 173 110 * possible). 174 111 * 175 - * FIXME: We should be monitoring cluster allocation and increment the MFT zone 176 - * size dynamically but this is something for the future. We will just cause 177 - * heavier fragmentation by not doing it and I am not even sure Windows would 178 - * grow the MFT zone dynamically, so it might even be correct not to do this. 179 - * The overhead in doing dynamic MFT zone expansion would be very large and 180 - * unlikely worth the effort. (AIA) 181 - * 182 - * TODO: I have added in double the required zone position pointer wrap around 183 - * logic which can be optimized to having only one of the two logic sets. 184 - * However, having the double logic will work fine, but if we have only one of 185 - * the sets and we get it wrong somewhere, then we get into trouble, so 186 - * removing the duplicate logic requires _very_ careful consideration of _all_ 187 - * possible code paths. So at least for now, I am leaving the double logic - 188 - * better safe than sorry... (AIA) 189 - * 190 112 * Locking: - The volume lcn bitmap must be unlocked on entry and is unlocked 191 113 * on return. 192 114 * - This function takes the volume lcn bitmap lock for writing and 193 115 * modifies the bitmap contents. 116 + * 117 + * Return: Runlist describing the allocated cluster(s) on success, error pointer 118 + * on failure. 194 119 */ 195 - runlist_element *ntfs_cluster_alloc(ntfs_volume *vol, const VCN start_vcn, 196 - const s64 count, const LCN start_lcn, 197 - const NTFS_CLUSTER_ALLOCATION_ZONES zone, 198 - const bool is_extension) 120 + struct runlist_element *ntfs_cluster_alloc(struct ntfs_volume *vol, const s64 start_vcn, 121 + const s64 count, const s64 start_lcn, 122 + const int zone, 123 + const bool is_extension, 124 + const bool is_contig, 125 + const bool is_dealloc) 199 126 { 200 - LCN zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn; 201 - LCN prev_lcn = 0, prev_run_len = 0, mft_zone_size; 202 - s64 clusters; 127 + s64 zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn; 128 + s64 prev_lcn = 0, prev_run_len = 0, mft_zone_size; 129 + s64 clusters, free_clusters; 203 130 loff_t i_size; 204 131 struct inode *lcnbmp_vi; 205 - runlist_element *rl = NULL; 132 + struct runlist_element *rl = NULL; 206 133 struct address_space *mapping; 207 - struct page *page = NULL; 208 - u8 *buf, *byte; 209 - int err = 0, rlpos, rlsize, buf_size; 134 + struct folio *folio = NULL; 135 + u8 *buf = NULL, *byte; 136 + int err = 0, rlpos, rlsize, buf_size, pg_off; 210 137 u8 pass, done_zones, search_zone, need_writeback = 0, bit; 138 + unsigned int memalloc_flags; 139 + u8 has_guess, used_zone_pos; 140 + pgoff_t index; 211 141 212 - ntfs_debug("Entering for start_vcn 0x%llx, count 0x%llx, start_lcn " 213 - "0x%llx, zone %s_ZONE.", (unsigned long long)start_vcn, 214 - (unsigned long long)count, 215 - (unsigned long long)start_lcn, 142 + ntfs_debug("Entering for start_vcn 0x%llx, count 0x%llx, start_lcn 0x%llx, zone %s_ZONE.", 143 + start_vcn, count, start_lcn, 216 144 zone == MFT_ZONE ? "MFT" : "DATA"); 217 - BUG_ON(!vol); 145 + 218 146 lcnbmp_vi = vol->lcnbmp_ino; 219 - BUG_ON(!lcnbmp_vi); 220 - BUG_ON(start_vcn < 0); 221 - BUG_ON(count < 0); 222 - BUG_ON(start_lcn < -1); 223 - BUG_ON(zone < FIRST_ZONE); 224 - BUG_ON(zone > LAST_ZONE); 147 + if (start_vcn < 0 || start_lcn < LCN_HOLE || 148 + zone < FIRST_ZONE || zone > LAST_ZONE) 149 + return ERR_PTR(-EINVAL); 225 150 226 151 /* Return NULL if @count is zero. */ 227 - if (!count) 228 - return NULL; 152 + if (count < 0 || !count) 153 + return ERR_PTR(-EINVAL); 154 + 155 + memalloc_flags = memalloc_nofs_save(); 156 + 157 + if (!NVolFreeClusterKnown(vol)) 158 + wait_event(vol->free_waitq, NVolFreeClusterKnown(vol)); 159 + free_clusters = atomic64_read(&vol->free_clusters); 160 + 229 161 /* Take the lcnbmp lock for writing. */ 230 162 down_write(&vol->lcnbmp_lock); 163 + if (is_dealloc == false) 164 + free_clusters -= atomic64_read(&vol->dirty_clusters); 165 + 166 + if (free_clusters < count) { 167 + err = -ENOSPC; 168 + goto out_restore; 169 + } 170 + 231 171 /* 232 172 * If no specific @start_lcn was requested, use the current data zone 233 173 * position, otherwise use the requested @start_lcn but make sure it ··· 249 183 * volume) and 4 for data zone 2 (start of volume till start of mft 250 184 * zone). 251 185 */ 186 + has_guess = 1; 252 187 zone_start = start_lcn; 188 + 253 189 if (zone_start < 0) { 254 190 if (zone == DATA_ZONE) 255 191 zone_start = vol->data1_zone_pos; ··· 264 196 */ 265 197 pass = 2; 266 198 } 267 - } else if (zone == DATA_ZONE && zone_start >= vol->mft_zone_start && 268 - zone_start < vol->mft_zone_end) { 269 - zone_start = vol->mft_zone_end; 270 - /* 271 - * Starting at beginning of data1_zone which means a single 272 - * pass in this zone is sufficient. 273 - */ 274 - pass = 2; 275 - } else if (zone == MFT_ZONE && (zone_start < vol->mft_zone_start || 276 - zone_start >= vol->mft_zone_end)) { 277 - zone_start = vol->mft_lcn; 278 - if (!vol->mft_zone_end) 279 - zone_start = 0; 280 - /* 281 - * Starting at beginning of volume which means a single pass 282 - * is sufficient. 283 - */ 284 - pass = 2; 199 + has_guess = 0; 285 200 } 286 - if (zone == MFT_ZONE) { 287 - zone_end = vol->mft_zone_end; 288 - search_zone = 1; 289 - } else /* if (zone == DATA_ZONE) */ { 201 + 202 + used_zone_pos = has_guess ? 0 : 1; 203 + 204 + if (!zone_start || zone_start == vol->mft_zone_start || 205 + zone_start == vol->mft_zone_end) 206 + pass = 2; 207 + 208 + if (zone_start < vol->mft_zone_start) { 209 + zone_end = vol->mft_zone_start; 210 + search_zone = 4; 290 211 /* Skip searching the mft zone. */ 291 212 done_zones |= 1; 292 - if (zone_start >= vol->mft_zone_end) { 293 - zone_end = vol->nr_clusters; 294 - search_zone = 2; 295 - } else { 296 - zone_end = vol->mft_zone_start; 297 - search_zone = 4; 298 - } 213 + } else if (zone_start < vol->mft_zone_end) { 214 + zone_end = vol->mft_zone_end; 215 + search_zone = 1; 216 + } else { 217 + zone_end = vol->nr_clusters; 218 + search_zone = 2; 219 + /* Skip searching the mft zone. */ 220 + done_zones |= 1; 299 221 } 222 + 300 223 /* 301 224 * bmp_pos is the current bit position inside the bitmap. We use 302 225 * bmp_initial_pos to determine whether or not to do a zone switch. ··· 300 241 mapping = lcnbmp_vi->i_mapping; 301 242 i_size = i_size_read(lcnbmp_vi); 302 243 while (1) { 303 - ntfs_debug("Start of outer while loop: done_zones 0x%x, " 304 - "search_zone %i, pass %i, zone_start 0x%llx, " 305 - "zone_end 0x%llx, bmp_initial_pos 0x%llx, " 306 - "bmp_pos 0x%llx, rlpos %i, rlsize %i.", 244 + ntfs_debug("Start of outer while loop: done_zones 0x%x, search_zone %i, pass %i, zone_start 0x%llx, zone_end 0x%llx, bmp_initial_pos 0x%llx, bmp_pos 0x%llx, rlpos %i, rlsize %i.", 307 245 done_zones, search_zone, pass, 308 - (unsigned long long)zone_start, 309 - (unsigned long long)zone_end, 310 - (unsigned long long)bmp_initial_pos, 311 - (unsigned long long)bmp_pos, rlpos, rlsize); 246 + zone_start, zone_end, bmp_initial_pos, 247 + bmp_pos, rlpos, rlsize); 312 248 /* Loop until we run out of free clusters. */ 313 249 last_read_pos = bmp_pos >> 3; 314 - ntfs_debug("last_read_pos 0x%llx.", 315 - (unsigned long long)last_read_pos); 316 - if (last_read_pos > i_size) { 317 - ntfs_debug("End of attribute reached. " 318 - "Skipping to zone_pass_done."); 250 + ntfs_debug("last_read_pos 0x%llx.", last_read_pos); 251 + if (last_read_pos >= i_size) { 252 + ntfs_debug("End of attribute reached. Skipping to zone_pass_done."); 319 253 goto zone_pass_done; 320 254 } 321 - if (likely(page)) { 255 + if (likely(folio)) { 322 256 if (need_writeback) { 323 257 ntfs_debug("Marking page dirty."); 324 - flush_dcache_page(page); 325 - set_page_dirty(page); 258 + folio_mark_dirty(folio); 326 259 need_writeback = 0; 327 260 } 328 - ntfs_unmap_page(page); 261 + folio_unlock(folio); 262 + kunmap_local(buf); 263 + folio_put(folio); 264 + folio = NULL; 329 265 } 330 - page = ntfs_map_page(mapping, last_read_pos >> 331 - PAGE_SHIFT); 332 - if (IS_ERR(page)) { 333 - err = PTR_ERR(page); 334 - ntfs_error(vol->sb, "Failed to map page."); 335 - goto out; 336 - } 337 - buf_size = last_read_pos & ~PAGE_MASK; 338 - buf = page_address(page) + buf_size; 339 - buf_size = PAGE_SIZE - buf_size; 266 + 267 + index = last_read_pos >> PAGE_SHIFT; 268 + pg_off = last_read_pos & ~PAGE_MASK; 269 + buf_size = PAGE_SIZE - pg_off; 340 270 if (unlikely(last_read_pos + buf_size > i_size)) 341 271 buf_size = i_size - last_read_pos; 342 272 buf_size <<= 3; 343 273 lcn = bmp_pos & 7; 344 - bmp_pos &= ~(LCN)7; 345 - ntfs_debug("Before inner while loop: buf_size %i, lcn 0x%llx, " 346 - "bmp_pos 0x%llx, need_writeback %i.", buf_size, 347 - (unsigned long long)lcn, 348 - (unsigned long long)bmp_pos, need_writeback); 274 + bmp_pos &= ~(s64)7; 275 + 276 + if (vol->lcn_empty_bits_per_page[index] == 0) 277 + goto next_bmp_pos; 278 + 279 + folio = read_mapping_folio(mapping, index, NULL); 280 + if (IS_ERR(folio)) { 281 + err = PTR_ERR(folio); 282 + ntfs_error(vol->sb, "Failed to map page."); 283 + goto out; 284 + } 285 + 286 + folio_lock(folio); 287 + buf = kmap_local_folio(folio, 0) + pg_off; 288 + ntfs_debug("Before inner while loop: buf_size %i, lcn 0x%llx, bmp_pos 0x%llx, need_writeback %i.", 289 + buf_size, lcn, bmp_pos, need_writeback); 349 290 while (lcn < buf_size && lcn + bmp_pos < zone_end) { 350 291 byte = buf + (lcn >> 3); 351 - ntfs_debug("In inner while loop: buf_size %i, " 352 - "lcn 0x%llx, bmp_pos 0x%llx, " 353 - "need_writeback %i, byte ofs 0x%x, " 354 - "*byte 0x%x.", buf_size, 355 - (unsigned long long)lcn, 356 - (unsigned long long)bmp_pos, 357 - need_writeback, 292 + ntfs_debug("In inner while loop: buf_size %i, lcn 0x%llx, bmp_pos 0x%llx, need_writeback %i, byte ofs 0x%x, *byte 0x%x.", 293 + buf_size, lcn, bmp_pos, need_writeback, 358 294 (unsigned int)(lcn >> 3), 359 295 (unsigned int)*byte); 360 - /* Skip full bytes. */ 361 - if (*byte == 0xff) { 362 - lcn = (lcn + 8) & ~(LCN)7; 363 - ntfs_debug("Continuing while loop 1."); 364 - continue; 365 - } 366 296 bit = 1 << (lcn & 7); 367 297 ntfs_debug("bit 0x%x.", bit); 368 - /* If the bit is already set, go onto the next one. */ 369 - if (*byte & bit) { 370 - lcn++; 371 - ntfs_debug("Continuing while loop 2."); 298 + 299 + if (has_guess) { 300 + if (*byte & bit) { 301 + if (is_contig == true && prev_run_len > 0) 302 + goto done; 303 + 304 + has_guess = 0; 305 + break; 306 + } 307 + } else { 308 + lcn = max_empty_bit_range(buf, buf_size >> 3); 309 + if (lcn < 0) 310 + break; 311 + has_guess = 1; 372 312 continue; 373 313 } 374 314 /* 375 315 * Allocate more memory if needed, including space for 376 316 * the terminator element. 377 - * ntfs_malloc_nofs() operates on whole pages only. 317 + * kvzalloc() operates on whole pages only. 378 318 */ 379 319 if ((rlpos + 2) * sizeof(*rl) > rlsize) { 380 - runlist_element *rl2; 320 + struct runlist_element *rl2; 381 321 382 322 ntfs_debug("Reallocating memory."); 383 323 if (!rl) 384 - ntfs_debug("First free bit is at LCN " 385 - "0x%llx.", 386 - (unsigned long long) 387 - (lcn + bmp_pos)); 388 - rl2 = ntfs_malloc_nofs(rlsize + (int)PAGE_SIZE); 324 + ntfs_debug("First free bit is at s64 0x%llx.", 325 + lcn + bmp_pos); 326 + rl2 = kvzalloc(rlsize + PAGE_SIZE, GFP_NOFS); 389 327 if (unlikely(!rl2)) { 390 328 err = -ENOMEM; 391 - ntfs_error(vol->sb, "Failed to " 392 - "allocate memory."); 329 + ntfs_error(vol->sb, "Failed to allocate memory."); 393 330 goto out; 394 331 } 395 332 memcpy(rl2, rl, rlsize); 396 - ntfs_free(rl); 333 + kvfree(rl); 397 334 rl = rl2; 398 335 rlsize += PAGE_SIZE; 399 336 ntfs_debug("Reallocated memory, rlsize 0x%x.", ··· 401 346 need_writeback = 1; 402 347 ntfs_debug("*byte 0x%x, need_writeback is set.", 403 348 (unsigned int)*byte); 349 + ntfs_dec_free_clusters(vol, 1); 350 + ntfs_set_lcn_empty_bits(vol, index, 1, 1); 351 + 404 352 /* 405 353 * Coalesce with previous run if adjacent LCNs. 406 354 * Otherwise, append a new run. 407 355 */ 408 - ntfs_debug("Adding run (lcn 0x%llx, len 0x%llx), " 409 - "prev_lcn 0x%llx, lcn 0x%llx, " 410 - "bmp_pos 0x%llx, prev_run_len 0x%llx, " 411 - "rlpos %i.", 412 - (unsigned long long)(lcn + bmp_pos), 413 - 1ULL, (unsigned long long)prev_lcn, 414 - (unsigned long long)lcn, 415 - (unsigned long long)bmp_pos, 416 - (unsigned long long)prev_run_len, 417 - rlpos); 356 + ntfs_debug("Adding run (lcn 0x%llx, len 0x%llx), prev_lcn 0x%llx, lcn 0x%llx, bmp_pos 0x%llx, prev_run_len 0x%llx, rlpos %i.", 357 + lcn + bmp_pos, 1ULL, prev_lcn, 358 + lcn, bmp_pos, prev_run_len, rlpos); 418 359 if (prev_lcn == lcn + bmp_pos - prev_run_len && rlpos) { 419 - ntfs_debug("Coalescing to run (lcn 0x%llx, " 420 - "len 0x%llx).", 421 - (unsigned long long) 360 + ntfs_debug("Coalescing to run (lcn 0x%llx, len 0x%llx).", 422 361 rl[rlpos - 1].lcn, 423 - (unsigned long long) 424 362 rl[rlpos - 1].length); 425 363 rl[rlpos - 1].length = ++prev_run_len; 426 - ntfs_debug("Run now (lcn 0x%llx, len 0x%llx), " 427 - "prev_run_len 0x%llx.", 428 - (unsigned long long) 364 + ntfs_debug("Run now (lcn 0x%llx, len 0x%llx), prev_run_len 0x%llx.", 429 365 rl[rlpos - 1].lcn, 430 - (unsigned long long) 431 366 rl[rlpos - 1].length, 432 - (unsigned long long) 433 367 prev_run_len); 434 368 } else { 435 369 if (likely(rlpos)) { 436 - ntfs_debug("Adding new run, (previous " 437 - "run lcn 0x%llx, " 438 - "len 0x%llx).", 439 - (unsigned long long) 440 - rl[rlpos - 1].lcn, 441 - (unsigned long long) 442 - rl[rlpos - 1].length); 370 + ntfs_debug("Adding new run, (previous run lcn 0x%llx, len 0x%llx).", 371 + rl[rlpos - 1].lcn, rl[rlpos - 1].length); 443 372 rl[rlpos].vcn = rl[rlpos - 1].vcn + 444 373 prev_run_len; 445 374 } else { 446 - ntfs_debug("Adding new run, is first " 447 - "run."); 375 + ntfs_debug("Adding new run, is first run."); 448 376 rl[rlpos].vcn = start_vcn; 449 377 } 450 378 rl[rlpos].lcn = prev_lcn = lcn + bmp_pos; ··· 436 398 } 437 399 /* Done? */ 438 400 if (!--clusters) { 439 - LCN tc; 401 + s64 tc; 402 + done: 403 + if (!used_zone_pos) 404 + goto out; 440 405 /* 441 406 * Update the current zone position. Positions 442 407 * of already scanned zones have been updated 443 408 * during the respective zone switches. 444 409 */ 445 410 tc = lcn + bmp_pos + 1; 446 - ntfs_debug("Done. Updating current zone " 447 - "position, tc 0x%llx, " 448 - "search_zone %i.", 449 - (unsigned long long)tc, 450 - search_zone); 411 + ntfs_debug("Done. Updating current zone position, tc 0x%llx, search_zone %i.", 412 + tc, search_zone); 451 413 switch (search_zone) { 452 414 case 1: 453 - ntfs_debug("Before checks, " 454 - "vol->mft_zone_pos " 455 - "0x%llx.", 456 - (unsigned long long) 415 + ntfs_debug("Before checks, vol->mft_zone_pos 0x%llx.", 457 416 vol->mft_zone_pos); 458 417 if (tc >= vol->mft_zone_end) { 459 418 vol->mft_zone_pos = ··· 462 427 tc > vol->mft_zone_pos) 463 428 && tc >= vol->mft_lcn) 464 429 vol->mft_zone_pos = tc; 465 - ntfs_debug("After checks, " 466 - "vol->mft_zone_pos " 467 - "0x%llx.", 468 - (unsigned long long) 430 + ntfs_debug("After checks, vol->mft_zone_pos 0x%llx.", 469 431 vol->mft_zone_pos); 470 432 break; 471 433 case 2: 472 - ntfs_debug("Before checks, " 473 - "vol->data1_zone_pos " 474 - "0x%llx.", 475 - (unsigned long long) 434 + ntfs_debug("Before checks, vol->data1_zone_pos 0x%llx.", 476 435 vol->data1_zone_pos); 477 436 if (tc >= vol->nr_clusters) 478 437 vol->data1_zone_pos = ··· 476 447 tc > vol->data1_zone_pos) 477 448 && tc >= vol->mft_zone_end) 478 449 vol->data1_zone_pos = tc; 479 - ntfs_debug("After checks, " 480 - "vol->data1_zone_pos " 481 - "0x%llx.", 482 - (unsigned long long) 450 + ntfs_debug("After checks, vol->data1_zone_pos 0x%llx.", 483 451 vol->data1_zone_pos); 484 452 break; 485 453 case 4: 486 - ntfs_debug("Before checks, " 487 - "vol->data2_zone_pos " 488 - "0x%llx.", 489 - (unsigned long long) 454 + ntfs_debug("Before checks, vol->data2_zone_pos 0x%llx.", 490 455 vol->data2_zone_pos); 491 456 if (tc >= vol->mft_zone_start) 492 457 vol->data2_zone_pos = 0; ··· 488 465 vol->data2_zone_pos || 489 466 tc > vol->data2_zone_pos) 490 467 vol->data2_zone_pos = tc; 491 - ntfs_debug("After checks, " 492 - "vol->data2_zone_pos " 493 - "0x%llx.", 494 - (unsigned long long) 468 + ntfs_debug("After checks, vol->data2_zone_pos 0x%llx.", 495 469 vol->data2_zone_pos); 496 470 break; 497 471 default: 498 - BUG(); 472 + WARN_ON(1); 499 473 } 500 474 ntfs_debug("Finished. Going to out."); 501 475 goto out; 502 476 } 503 477 lcn++; 504 478 } 505 - bmp_pos += buf_size; 506 - ntfs_debug("After inner while loop: buf_size 0x%x, lcn " 507 - "0x%llx, bmp_pos 0x%llx, need_writeback %i.", 508 - buf_size, (unsigned long long)lcn, 509 - (unsigned long long)bmp_pos, need_writeback); 479 + 480 + if (!used_zone_pos) { 481 + used_zone_pos = 1; 482 + if (search_zone == 1) 483 + zone_start = vol->mft_zone_pos; 484 + else if (search_zone == 2) 485 + zone_start = vol->data1_zone_pos; 486 + else 487 + zone_start = vol->data2_zone_pos; 488 + 489 + if (!zone_start || zone_start == vol->mft_zone_start || 490 + zone_start == vol->mft_zone_end) 491 + pass = 2; 492 + bmp_pos = zone_start; 493 + } else { 494 + next_bmp_pos: 495 + bmp_pos += buf_size; 496 + } 497 + 498 + ntfs_debug("After inner while loop: buf_size 0x%x, lcn 0x%llx, bmp_pos 0x%llx, need_writeback %i.", 499 + buf_size, lcn, bmp_pos, need_writeback); 510 500 if (bmp_pos < zone_end) { 511 - ntfs_debug("Continuing outer while loop, " 512 - "bmp_pos 0x%llx, zone_end 0x%llx.", 513 - (unsigned long long)bmp_pos, 514 - (unsigned long long)zone_end); 501 + ntfs_debug("Continuing outer while loop, bmp_pos 0x%llx, zone_end 0x%llx.", 502 + bmp_pos, zone_end); 515 503 continue; 516 504 } 517 505 zone_pass_done: /* Finished with the current zone pass. */ ··· 545 511 zone_start = 0; 546 512 break; 547 513 default: 548 - BUG(); 514 + WARN_ON(1); 549 515 } 550 516 /* Sanity check. */ 551 517 if (zone_end < zone_start) 552 518 zone_end = zone_start; 553 519 bmp_pos = zone_start; 554 - ntfs_debug("Continuing outer while loop, pass 2, " 555 - "zone_start 0x%llx, zone_end 0x%llx, " 556 - "bmp_pos 0x%llx.", 557 - (unsigned long long)zone_start, 558 - (unsigned long long)zone_end, 559 - (unsigned long long)bmp_pos); 520 + ntfs_debug("Continuing outer while loop, pass 2, zone_start 0x%llx, zone_end 0x%llx, bmp_pos 0x%llx.", 521 + zone_start, zone_end, bmp_pos); 560 522 continue; 561 523 } /* pass == 2 */ 562 524 done_zones_check: 563 - ntfs_debug("At done_zones_check, search_zone %i, done_zones " 564 - "before 0x%x, done_zones after 0x%x.", 525 + ntfs_debug("At done_zones_check, search_zone %i, done_zones before 0x%x, done_zones after 0x%x.", 565 526 search_zone, done_zones, 566 527 done_zones | search_zone); 567 528 done_zones |= search_zone; ··· 566 537 pass = 1; 567 538 switch (search_zone) { 568 539 case 1: 569 - ntfs_debug("Switching from mft zone to data1 " 570 - "zone."); 540 + ntfs_debug("Switching from mft zone to data1 zone."); 571 541 /* Update mft zone position. */ 572 - if (rlpos) { 573 - LCN tc; 542 + if (rlpos && used_zone_pos) { 543 + s64 tc; 574 544 575 - ntfs_debug("Before checks, " 576 - "vol->mft_zone_pos " 577 - "0x%llx.", 578 - (unsigned long long) 545 + ntfs_debug("Before checks, vol->mft_zone_pos 0x%llx.", 579 546 vol->mft_zone_pos); 580 547 tc = rl[rlpos - 1].lcn + 581 548 rl[rlpos - 1].length; ··· 585 560 tc > vol->mft_zone_pos) 586 561 && tc >= vol->mft_lcn) 587 562 vol->mft_zone_pos = tc; 588 - ntfs_debug("After checks, " 589 - "vol->mft_zone_pos " 590 - "0x%llx.", 591 - (unsigned long long) 563 + ntfs_debug("After checks, vol->mft_zone_pos 0x%llx.", 592 564 vol->mft_zone_pos); 593 565 } 594 566 /* Switch from mft zone to data1 zone. */ ··· 602 580 } 603 581 break; 604 582 case 2: 605 - ntfs_debug("Switching from data1 zone to " 606 - "data2 zone."); 583 + ntfs_debug("Switching from data1 zone to data2 zone."); 607 584 /* Update data1 zone position. */ 608 - if (rlpos) { 609 - LCN tc; 585 + if (rlpos && used_zone_pos) { 586 + s64 tc; 610 587 611 - ntfs_debug("Before checks, " 612 - "vol->data1_zone_pos " 613 - "0x%llx.", 614 - (unsigned long long) 588 + ntfs_debug("Before checks, vol->data1_zone_pos 0x%llx.", 615 589 vol->data1_zone_pos); 616 590 tc = rl[rlpos - 1].lcn + 617 591 rl[rlpos - 1].length; ··· 619 601 tc > vol->data1_zone_pos) 620 602 && tc >= vol->mft_zone_end) 621 603 vol->data1_zone_pos = tc; 622 - ntfs_debug("After checks, " 623 - "vol->data1_zone_pos " 624 - "0x%llx.", 625 - (unsigned long long) 604 + ntfs_debug("After checks, vol->data1_zone_pos 0x%llx.", 626 605 vol->data1_zone_pos); 627 606 } 628 607 /* Switch from data1 zone to data2 zone. */ ··· 636 621 } 637 622 break; 638 623 case 4: 639 - ntfs_debug("Switching from data2 zone to " 640 - "data1 zone."); 624 + ntfs_debug("Switching from data2 zone to data1 zone."); 641 625 /* Update data2 zone position. */ 642 - if (rlpos) { 643 - LCN tc; 626 + if (rlpos && used_zone_pos) { 627 + s64 tc; 644 628 645 - ntfs_debug("Before checks, " 646 - "vol->data2_zone_pos " 647 - "0x%llx.", 648 - (unsigned long long) 629 + ntfs_debug("Before checks, vol->data2_zone_pos 0x%llx.", 649 630 vol->data2_zone_pos); 650 631 tc = rl[rlpos - 1].lcn + 651 632 rl[rlpos - 1].length; ··· 651 640 vol->data2_zone_pos || 652 641 tc > vol->data2_zone_pos) 653 642 vol->data2_zone_pos = tc; 654 - ntfs_debug("After checks, " 655 - "vol->data2_zone_pos " 656 - "0x%llx.", 657 - (unsigned long long) 643 + ntfs_debug("After checks, vol->data2_zone_pos 0x%llx.", 658 644 vol->data2_zone_pos); 659 645 } 660 646 /* Switch from data2 zone to data1 zone. */ 661 647 goto switch_to_data1_zone; 662 648 default: 663 - BUG(); 649 + WARN_ON(1); 664 650 } 665 - ntfs_debug("After zone switch, search_zone %i, " 666 - "pass %i, bmp_initial_pos 0x%llx, " 667 - "zone_start 0x%llx, zone_end 0x%llx.", 651 + ntfs_debug("After zone switch, search_zone %i, pass %i, bmp_initial_pos 0x%llx, zone_start 0x%llx, zone_end 0x%llx.", 668 652 search_zone, pass, 669 - (unsigned long long)bmp_initial_pos, 670 - (unsigned long long)zone_start, 671 - (unsigned long long)zone_end); 653 + bmp_initial_pos, 654 + zone_start, 655 + zone_end); 672 656 bmp_pos = zone_start; 673 657 if (zone_start == zone_end) { 674 - ntfs_debug("Empty zone, going to " 675 - "done_zones_check."); 658 + ntfs_debug("Empty zone, going to done_zones_check."); 676 659 /* Empty zone. Don't bother searching it. */ 677 660 goto done_zones_check; 678 661 } ··· 679 674 * MFT_ZONE, we have really run out of space. 680 675 */ 681 676 mft_zone_size = vol->mft_zone_end - vol->mft_zone_start; 682 - ntfs_debug("vol->mft_zone_start 0x%llx, vol->mft_zone_end " 683 - "0x%llx, mft_zone_size 0x%llx.", 684 - (unsigned long long)vol->mft_zone_start, 685 - (unsigned long long)vol->mft_zone_end, 686 - (unsigned long long)mft_zone_size); 677 + ntfs_debug("vol->mft_zone_start 0x%llx, vol->mft_zone_end 0x%llx, mft_zone_size 0x%llx.", 678 + vol->mft_zone_start, vol->mft_zone_end, 679 + mft_zone_size); 687 680 if (zone == MFT_ZONE || mft_zone_size <= 0) { 688 681 ntfs_debug("No free clusters left, going to out."); 689 682 /* Really no more space left on device. */ ··· 706 703 search_zone = 2; 707 704 pass = 2; 708 705 done_zones &= ~2; 709 - ntfs_debug("After shrinking mft zone, mft_zone_size 0x%llx, " 710 - "vol->mft_zone_start 0x%llx, " 711 - "vol->mft_zone_end 0x%llx, " 712 - "vol->mft_zone_pos 0x%llx, search_zone 2, " 713 - "pass 2, dones_zones 0x%x, zone_start 0x%llx, " 714 - "zone_end 0x%llx, vol->data1_zone_pos 0x%llx, " 715 - "continuing outer while loop.", 716 - (unsigned long long)mft_zone_size, 717 - (unsigned long long)vol->mft_zone_start, 718 - (unsigned long long)vol->mft_zone_end, 719 - (unsigned long long)vol->mft_zone_pos, 720 - done_zones, (unsigned long long)zone_start, 721 - (unsigned long long)zone_end, 722 - (unsigned long long)vol->data1_zone_pos); 706 + ntfs_debug("After shrinking mft zone, mft_zone_size 0x%llx, vol->mft_zone_start 0x%llx, vol->mft_zone_end 0x%llx, vol->mft_zone_pos 0x%llx, search_zone 2, pass 2, dones_zones 0x%x, zone_start 0x%llx, zone_end 0x%llx, vol->data1_zone_pos 0x%llx, continuing outer while loop.", 707 + mft_zone_size, vol->mft_zone_start, 708 + vol->mft_zone_end, vol->mft_zone_pos, 709 + done_zones, zone_start, zone_end, 710 + vol->data1_zone_pos); 723 711 } 724 712 ntfs_debug("After outer while loop."); 725 713 out: ··· 721 727 rl[rlpos].lcn = is_extension ? LCN_ENOENT : LCN_RL_NOT_MAPPED; 722 728 rl[rlpos].length = 0; 723 729 } 724 - if (likely(page && !IS_ERR(page))) { 730 + if (likely(folio && !IS_ERR(folio))) { 725 731 if (need_writeback) { 726 732 ntfs_debug("Marking page dirty."); 727 - flush_dcache_page(page); 728 - set_page_dirty(page); 733 + folio_mark_dirty(folio); 729 734 need_writeback = 0; 730 735 } 731 - ntfs_unmap_page(page); 736 + folio_unlock(folio); 737 + kunmap_local(buf); 738 + folio_put(folio); 732 739 } 733 740 if (likely(!err)) { 734 - up_write(&vol->lcnbmp_lock); 741 + if (is_dealloc == true) 742 + ntfs_release_dirty_clusters(vol, rl->length); 735 743 ntfs_debug("Done."); 736 - return rl; 744 + if (rl == NULL) 745 + err = -EIO; 746 + goto out_restore; 737 747 } 738 - ntfs_error(vol->sb, "Failed to allocate clusters, aborting " 739 - "(error %i).", err); 748 + if (err != -ENOSPC) 749 + ntfs_error(vol->sb, 750 + "Failed to allocate clusters, aborting (error %i).", 751 + err); 740 752 if (rl) { 741 753 int err2; 742 754 743 755 if (err == -ENOSPC) 744 - ntfs_debug("Not enough space to complete allocation, " 745 - "err -ENOSPC, first free lcn 0x%llx, " 746 - "could allocate up to 0x%llx " 747 - "clusters.", 748 - (unsigned long long)rl[0].lcn, 749 - (unsigned long long)(count - clusters)); 756 + ntfs_debug("Not enough space to complete allocation, err -ENOSPC, first free lcn 0x%llx, could allocate up to 0x%llx clusters.", 757 + rl[0].lcn, count - clusters); 750 758 /* Deallocate all allocated clusters. */ 751 759 ntfs_debug("Attempting rollback..."); 752 760 err2 = ntfs_cluster_free_from_rl_nolock(vol, rl); 753 761 if (err2) { 754 - ntfs_error(vol->sb, "Failed to rollback (error %i). " 755 - "Leaving inconsistent metadata! " 756 - "Unmount and run chkdsk.", err2); 762 + ntfs_error(vol->sb, 763 + "Failed to rollback (error %i). Leaving inconsistent metadata! Unmount and run chkdsk.", 764 + err2); 757 765 NVolSetErrors(vol); 758 766 } 759 767 /* Free the runlist. */ 760 - ntfs_free(rl); 768 + kvfree(rl); 761 769 } else if (err == -ENOSPC) 762 - ntfs_debug("No space left at all, err = -ENOSPC, first free " 763 - "lcn = 0x%llx.", 764 - (long long)vol->data1_zone_pos); 770 + ntfs_debug("No space left at all, err = -ENOSPC, first free lcn = 0x%llx.", 771 + vol->data1_zone_pos); 772 + atomic64_set(&vol->dirty_clusters, 0); 773 + 774 + out_restore: 765 775 up_write(&vol->lcnbmp_lock); 766 - return ERR_PTR(err); 776 + memalloc_nofs_restore(memalloc_flags); 777 + 778 + return err < 0 ? ERR_PTR(err) : rl; 767 779 } 768 780 769 - /** 781 + /* 770 782 * __ntfs_cluster_free - free clusters on an ntfs volume 771 783 * @ni: ntfs inode whose runlist describes the clusters to free 772 784 * @start_vcn: vcn in the runlist of @ni at which to start freeing clusters ··· 801 801 * you will probably want to do: 802 802 * m = ctx->mrec; 803 803 * a = ctx->attr; 804 - * Assuming you cache ctx->attr in a variable @a of type ATTR_RECORD * and that 805 - * you cache ctx->mrec in a variable @m of type MFT_RECORD *. 804 + * Assuming you cache ctx->attr in a variable @a of type attr_record * and that 805 + * you cache ctx->mrec in a variable @m of type struct mft_record *. 806 806 * 807 807 * @is_rollback should always be 'false', it is for internal use to rollback 808 808 * errors. You probably want to use ntfs_cluster_free() instead. ··· 832 832 * - If @ctx is not NULL, the base mft record must be mapped on entry 833 833 * and it will be left mapped on return. 834 834 */ 835 - s64 __ntfs_cluster_free(ntfs_inode *ni, const VCN start_vcn, s64 count, 836 - ntfs_attr_search_ctx *ctx, const bool is_rollback) 835 + s64 __ntfs_cluster_free(struct ntfs_inode *ni, const s64 start_vcn, s64 count, 836 + struct ntfs_attr_search_ctx *ctx, const bool is_rollback) 837 837 { 838 838 s64 delta, to_free, total_freed, real_freed; 839 - ntfs_volume *vol; 839 + struct ntfs_volume *vol; 840 840 struct inode *lcnbmp_vi; 841 - runlist_element *rl; 841 + struct runlist_element *rl; 842 842 int err; 843 + unsigned int memalloc_flags; 843 844 844 - BUG_ON(!ni); 845 - ntfs_debug("Entering for i_ino 0x%lx, start_vcn 0x%llx, count " 846 - "0x%llx.%s", ni->mft_no, (unsigned long long)start_vcn, 847 - (unsigned long long)count, 845 + ntfs_debug("Entering for i_ino 0x%lx, start_vcn 0x%llx, count 0x%llx.%s", 846 + ni->mft_no, start_vcn, count, 848 847 is_rollback ? " (rollback)" : ""); 849 848 vol = ni->vol; 850 849 lcnbmp_vi = vol->lcnbmp_ino; 851 - BUG_ON(!lcnbmp_vi); 852 - BUG_ON(start_vcn < 0); 853 - BUG_ON(count < -1); 850 + if (start_vcn < 0 || count < -1) 851 + return -EINVAL; 852 + 853 + if (!NVolFreeClusterKnown(vol)) 854 + wait_event(vol->free_waitq, NVolFreeClusterKnown(vol)); 855 + 854 856 /* 855 857 * Lock the lcn bitmap for writing but only if not rolling back. We 856 858 * must hold the lock all the way including through rollback otherwise ··· 860 858 * dropped the lock, anyone could have set the bit again, thus 861 859 * allocating the cluster for another use. 862 860 */ 863 - if (likely(!is_rollback)) 861 + if (likely(!is_rollback)) { 862 + memalloc_flags = memalloc_nofs_save(); 864 863 down_write(&vol->lcnbmp_lock); 864 + } 865 865 866 866 total_freed = real_freed = 0; 867 867 868 868 rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, ctx); 869 869 if (IS_ERR(rl)) { 870 - if (!is_rollback) 871 - ntfs_error(vol->sb, "Failed to find first runlist " 872 - "element (error %li), aborting.", 873 - PTR_ERR(rl)); 874 870 err = PTR_ERR(rl); 871 + if (err == -ENOENT) { 872 + if (likely(!is_rollback)) { 873 + up_write(&vol->lcnbmp_lock); 874 + memalloc_nofs_restore(memalloc_flags); 875 + } 876 + return 0; 877 + } 878 + 879 + if (!is_rollback) 880 + ntfs_error(vol->sb, 881 + "Failed to find first runlist element (error %d), aborting.", 882 + err); 875 883 goto err_out; 876 884 } 877 885 if (unlikely(rl->lcn < LCN_HOLE)) { 878 886 if (!is_rollback) 879 - ntfs_error(vol->sb, "First runlist element has " 880 - "invalid lcn, aborting."); 887 + ntfs_error(vol->sb, "First runlist element has invalid lcn, aborting."); 881 888 err = -EIO; 882 889 goto err_out; 883 890 } ··· 904 893 to_free, likely(!is_rollback) ? 0 : 1); 905 894 if (unlikely(err)) { 906 895 if (!is_rollback) 907 - ntfs_error(vol->sb, "Failed to clear first run " 908 - "(error %i), aborting.", err); 896 + ntfs_error(vol->sb, 897 + "Failed to clear first run (error %i), aborting.", 898 + err); 909 899 goto err_out; 910 900 } 911 901 /* We have freed @to_free real clusters. */ 912 902 real_freed = to_free; 913 - }; 903 + } 914 904 /* Go to the next run and adjust the number of clusters left to free. */ 915 905 ++rl; 916 906 if (count >= 0) ··· 925 913 */ 926 914 for (; rl->length && count != 0; ++rl) { 927 915 if (unlikely(rl->lcn < LCN_HOLE)) { 928 - VCN vcn; 916 + s64 vcn; 929 917 930 918 /* Attempt to map runlist. */ 931 919 vcn = rl->vcn; ··· 933 921 if (IS_ERR(rl)) { 934 922 err = PTR_ERR(rl); 935 923 if (!is_rollback) 936 - ntfs_error(vol->sb, "Failed to map " 937 - "runlist fragment or " 938 - "failed to find " 939 - "subsequent runlist " 940 - "element."); 924 + ntfs_error(vol->sb, 925 + "Failed to map runlist fragment or failed to find subsequent runlist element."); 941 926 goto err_out; 942 927 } 943 928 if (unlikely(rl->lcn < LCN_HOLE)) { 944 929 if (!is_rollback) 945 - ntfs_error(vol->sb, "Runlist element " 946 - "has invalid lcn " 947 - "(0x%llx).", 948 - (unsigned long long) 949 - rl->lcn); 930 + ntfs_error(vol->sb, 931 + "Runlist element has invalid lcn (0x%llx).", 932 + rl->lcn); 950 933 err = -EIO; 951 934 goto err_out; 952 935 } ··· 957 950 to_free, likely(!is_rollback) ? 0 : 1); 958 951 if (unlikely(err)) { 959 952 if (!is_rollback) 960 - ntfs_error(vol->sb, "Failed to clear " 961 - "subsequent run."); 953 + ntfs_error(vol->sb, "Failed to clear subsequent run."); 962 954 goto err_out; 963 955 } 964 956 /* We have freed @to_free real clusters. */ ··· 966 960 /* Adjust the number of clusters left to free. */ 967 961 if (count >= 0) 968 962 count -= to_free; 969 - 963 + 970 964 /* Update the total done clusters. */ 971 965 total_freed += to_free; 972 966 } 973 - if (likely(!is_rollback)) 967 + ntfs_inc_free_clusters(vol, real_freed); 968 + if (likely(!is_rollback)) { 974 969 up_write(&vol->lcnbmp_lock); 970 + memalloc_nofs_restore(memalloc_flags); 971 + } 975 972 976 - BUG_ON(count > 0); 973 + WARN_ON(count > 0); 974 + 975 + if (NVolDiscard(vol) && !is_rollback) { 976 + s64 total_discarded = 0, rl_off; 977 + u32 gran = bdev_discard_granularity(vol->sb->s_bdev); 978 + 979 + rl = ntfs_attr_find_vcn_nolock(ni, start_vcn, ctx); 980 + if (IS_ERR(rl)) 981 + return real_freed; 982 + rl_off = start_vcn - rl->vcn; 983 + while (rl->length && total_discarded < total_freed) { 984 + s64 to_discard = rl->length - rl_off; 985 + 986 + if (to_discard + total_discarded > total_freed) 987 + to_discard = total_freed - total_discarded; 988 + if (rl->lcn >= 0) { 989 + sector_t start_sector, end_sector; 990 + int ret; 991 + 992 + start_sector = ALIGN(NTFS_CLU_TO_B(vol, rl->lcn + rl_off), 993 + gran) >> SECTOR_SHIFT; 994 + end_sector = ALIGN_DOWN(NTFS_CLU_TO_B(vol, 995 + rl->lcn + rl_off + to_discard), 996 + gran) >> SECTOR_SHIFT; 997 + if (start_sector < end_sector) { 998 + ret = blkdev_issue_discard(vol->sb->s_bdev, start_sector, 999 + end_sector - start_sector, 1000 + GFP_NOFS); 1001 + if (ret) 1002 + break; 1003 + } 1004 + } 1005 + 1006 + total_discarded += to_discard; 1007 + ++rl; 1008 + rl_off = 0; 1009 + } 1010 + } 977 1011 978 1012 /* We are done. Return the number of actually freed clusters. */ 979 1013 ntfs_debug("Done."); ··· 1024 978 /* If no real clusters were freed, no need to rollback. */ 1025 979 if (!real_freed) { 1026 980 up_write(&vol->lcnbmp_lock); 981 + memalloc_nofs_restore(memalloc_flags); 1027 982 return err; 1028 983 } 1029 984 /* ··· 1034 987 */ 1035 988 delta = __ntfs_cluster_free(ni, start_vcn, total_freed, ctx, true); 1036 989 if (delta < 0) { 1037 - ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving " 1038 - "inconsistent metadata! Unmount and run " 1039 - "chkdsk.", (int)delta); 990 + ntfs_error(vol->sb, 991 + "Failed to rollback (error %i). Leaving inconsistent metadata! Unmount and run chkdsk.", 992 + (int)delta); 1040 993 NVolSetErrors(vol); 1041 994 } 995 + ntfs_dec_free_clusters(vol, delta); 1042 996 up_write(&vol->lcnbmp_lock); 997 + memalloc_nofs_restore(memalloc_flags); 1043 998 ntfs_error(vol->sb, "Aborting (error %i).", err); 1044 999 return err; 1045 1000 } 1046 - 1047 - #endif /* NTFS_RW */
+769 -596
fs/ntfs/runlist.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 2 /* 3 - * runlist.c - NTFS runlist handling code. Part of the Linux-NTFS project. 3 + * NTFS runlist handling code. 4 4 * 5 5 * Copyright (c) 2001-2007 Anton Altaparmakov 6 6 * Copyright (c) 2002-2005 Richard Russon 7 + * Copyright (c) 2025 LG Electronics Co., Ltd. 8 + * 9 + * Part of this file is based on code from the NTFS-3G. 10 + * and is copyrighted by the respective authors below: 11 + * Copyright (c) 2002-2005 Anton Altaparmakov 12 + * Copyright (c) 2002-2005 Richard Russon 13 + * Copyright (c) 2002-2008 Szabolcs Szakacsits 14 + * Copyright (c) 2004 Yura Pakhuchiy 15 + * Copyright (c) 2007-2022 Jean-Pierre Andre 7 16 */ 8 17 9 - #include "debug.h" 10 - #include "dir.h" 11 - #include "endian.h" 12 - #include "malloc.h" 13 18 #include "ntfs.h" 19 + #include "attrib.h" 14 20 15 - /** 21 + /* 16 22 * ntfs_rl_mm - runlist memmove 23 + * @base: base runlist array 24 + * @dst: destination index in @base 25 + * @src: source index in @base 26 + * @size: number of elements to move 17 27 * 18 28 * It is up to the caller to serialize access to the runlist @base. 19 29 */ 20 - static inline void ntfs_rl_mm(runlist_element *base, int dst, int src, 21 - int size) 30 + static inline void ntfs_rl_mm(struct runlist_element *base, int dst, int src, int size) 22 31 { 23 32 if (likely((dst != src) && (size > 0))) 24 33 memmove(base + dst, base + src, size * sizeof(*base)); 25 34 } 26 35 27 - /** 36 + /* 28 37 * ntfs_rl_mc - runlist memory copy 38 + * @dstbase: destination runlist array 39 + * @dst: destination index in @dstbase 40 + * @srcbase: source runlist array 41 + * @src: source index in @srcbase 42 + * @size: number of elements to copy 29 43 * 30 44 * It is up to the caller to serialize access to the runlists @dstbase and 31 45 * @srcbase. 32 46 */ 33 - static inline void ntfs_rl_mc(runlist_element *dstbase, int dst, 34 - runlist_element *srcbase, int src, int size) 47 + static inline void ntfs_rl_mc(struct runlist_element *dstbase, int dst, 48 + struct runlist_element *srcbase, int src, int size) 35 49 { 36 50 if (likely(size > 0)) 37 51 memcpy(dstbase + dst, srcbase + src, size * sizeof(*dstbase)); 38 52 } 39 53 40 - /** 54 + /* 41 55 * ntfs_rl_realloc - Reallocate memory for runlists 42 56 * @rl: original runlist 43 57 * @old_size: number of runlist elements in the original runlist @rl ··· 67 53 * memory, the function will return the original pointer. 68 54 * 69 55 * On success, return a pointer to the newly allocated, or recycled, memory. 70 - * On error, return -errno. The following error codes are defined: 71 - * -ENOMEM - Not enough memory to allocate runlist array. 72 - * -EINVAL - Invalid parameters were passed in. 56 + * On error, return -errno. 73 57 */ 74 - static inline runlist_element *ntfs_rl_realloc(runlist_element *rl, 58 + struct runlist_element *ntfs_rl_realloc(struct runlist_element *rl, 75 59 int old_size, int new_size) 76 60 { 77 - runlist_element *new_rl; 61 + struct runlist_element *new_rl; 78 62 79 - old_size = PAGE_ALIGN(old_size * sizeof(*rl)); 80 - new_size = PAGE_ALIGN(new_size * sizeof(*rl)); 63 + old_size = old_size * sizeof(*rl); 64 + new_size = new_size * sizeof(*rl); 81 65 if (old_size == new_size) 82 66 return rl; 83 67 84 - new_rl = ntfs_malloc_nofs(new_size); 68 + new_rl = kvzalloc(new_size, GFP_NOFS); 85 69 if (unlikely(!new_rl)) 86 70 return ERR_PTR(-ENOMEM); 87 71 ··· 87 75 if (unlikely(old_size > new_size)) 88 76 old_size = new_size; 89 77 memcpy(new_rl, rl, old_size); 90 - ntfs_free(rl); 78 + kvfree(rl); 91 79 } 92 80 return new_rl; 93 81 } 94 82 95 - /** 83 + /* 96 84 * ntfs_rl_realloc_nofail - Reallocate memory for runlists 97 85 * @rl: original runlist 98 86 * @old_size: number of runlist elements in the original runlist @rl ··· 111 99 * memory, the function will return the original pointer. 112 100 * 113 101 * On success, return a pointer to the newly allocated, or recycled, memory. 114 - * On error, return -errno. The following error codes are defined: 115 - * -ENOMEM - Not enough memory to allocate runlist array. 116 - * -EINVAL - Invalid parameters were passed in. 102 + * On error, return -errno. 117 103 */ 118 - static inline runlist_element *ntfs_rl_realloc_nofail(runlist_element *rl, 104 + static inline struct runlist_element *ntfs_rl_realloc_nofail(struct runlist_element *rl, 119 105 int old_size, int new_size) 120 106 { 121 - runlist_element *new_rl; 107 + struct runlist_element *new_rl; 122 108 123 - old_size = PAGE_ALIGN(old_size * sizeof(*rl)); 124 - new_size = PAGE_ALIGN(new_size * sizeof(*rl)); 109 + old_size = old_size * sizeof(*rl); 110 + new_size = new_size * sizeof(*rl); 125 111 if (old_size == new_size) 126 112 return rl; 127 113 128 - new_rl = ntfs_malloc_nofs_nofail(new_size); 129 - BUG_ON(!new_rl); 130 - 114 + new_rl = kvmalloc(new_size, GFP_NOFS | __GFP_NOFAIL); 131 115 if (likely(rl != NULL)) { 132 116 if (unlikely(old_size > new_size)) 133 117 old_size = new_size; 134 118 memcpy(new_rl, rl, old_size); 135 - ntfs_free(rl); 119 + kvfree(rl); 136 120 } 137 121 return new_rl; 138 122 } 139 123 140 - /** 124 + /* 141 125 * ntfs_are_rl_mergeable - test if two runlists can be joined together 142 126 * @dst: original runlist 143 127 * @src: new runlist to test for mergeability with @dst ··· 146 138 * Return: true Success, the runlists can be merged. 147 139 * false Failure, the runlists cannot be merged. 148 140 */ 149 - static inline bool ntfs_are_rl_mergeable(runlist_element *dst, 150 - runlist_element *src) 141 + static inline bool ntfs_are_rl_mergeable(struct runlist_element *dst, 142 + struct runlist_element *src) 151 143 { 152 - BUG_ON(!dst); 153 - BUG_ON(!src); 154 - 155 144 /* We can merge unmapped regions even if they are misaligned. */ 156 145 if ((dst->lcn == LCN_RL_NOT_MAPPED) && (src->lcn == LCN_RL_NOT_MAPPED)) 157 146 return true; ··· 162 157 /* If we are merging two holes, we can merge them. */ 163 158 if ((dst->lcn == LCN_HOLE) && (src->lcn == LCN_HOLE)) 164 159 return true; 160 + /* If we are merging two dealloc, we can merge them. */ 161 + if ((dst->lcn == LCN_DELALLOC) && (src->lcn == LCN_DELALLOC)) 162 + return true; 165 163 /* Cannot merge. */ 166 164 return false; 167 165 } 168 166 169 - /** 167 + /* 170 168 * __ntfs_rl_merge - merge two runlists without testing if they can be merged 171 169 * @dst: original, destination runlist 172 170 * @src: new runlist to merge with @dst ··· 180 172 * 181 173 * It is up to the caller to serialize access to the runlists @dst and @src. 182 174 */ 183 - static inline void __ntfs_rl_merge(runlist_element *dst, runlist_element *src) 175 + static inline void __ntfs_rl_merge(struct runlist_element *dst, struct runlist_element *src) 184 176 { 185 177 dst->length += src->length; 186 178 } 187 179 188 - /** 180 + /* 189 181 * ntfs_rl_append - append a runlist after a given element 190 - * @dst: original runlist to be worked on 191 - * @dsize: number of elements in @dst (including end marker) 192 - * @src: runlist to be inserted into @dst 193 - * @ssize: number of elements in @src (excluding end marker) 194 - * @loc: append the new runlist @src after this element in @dst 182 + * @dst: destination runlist to append to 183 + * @dsize: number of elements in @dst 184 + * @src: source runlist to append from 185 + * @ssize: number of elements in @src 186 + * @loc: index in @dst after which to append @src 187 + * @new_size: on success, set to the new combined size 195 188 * 196 189 * Append the runlist @src after element @loc in @dst. Merge the right end of 197 190 * the new runlist, if necessary. Adjust the size of the hole before the ··· 205 196 * the pointers for anything any more. (Strictly speaking the returned runlist 206 197 * may be the same as @dst but this is irrelevant.) 207 198 * 208 - * On error, return -errno. Both runlists are left unmodified. The following 209 - * error codes are defined: 210 - * -ENOMEM - Not enough memory to allocate runlist array. 211 - * -EINVAL - Invalid parameters were passed in. 199 + * On error, return -errno. Both runlists are left unmodified. 212 200 */ 213 - static inline runlist_element *ntfs_rl_append(runlist_element *dst, 214 - int dsize, runlist_element *src, int ssize, int loc) 201 + static inline struct runlist_element *ntfs_rl_append(struct runlist_element *dst, 202 + int dsize, struct runlist_element *src, int ssize, int loc, 203 + size_t *new_size) 215 204 { 216 205 bool right = false; /* Right end of @src needs merging. */ 217 206 int marker; /* End of the inserted runs. */ 218 - 219 - BUG_ON(!dst); 220 - BUG_ON(!src); 221 207 222 208 /* First, check if the right hand end needs merging. */ 223 209 if ((loc + 1) < dsize) ··· 222 218 dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - right); 223 219 if (IS_ERR(dst)) 224 220 return dst; 221 + 222 + *new_size = dsize + ssize - right; 225 223 /* 226 224 * We are guaranteed to succeed from here so can start modifying the 227 225 * original runlists. ··· 250 244 return dst; 251 245 } 252 246 253 - /** 247 + /* 254 248 * ntfs_rl_insert - insert a runlist into another 255 - * @dst: original runlist to be worked on 256 - * @dsize: number of elements in @dst (including end marker) 257 - * @src: new runlist to be inserted 258 - * @ssize: number of elements in @src (excluding end marker) 259 - * @loc: insert the new runlist @src before this element in @dst 249 + * @dst: destination runlist to insert into 250 + * @dsize: number of elements in @dst 251 + * @src: source runlist to insert from 252 + * @ssize: number of elements in @src 253 + * @loc: index in @dst at which to insert @src 254 + * @new_size: on success, set to the new combined size 260 255 * 261 256 * Insert the runlist @src before element @loc in the runlist @dst. Merge the 262 257 * left end of the new runlist, if necessary. Adjust the size of the hole ··· 270 263 * the pointers for anything any more. (Strictly speaking the returned runlist 271 264 * may be the same as @dst but this is irrelevant.) 272 265 * 273 - * On error, return -errno. Both runlists are left unmodified. The following 274 - * error codes are defined: 275 - * -ENOMEM - Not enough memory to allocate runlist array. 276 - * -EINVAL - Invalid parameters were passed in. 266 + * On error, return -errno. Both runlists are left unmodified. 277 267 */ 278 - static inline runlist_element *ntfs_rl_insert(runlist_element *dst, 279 - int dsize, runlist_element *src, int ssize, int loc) 268 + static inline struct runlist_element *ntfs_rl_insert(struct runlist_element *dst, 269 + int dsize, struct runlist_element *src, int ssize, int loc, 270 + size_t *new_size) 280 271 { 281 272 bool left = false; /* Left end of @src needs merging. */ 282 273 bool disc = false; /* Discontinuity between @dst and @src. */ 283 274 int marker; /* End of the inserted runs. */ 284 - 285 - BUG_ON(!dst); 286 - BUG_ON(!src); 287 275 288 276 /* 289 277 * disc => Discontinuity between the end of @dst and the start of @src. ··· 304 302 dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left + disc); 305 303 if (IS_ERR(dst)) 306 304 return dst; 305 + 306 + *new_size = dsize + ssize - left + disc; 307 307 /* 308 308 * We are guaranteed to succeed from here so can start modifying the 309 309 * original runlist. ··· 328 324 /* Adjust the VCN of the first run after the insertion... */ 329 325 dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length; 330 326 /* ... and the length. */ 331 - if (dst[marker].lcn == LCN_HOLE || dst[marker].lcn == LCN_RL_NOT_MAPPED) 327 + if (dst[marker].lcn == LCN_HOLE || dst[marker].lcn == LCN_RL_NOT_MAPPED || 328 + dst[marker].lcn == LCN_DELALLOC) 332 329 dst[marker].length = dst[marker + 1].vcn - dst[marker].vcn; 333 330 334 331 /* Writing beyond the end of the file and there is a discontinuity. */ ··· 346 341 return dst; 347 342 } 348 343 349 - /** 344 + /* 350 345 * ntfs_rl_replace - overwrite a runlist element with another runlist 351 - * @dst: original runlist to be worked on 352 - * @dsize: number of elements in @dst (including end marker) 353 - * @src: new runlist to be inserted 354 - * @ssize: number of elements in @src (excluding end marker) 355 - * @loc: index in runlist @dst to overwrite with @src 346 + * @dst: destination runlist to replace in 347 + * @dsize: number of elements in @dst 348 + * @src: source runlist to replace with 349 + * @ssize: number of elements in @src 350 + * @loc: index in @dst to replace 351 + * @new_size: on success, set to the new combined size 356 352 * 357 353 * Replace the runlist element @dst at @loc with @src. Merge the left and 358 354 * right ends of the inserted runlist, if necessary. ··· 365 359 * the pointers for anything any more. (Strictly speaking the returned runlist 366 360 * may be the same as @dst but this is irrelevant.) 367 361 * 368 - * On error, return -errno. Both runlists are left unmodified. The following 369 - * error codes are defined: 370 - * -ENOMEM - Not enough memory to allocate runlist array. 371 - * -EINVAL - Invalid parameters were passed in. 362 + * On error, return -errno. Both runlists are left unmodified. 372 363 */ 373 - static inline runlist_element *ntfs_rl_replace(runlist_element *dst, 374 - int dsize, runlist_element *src, int ssize, int loc) 364 + static inline struct runlist_element *ntfs_rl_replace(struct runlist_element *dst, 365 + int dsize, struct runlist_element *src, int ssize, int loc, 366 + size_t *new_size) 375 367 { 376 - signed delta; 368 + int delta; 377 369 bool left = false; /* Left end of @src needs merging. */ 378 370 bool right = false; /* Right end of @src needs merging. */ 379 371 int tail; /* Start of tail of @dst. */ 380 372 int marker; /* End of the inserted runs. */ 381 - 382 - BUG_ON(!dst); 383 - BUG_ON(!src); 384 373 385 374 /* First, see if the left and right ends need merging. */ 386 375 if ((loc + 1) < dsize) ··· 392 391 if (IS_ERR(dst)) 393 392 return dst; 394 393 } 394 + 395 + *new_size = dsize + delta; 395 396 /* 396 397 * We are guaranteed to succeed from here so can start modifying the 397 398 * original runlists. ··· 432 429 return dst; 433 430 } 434 431 435 - /** 432 + /* 436 433 * ntfs_rl_split - insert a runlist into the centre of a hole 437 - * @dst: original runlist to be worked on 438 - * @dsize: number of elements in @dst (including end marker) 439 - * @src: new runlist to be inserted 440 - * @ssize: number of elements in @src (excluding end marker) 441 - * @loc: index in runlist @dst at which to split and insert @src 434 + * @dst: destination runlist with a hole 435 + * @dsize: number of elements in @dst 436 + * @src: source runlist to insert 437 + * @ssize: number of elements in @src 438 + * @loc: index in @dst of the hole to split 439 + * @new_size: on success, set to the new combined size 442 440 * 443 441 * Split the runlist @dst at @loc into two and insert @new in between the two 444 442 * fragments. No merging of runlists is necessary. Adjust the size of the ··· 452 448 * the pointers for anything any more. (Strictly speaking the returned runlist 453 449 * may be the same as @dst but this is irrelevant.) 454 450 * 455 - * On error, return -errno. Both runlists are left unmodified. The following 456 - * error codes are defined: 457 - * -ENOMEM - Not enough memory to allocate runlist array. 458 - * -EINVAL - Invalid parameters were passed in. 451 + * On error, return -errno. Both runlists are left unmodified. 459 452 */ 460 - static inline runlist_element *ntfs_rl_split(runlist_element *dst, int dsize, 461 - runlist_element *src, int ssize, int loc) 453 + static inline struct runlist_element *ntfs_rl_split(struct runlist_element *dst, int dsize, 454 + struct runlist_element *src, int ssize, int loc, 455 + size_t *new_size) 462 456 { 463 - BUG_ON(!dst); 464 - BUG_ON(!src); 465 - 466 457 /* Space required: @dst size + @src size + one new hole. */ 467 458 dst = ntfs_rl_realloc(dst, dsize, dsize + ssize + 1); 468 459 if (IS_ERR(dst)) 469 460 return dst; 461 + 462 + *new_size = dsize + ssize + 1; 470 463 /* 471 464 * We are guaranteed to succeed from here so can start modifying the 472 465 * original runlists. ··· 481 480 return dst; 482 481 } 483 482 484 - /** 483 + /* 485 484 * ntfs_runlists_merge - merge two runlists into one 486 - * @drl: original runlist to be worked on 487 - * @srl: new runlist to be merged into @drl 485 + * @d_runlist: destination runlist structure to merge into 486 + * @srl: source runlist to merge from 487 + * @s_rl_count: number of elements in @srl (0 to auto-detect) 488 + * @new_rl_count: on success, set to the new combined runlist size 488 489 * 489 490 * First we sanity check the two runlists @srl and @drl to make sure that they 490 491 * are sensible and can be merged. The runlist @srl must be either after the ··· 511 508 * the pointers for anything any more. (Strictly speaking the returned runlist 512 509 * may be the same as @dst but this is irrelevant.) 513 510 * 514 - * On error, return -errno. Both runlists are left unmodified. The following 515 - * error codes are defined: 516 - * -ENOMEM - Not enough memory to allocate runlist array. 517 - * -EINVAL - Invalid parameters were passed in. 518 - * -ERANGE - The runlists overlap and cannot be merged. 511 + * On error, return -errno. Both runlists are left unmodified. 519 512 */ 520 - runlist_element *ntfs_runlists_merge(runlist_element *drl, 521 - runlist_element *srl) 513 + struct runlist_element *ntfs_runlists_merge(struct runlist *d_runlist, 514 + struct runlist_element *srl, size_t s_rl_count, 515 + size_t *new_rl_count) 522 516 { 523 517 int di, si; /* Current index into @[ds]rl. */ 524 518 int sstart; /* First index with lcn > LCN_RL_NOT_MAPPED. */ 525 519 int dins; /* Index into @drl at which to insert @srl. */ 526 520 int dend, send; /* Last index into @[ds]rl. */ 527 - int dfinal, sfinal; /* The last index into @[ds]rl with 528 - lcn >= LCN_HOLE. */ 521 + int dfinal, sfinal; /* The last index into @[ds]rl with lcn >= LCN_HOLE. */ 529 522 int marker = 0; 530 - VCN marker_vcn = 0; 523 + s64 marker_vcn = 0; 524 + struct runlist_element *drl = d_runlist->rl, *rl; 531 525 532 526 #ifdef DEBUG 533 527 ntfs_debug("dst:"); ··· 539 539 if (IS_ERR(srl) || IS_ERR(drl)) 540 540 return ERR_PTR(-EINVAL); 541 541 542 + if (s_rl_count == 0) { 543 + for (; srl[s_rl_count].length; s_rl_count++) 544 + ; 545 + s_rl_count++; 546 + } 547 + 542 548 /* Check for the case where the first mapping is being done now. */ 543 549 if (unlikely(!drl)) { 544 550 drl = srl; 545 551 /* Complete the source runlist if necessary. */ 546 552 if (unlikely(drl[0].vcn)) { 547 553 /* Scan to the end of the source runlist. */ 548 - for (dend = 0; likely(drl[dend].length); dend++) 549 - ; 550 - dend++; 551 - drl = ntfs_rl_realloc(drl, dend, dend + 1); 554 + drl = ntfs_rl_realloc(drl, s_rl_count, s_rl_count + 1); 552 555 if (IS_ERR(drl)) 553 556 return drl; 554 557 /* Insert start element at the front of the runlist. */ 555 - ntfs_rl_mm(drl, 1, 0, dend); 558 + ntfs_rl_mm(drl, 1, 0, s_rl_count); 556 559 drl[0].vcn = 0; 557 560 drl[0].lcn = LCN_RL_NOT_MAPPED; 558 561 drl[0].length = drl[1].vcn; 562 + s_rl_count++; 559 563 } 564 + 565 + *new_rl_count = s_rl_count; 560 566 goto finished; 561 567 } 568 + 569 + if (d_runlist->count < 1 || s_rl_count < 2) 570 + return ERR_PTR(-EINVAL); 562 571 563 572 si = di = 0; 564 573 ··· 576 567 si++; 577 568 578 569 /* Can't have an entirely unmapped source runlist. */ 579 - BUG_ON(!srl[si].length); 570 + WARN_ON(!srl[si].length); 580 571 581 572 /* Record the starting points. */ 582 573 sstart = si; ··· 586 577 * be inserted. If we reach the end of @drl, @srl just needs to be 587 578 * appended to @drl. 588 579 */ 589 - for (; drl[di].length; di++) { 590 - if (drl[di].vcn + drl[di].length > srl[sstart].vcn) 591 - break; 592 - } 580 + rl = __ntfs_attr_find_vcn_nolock(d_runlist, srl[sstart].vcn); 581 + if (IS_ERR(rl)) 582 + di = (int)d_runlist->count - 1; 583 + else 584 + di = (int)(rl - d_runlist->rl); 593 585 dins = di; 594 586 595 587 /* Sanity check for illegal overlaps. */ ··· 601 591 } 602 592 603 593 /* Scan to the end of both runlists in order to know their sizes. */ 604 - for (send = si; srl[send].length; send++) 605 - ; 606 - for (dend = di; drl[dend].length; dend++) 607 - ; 594 + send = (int)s_rl_count - 1; 595 + dend = (int)d_runlist->count - 1; 608 596 609 597 if (srl[send].lcn == LCN_ENOENT) 610 598 marker_vcn = srl[marker = send].vcn; ··· 630 622 ss++; 631 623 if (marker && (drl[dins].vcn + drl[dins].length > srl[send - 1].vcn)) 632 624 finish = false; 633 - #if 0 634 - ntfs_debug("dfinal = %i, dend = %i", dfinal, dend); 635 - ntfs_debug("sstart = %i, sfinal = %i, send = %i", sstart, sfinal, send); 636 - ntfs_debug("start = %i, finish = %i", start, finish); 637 - ntfs_debug("ds = %i, ss = %i, dins = %i", ds, ss, dins); 638 - #endif 625 + 639 626 if (start) { 640 627 if (finish) 641 - drl = ntfs_rl_replace(drl, ds, srl + sstart, ss, dins); 628 + drl = ntfs_rl_replace(drl, ds, srl + sstart, ss, dins, new_rl_count); 642 629 else 643 - drl = ntfs_rl_insert(drl, ds, srl + sstart, ss, dins); 630 + drl = ntfs_rl_insert(drl, ds, srl + sstart, ss, dins, new_rl_count); 644 631 } else { 645 632 if (finish) 646 - drl = ntfs_rl_append(drl, ds, srl + sstart, ss, dins); 633 + drl = ntfs_rl_append(drl, ds, srl + sstart, ss, dins, new_rl_count); 647 634 else 648 - drl = ntfs_rl_split(drl, ds, srl + sstart, ss, dins); 635 + drl = ntfs_rl_split(drl, ds, srl + sstart, ss, dins, new_rl_count); 649 636 } 650 637 if (IS_ERR(drl)) { 651 638 ntfs_error(NULL, "Merge failed."); 652 639 return drl; 653 640 } 654 - ntfs_free(srl); 641 + kvfree(srl); 655 642 if (marker) { 656 643 ntfs_debug("Triggering marker code."); 657 644 for (ds = dend; drl[ds].length; ds++) ··· 656 653 int slots = 0; 657 654 658 655 if (drl[ds].vcn == marker_vcn) { 659 - ntfs_debug("Old marker = 0x%llx, replacing " 660 - "with LCN_ENOENT.", 661 - (unsigned long long) 656 + ntfs_debug("Old marker = 0x%llx, replacing with LCN_ENOENT.", 662 657 drl[ds].lcn); 663 658 drl[ds].lcn = LCN_ENOENT; 664 659 goto finished; ··· 676 675 drl = ntfs_rl_realloc_nofail(drl, ds, 677 676 ds + 2); 678 677 slots = 2; 678 + *new_rl_count += 2; 679 679 } 680 680 ds++; 681 681 /* Need to set vcn if it isn't set already. */ ··· 690 688 drl[ds].length = marker_vcn - drl[ds].vcn; 691 689 /* Finally add the ENOENT terminator. */ 692 690 ds++; 693 - if (!slots) 691 + if (!slots) { 694 692 drl = ntfs_rl_realloc_nofail(drl, ds, ds + 1); 693 + *new_rl_count += 1; 694 + } 695 695 drl[ds].vcn = marker_vcn; 696 696 drl[ds].lcn = LCN_ENOENT; 697 697 drl[ds].length = (s64)0; ··· 708 704 return drl; 709 705 } 710 706 711 - /** 707 + /* 712 708 * ntfs_mapping_pairs_decompress - convert mapping pairs array to runlist 713 - * @vol: ntfs volume on which the attribute resides 714 - * @attr: attribute record whose mapping pairs array to decompress 715 - * @old_rl: optional runlist in which to insert @attr's runlist 709 + * @vol: ntfs volume 710 + * @attr: attribute record whose mapping pairs to decompress 711 + * @old_runlist: optional runlist to merge the decompressed runlist into 712 + * @new_rl_count: on success, set to the new runlist size 716 713 * 717 714 * It is up to the caller to serialize access to the runlist @old_rl. 718 715 * ··· 725 720 * returned. The original @old_rl is deallocated. 726 721 * 727 722 * On error, return -errno. @old_rl is left unmodified in that case. 728 - * 729 - * The following error codes are defined: 730 - * -ENOMEM - Not enough memory to allocate runlist array. 731 - * -EIO - Corrupt runlist. 732 - * -EINVAL - Invalid parameters were passed in. 733 - * -ERANGE - The two runlists overlap. 734 - * 735 - * FIXME: For now we take the conceptionally simplest approach of creating the 736 - * new runlist disregarding the already existing one and then splicing the 737 - * two into one, if that is possible (we check for overlap and discard the new 738 - * runlist if overlap present before returning ERR_PTR(-ERANGE)). 739 723 */ 740 - runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol, 741 - const ATTR_RECORD *attr, runlist_element *old_rl) 724 + struct runlist_element *ntfs_mapping_pairs_decompress(const struct ntfs_volume *vol, 725 + const struct attr_record *attr, struct runlist *old_runlist, 726 + size_t *new_rl_count) 742 727 { 743 - VCN vcn; /* Current vcn. */ 744 - LCN lcn; /* Current lcn. */ 728 + s64 vcn; /* Current vcn. */ 729 + s64 lcn; /* Current lcn. */ 745 730 s64 deltaxcn; /* Change in [vl]cn. */ 746 - runlist_element *rl; /* The output runlist. */ 731 + struct runlist_element *rl, *new_rl; /* The output runlist. */ 747 732 u8 *buf; /* Current position in mapping pairs array. */ 748 733 u8 *attr_end; /* End of attribute. */ 749 734 int rlsize; /* Size of runlist buffer. */ 750 - u16 rlpos; /* Current runlist position in units of 751 - runlist_elements. */ 735 + u16 rlpos; /* Current runlist position in units of struct runlist_elements. */ 752 736 u8 b; /* Current byte offset in buf. */ 753 737 754 738 #ifdef DEBUG 755 739 /* Make sure attr exists and is non-resident. */ 756 - if (!attr || !attr->non_resident || sle64_to_cpu( 757 - attr->data.non_resident.lowest_vcn) < (VCN)0) { 740 + if (!attr || !attr->non_resident) { 758 741 ntfs_error(vol->sb, "Invalid arguments."); 759 742 return ERR_PTR(-EINVAL); 760 743 } 761 744 #endif 762 745 /* Start at vcn = lowest_vcn and lcn 0. */ 763 - vcn = sle64_to_cpu(attr->data.non_resident.lowest_vcn); 746 + vcn = le64_to_cpu(attr->data.non_resident.lowest_vcn); 764 747 lcn = 0; 765 748 /* Get start of the mapping pairs array. */ 766 - buf = (u8*)attr + le16_to_cpu( 767 - attr->data.non_resident.mapping_pairs_offset); 768 - attr_end = (u8*)attr + le32_to_cpu(attr->length); 769 - if (unlikely(buf < (u8*)attr || buf > attr_end)) { 749 + buf = (u8 *)attr + 750 + le16_to_cpu(attr->data.non_resident.mapping_pairs_offset); 751 + attr_end = (u8 *)attr + le32_to_cpu(attr->length); 752 + if (unlikely(buf < (u8 *)attr || buf > attr_end)) { 770 753 ntfs_error(vol->sb, "Corrupt attribute."); 771 754 return ERR_PTR(-EIO); 772 755 } 773 - /* If the mapping pairs array is valid but empty, nothing to do. */ 774 - if (!vcn && !*buf) 775 - return old_rl; 756 + 776 757 /* Current position in runlist array. */ 777 758 rlpos = 0; 778 759 /* Allocate first page and set current runlist size to one page. */ 779 - rl = ntfs_malloc_nofs(rlsize = PAGE_SIZE); 760 + rl = kvzalloc(rlsize = PAGE_SIZE, GFP_NOFS); 780 761 if (unlikely(!rl)) 781 762 return ERR_PTR(-ENOMEM); 782 763 /* Insert unmapped starting element if necessary. */ ··· 775 784 while (buf < attr_end && *buf) { 776 785 /* 777 786 * Allocate more memory if needed, including space for the 778 - * not-mapped and terminator elements. ntfs_malloc_nofs() 787 + * not-mapped and terminator elements. kvzalloc() 779 788 * operates on whole pages only. 780 789 */ 781 - if (((rlpos + 3) * sizeof(*old_rl)) > rlsize) { 782 - runlist_element *rl2; 790 + if (((rlpos + 3) * sizeof(*rl)) > rlsize) { 791 + struct runlist_element *rl2; 783 792 784 - rl2 = ntfs_malloc_nofs(rlsize + (int)PAGE_SIZE); 793 + rl2 = kvzalloc(rlsize + PAGE_SIZE, GFP_NOFS); 785 794 if (unlikely(!rl2)) { 786 - ntfs_free(rl); 795 + kvfree(rl); 787 796 return ERR_PTR(-ENOMEM); 788 797 } 789 798 memcpy(rl2, rl, rlsize); 790 - ntfs_free(rl); 799 + kvfree(rl); 791 800 rl = rl2; 792 801 rlsize += PAGE_SIZE; 793 802 } ··· 807 816 for (deltaxcn = (s8)buf[b--]; b; b--) 808 817 deltaxcn = (deltaxcn << 8) + buf[b]; 809 818 } else { /* The length entry is compulsory. */ 810 - ntfs_error(vol->sb, "Missing length entry in mapping " 811 - "pairs array."); 819 + ntfs_error(vol->sb, "Missing length entry in mapping pairs array."); 812 820 deltaxcn = (s64)-1; 813 821 } 814 822 /* ··· 815 825 * hence clean-up and return NULL. 816 826 */ 817 827 if (unlikely(deltaxcn < 0)) { 818 - ntfs_error(vol->sb, "Invalid length in mapping pairs " 819 - "array."); 828 + ntfs_error(vol->sb, "Invalid length in mapping pairs array."); 820 829 goto err_out; 821 830 } 822 831 /* ··· 835 846 else { 836 847 /* Get the lcn change which really can be negative. */ 837 848 u8 b2 = *buf & 0xf; 849 + 838 850 b = b2 + ((*buf >> 4) & 0xf); 839 851 if (buf + b > attr_end) 840 852 goto io_error; ··· 852 862 * can investigate it further! 853 863 */ 854 864 if (vol->major_ver < 3) { 855 - if (unlikely(deltaxcn == (LCN)-1)) 865 + if (unlikely(deltaxcn == -1)) 856 866 ntfs_error(vol->sb, "lcn delta == -1"); 857 - if (unlikely(lcn == (LCN)-1)) 867 + if (unlikely(lcn == -1)) 858 868 ntfs_error(vol->sb, "lcn == -1"); 859 869 } 860 870 #endif 861 871 /* Check lcn is not below -1. */ 862 - if (unlikely(lcn < (LCN)-1)) { 863 - ntfs_error(vol->sb, "Invalid LCN < -1 in " 864 - "mapping pairs array."); 872 + if (unlikely(lcn < -1)) { 873 + ntfs_error(vol->sb, "Invalid s64 < -1 in mapping pairs array."); 865 874 goto err_out; 866 875 } 876 + 877 + /* chkdsk accepts zero-sized runs only for holes */ 878 + if ((lcn != -1) && !rl[rlpos].length) { 879 + ntfs_error(vol->sb, 880 + "Invalid zero-sized data run(lcn : %lld).\n", 881 + lcn); 882 + goto err_out; 883 + } 884 + 867 885 /* Enter the current lcn into the runlist element. */ 868 886 rl[rlpos].lcn = lcn; 869 887 } 870 - /* Get to the next runlist element. */ 871 - rlpos++; 888 + /* Get to the next runlist element, skipping zero-sized holes */ 889 + if (rl[rlpos].length) 890 + rlpos++; 872 891 /* Increment the buffer position to the next mapping pair. */ 873 892 buf += (*buf & 0xf) + ((*buf >> 4) & 0xf) + 1; 874 893 } ··· 887 888 * If there is a highest_vcn specified, it must be equal to the final 888 889 * vcn in the runlist - 1, or something has gone badly wrong. 889 890 */ 890 - deltaxcn = sle64_to_cpu(attr->data.non_resident.highest_vcn); 891 + deltaxcn = le64_to_cpu(attr->data.non_resident.highest_vcn); 891 892 if (unlikely(deltaxcn && vcn - 1 != deltaxcn)) { 892 893 mpa_err: 893 - ntfs_error(vol->sb, "Corrupt mapping pairs array in " 894 - "non-resident attribute."); 894 + ntfs_error(vol->sb, "Corrupt mapping pairs array in non-resident attribute."); 895 895 goto err_out; 896 896 } 897 897 /* Setup not mapped runlist element if this is the base extent. */ 898 898 if (!attr->data.non_resident.lowest_vcn) { 899 - VCN max_cluster; 899 + s64 max_cluster; 900 900 901 - max_cluster = ((sle64_to_cpu( 902 - attr->data.non_resident.allocated_size) + 901 + max_cluster = ((le64_to_cpu(attr->data.non_resident.allocated_size) + 903 902 vol->cluster_size - 1) >> 904 903 vol->cluster_size_bits) - 1; 905 904 /* ··· 912 915 * this one. 913 916 */ 914 917 if (deltaxcn < max_cluster) { 915 - ntfs_debug("More extents to follow; deltaxcn " 916 - "= 0x%llx, max_cluster = " 917 - "0x%llx", 918 - (unsigned long long)deltaxcn, 919 - (unsigned long long) 920 - max_cluster); 918 + ntfs_debug("More extents to follow; deltaxcn = 0x%llx, max_cluster = 0x%llx", 919 + deltaxcn, max_cluster); 921 920 rl[rlpos].vcn = vcn; 922 921 vcn += rl[rlpos].length = max_cluster - 923 922 deltaxcn; 924 923 rl[rlpos].lcn = LCN_RL_NOT_MAPPED; 925 924 rlpos++; 926 925 } else if (unlikely(deltaxcn > max_cluster)) { 927 - ntfs_error(vol->sb, "Corrupt attribute. " 928 - "deltaxcn = 0x%llx, " 929 - "max_cluster = 0x%llx", 930 - (unsigned long long)deltaxcn, 931 - (unsigned long long) 932 - max_cluster); 926 + ntfs_error(vol->sb, 927 + "Corrupt attribute. deltaxcn = 0x%llx, max_cluster = 0x%llx", 928 + deltaxcn, max_cluster); 933 929 goto mpa_err; 934 930 } 935 931 } ··· 934 944 rl[rlpos].vcn = vcn; 935 945 rl[rlpos].length = (s64)0; 936 946 /* If no existing runlist was specified, we are done. */ 937 - if (!old_rl) { 947 + if (!old_runlist || !old_runlist->rl) { 948 + *new_rl_count = rlpos + 1; 938 949 ntfs_debug("Mapping pairs array successfully decompressed:"); 939 950 ntfs_debug_dump_runlist(rl); 940 951 return rl; 941 952 } 942 953 /* Now combine the new and old runlists checking for overlaps. */ 943 - old_rl = ntfs_runlists_merge(old_rl, rl); 944 - if (!IS_ERR(old_rl)) 945 - return old_rl; 946 - ntfs_free(rl); 954 + new_rl = ntfs_runlists_merge(old_runlist, rl, rlpos + 1, new_rl_count); 955 + if (!IS_ERR(new_rl)) 956 + return new_rl; 957 + kvfree(rl); 947 958 ntfs_error(vol->sb, "Failed to merge runlists."); 948 - return old_rl; 959 + return new_rl; 949 960 io_error: 950 961 ntfs_error(vol->sb, "Corrupt attribute."); 951 962 err_out: 952 - ntfs_free(rl); 963 + kvfree(rl); 953 964 return ERR_PTR(-EIO); 954 965 } 955 966 956 - /** 967 + /* 957 968 * ntfs_rl_vcn_to_lcn - convert a vcn into a lcn given a runlist 958 969 * @rl: runlist to use for conversion 959 970 * @vcn: vcn to convert ··· 978 987 * - This function does not touch the lock, nor does it modify the 979 988 * runlist. 980 989 */ 981 - LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn) 990 + s64 ntfs_rl_vcn_to_lcn(const struct runlist_element *rl, const s64 vcn) 982 991 { 983 992 int i; 984 993 985 - BUG_ON(vcn < 0); 986 994 /* 987 995 * If rl is NULL, assume that we have found an unmapped runlist. The 988 996 * caller can then attempt to map it and fail appropriately if ··· 995 1005 return LCN_ENOENT; 996 1006 997 1007 for (i = 0; likely(rl[i].length); i++) { 998 - if (unlikely(vcn < rl[i+1].vcn)) { 999 - if (likely(rl[i].lcn >= (LCN)0)) 1008 + if (vcn < rl[i+1].vcn) { 1009 + if (likely(rl[i].lcn >= 0)) 1000 1010 return rl[i].lcn + (vcn - rl[i].vcn); 1001 1011 return rl[i].lcn; 1002 1012 } ··· 1005 1015 * The terminator element is setup to the correct value, i.e. one of 1006 1016 * LCN_HOLE, LCN_RL_NOT_MAPPED, or LCN_ENOENT. 1007 1017 */ 1008 - if (likely(rl[i].lcn < (LCN)0)) 1018 + if (likely(rl[i].lcn < 0)) 1009 1019 return rl[i].lcn; 1010 1020 /* Just in case... We could replace this with BUG() some day. */ 1011 1021 return LCN_ENOENT; 1012 1022 } 1013 1023 1014 - #ifdef NTFS_RW 1015 - 1016 - /** 1024 + /* 1017 1025 * ntfs_rl_find_vcn_nolock - find a vcn in a runlist 1018 1026 * @rl: runlist to search 1019 1027 * @vcn: vcn to find ··· 1024 1036 * 1025 1037 * Locking: The runlist must be locked on entry. 1026 1038 */ 1027 - runlist_element *ntfs_rl_find_vcn_nolock(runlist_element *rl, const VCN vcn) 1039 + struct runlist_element *ntfs_rl_find_vcn_nolock(struct runlist_element *rl, const s64 vcn) 1028 1040 { 1029 - BUG_ON(vcn < 0); 1030 1041 if (unlikely(!rl || vcn < rl[0].vcn)) 1031 1042 return NULL; 1032 1043 while (likely(rl->length)) { ··· 1041 1054 return NULL; 1042 1055 } 1043 1056 1044 - /** 1057 + /* 1045 1058 * ntfs_get_nr_significant_bytes - get number of bytes needed to store a number 1046 1059 * @n: number for which to get the number of bytes for 1047 1060 * ··· 1072 1085 return i; 1073 1086 } 1074 1087 1075 - /** 1088 + /* 1076 1089 * ntfs_get_size_for_mapping_pairs - get bytes needed for mapping pairs array 1077 - * @vol: ntfs volume (needed for the ntfs version) 1078 - * @rl: locked runlist to determine the size of the mapping pairs of 1079 - * @first_vcn: first vcn which to include in the mapping pairs array 1080 - * @last_vcn: last vcn which to include in the mapping pairs array 1090 + * @vol: ntfs volume 1091 + * @rl: runlist to calculate the mapping pairs array size for 1092 + * @first_vcn: first vcn which to include in the mapping pairs array 1093 + * @last_vcn: last vcn which to include in the mapping pairs array 1094 + * @max_mp_size: maximum size to return (0 or less means unlimited) 1081 1095 * 1082 1096 * Walk the locked runlist @rl and calculate the size in bytes of the mapping 1083 1097 * pairs array corresponding to the runlist @rl, starting at vcn @first_vcn and ··· 1094 1106 * If @rl is NULL, just return 1 (for the single terminator byte). 1095 1107 * 1096 1108 * Return the calculated size in bytes on success. On error, return -errno. 1097 - * The following error codes are defined: 1098 - * -EINVAL - Run list contains unmapped elements. Make sure to only pass 1099 - * fully mapped runlists to this function. 1100 - * -EIO - The runlist is corrupt. 1101 - * 1102 - * Locking: @rl must be locked on entry (either for reading or writing), it 1103 - * remains locked throughout, and is left locked upon return. 1104 1109 */ 1105 - int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol, 1106 - const runlist_element *rl, const VCN first_vcn, 1107 - const VCN last_vcn) 1110 + int ntfs_get_size_for_mapping_pairs(const struct ntfs_volume *vol, 1111 + const struct runlist_element *rl, const s64 first_vcn, 1112 + const s64 last_vcn, int max_mp_size) 1108 1113 { 1109 - LCN prev_lcn; 1114 + s64 prev_lcn; 1110 1115 int rls; 1111 1116 bool the_end = false; 1112 1117 1113 - BUG_ON(first_vcn < 0); 1114 - BUG_ON(last_vcn < -1); 1115 - BUG_ON(last_vcn >= 0 && first_vcn > last_vcn); 1118 + if (first_vcn < 0 || last_vcn < -1) 1119 + return -EINVAL; 1120 + 1121 + if (last_vcn >= 0 && first_vcn > last_vcn) 1122 + return -EINVAL; 1123 + 1116 1124 if (!rl) { 1117 - BUG_ON(first_vcn); 1118 - BUG_ON(last_vcn > 0); 1125 + WARN_ON(first_vcn); 1126 + WARN_ON(last_vcn > 0); 1119 1127 return 1; 1120 1128 } 1129 + if (max_mp_size <= 0) 1130 + max_mp_size = INT_MAX; 1121 1131 /* Skip to runlist element containing @first_vcn. */ 1122 1132 while (rl->length && first_vcn >= rl[1].vcn) 1123 1133 rl++; ··· 1138 1152 */ 1139 1153 if (unlikely(last_vcn >= 0 && rl[1].vcn > last_vcn)) { 1140 1154 s64 s1 = last_vcn + 1; 1155 + 1141 1156 if (unlikely(rl[1].vcn > s1)) 1142 1157 length = s1 - rl->vcn; 1143 1158 the_end = true; ··· 1175 1188 */ 1176 1189 if (unlikely(last_vcn >= 0 && rl[1].vcn > last_vcn)) { 1177 1190 s64 s1 = last_vcn + 1; 1191 + 1178 1192 if (unlikely(rl[1].vcn > s1)) 1179 1193 length = s1 - rl->vcn; 1180 1194 the_end = true; ··· 1195 1207 prev_lcn); 1196 1208 prev_lcn = rl->lcn; 1197 1209 } 1210 + 1211 + if (rls > max_mp_size) 1212 + break; 1198 1213 } 1199 1214 return rls; 1200 1215 err_out: ··· 1208 1217 return rls; 1209 1218 } 1210 1219 1211 - /** 1220 + /* 1212 1221 * ntfs_write_significant_bytes - write the significant bytes of a number 1213 1222 * @dst: destination buffer to write to 1214 1223 * @dst_max: pointer to last byte of destination buffer for bounds checking ··· 1259 1268 return -ENOSPC; 1260 1269 } 1261 1270 1262 - /** 1271 + /* 1263 1272 * ntfs_mapping_pairs_build - build the mapping pairs array from a runlist 1264 - * @vol: ntfs volume (needed for the ntfs version) 1265 - * @dst: destination buffer to which to write the mapping pairs array 1266 - * @dst_len: size of destination buffer @dst in bytes 1267 - * @rl: locked runlist for which to build the mapping pairs array 1268 - * @first_vcn: first vcn which to include in the mapping pairs array 1269 - * @last_vcn: last vcn which to include in the mapping pairs array 1270 - * @stop_vcn: first vcn outside destination buffer on success or -ENOSPC 1273 + * @vol: ntfs volume 1274 + * @dst: destination buffer to build mapping pairs array into 1275 + * @dst_len: size of @dst in bytes 1276 + * @rl: runlist to build the mapping pairs array from 1277 + * @first_vcn: first vcn which to include in the mapping pairs array 1278 + * @last_vcn: last vcn which to include in the mapping pairs array 1279 + * @stop_vcn: on return, set to the first vcn outside the destination buffer 1280 + * @stop_rl: on return, set to the runlist element where encoding stopped 1281 + * @de_cluster_count: on return, set to the number of clusters encoded 1271 1282 * 1272 1283 * Create the mapping pairs array from the locked runlist @rl, starting at vcn 1273 1284 * @first_vcn and finishing with vcn @last_vcn and save the array in @dst. ··· 1299 1306 * Locking: @rl must be locked on entry (either for reading or writing), it 1300 1307 * remains locked throughout, and is left locked upon return. 1301 1308 */ 1302 - int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst, 1303 - const int dst_len, const runlist_element *rl, 1304 - const VCN first_vcn, const VCN last_vcn, VCN *const stop_vcn) 1309 + int ntfs_mapping_pairs_build(const struct ntfs_volume *vol, s8 *dst, 1310 + const int dst_len, const struct runlist_element *rl, 1311 + const s64 first_vcn, const s64 last_vcn, s64 *const stop_vcn, 1312 + struct runlist_element **stop_rl, unsigned int *de_cluster_count) 1305 1313 { 1306 - LCN prev_lcn; 1314 + s64 prev_lcn; 1307 1315 s8 *dst_max, *dst_next; 1308 1316 int err = -ENOSPC; 1309 1317 bool the_end = false; 1310 1318 s8 len_len, lcn_len; 1319 + unsigned int de_cnt = 0; 1311 1320 1312 - BUG_ON(first_vcn < 0); 1313 - BUG_ON(last_vcn < -1); 1314 - BUG_ON(last_vcn >= 0 && first_vcn > last_vcn); 1315 - BUG_ON(dst_len < 1); 1321 + if (first_vcn < 0 || last_vcn < -1 || dst_len < 1) 1322 + return -EINVAL; 1323 + if (last_vcn >= 0 && first_vcn > last_vcn) 1324 + return -EINVAL; 1325 + 1316 1326 if (!rl) { 1317 - BUG_ON(first_vcn); 1318 - BUG_ON(last_vcn > 0); 1327 + WARN_ON(first_vcn || last_vcn > 0); 1319 1328 if (stop_vcn) 1320 1329 *stop_vcn = 0; 1321 1330 /* Terminator byte. */ ··· 1349 1354 */ 1350 1355 if (unlikely(last_vcn >= 0 && rl[1].vcn > last_vcn)) { 1351 1356 s64 s1 = last_vcn + 1; 1357 + 1352 1358 if (unlikely(rl[1].vcn > s1)) 1353 1359 length = s1 - rl->vcn; 1354 1360 the_end = true; ··· 1364 1368 * If the logical cluster number (lcn) denotes a hole and we 1365 1369 * are on NTFS 3.0+, we don't store it at all, i.e. we need 1366 1370 * zero space. On earlier NTFS versions we just write the lcn 1367 - * change. FIXME: Do we need to write the lcn change or just 1368 - * the lcn in that case? Not sure as I have never seen this 1369 - * case on NT4. - We assume that we just need to write the lcn 1370 - * change until someone tells us otherwise... (AIA) 1371 + * change. 1371 1372 */ 1372 1373 if (likely(rl->lcn >= 0 || vol->major_ver < 3)) { 1373 1374 prev_lcn = rl->lcn; ··· 1399 1406 */ 1400 1407 if (unlikely(last_vcn >= 0 && rl[1].vcn > last_vcn)) { 1401 1408 s64 s1 = last_vcn + 1; 1409 + 1402 1410 if (unlikely(rl[1].vcn > s1)) 1403 1411 length = s1 - rl->vcn; 1404 1412 the_end = true; ··· 1413 1419 * If the logical cluster number (lcn) denotes a hole and we 1414 1420 * are on NTFS 3.0+, we don't store it at all, i.e. we need 1415 1421 * zero space. On earlier NTFS versions we just write the lcn 1416 - * change. FIXME: Do we need to write the lcn change or just 1417 - * the lcn in that case? Not sure as I have never seen this 1418 - * case on NT4. - We assume that we just need to write the lcn 1419 - * change until someone tells us otherwise... (AIA) 1422 + * change. 1420 1423 */ 1421 1424 if (likely(rl->lcn >= 0 || vol->major_ver < 3)) { 1422 1425 /* Write change in lcn. */ ··· 1422 1431 if (unlikely(lcn_len < 0)) 1423 1432 goto size_err; 1424 1433 prev_lcn = rl->lcn; 1425 - } else 1434 + } else { 1435 + if (rl->lcn == LCN_DELALLOC) 1436 + de_cnt += rl->length; 1426 1437 lcn_len = 0; 1438 + } 1427 1439 dst_next = dst + len_len + lcn_len + 1; 1428 1440 if (unlikely(dst_next > dst_max)) 1429 1441 goto size_err; ··· 1436 1442 dst = dst_next; 1437 1443 } 1438 1444 /* Success. */ 1445 + if (de_cluster_count) 1446 + *de_cluster_count = de_cnt; 1439 1447 err = 0; 1440 1448 size_err: 1441 1449 /* Set stop vcn. */ 1442 1450 if (stop_vcn) 1443 1451 *stop_vcn = rl->vcn; 1452 + if (stop_rl) 1453 + *stop_rl = (struct runlist_element *)rl; 1444 1454 /* Add terminator byte. */ 1445 1455 *dst = 0; 1446 1456 return err; ··· 1456 1458 return err; 1457 1459 } 1458 1460 1459 - /** 1461 + /* 1460 1462 * ntfs_rl_truncate_nolock - truncate a runlist starting at a specified vcn 1461 1463 * @vol: ntfs volume (needed for error output) 1462 1464 * @runlist: runlist to truncate ··· 1480 1482 * 1481 1483 * Locking: The caller must hold @runlist->lock for writing. 1482 1484 */ 1483 - int ntfs_rl_truncate_nolock(const ntfs_volume *vol, runlist *const runlist, 1485 + int ntfs_rl_truncate_nolock(const struct ntfs_volume *vol, struct runlist *const runlist, 1484 1486 const s64 new_length) 1485 1487 { 1486 - runlist_element *rl; 1488 + struct runlist_element *rl; 1487 1489 int old_size; 1488 1490 1489 1491 ntfs_debug("Entering for new_length 0x%llx.", (long long)new_length); 1490 - BUG_ON(!runlist); 1491 - BUG_ON(new_length < 0); 1492 + 1493 + if (!runlist || new_length < 0) 1494 + return -EINVAL; 1495 + 1492 1496 rl = runlist->rl; 1493 - if (!new_length) { 1494 - ntfs_debug("Freeing runlist."); 1495 - runlist->rl = NULL; 1496 - if (rl) 1497 - ntfs_free(rl); 1498 - return 0; 1499 - } 1500 - if (unlikely(!rl)) { 1501 - /* 1502 - * Create a runlist consisting of a sparse runlist element of 1503 - * length @new_length followed by a terminator runlist element. 1504 - */ 1505 - rl = ntfs_malloc_nofs(PAGE_SIZE); 1506 - if (unlikely(!rl)) { 1507 - ntfs_error(vol->sb, "Not enough memory to allocate " 1508 - "runlist element buffer."); 1509 - return -ENOMEM; 1510 - } 1511 - runlist->rl = rl; 1512 - rl[1].length = rl->vcn = 0; 1513 - rl->lcn = LCN_HOLE; 1514 - rl[1].vcn = rl->length = new_length; 1515 - rl[1].lcn = LCN_ENOENT; 1516 - return 0; 1517 - } 1518 - BUG_ON(new_length < rl->vcn); 1497 + if (new_length < rl->vcn) 1498 + return -EINVAL; 1499 + 1519 1500 /* Find @new_length in the runlist. */ 1520 1501 while (likely(rl->length && new_length >= rl[1].vcn)) 1521 1502 rl++; ··· 1503 1526 * If at the end of the runlist we need to expand it. 1504 1527 */ 1505 1528 if (rl->length) { 1506 - runlist_element *trl; 1529 + struct runlist_element *trl; 1507 1530 bool is_end; 1508 1531 1509 1532 ntfs_debug("Shrinking runlist."); ··· 1527 1550 rl->length = 0; 1528 1551 } 1529 1552 rl->lcn = LCN_ENOENT; 1553 + runlist->count = rl - runlist->rl + 1; 1530 1554 /* Reallocate memory if necessary. */ 1531 1555 if (!is_end) { 1532 1556 int new_size = rl - runlist->rl + 1; 1557 + 1533 1558 rl = ntfs_rl_realloc(runlist->rl, old_size, new_size); 1534 1559 if (IS_ERR(rl)) 1535 - ntfs_warning(vol->sb, "Failed to shrink " 1536 - "runlist buffer. This just " 1537 - "wastes a bit of memory " 1538 - "temporarily so we ignore it " 1539 - "and return success."); 1560 + ntfs_warning(vol->sb, 1561 + "Failed to shrink runlist buffer. This just wastes a bit of memory temporarily so we ignore it and return success."); 1540 1562 else 1541 1563 runlist->rl = rl; 1542 1564 } ··· 1555 1579 rl = ntfs_rl_realloc(runlist->rl, old_size, 1556 1580 old_size + 1); 1557 1581 if (IS_ERR(rl)) { 1558 - ntfs_error(vol->sb, "Failed to expand runlist " 1559 - "buffer, aborting."); 1582 + ntfs_error(vol->sb, "Failed to expand runlist buffer, aborting."); 1560 1583 return PTR_ERR(rl); 1561 1584 } 1562 1585 runlist->rl = rl; ··· 1570 1595 /* Add a new terminator runlist element. */ 1571 1596 rl++; 1572 1597 rl->length = 0; 1598 + runlist->count = old_size + 1; 1573 1599 } 1574 1600 rl->vcn = new_length; 1575 1601 rl->lcn = LCN_ENOENT; ··· 1582 1606 return 0; 1583 1607 } 1584 1608 1585 - /** 1586 - * ntfs_rl_punch_nolock - punch a hole into a runlist 1587 - * @vol: ntfs volume (needed for error output) 1588 - * @runlist: runlist to punch a hole into 1589 - * @start: starting VCN of the hole to be created 1590 - * @length: size of the hole to be created in units of clusters 1609 + /* 1610 + * ntfs_rl_sparse - check whether runlist have sparse regions or not. 1611 + * @rl: runlist to check 1591 1612 * 1592 - * Punch a hole into the runlist @runlist starting at VCN @start and of size 1593 - * @length clusters. 1594 - * 1595 - * Return 0 on success and -errno on error, in which case @runlist has not been 1596 - * modified. 1597 - * 1598 - * If @start and/or @start + @length are outside the runlist return error code 1599 - * -ENOENT. 1600 - * 1601 - * If the runlist contains unmapped or error elements between @start and @start 1602 - * + @length return error code -EINVAL. 1603 - * 1604 - * Locking: The caller must hold @runlist->lock for writing. 1613 + * Return 1 if have, 0 if not, -errno on error. 1605 1614 */ 1606 - int ntfs_rl_punch_nolock(const ntfs_volume *vol, runlist *const runlist, 1607 - const VCN start, const s64 length) 1615 + int ntfs_rl_sparse(struct runlist_element *rl) 1608 1616 { 1609 - const VCN end = start + length; 1610 - s64 delta; 1611 - runlist_element *rl, *rl_end, *rl_real_end, *trl; 1612 - int old_size; 1613 - bool lcn_fixup = false; 1617 + struct runlist_element *rlc; 1614 1618 1615 - ntfs_debug("Entering for start 0x%llx, length 0x%llx.", 1616 - (long long)start, (long long)length); 1617 - BUG_ON(!runlist); 1618 - BUG_ON(start < 0); 1619 - BUG_ON(length < 0); 1620 - BUG_ON(end < 0); 1621 - rl = runlist->rl; 1622 - if (unlikely(!rl)) { 1623 - if (likely(!start && !length)) 1624 - return 0; 1625 - return -ENOENT; 1626 - } 1627 - /* Find @start in the runlist. */ 1628 - while (likely(rl->length && start >= rl[1].vcn)) 1629 - rl++; 1630 - rl_end = rl; 1631 - /* Find @end in the runlist. */ 1632 - while (likely(rl_end->length && end >= rl_end[1].vcn)) { 1633 - /* Verify there are no unmapped or error elements. */ 1634 - if (unlikely(rl_end->lcn < LCN_HOLE)) 1635 - return -EINVAL; 1636 - rl_end++; 1637 - } 1638 - /* Check the last element. */ 1639 - if (unlikely(rl_end->length && rl_end->lcn < LCN_HOLE)) 1619 + if (!rl) 1640 1620 return -EINVAL; 1641 - /* This covers @start being out of bounds, too. */ 1642 - if (!rl_end->length && end > rl_end->vcn) 1643 - return -ENOENT; 1644 - if (!length) 1645 - return 0; 1646 - if (!rl->length) 1647 - return -ENOENT; 1648 - rl_real_end = rl_end; 1649 - /* Determine the runlist size. */ 1650 - while (likely(rl_real_end->length)) 1651 - rl_real_end++; 1652 - old_size = rl_real_end - runlist->rl + 1; 1653 - /* If @start is in a hole simply extend the hole. */ 1654 - if (rl->lcn == LCN_HOLE) { 1655 - /* 1656 - * If both @start and @end are in the same sparse run, we are 1657 - * done. 1658 - */ 1659 - if (end <= rl[1].vcn) { 1660 - ntfs_debug("Done (requested hole is already sparse)."); 1661 - return 0; 1621 + 1622 + for (rlc = rl; rlc->length; rlc++) 1623 + if (rlc->lcn < 0) { 1624 + if (rlc->lcn != LCN_HOLE && rlc->lcn != LCN_DELALLOC) { 1625 + pr_err("%s: bad runlist", __func__); 1626 + return -EINVAL; 1627 + } 1628 + return 1; 1662 1629 } 1663 - extend_hole: 1664 - /* Extend the hole. */ 1665 - rl->length = end - rl->vcn; 1666 - /* If @end is in a hole, merge it with the current one. */ 1667 - if (rl_end->lcn == LCN_HOLE) { 1668 - rl_end++; 1669 - rl->length = rl_end->vcn - rl->vcn; 1670 - } 1671 - /* We have done the hole. Now deal with the remaining tail. */ 1672 - rl++; 1673 - /* Cut out all runlist elements up to @end. */ 1674 - if (rl < rl_end) 1675 - memmove(rl, rl_end, (rl_real_end - rl_end + 1) * 1676 - sizeof(*rl)); 1677 - /* Adjust the beginning of the tail if necessary. */ 1678 - if (end > rl->vcn) { 1679 - delta = end - rl->vcn; 1680 - rl->vcn = end; 1681 - rl->length -= delta; 1682 - /* Only adjust the lcn if it is real. */ 1683 - if (rl->lcn >= 0) 1684 - rl->lcn += delta; 1685 - } 1686 - shrink_allocation: 1687 - /* Reallocate memory if the allocation changed. */ 1688 - if (rl < rl_end) { 1689 - rl = ntfs_rl_realloc(runlist->rl, old_size, 1690 - old_size - (rl_end - rl)); 1691 - if (IS_ERR(rl)) 1692 - ntfs_warning(vol->sb, "Failed to shrink " 1693 - "runlist buffer. This just " 1694 - "wastes a bit of memory " 1695 - "temporarily so we ignore it " 1696 - "and return success."); 1697 - else 1698 - runlist->rl = rl; 1699 - } 1700 - ntfs_debug("Done (extend hole)."); 1701 - return 0; 1702 - } 1703 - /* 1704 - * If @start is at the beginning of a run things are easier as there is 1705 - * no need to split the first run. 1706 - */ 1707 - if (start == rl->vcn) { 1708 - /* 1709 - * @start is at the beginning of a run. 1710 - * 1711 - * If the previous run is sparse, extend its hole. 1712 - * 1713 - * If @end is not in the same run, switch the run to be sparse 1714 - * and extend the newly created hole. 1715 - * 1716 - * Thus both of these cases reduce the problem to the above 1717 - * case of "@start is in a hole". 1718 - */ 1719 - if (rl > runlist->rl && (rl - 1)->lcn == LCN_HOLE) { 1720 - rl--; 1721 - goto extend_hole; 1722 - } 1723 - if (end >= rl[1].vcn) { 1724 - rl->lcn = LCN_HOLE; 1725 - goto extend_hole; 1726 - } 1727 - /* 1728 - * The final case is when @end is in the same run as @start. 1729 - * For this need to split the run into two. One run for the 1730 - * sparse region between the beginning of the old run, i.e. 1731 - * @start, and @end and one for the remaining non-sparse 1732 - * region, i.e. between @end and the end of the old run. 1733 - */ 1734 - trl = ntfs_rl_realloc(runlist->rl, old_size, old_size + 1); 1735 - if (IS_ERR(trl)) 1736 - goto enomem_out; 1737 - old_size++; 1738 - if (runlist->rl != trl) { 1739 - rl = trl + (rl - runlist->rl); 1740 - rl_end = trl + (rl_end - runlist->rl); 1741 - rl_real_end = trl + (rl_real_end - runlist->rl); 1742 - runlist->rl = trl; 1743 - } 1744 - split_end: 1745 - /* Shift all the runs up by one. */ 1746 - memmove(rl + 1, rl, (rl_real_end - rl + 1) * sizeof(*rl)); 1747 - /* Finally, setup the two split runs. */ 1748 - rl->lcn = LCN_HOLE; 1749 - rl->length = length; 1750 - rl++; 1751 - rl->vcn += length; 1752 - /* Only adjust the lcn if it is real. */ 1753 - if (rl->lcn >= 0 || lcn_fixup) 1754 - rl->lcn += length; 1755 - rl->length -= length; 1756 - ntfs_debug("Done (split one)."); 1757 - return 0; 1758 - } 1759 - /* 1760 - * @start is neither in a hole nor at the beginning of a run. 1761 - * 1762 - * If @end is in a hole, things are easier as simply truncating the run 1763 - * @start is in to end at @start - 1, deleting all runs after that up 1764 - * to @end, and finally extending the beginning of the run @end is in 1765 - * to be @start is all that is needed. 1766 - */ 1767 - if (rl_end->lcn == LCN_HOLE) { 1768 - /* Truncate the run containing @start. */ 1769 - rl->length = start - rl->vcn; 1770 - rl++; 1771 - /* Cut out all runlist elements up to @end. */ 1772 - if (rl < rl_end) 1773 - memmove(rl, rl_end, (rl_real_end - rl_end + 1) * 1774 - sizeof(*rl)); 1775 - /* Extend the beginning of the run @end is in to be @start. */ 1776 - rl->vcn = start; 1777 - rl->length = rl[1].vcn - start; 1778 - goto shrink_allocation; 1779 - } 1780 - /* 1781 - * If @end is not in a hole there are still two cases to distinguish. 1782 - * Either @end is or is not in the same run as @start. 1783 - * 1784 - * The second case is easier as it can be reduced to an already solved 1785 - * problem by truncating the run @start is in to end at @start - 1. 1786 - * Then, if @end is in the next run need to split the run into a sparse 1787 - * run followed by a non-sparse run (already covered above) and if @end 1788 - * is not in the next run switching it to be sparse, again reduces the 1789 - * problem to the already covered case of "@start is in a hole". 1790 - */ 1791 - if (end >= rl[1].vcn) { 1792 - /* 1793 - * If @end is not in the next run, reduce the problem to the 1794 - * case of "@start is in a hole". 1795 - */ 1796 - if (rl[1].length && end >= rl[2].vcn) { 1797 - /* Truncate the run containing @start. */ 1798 - rl->length = start - rl->vcn; 1799 - rl++; 1800 - rl->vcn = start; 1801 - rl->lcn = LCN_HOLE; 1802 - goto extend_hole; 1803 - } 1804 - trl = ntfs_rl_realloc(runlist->rl, old_size, old_size + 1); 1805 - if (IS_ERR(trl)) 1806 - goto enomem_out; 1807 - old_size++; 1808 - if (runlist->rl != trl) { 1809 - rl = trl + (rl - runlist->rl); 1810 - rl_end = trl + (rl_end - runlist->rl); 1811 - rl_real_end = trl + (rl_real_end - runlist->rl); 1812 - runlist->rl = trl; 1813 - } 1814 - /* Truncate the run containing @start. */ 1815 - rl->length = start - rl->vcn; 1816 - rl++; 1817 - /* 1818 - * @end is in the next run, reduce the problem to the case 1819 - * where "@start is at the beginning of a run and @end is in 1820 - * the same run as @start". 1821 - */ 1822 - delta = rl->vcn - start; 1823 - rl->vcn = start; 1824 - if (rl->lcn >= 0) { 1825 - rl->lcn -= delta; 1826 - /* Need this in case the lcn just became negative. */ 1827 - lcn_fixup = true; 1828 - } 1829 - rl->length += delta; 1830 - goto split_end; 1831 - } 1832 - /* 1833 - * The first case from above, i.e. @end is in the same run as @start. 1834 - * We need to split the run into three. One run for the non-sparse 1835 - * region between the beginning of the old run and @start, one for the 1836 - * sparse region between @start and @end, and one for the remaining 1837 - * non-sparse region, i.e. between @end and the end of the old run. 1838 - */ 1839 - trl = ntfs_rl_realloc(runlist->rl, old_size, old_size + 2); 1840 - if (IS_ERR(trl)) 1841 - goto enomem_out; 1842 - old_size += 2; 1843 - if (runlist->rl != trl) { 1844 - rl = trl + (rl - runlist->rl); 1845 - rl_end = trl + (rl_end - runlist->rl); 1846 - rl_real_end = trl + (rl_real_end - runlist->rl); 1847 - runlist->rl = trl; 1848 - } 1849 - /* Shift all the runs up by two. */ 1850 - memmove(rl + 2, rl, (rl_real_end - rl + 1) * sizeof(*rl)); 1851 - /* Finally, setup the three split runs. */ 1852 - rl->length = start - rl->vcn; 1853 - rl++; 1854 - rl->vcn = start; 1855 - rl->lcn = LCN_HOLE; 1856 - rl->length = length; 1857 - rl++; 1858 - delta = end - rl->vcn; 1859 - rl->vcn = end; 1860 - rl->lcn += delta; 1861 - rl->length -= delta; 1862 - ntfs_debug("Done (split both)."); 1863 1630 return 0; 1864 - enomem_out: 1865 - ntfs_error(vol->sb, "Not enough memory to extend runlist buffer."); 1866 - return -ENOMEM; 1867 1631 } 1868 1632 1869 - #endif /* NTFS_RW */ 1633 + /* 1634 + * ntfs_rl_get_compressed_size - calculate length of non sparse regions 1635 + * @vol: ntfs volume (need for cluster size) 1636 + * @rl: runlist to calculate for 1637 + * 1638 + * Return compressed size or -errno on error. 1639 + */ 1640 + s64 ntfs_rl_get_compressed_size(struct ntfs_volume *vol, struct runlist_element *rl) 1641 + { 1642 + struct runlist_element *rlc; 1643 + s64 ret = 0; 1644 + 1645 + if (!rl) 1646 + return -EINVAL; 1647 + 1648 + for (rlc = rl; rlc->length; rlc++) { 1649 + if (rlc->lcn < 0) { 1650 + if (rlc->lcn != LCN_HOLE && rlc->lcn != LCN_DELALLOC) { 1651 + ntfs_error(vol->sb, "%s: bad runlist, rlc->lcn : %lld", 1652 + __func__, rlc->lcn); 1653 + return -EINVAL; 1654 + } 1655 + } else 1656 + ret += rlc->length; 1657 + } 1658 + return NTFS_CLU_TO_B(vol, ret); 1659 + } 1660 + 1661 + static inline bool ntfs_rle_lcn_contiguous(struct runlist_element *left_rle, 1662 + struct runlist_element *right_rle) 1663 + { 1664 + if (left_rle->lcn > LCN_HOLE && 1665 + left_rle->lcn + left_rle->length == right_rle->lcn) 1666 + return true; 1667 + else if (left_rle->lcn == LCN_HOLE && right_rle->lcn == LCN_HOLE) 1668 + return true; 1669 + else 1670 + return false; 1671 + } 1672 + 1673 + static inline bool ntfs_rle_contain(struct runlist_element *rle, s64 vcn) 1674 + { 1675 + if (rle->length > 0 && 1676 + vcn >= rle->vcn && vcn < rle->vcn + rle->length) 1677 + return true; 1678 + else 1679 + return false; 1680 + } 1681 + 1682 + struct runlist_element *ntfs_rl_insert_range(struct runlist_element *dst_rl, int dst_cnt, 1683 + struct runlist_element *src_rl, int src_cnt, 1684 + size_t *new_rl_cnt) 1685 + { 1686 + struct runlist_element *i_rl, *new_rl, *src_rl_origin = src_rl; 1687 + struct runlist_element dst_rl_split; 1688 + s64 start_vcn = src_rl[0].vcn; 1689 + int new_1st_cnt, new_2nd_cnt, new_3rd_cnt, new_cnt; 1690 + 1691 + if (!dst_rl || !src_rl || !new_rl_cnt) 1692 + return ERR_PTR(-EINVAL); 1693 + if (dst_cnt <= 0 || src_cnt <= 0) 1694 + return ERR_PTR(-EINVAL); 1695 + if (!(dst_rl[dst_cnt - 1].lcn == LCN_ENOENT && 1696 + dst_rl[dst_cnt - 1].length == 0) || 1697 + src_rl[src_cnt - 1].lcn < LCN_HOLE) 1698 + return ERR_PTR(-EINVAL); 1699 + 1700 + start_vcn = src_rl[0].vcn; 1701 + 1702 + i_rl = ntfs_rl_find_vcn_nolock(dst_rl, start_vcn); 1703 + if (!i_rl || 1704 + (i_rl->lcn == LCN_ENOENT && i_rl->vcn != start_vcn) || 1705 + (i_rl->lcn != LCN_ENOENT && !ntfs_rle_contain(i_rl, start_vcn))) 1706 + return ERR_PTR(-EINVAL); 1707 + 1708 + new_1st_cnt = (int)(i_rl - dst_rl); 1709 + if (new_1st_cnt > dst_cnt) 1710 + return ERR_PTR(-EINVAL); 1711 + new_3rd_cnt = dst_cnt - new_1st_cnt; 1712 + if (new_3rd_cnt < 1) 1713 + return ERR_PTR(-EINVAL); 1714 + 1715 + if (i_rl[0].vcn != start_vcn) { 1716 + if (i_rl[0].lcn == LCN_HOLE && src_rl[0].lcn == LCN_HOLE) 1717 + goto merge_src_rle; 1718 + 1719 + /* split @i_rl[0] and create @dst_rl_split */ 1720 + dst_rl_split.vcn = i_rl[0].vcn; 1721 + dst_rl_split.length = start_vcn - i_rl[0].vcn; 1722 + dst_rl_split.lcn = i_rl[0].lcn; 1723 + 1724 + i_rl[0].vcn = start_vcn; 1725 + i_rl[0].length -= dst_rl_split.length; 1726 + i_rl[0].lcn += dst_rl_split.length; 1727 + } else { 1728 + struct runlist_element *dst_rle, *src_rle; 1729 + merge_src_rle: 1730 + 1731 + /* not split @i_rl[0] */ 1732 + dst_rl_split.lcn = LCN_ENOENT; 1733 + 1734 + /* merge @src_rl's first run and @i_rl[0]'s left run if possible */ 1735 + dst_rle = &dst_rl[new_1st_cnt - 1]; 1736 + src_rle = &src_rl[0]; 1737 + if (new_1st_cnt > 0 && ntfs_rle_lcn_contiguous(dst_rle, src_rle)) { 1738 + WARN_ON(dst_rle->vcn + dst_rle->length != src_rle->vcn); 1739 + dst_rle->length += src_rle->length; 1740 + src_rl++; 1741 + src_cnt--; 1742 + } else { 1743 + /* merge @src_rl's last run and @i_rl[0]'s right if possible */ 1744 + dst_rle = &dst_rl[new_1st_cnt]; 1745 + src_rle = &src_rl[src_cnt - 1]; 1746 + 1747 + if (ntfs_rle_lcn_contiguous(dst_rle, src_rle)) { 1748 + dst_rle->length += src_rle->length; 1749 + src_cnt--; 1750 + } 1751 + } 1752 + } 1753 + 1754 + new_2nd_cnt = src_cnt; 1755 + new_cnt = new_1st_cnt + new_2nd_cnt + new_3rd_cnt; 1756 + new_cnt += dst_rl_split.lcn >= LCN_HOLE ? 1 : 0; 1757 + new_rl = kvcalloc(new_cnt, sizeof(*new_rl), GFP_NOFS); 1758 + if (!new_rl) 1759 + return ERR_PTR(-ENOMEM); 1760 + 1761 + /* Copy the @dst_rl's first half to @new_rl */ 1762 + ntfs_rl_mc(new_rl, 0, dst_rl, 0, new_1st_cnt); 1763 + if (dst_rl_split.lcn >= LCN_HOLE) { 1764 + ntfs_rl_mc(new_rl, new_1st_cnt, &dst_rl_split, 0, 1); 1765 + new_1st_cnt++; 1766 + } 1767 + /* Copy the @src_rl to @new_rl */ 1768 + ntfs_rl_mc(new_rl, new_1st_cnt, src_rl, 0, new_2nd_cnt); 1769 + /* Copy the @dst_rl's second half to @new_rl */ 1770 + if (new_3rd_cnt >= 1) { 1771 + struct runlist_element *rl, *rl_3rd; 1772 + int dst_1st_cnt = dst_rl_split.lcn >= LCN_HOLE ? 1773 + new_1st_cnt - 1 : new_1st_cnt; 1774 + 1775 + ntfs_rl_mc(new_rl, new_1st_cnt + new_2nd_cnt, 1776 + dst_rl, dst_1st_cnt, new_3rd_cnt); 1777 + /* Update vcn of the @dst_rl's second half runs to reflect 1778 + * appended @src_rl. 1779 + */ 1780 + if (new_1st_cnt + new_2nd_cnt == 0) { 1781 + rl_3rd = &new_rl[new_1st_cnt + new_2nd_cnt + 1]; 1782 + rl = &new_rl[new_1st_cnt + new_2nd_cnt]; 1783 + } else { 1784 + rl_3rd = &new_rl[new_1st_cnt + new_2nd_cnt]; 1785 + rl = &new_rl[new_1st_cnt + new_2nd_cnt - 1]; 1786 + } 1787 + do { 1788 + rl_3rd->vcn = rl->vcn + rl->length; 1789 + if (rl_3rd->length <= 0) 1790 + break; 1791 + rl = rl_3rd; 1792 + rl_3rd++; 1793 + } while (1); 1794 + } 1795 + *new_rl_cnt = new_1st_cnt + new_2nd_cnt + new_3rd_cnt; 1796 + 1797 + kvfree(dst_rl); 1798 + kvfree(src_rl_origin); 1799 + return new_rl; 1800 + } 1801 + 1802 + struct runlist_element *ntfs_rl_punch_hole(struct runlist_element *dst_rl, int dst_cnt, 1803 + s64 start_vcn, s64 len, 1804 + struct runlist_element **punch_rl, 1805 + size_t *new_rl_cnt) 1806 + { 1807 + struct runlist_element *s_rl, *e_rl, *new_rl, *dst_3rd_rl, hole_rl[1]; 1808 + s64 end_vcn; 1809 + int new_1st_cnt, dst_3rd_cnt, new_cnt, punch_cnt, merge_cnt; 1810 + bool begin_split, end_split, one_split_3; 1811 + 1812 + if (dst_cnt < 2 || 1813 + !(dst_rl[dst_cnt - 1].lcn == LCN_ENOENT && 1814 + dst_rl[dst_cnt - 1].length == 0)) 1815 + return ERR_PTR(-EINVAL); 1816 + 1817 + end_vcn = min(start_vcn + len - 1, 1818 + dst_rl[dst_cnt - 2].vcn + dst_rl[dst_cnt - 2].length - 1); 1819 + 1820 + s_rl = ntfs_rl_find_vcn_nolock(dst_rl, start_vcn); 1821 + if (!s_rl || 1822 + s_rl->lcn <= LCN_ENOENT || 1823 + !ntfs_rle_contain(s_rl, start_vcn)) 1824 + return ERR_PTR(-EINVAL); 1825 + 1826 + begin_split = s_rl->vcn != start_vcn ? true : false; 1827 + 1828 + e_rl = ntfs_rl_find_vcn_nolock(dst_rl, end_vcn); 1829 + if (!e_rl || 1830 + e_rl->lcn <= LCN_ENOENT || 1831 + !ntfs_rle_contain(e_rl, end_vcn)) 1832 + return ERR_PTR(-EINVAL); 1833 + 1834 + end_split = e_rl->vcn + e_rl->length - 1 != end_vcn ? true : false; 1835 + 1836 + /* @s_rl has to be split into left, punched hole, and right */ 1837 + one_split_3 = e_rl == s_rl && begin_split && end_split ? true : false; 1838 + 1839 + punch_cnt = (int)(e_rl - s_rl) + 1; 1840 + 1841 + *punch_rl = kvcalloc(punch_cnt + 1, sizeof(struct runlist_element), 1842 + GFP_NOFS); 1843 + if (!*punch_rl) 1844 + return ERR_PTR(-ENOMEM); 1845 + 1846 + new_cnt = dst_cnt - (int)(e_rl - s_rl + 1) + 3; 1847 + new_rl = kvcalloc(new_cnt, sizeof(struct runlist_element), GFP_NOFS); 1848 + if (!new_rl) { 1849 + kvfree(*punch_rl); 1850 + *punch_rl = NULL; 1851 + return ERR_PTR(-ENOMEM); 1852 + } 1853 + 1854 + new_1st_cnt = (int)(s_rl - dst_rl) + 1; 1855 + ntfs_rl_mc(*punch_rl, 0, dst_rl, new_1st_cnt - 1, punch_cnt); 1856 + 1857 + (*punch_rl)[punch_cnt].lcn = LCN_ENOENT; 1858 + (*punch_rl)[punch_cnt].length = 0; 1859 + 1860 + if (!begin_split) 1861 + new_1st_cnt--; 1862 + dst_3rd_rl = e_rl; 1863 + dst_3rd_cnt = (int)(&dst_rl[dst_cnt - 1] - e_rl) + 1; 1864 + if (!end_split) { 1865 + dst_3rd_rl++; 1866 + dst_3rd_cnt--; 1867 + } 1868 + 1869 + /* Copy the 1st part of @dst_rl into @new_rl */ 1870 + ntfs_rl_mc(new_rl, 0, dst_rl, 0, new_1st_cnt); 1871 + if (begin_split) { 1872 + /* the @e_rl has to be splited and copied into the last of @new_rl 1873 + * and the first of @punch_rl 1874 + */ 1875 + s64 first_cnt = start_vcn - dst_rl[new_1st_cnt - 1].vcn; 1876 + 1877 + if (new_1st_cnt) 1878 + new_rl[new_1st_cnt - 1].length = first_cnt; 1879 + 1880 + (*punch_rl)[0].vcn = start_vcn; 1881 + (*punch_rl)[0].length -= first_cnt; 1882 + if ((*punch_rl)[0].lcn > LCN_HOLE) 1883 + (*punch_rl)[0].lcn += first_cnt; 1884 + } 1885 + 1886 + /* Copy a hole into @new_rl */ 1887 + hole_rl[0].vcn = start_vcn; 1888 + hole_rl[0].length = (s64)len; 1889 + hole_rl[0].lcn = LCN_HOLE; 1890 + ntfs_rl_mc(new_rl, new_1st_cnt, hole_rl, 0, 1); 1891 + 1892 + /* Copy the 3rd part of @dst_rl into @new_rl */ 1893 + ntfs_rl_mc(new_rl, new_1st_cnt + 1, dst_3rd_rl, 0, dst_3rd_cnt); 1894 + if (end_split) { 1895 + /* the @e_rl has to be splited and copied into the first of 1896 + * @new_rl and the last of @punch_rl 1897 + */ 1898 + s64 first_cnt = end_vcn - dst_3rd_rl[0].vcn + 1; 1899 + 1900 + new_rl[new_1st_cnt + 1].vcn = end_vcn + 1; 1901 + new_rl[new_1st_cnt + 1].length -= first_cnt; 1902 + if (new_rl[new_1st_cnt + 1].lcn > LCN_HOLE) 1903 + new_rl[new_1st_cnt + 1].lcn += first_cnt; 1904 + 1905 + if (one_split_3) 1906 + (*punch_rl)[punch_cnt - 1].length -= 1907 + new_rl[new_1st_cnt + 1].length; 1908 + else 1909 + (*punch_rl)[punch_cnt - 1].length = first_cnt; 1910 + } 1911 + 1912 + /* Merge left and hole, or hole and right in @new_rl, if left or right 1913 + * consists of holes. 1914 + */ 1915 + merge_cnt = 0; 1916 + if (new_1st_cnt > 0 && new_rl[new_1st_cnt - 1].lcn == LCN_HOLE) { 1917 + /* Merge right and hole */ 1918 + s_rl = &new_rl[new_1st_cnt - 1]; 1919 + s_rl->length += s_rl[1].length; 1920 + merge_cnt = 1; 1921 + /* Merge left and right */ 1922 + if (new_1st_cnt + 1 < new_cnt && 1923 + new_rl[new_1st_cnt + 1].lcn == LCN_HOLE) { 1924 + s_rl->length += s_rl[2].length; 1925 + merge_cnt++; 1926 + } 1927 + } else if (new_1st_cnt + 1 < new_cnt && 1928 + new_rl[new_1st_cnt + 1].lcn == LCN_HOLE) { 1929 + /* Merge left and hole */ 1930 + s_rl = &new_rl[new_1st_cnt]; 1931 + s_rl->length += s_rl[1].length; 1932 + merge_cnt = 1; 1933 + } 1934 + if (merge_cnt) { 1935 + struct runlist_element *d_rl, *src_rl; 1936 + 1937 + d_rl = s_rl + 1; 1938 + src_rl = s_rl + 1 + merge_cnt; 1939 + ntfs_rl_mm(new_rl, (int)(d_rl - new_rl), (int)(src_rl - new_rl), 1940 + (int)(&new_rl[new_cnt - 1] - src_rl) + 1); 1941 + } 1942 + 1943 + (*punch_rl)[punch_cnt].vcn = (*punch_rl)[punch_cnt - 1].vcn + 1944 + (*punch_rl)[punch_cnt - 1].length; 1945 + 1946 + /* punch_cnt elements of dst are replaced with one hole */ 1947 + *new_rl_cnt = dst_cnt - (punch_cnt - (int)begin_split - (int)end_split) + 1948 + 1 - merge_cnt; 1949 + kvfree(dst_rl); 1950 + return new_rl; 1951 + } 1952 + 1953 + struct runlist_element *ntfs_rl_collapse_range(struct runlist_element *dst_rl, int dst_cnt, 1954 + s64 start_vcn, s64 len, 1955 + struct runlist_element **punch_rl, 1956 + size_t *new_rl_cnt) 1957 + { 1958 + struct runlist_element *s_rl, *e_rl, *new_rl, *dst_3rd_rl; 1959 + s64 end_vcn; 1960 + int new_1st_cnt, dst_3rd_cnt, new_cnt, punch_cnt, merge_cnt, i; 1961 + bool begin_split, end_split, one_split_3; 1962 + 1963 + if (dst_cnt < 2 || 1964 + !(dst_rl[dst_cnt - 1].lcn == LCN_ENOENT && 1965 + dst_rl[dst_cnt - 1].length == 0)) 1966 + return ERR_PTR(-EINVAL); 1967 + 1968 + end_vcn = min(start_vcn + len - 1, 1969 + dst_rl[dst_cnt - 1].vcn - 1); 1970 + 1971 + s_rl = ntfs_rl_find_vcn_nolock(dst_rl, start_vcn); 1972 + if (!s_rl || 1973 + s_rl->lcn <= LCN_ENOENT || 1974 + !ntfs_rle_contain(s_rl, start_vcn)) 1975 + return ERR_PTR(-EINVAL); 1976 + 1977 + begin_split = s_rl->vcn != start_vcn ? true : false; 1978 + 1979 + e_rl = ntfs_rl_find_vcn_nolock(dst_rl, end_vcn); 1980 + if (!e_rl || 1981 + e_rl->lcn <= LCN_ENOENT || 1982 + !ntfs_rle_contain(e_rl, end_vcn)) 1983 + return ERR_PTR(-EINVAL); 1984 + 1985 + end_split = e_rl->vcn + e_rl->length - 1 != end_vcn ? true : false; 1986 + 1987 + /* @s_rl has to be split into left, collapsed, and right */ 1988 + one_split_3 = e_rl == s_rl && begin_split && end_split ? true : false; 1989 + 1990 + punch_cnt = (int)(e_rl - s_rl) + 1; 1991 + *punch_rl = kvcalloc(punch_cnt + 1, sizeof(struct runlist_element), 1992 + GFP_NOFS); 1993 + if (!*punch_rl) 1994 + return ERR_PTR(-ENOMEM); 1995 + 1996 + new_cnt = dst_cnt - (int)(e_rl - s_rl + 1) + 3; 1997 + new_rl = kvcalloc(new_cnt, sizeof(struct runlist_element), GFP_NOFS); 1998 + if (!new_rl) { 1999 + kvfree(*punch_rl); 2000 + *punch_rl = NULL; 2001 + return ERR_PTR(-ENOMEM); 2002 + } 2003 + 2004 + new_1st_cnt = (int)(s_rl - dst_rl) + 1; 2005 + ntfs_rl_mc(*punch_rl, 0, dst_rl, new_1st_cnt - 1, punch_cnt); 2006 + (*punch_rl)[punch_cnt].lcn = LCN_ENOENT; 2007 + (*punch_rl)[punch_cnt].length = 0; 2008 + 2009 + if (!begin_split) 2010 + new_1st_cnt--; 2011 + dst_3rd_rl = e_rl; 2012 + dst_3rd_cnt = (int)(&dst_rl[dst_cnt - 1] - e_rl) + 1; 2013 + if (!end_split) { 2014 + dst_3rd_rl++; 2015 + dst_3rd_cnt--; 2016 + } 2017 + 2018 + /* Copy the 1st part of @dst_rl into @new_rl */ 2019 + ntfs_rl_mc(new_rl, 0, dst_rl, 0, new_1st_cnt); 2020 + if (begin_split) { 2021 + /* the @e_rl has to be splited and copied into the last of @new_rl 2022 + * and the first of @punch_rl 2023 + */ 2024 + s64 first_cnt = start_vcn - dst_rl[new_1st_cnt - 1].vcn; 2025 + 2026 + new_rl[new_1st_cnt - 1].length = first_cnt; 2027 + 2028 + (*punch_rl)[0].vcn = start_vcn; 2029 + (*punch_rl)[0].length -= first_cnt; 2030 + if ((*punch_rl)[0].lcn > LCN_HOLE) 2031 + (*punch_rl)[0].lcn += first_cnt; 2032 + } 2033 + 2034 + /* Copy the 3rd part of @dst_rl into @new_rl */ 2035 + ntfs_rl_mc(new_rl, new_1st_cnt, dst_3rd_rl, 0, dst_3rd_cnt); 2036 + if (end_split) { 2037 + /* the @e_rl has to be splited and copied into the first of 2038 + * @new_rl and the last of @punch_rl 2039 + */ 2040 + s64 first_cnt = end_vcn - dst_3rd_rl[0].vcn + 1; 2041 + 2042 + new_rl[new_1st_cnt].vcn = end_vcn + 1; 2043 + new_rl[new_1st_cnt].length -= first_cnt; 2044 + if (new_rl[new_1st_cnt].lcn > LCN_HOLE) 2045 + new_rl[new_1st_cnt].lcn += first_cnt; 2046 + 2047 + if (one_split_3) 2048 + (*punch_rl)[punch_cnt - 1].length -= 2049 + new_rl[new_1st_cnt].length; 2050 + else 2051 + (*punch_rl)[punch_cnt - 1].length = first_cnt; 2052 + } 2053 + 2054 + /* Adjust vcn */ 2055 + if (new_1st_cnt == 0) 2056 + new_rl[new_1st_cnt].vcn = 0; 2057 + for (i = new_1st_cnt == 0 ? 1 : new_1st_cnt; new_rl[i].length; i++) 2058 + new_rl[i].vcn = new_rl[i - 1].vcn + new_rl[i - 1].length; 2059 + new_rl[i].vcn = new_rl[i - 1].vcn + new_rl[i - 1].length; 2060 + 2061 + /* Merge left and hole, or hole and right in @new_rl, if left or right 2062 + * consists of holes. 2063 + */ 2064 + merge_cnt = 0; 2065 + i = new_1st_cnt == 0 ? 1 : new_1st_cnt; 2066 + if (ntfs_rle_lcn_contiguous(&new_rl[i - 1], &new_rl[i])) { 2067 + /* Merge right and left */ 2068 + s_rl = &new_rl[new_1st_cnt - 1]; 2069 + s_rl->length += s_rl[1].length; 2070 + merge_cnt = 1; 2071 + } 2072 + if (merge_cnt) { 2073 + struct runlist_element *d_rl, *src_rl; 2074 + 2075 + d_rl = s_rl + 1; 2076 + src_rl = s_rl + 1 + merge_cnt; 2077 + ntfs_rl_mm(new_rl, (int)(d_rl - new_rl), (int)(src_rl - new_rl), 2078 + (int)(&new_rl[new_cnt - 1] - src_rl) + 1); 2079 + } 2080 + 2081 + (*punch_rl)[punch_cnt].vcn = (*punch_rl)[punch_cnt - 1].vcn + 2082 + (*punch_rl)[punch_cnt - 1].length; 2083 + 2084 + /* punch_cnt elements of dst are extracted */ 2085 + *new_rl_cnt = dst_cnt - (punch_cnt - (int)begin_split - (int)end_split) - 2086 + merge_cnt; 2087 + 2088 + kvfree(dst_rl); 2089 + return new_rl; 2090 + }