xref: /linux/fs/ntfs/wof.c (revision 3f11c48d4f94bfa58eaff60588f81a5484c34ca3)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Windows System Compression (WOF) decompression glue.
4  *
5  * Copyright (c) 2026 LG Electronics Co., Ltd.
6  */
7 
8 #include <linux/fs.h>
9 #include <linux/blkdev.h>
10 #include <linux/overflow.h>
11 #include <linux/pagemap.h>
12 #include <linux/sched/mm.h>
13 #include <linux/slab.h>
14 #include <linux/unaligned.h>
15 #include <linux/vmalloc.h>
16 
17 #include "ntfs.h"
18 #include "inode.h"
19 #include "debug.h"
20 #include "ntfs_codec.h"
21 #include "attrib.h"
22 
23 static const __le16 WOF_NAME[] = {
24 	cpu_to_le16('W'), cpu_to_le16('o'), cpu_to_le16('f'),
25 	cpu_to_le16('C'), cpu_to_le16('o'), cpu_to_le16('m'),
26 	cpu_to_le16('p'), cpu_to_le16('r'), cpu_to_le16('e'),
27 	cpu_to_le16('s'), cpu_to_le16('s'), cpu_to_le16('e'),
28 	cpu_to_le16('d'), cpu_to_le16('D'), cpu_to_le16('a'),
29 	cpu_to_le16('t'), cpu_to_le16('a'),
30 };
31 
32 #define WOF_NAME_LEN 17
33 
34 #define NTFS_WOF_MAX_COMP_UNIT (1U << 15)
35 #define NTFS_WOF_MAX_PAGES \
36 	DIV_ROUND_UP(NTFS_WOF_MAX_COMP_UNIT + PAGE_SIZE - 1, PAGE_SIZE)
37 
38 struct ntfs_wof_workspace {
39 	struct mutex *lock;
40 	const struct ntfs_codec_ops *codec;
41 	u32 comp_unit;
42 	void *output;
43 	void *scratch;
44 };
45 
46 static DEFINE_MUTEX(ntfs_wof_xpress4k_lock);
47 static DEFINE_MUTEX(ntfs_wof_xpress8k_lock);
48 static DEFINE_MUTEX(ntfs_wof_xpress16k_lock);
49 static DEFINE_MUTEX(ntfs_wof_lzx32k_lock);
50 
51 static struct ntfs_wof_workspace ntfs_wof_xpress4k_workspace = {
52 	.lock = &ntfs_wof_xpress4k_lock,
53 	.codec = &ntfs_xpress4k_codec_ops,
54 	.comp_unit = 1U << 12,
55 };
56 
57 static struct ntfs_wof_workspace ntfs_wof_xpress8k_workspace = {
58 	.lock = &ntfs_wof_xpress8k_lock,
59 	.codec = &ntfs_xpress8k_codec_ops,
60 	.comp_unit = 1U << 13,
61 };
62 
63 static struct ntfs_wof_workspace ntfs_wof_xpress16k_workspace = {
64 	.lock = &ntfs_wof_xpress16k_lock,
65 	.codec = &ntfs_xpress16k_codec_ops,
66 	.comp_unit = 1U << 14,
67 };
68 
69 static struct ntfs_wof_workspace ntfs_wof_lzx32k_workspace = {
70 	.lock = &ntfs_wof_lzx32k_lock,
71 	.codec = &ntfs_lzx32k_codec_ops,
72 	.comp_unit = 1U << 15,
73 };
74 
75 static struct ntfs_wof_workspace *const ntfs_wof_workspaces[] = {
76 	&ntfs_wof_xpress4k_workspace,
77 	&ntfs_wof_xpress8k_workspace,
78 	&ntfs_wof_xpress16k_workspace,
79 	&ntfs_wof_lzx32k_workspace,
80 };
81 
82 static struct ntfs_wof_workspace *ntfs_wof_workspace(u8 block_size_bits)
83 {
84 	switch (block_size_bits) {
85 	case 12:
86 		return &ntfs_wof_xpress4k_workspace;
87 	case 13:
88 		return &ntfs_wof_xpress8k_workspace;
89 	case 14:
90 		return &ntfs_wof_xpress16k_workspace;
91 	case 15:
92 		return &ntfs_wof_lzx32k_workspace;
93 	default:
94 		return NULL;
95 	}
96 }
97 
98 /*
99  * Size of the buffer a chunk is read into.  A chunk is read straight off the
100  * device, so the buffer has to hold @comp_unit bytes plus the leading partial
101  * sector.
102  */
103 static size_t ntfs_wof_input_size(const struct ntfs_wof_workspace *ws)
104 {
105 	return round_up((size_t)ws->comp_unit + 511, 512);
106 }
107 
108 static int ntfs_wof_workspace_prepare(struct ntfs_wof_workspace *ws)
109 {
110 	void *output, *scratch;
111 	size_t scratch_size;
112 
113 	if (ws->output)
114 		return 0;
115 
116 	scratch_size = ws->codec->scratch_size(ws->comp_unit);
117 	if (!scratch_size)
118 		return -EINVAL;
119 
120 	output = kvmalloc(ws->comp_unit, GFP_NOFS);
121 	scratch = kvzalloc(scratch_size, GFP_NOFS);
122 	if (!output || !scratch) {
123 		kvfree(output);
124 		kvfree(scratch);
125 		return -ENOMEM;
126 	}
127 
128 	ws->output = output;
129 	ws->scratch = scratch;
130 	return 0;
131 }
132 
133 void ntfs_wof_free_workspaces(void)
134 {
135 	unsigned int i;
136 
137 	for (i = 0; i < ARRAY_SIZE(ntfs_wof_workspaces); i++) {
138 		struct ntfs_wof_workspace *ws = ntfs_wof_workspaces[i];
139 
140 		mutex_lock(ws->lock);
141 		kvfree(ws->output);
142 		kvfree(ws->scratch);
143 		ws->output = NULL;
144 		ws->scratch = NULL;
145 		mutex_unlock(ws->lock);
146 	}
147 }
148 
149 static int ntfs_bdev_read_from_rl(struct ntfs_volume *vol,
150 				  struct runlist *runlist,
151 				  sector_t start_sector, u64 sector_count,
152 				  void *buf)
153 {
154 	struct runlist_element *rl;
155 	u32 sec_per_clu_bits;
156 	s64 vcn;
157 	u64 sec_off;
158 	size_t buf_off = 0;
159 	unsigned int nofs_flags;
160 	int err;
161 
162 	if (vol->cluster_size_bits < 9)
163 		return -EINVAL;
164 	sec_per_clu_bits = vol->cluster_size_bits - 9;
165 	vcn = start_sector >> sec_per_clu_bits;
166 	sec_off = start_sector & ((1ULL << sec_per_clu_bits) - 1);
167 
168 	nofs_flags = memalloc_nofs_save();
169 	down_read(&runlist->lock);
170 	if (!runlist->rl) {
171 		err = -EINVAL;
172 		goto out_unlock;
173 	}
174 
175 	rl = __ntfs_attr_find_vcn_nolock(runlist, vcn);
176 	if (IS_ERR(rl)) {
177 		err = PTR_ERR(rl);
178 		goto out_unlock;
179 	}
180 
181 	while (sector_count > 0) {
182 		s64 lcn;
183 		s64 rl_end;
184 		u64 byte_off, byte_len, sectors, available;
185 
186 		if (rl->length <= 0 || vcn < rl->vcn) {
187 			err = -EINVAL;
188 			goto out_unlock;
189 		}
190 
191 		lcn = ntfs_rl_vcn_to_lcn(rl, vcn);
192 		if (lcn < 0 && lcn != LCN_HOLE) {
193 			err = -EINVAL;
194 			goto out_unlock;
195 		}
196 
197 		if (check_add_overflow(rl->vcn, rl->length, &rl_end) ||
198 		    rl_end <= vcn ||
199 		    (u64)(rl_end - vcn) > (U64_MAX >> sec_per_clu_bits)) {
200 			err = -EOVERFLOW;
201 			goto out_unlock;
202 		}
203 		available = (u64)(rl_end - vcn) << sec_per_clu_bits;
204 		if (available <= sec_off) {
205 			err = -EINVAL;
206 			goto out_unlock;
207 		}
208 		available -= sec_off;
209 		sectors = min_t(u64, sector_count, available);
210 		if (check_mul_overflow(sectors, (u64)SECTOR_SIZE, &byte_len) ||
211 		    byte_len > SIZE_MAX - buf_off) {
212 			err = -EOVERFLOW;
213 			goto out_unlock;
214 		}
215 
216 		if (lcn == LCN_HOLE) {
217 			memset((u8 *)buf + buf_off, 0, byte_len);
218 		} else {
219 			byte_off = ntfs_cluster_to_bytes(vol, lcn);
220 			if (check_add_overflow(byte_off, sec_off << 9,
221 					       &byte_off) ||
222 			    byte_off > S64_MAX) {
223 				err = -EOVERFLOW;
224 				goto out_unlock;
225 			}
226 			err = ntfs_bdev_read(vol->sb->s_bdev,
227 					     (char *)buf + buf_off,
228 					     (loff_t)byte_off, byte_len);
229 			if (err)
230 				goto out_unlock;
231 		}
232 
233 		buf_off += byte_len;
234 		sector_count -= sectors;
235 		rl++;
236 		vcn = rl->vcn;
237 		sec_off = 0;
238 	}
239 
240 	err = 0;
241 out_unlock:
242 	up_read(&runlist->lock);
243 	memalloc_nofs_restore(nofs_flags);
244 	return err;
245 }
246 
247 static int parse_wof_chunk_table(struct ntfs_inode *base_ni,
248 				 struct ntfs_inode *ni, u64 chunk_idx,
249 				 u64 chunk_count, u32 decomp_size,
250 				 u64 *chunk_offset, u32 *chunk_size,
251 				 void *table_buf, size_t table_buf_size)
252 {
253 	u8 bytes_per_off;
254 	u8 *buf;
255 	u64 off[2];
256 	u64 byte_off, chunk_data_size, table_size;
257 	u32 bytes_to_read;
258 	int ret = 0;
259 
260 	if (i_size_read(VFS_I(base_ni)) < (1ULL << 32))
261 		bytes_per_off = sizeof(__le32);
262 	else
263 		bytes_per_off = sizeof(__le64);
264 
265 	if (!chunk_count || chunk_idx >= chunk_count)
266 		return -EINVAL;
267 
268 	table_size = (chunk_count - 1) * bytes_per_off;
269 	if (ni->data_size < 0 || (u64)ni->data_size < table_size)
270 		return -EINVAL;
271 	chunk_data_size = (u64)ni->data_size - table_size;
272 
273 	if (chunk_count == 1) {
274 		if (chunk_data_size > decomp_size)
275 			return -EINVAL;
276 		*chunk_offset = 0;
277 		*chunk_size = chunk_data_size;
278 		goto out;
279 	}
280 
281 	byte_off = chunk_idx ? (chunk_idx - 1) * bytes_per_off : 0;
282 	bytes_to_read = chunk_idx + 1 == chunk_count ?
283 				bytes_per_off :
284 				(chunk_idx ? 2 : 1) * bytes_per_off;
285 
286 	if (NInoNonResident(ni)) {
287 		sector_t start_sector = byte_off >> 9;
288 		u32 sector_off = byte_off & ((1 << 9) - 1);
289 		u32 sectors = DIV_ROUND_UP(sector_off + bytes_to_read, 512);
290 
291 		if ((size_t)sectors << 9 > table_buf_size)
292 			return -EINVAL;
293 		buf = table_buf;
294 		ret = ntfs_bdev_read_from_rl(ni->vol, &ni->runlist,
295 					     start_sector, sectors, buf);
296 		if (ret)
297 			return -EIO;
298 		buf += sector_off;
299 	} else {
300 		struct ntfs_attr_search_ctx *ctx;
301 		u32 value_length;
302 		u16 value_offset;
303 
304 		if (bytes_to_read > table_buf_size)
305 			return -EINVAL;
306 
307 		mutex_lock(&base_ni->mrec_lock);
308 		ctx = ntfs_attr_get_search_ctx(base_ni, NULL);
309 		if (!ctx) {
310 			ret = -ENOMEM;
311 			goto out_unlock_mrec;
312 		}
313 		ret = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
314 				       CASE_SENSITIVE,
315 				       0, NULL, 0, ctx);
316 		if (ret)
317 			goto out_put_ctx;
318 
319 		value_length =
320 			le32_to_cpu(ctx->attr->data.resident.value_length);
321 		value_offset =
322 			le16_to_cpu(ctx->attr->data.resident.value_offset);
323 		if (byte_off + bytes_to_read > value_length) {
324 			ret = -EINVAL;
325 			goto out_put_ctx;
326 		}
327 		memcpy(table_buf, (u8 *)ctx->attr + value_offset + byte_off,
328 		       bytes_to_read);
329 		buf = table_buf;
330 out_put_ctx:
331 		ntfs_attr_put_search_ctx(ctx);
332 out_unlock_mrec:
333 		mutex_unlock(&base_ni->mrec_lock);
334 		if (ret)
335 			return ret;
336 	}
337 
338 	if (bytes_per_off == sizeof(__le32)) {
339 		off[0] = chunk_idx ? get_unaligned_le32(buf) : 0;
340 		if (chunk_idx + 1 == chunk_count)
341 			off[1] = chunk_data_size;
342 		else if (chunk_idx)
343 			off[1] = get_unaligned_le32(buf + bytes_per_off);
344 		else
345 			off[1] = get_unaligned_le32(buf);
346 	} else {
347 		off[0] = chunk_idx ? get_unaligned_le64(buf) : 0;
348 		if (chunk_idx + 1 == chunk_count)
349 			off[1] = chunk_data_size;
350 		else if (chunk_idx)
351 			off[1] = get_unaligned_le64(buf + bytes_per_off);
352 		else
353 			off[1] = get_unaligned_le64(buf);
354 	}
355 
356 	if (off[1] <= off[0] || off[1] > chunk_data_size ||
357 	    off[1] - off[0] > decomp_size)
358 		return -EINVAL;
359 
360 	*chunk_offset = table_size + off[0];
361 	*chunk_size = off[1] - off[0];
362 out:
363 	if (!*chunk_size)
364 		return -EINVAL;
365 	return 0;
366 }
367 
368 static int ntfs_read_wof_chunk(struct ntfs_volume *vol,
369 			       struct ntfs_inode *wof_ni, u64 chunk_offset,
370 			       u32 chunk_size, void *input, size_t input_size,
371 			       char **chunk_mem)
372 {
373 	struct ntfs_inode *base_ni = wof_ni->ext.base_ntfs_ino;
374 	struct ntfs_attr_search_ctx *ctx;
375 	u32 input_offset = chunk_offset & 511;
376 	u32 input_size_aligned;
377 	u32 value_length;
378 	u16 value_offset;
379 	int err;
380 
381 	input_size_aligned = round_up(chunk_size + input_offset, 512);
382 	if (input_size_aligned > input_size)
383 		return -EINVAL;
384 
385 	if (NInoNonResident(wof_ni)) {
386 		err = ntfs_bdev_read_from_rl(vol, &wof_ni->runlist,
387 					     chunk_offset >> 9,
388 					     input_size_aligned >> 9, input);
389 		if (err)
390 			return err;
391 		*chunk_mem = (u8 *)input + input_offset;
392 		return 0;
393 	}
394 
395 	mutex_lock(&base_ni->mrec_lock);
396 	ctx = ntfs_attr_get_search_ctx(base_ni, NULL);
397 	if (!ctx) {
398 		err = -ENOMEM;
399 		goto out_unlock_mrec;
400 	}
401 
402 	err = ntfs_attr_lookup(wof_ni->type, wof_ni->name, wof_ni->name_len,
403 			       CASE_SENSITIVE,
404 			       0, NULL, 0, ctx);
405 	if (err)
406 		goto out_put_ctx;
407 
408 	value_length = le32_to_cpu(ctx->attr->data.resident.value_length);
409 	value_offset = le16_to_cpu(ctx->attr->data.resident.value_offset);
410 	if (chunk_offset + chunk_size > value_length) {
411 		err = -EINVAL;
412 		goto out_put_ctx;
413 	}
414 	memcpy(input, (u8 *)ctx->attr + value_offset + chunk_offset,
415 	       chunk_size);
416 	*chunk_mem = input;
417 out_put_ctx:
418 	ntfs_attr_put_search_ctx(ctx);
419 out_unlock_mrec:
420 	mutex_unlock(&base_ni->mrec_lock);
421 	return err;
422 }
423 
424 struct ntfs_wof_dest {
425 	struct folio *folios[NTFS_WOF_MAX_PAGES];
426 	struct page *pages[NTFS_WOF_MAX_PAGES];
427 	unsigned int nr_folios;
428 	unsigned int nr_pages;
429 };
430 
431 static void ntfs_wof_release_dest(struct ntfs_wof_dest *dest,
432 				  struct folio *target, bool success)
433 {
434 	unsigned int i;
435 
436 	for (i = 0; i < dest->nr_folios; i++) {
437 		struct folio *folio = dest->folios[i];
438 
439 		if (folio == target)
440 			continue;
441 		if (success) {
442 			flush_dcache_folio(folio);
443 			folio_mark_uptodate(folio);
444 		} else {
445 			folio_clear_uptodate(folio);
446 		}
447 		folio_unlock(folio);
448 		folio_put(folio);
449 	}
450 }
451 
452 static int ntfs_wof_collect_dest(struct address_space *mapping,
453 				 struct folio *target, loff_t chunk_start,
454 				 loff_t chunk_end, struct ntfs_wof_dest *dest)
455 {
456 	pgoff_t index, last, page_index;
457 	unsigned int i;
458 
459 	memset(dest, 0, sizeof(*dest));
460 	index = chunk_start >> PAGE_SHIFT;
461 	last = (chunk_end - 1) >> PAGE_SHIFT;
462 	while (index <= last) {
463 		struct folio *folio;
464 		pgoff_t next;
465 		bool is_target;
466 
467 		if (folio_contains(target, index)) {
468 			folio = target;
469 			is_target = true;
470 		} else {
471 			folio = __filemap_get_folio(
472 				mapping, index,
473 				FGP_LOCK | FGP_CREAT | FGP_NOFS | FGP_NOWAIT,
474 				GFP_NOFS);
475 			if (IS_ERR(folio))
476 				return PTR_ERR(folio);
477 			is_target = false;
478 			if (folio_pos(folio) < chunk_start ||
479 			    folio_next_pos(folio) > chunk_end) {
480 				folio_unlock(folio);
481 				folio_put(folio);
482 				return -EAGAIN;
483 			}
484 		}
485 
486 		if (dest->nr_folios == ARRAY_SIZE(dest->folios)) {
487 			if (!is_target) {
488 				folio_unlock(folio);
489 				folio_put(folio);
490 			}
491 			return -EINVAL;
492 		}
493 		dest->folios[dest->nr_folios++] = folio;
494 		next = folio->index + folio_nr_pages(folio);
495 		if (next <= index)
496 			return -EAGAIN;
497 		index = next;
498 	}
499 
500 	for (page_index = chunk_start >> PAGE_SHIFT; page_index <= last;
501 	     page_index++) {
502 		struct folio *folio = NULL;
503 
504 		for (i = 0; i < dest->nr_folios; i++) {
505 			if (folio_contains(dest->folios[i], page_index)) {
506 				folio = dest->folios[i];
507 				break;
508 			}
509 		}
510 		if (!folio || dest->nr_pages == ARRAY_SIZE(dest->pages))
511 			return -EAGAIN;
512 		dest->pages[dest->nr_pages++] =
513 			folio_page(folio, page_index - folio->index);
514 	}
515 	return 0;
516 }
517 
518 static int ntfs_wof_decode(struct ntfs_wof_workspace *ws, const void *src,
519 			   u32 src_len, void *dst, u32 dst_len)
520 {
521 	if (src_len == dst_len) {
522 		memcpy(dst, src, dst_len);
523 		return 0;
524 	}
525 	return ws->codec->decompress_chunk(ws->scratch, src, src_len, dst,
526 					   dst_len, ws->comp_unit);
527 }
528 
529 static int ntfs_wof_decode_page_direct(struct ntfs_wof_workspace *ws,
530 				       struct folio *target, loff_t chunk_start,
531 				       const void *src, u32 src_len,
532 				       u32 dst_len)
533 {
534 	unsigned int page_offset = offset_in_page(chunk_start);
535 	struct page *page;
536 	pgoff_t page_index;
537 	void *addr;
538 	int err;
539 
540 	page_index = chunk_start >> PAGE_SHIFT;
541 	if (!folio_contains(target, page_index))
542 		return -EAGAIN;
543 
544 	page = folio_page(target, page_index - target->index);
545 	addr = kmap_local_page(page);
546 	err = ntfs_wof_decode(ws, src, src_len, (u8 *)addr + page_offset,
547 			      dst_len);
548 	kunmap_local(addr);
549 	if (err)
550 		return -EINVAL;
551 	return 0;
552 }
553 
554 static int ntfs_wof_decode_folios_direct(struct ntfs_wof_workspace *ws,
555 					 struct address_space *mapping,
556 					 struct folio *target,
557 					 loff_t chunk_start, loff_t chunk_end,
558 					 const void *src, u32 src_len,
559 					 u32 dst_len)
560 {
561 	unsigned int page_offset = offset_in_page(chunk_start);
562 	struct ntfs_wof_dest dest;
563 	void *addr;
564 	unsigned int nofs_flags;
565 	int err;
566 
567 	err = ntfs_wof_collect_dest(mapping, target, chunk_start, chunk_end,
568 				    &dest);
569 	if (err) {
570 		ntfs_wof_release_dest(&dest, target, false);
571 		return -EAGAIN;
572 	}
573 
574 	nofs_flags = memalloc_nofs_save();
575 	addr = vmap(dest.pages, dest.nr_pages, VM_MAP, PAGE_KERNEL);
576 	memalloc_nofs_restore(nofs_flags);
577 	if (!addr) {
578 		ntfs_wof_release_dest(&dest, target, false);
579 		return -EAGAIN;
580 	}
581 
582 	err = ntfs_wof_decode(ws, src, src_len, (u8 *)addr + page_offset,
583 			      dst_len);
584 	vunmap(addr);
585 	if (err) {
586 		ntfs_wof_release_dest(&dest, target, false);
587 		return -EINVAL;
588 	}
589 	ntfs_wof_release_dest(&dest, target, true);
590 	return 0;
591 }
592 
593 static int ntfs_wof_try_direct(struct ntfs_wof_workspace *ws,
594 			       struct address_space *mapping,
595 			       struct folio *target, loff_t chunk_start,
596 			       loff_t chunk_end, const void *src, u32 src_len,
597 			       u32 dst_len)
598 {
599 	unsigned int page_offset = offset_in_page(chunk_start);
600 
601 	if (dst_len <= PAGE_SIZE - page_offset)
602 		return ntfs_wof_decode_page_direct(ws, target, chunk_start, src,
603 						   src_len, dst_len);
604 
605 	return ntfs_wof_decode_folios_direct(ws, mapping, target, chunk_start,
606 					     chunk_end, src, src_len, dst_len);
607 }
608 
609 /*
610  * Decompress one chunk into @folio.  Only this step needs the workspace, so it
611  * is the only step that takes the workspace lock.
612  */
613 static int ntfs_wof_decompress_chunk(struct ntfs_wof_workspace *ws,
614 				     struct ntfs_volume *vol,
615 				     struct address_space *mapping,
616 				     struct folio *folio, loff_t folio_start,
617 				     loff_t folio_end, u64 chunk_file_offset,
618 				     char *chunk_mem, u32 chunk_size,
619 				     u32 decomp_size)
620 {
621 	loff_t chunk_end = chunk_file_offset + decomp_size;
622 	loff_t copy_start, copy_end;
623 	int err;
624 
625 	mutex_lock(ws->lock);
626 	err = ntfs_wof_workspace_prepare(ws);
627 	if (err)
628 		goto out_unlock;
629 
630 	err = ntfs_wof_try_direct(ws, mapping, folio, chunk_file_offset,
631 				  chunk_end, chunk_mem, chunk_size,
632 				  decomp_size);
633 	if (err != -EAGAIN)
634 		goto out_unlock;
635 
636 	err = ntfs_wof_decode(ws, chunk_mem, chunk_size, ws->output,
637 			      decomp_size);
638 	if (err) {
639 		ntfs_error(vol->sb, "Decompression failed: %d", err);
640 		err = -EINVAL;
641 		goto out_unlock;
642 	}
643 
644 	copy_start = max_t(loff_t, folio_start, chunk_file_offset);
645 	copy_end = min_t(loff_t, folio_end, chunk_file_offset + decomp_size);
646 	memcpy_to_folio(folio, copy_start - folio_start,
647 			ws->output + copy_start - chunk_file_offset,
648 			copy_end - copy_start);
649 out_unlock:
650 	mutex_unlock(ws->lock);
651 	return err;
652 }
653 
654 int ntfs_read_wof_compressed_block(struct folio *folio)
655 {
656 	struct address_space *mapping = folio->mapping;
657 	struct ntfs_inode *ni = NTFS_I(mapping->host), *wof_ni;
658 	struct inode *wof_inode;
659 	struct ntfs_volume *vol = ni->vol;
660 	struct ntfs_wof_workspace *ws;
661 	loff_t i_size = i_size_read(VFS_I(ni));
662 	loff_t folio_start = folio_pos(folio);
663 	loff_t folio_end = folio_next_pos(folio);
664 	char *chunk_mem;
665 	void *input;
666 	size_t input_size;
667 	u32 decomp_size;
668 	u64 chunk_count, chunk_idx, last_chunk, chunk_offset;
669 	int err = 0;
670 
671 	ws = ntfs_wof_workspace(ni->itype.compressed.block_size_bits);
672 	if (!ws) {
673 		err = -EOPNOTSUPP;
674 		goto out;
675 	}
676 
677 	if (folio_start >= i_size) {
678 		folio_zero_segment(folio, 0, folio_size(folio));
679 		goto out;
680 	}
681 
682 	wof_inode = ntfs_attr_iget(VFS_I(ni), AT_DATA, (__le16 *)WOF_NAME,
683 				   WOF_NAME_LEN);
684 	if (IS_ERR(wof_inode)) {
685 		err = PTR_ERR(wof_inode);
686 		goto out;
687 	}
688 
689 	wof_ni = NTFS_I(wof_inode);
690 	if (wof_ni->initialized_size != wof_ni->data_size) {
691 		ntfs_error(vol->sb,
692 			   "WOF compressed stream is not fully initialized (init %lld, data %lld).",
693 			   wof_ni->initialized_size, wof_ni->data_size);
694 		err = -EIO;
695 		goto out_iput;
696 	}
697 	if (NInoNonResident(wof_ni) && !NInoFullyMapped(wof_ni)) {
698 		down_write(&wof_ni->runlist.lock);
699 		if (!NInoFullyMapped(wof_ni))
700 			err = ntfs_attr_map_whole_runlist(wof_ni);
701 		up_write(&wof_ni->runlist.lock);
702 		if (err)
703 			goto out_iput;
704 	}
705 
706 	input_size = ntfs_wof_input_size(ws);
707 	input = kvmalloc(input_size, GFP_NOFS);
708 	if (!input) {
709 		err = -ENOMEM;
710 		goto out_iput;
711 	}
712 
713 	chunk_idx = div_u64(folio_start, ws->comp_unit);
714 	last_chunk =
715 		div_u64(min_t(loff_t, folio_end, i_size) - 1, ws->comp_unit);
716 	chunk_count = DIV_ROUND_UP_ULL(i_size, ws->comp_unit);
717 	for (; chunk_idx <= last_chunk; chunk_idx++) {
718 		u32 chunk_size;
719 
720 		decomp_size = chunk_idx + 1 == chunk_count ?
721 				      i_size - chunk_idx * ws->comp_unit :
722 				      ws->comp_unit;
723 		err = parse_wof_chunk_table(ni, wof_ni, chunk_idx, chunk_count,
724 					    decomp_size, &chunk_offset,
725 					    &chunk_size, input, input_size);
726 		if (err)
727 			goto out_free_input;
728 
729 		err = ntfs_read_wof_chunk(vol, wof_ni, chunk_offset, chunk_size,
730 					  input, input_size, &chunk_mem);
731 		if (err)
732 			goto out_free_input;
733 
734 		err = ntfs_wof_decompress_chunk(ws, vol, mapping, folio,
735 						folio_start, folio_end,
736 						chunk_idx * ws->comp_unit,
737 						chunk_mem, chunk_size,
738 						decomp_size);
739 		if (err)
740 			goto out_free_input;
741 	}
742 
743 	if (folio_end > i_size)
744 		folio_zero_segment(folio, i_size - folio_start,
745 				   folio_size(folio));
746 out_free_input:
747 	kvfree(input);
748 out_iput:
749 	iput(wof_inode);
750 out:
751 	if (!err) {
752 		flush_dcache_folio(folio);
753 		folio_mark_uptodate(folio);
754 	} else {
755 		folio_clear_uptodate(folio);
756 	}
757 	folio_unlock(folio);
758 	return err;
759 }
760