xref: /linux/fs/btrfs/lzo.c (revision c92b4d3dd59f9f71ac34b42d4603d2323a499ab0)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2008 Oracle.  All rights reserved.
4  */
5 
6 #include <linux/kernel.h>
7 #include <linux/slab.h>
8 #include <linux/mm.h>
9 #include <linux/init.h>
10 #include <linux/err.h>
11 #include <linux/sched.h>
12 #include <linux/pagemap.h>
13 #include <linux/bio.h>
14 #include <linux/lzo.h>
15 #include <linux/refcount.h>
16 #include "messages.h"
17 #include "compression.h"
18 #include "ctree.h"
19 #include "super.h"
20 #include "btrfs_inode.h"
21 
22 #define LZO_LEN	4
23 
24 /*
25  * Btrfs LZO compression format
26  *
27  * Regular and inlined LZO compressed data extents consist of:
28  *
29  * 1.  Header
30  *     Fixed size. LZO_LEN (4) bytes long, LE32.
31  *     Records the total size (including the header) of compressed data.
32  *
33  * 2.  Segment(s)
34  *     Variable size. Each segment includes one segment header, followed by data
35  *     payload.
36  *     One regular LZO compressed extent can have one or more segments.
37  *     For inlined LZO compressed extent, only one segment is allowed.
38  *     One segment represents at most one sector of uncompressed data.
39  *
40  * 2.1 Segment header
41  *     Fixed size. LZO_LEN (4) bytes long, LE32.
42  *     Records the total size of the segment (not including the header).
43  *     Segment header never crosses sector boundary, thus it's possible to
44  *     have at most 3 padding zeros at the end of the sector.
45  *
46  * 2.2 Data Payload
47  *     Variable size. Size up limit should be lzo1x_worst_compress(sectorsize)
48  *     which is 4419 for a 4KiB sectorsize.
49  *
50  * Example with 4K sectorsize:
51  * Page 1:
52  *          0     0x2   0x4   0x6   0x8   0xa   0xc   0xe     0x10
53  * 0x0000   |  Header   | SegHdr 01 | Data payload 01 ...     |
54  * ...
55  * 0x0ff0   | SegHdr  N | Data payload  N     ...          |00|
56  *                                                          ^^ padding zeros
57  * Page 2:
58  * 0x1000   | SegHdr N+1| Data payload N+1 ...                |
59  */
60 
61 struct workspace {
62 	void *mem;
63 	void *buf;	/* where decompressed data goes */
64 	void *cbuf;	/* where compressed data goes */
65 	struct list_head list;
66 };
67 
workspace_buf_length(const struct btrfs_fs_info * fs_info)68 static u32 workspace_buf_length(const struct btrfs_fs_info *fs_info)
69 {
70 	return lzo1x_worst_compress(fs_info->sectorsize);
71 }
workspace_cbuf_length(const struct btrfs_fs_info * fs_info)72 static u32 workspace_cbuf_length(const struct btrfs_fs_info *fs_info)
73 {
74 	return lzo1x_worst_compress(fs_info->sectorsize);
75 }
76 
lzo_free_workspace(struct list_head * ws)77 void lzo_free_workspace(struct list_head *ws)
78 {
79 	struct workspace *workspace = list_entry(ws, struct workspace, list);
80 
81 	kvfree(workspace->buf);
82 	kvfree(workspace->cbuf);
83 	kvfree(workspace->mem);
84 	kfree(workspace);
85 }
86 
lzo_alloc_workspace(struct btrfs_fs_info * fs_info)87 struct list_head *lzo_alloc_workspace(struct btrfs_fs_info *fs_info)
88 {
89 	struct workspace *workspace;
90 
91 	workspace = kzalloc_obj(*workspace);
92 	if (!workspace)
93 		return ERR_PTR(-ENOMEM);
94 
95 	workspace->mem = kvmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL | __GFP_NOWARN);
96 	workspace->buf = kvmalloc(workspace_buf_length(fs_info), GFP_KERNEL | __GFP_NOWARN);
97 	workspace->cbuf = kvmalloc(workspace_cbuf_length(fs_info), GFP_KERNEL | __GFP_NOWARN);
98 	if (!workspace->mem || !workspace->buf || !workspace->cbuf)
99 		goto fail;
100 
101 	INIT_LIST_HEAD(&workspace->list);
102 
103 	return &workspace->list;
104 fail:
105 	lzo_free_workspace(&workspace->list);
106 	return ERR_PTR(-ENOMEM);
107 }
108 
109 /*
110  * Write data into @out_folio and queue it into @out_bio.
111  *
112  * Return 0 if everything is fine and @total_out will be increased.
113  * Return <0 for error.
114  *
115  * The @out_folio can be NULL after a full folio is queued.
116  * Thus the caller should check and allocate a new folio when needed.
117  */
write_and_queue_folio(struct bio * out_bio,struct folio ** out_folio,u32 * total_out,u32 write_len)118 static int write_and_queue_folio(struct bio *out_bio, struct folio **out_folio,
119 				 u32 *total_out, u32 write_len)
120 {
121 	const u32 fsize = folio_size(*out_folio);
122 	const u32 foffset = offset_in_folio(*out_folio, *total_out);
123 
124 	ASSERT(out_folio && *out_folio);
125 	/* Should not cross folio boundary. */
126 	ASSERT(foffset + write_len <= fsize);
127 
128 	/* We can not use bio_add_folio_nofail() which doesn't do any merge. */
129 	if (!bio_add_folio(out_bio, *out_folio, write_len, foffset)) {
130 		/*
131 		 * We have allocated a bio that havs BTRFS_MAX_COMPRESSED_PAGES
132 		 * vecs, and all ranges inside the same folio should have been
133 		 * merged.  If bio_add_folio() still failed, that means we have
134 		 * reached the bvec limits.
135 		 *
136 		 * This should only happen at the beginning of a folio, and
137 		 * caller is responsible for releasing the folio, since it's
138 		 * not yet queued into the bio.
139 		 */
140 		ASSERT(IS_ALIGNED(*total_out, fsize));
141 		return -E2BIG;
142 	}
143 
144 	*total_out += write_len;
145 	/*
146 	 * The full folio has been filled and queued, reset @out_folio to NULL,
147 	 * so that error handling is fully handled by the bio.
148 	 */
149 	if (IS_ALIGNED(*total_out, fsize))
150 		*out_folio = NULL;
151 	return 0;
152 }
153 
154 /*
155  * Copy compressed data to bio.
156  *
157  * @out_bio:		The bio that will contain all the compressed data.
158  * @compressed_data:	The compressed data of this segment.
159  * @compressed_size:	The size of the compressed data.
160  * @out_folio:		The current output folio, will be updated if a new
161  *			folio is allocated.
162  * @total_out:		The total bytes of current output.
163  * @max_out:		The maximum size of the compressed data.
164  *
165  * Will do:
166  *
167  * - Write a segment header into the destination
168  * - Copy the compressed buffer into the destination
169  * - Make sure we have enough space in the last sector to fit a segment header
170  *   If not, we will pad at most (LZO_LEN (4)) - 1 bytes of zeros.
171  * - If a full folio is filled, it will be queued into @out_bio, and @out_folio
172  *   will be updated.
173  *
174  * Will allocate new pages when needed.
175  */
copy_compressed_data_to_bio(struct btrfs_fs_info * fs_info,struct bio * out_bio,const char * compressed_data,size_t compressed_size,struct folio ** out_folio,u32 * total_out,u32 max_out)176 static int copy_compressed_data_to_bio(struct btrfs_fs_info *fs_info,
177 				       struct bio *out_bio,
178 				       const char *compressed_data,
179 				       size_t compressed_size,
180 				       struct folio **out_folio,
181 				       u32 *total_out, u32 max_out)
182 {
183 	const u32 sectorsize = fs_info->sectorsize;
184 	const u32 sectorsize_bits = fs_info->sectorsize_bits;
185 	const u32 fsize = btrfs_min_folio_size(fs_info);
186 	const u32 old_size = out_bio->bi_iter.bi_size;
187 	u32 copy_start;
188 	u32 sector_bytes_left;
189 	char *kaddr;
190 	int ret;
191 
192 	ASSERT(out_folio);
193 
194 	/* There should be at least a lzo header queued. */
195 	ASSERT(old_size);
196 	ASSERT(old_size == *total_out);
197 
198 	/*
199 	 * We never allow a segment header crossing sector boundary, previous
200 	 * run should ensure we have enough space left inside the sector.
201 	 */
202 	ASSERT((old_size >> sectorsize_bits) == (old_size + LZO_LEN - 1) >> sectorsize_bits);
203 
204 	if (!*out_folio) {
205 		*out_folio = btrfs_alloc_compr_folio(fs_info, GFP_NOFS);
206 		if (!*out_folio)
207 			return -ENOMEM;
208 	}
209 
210 	/* Write the segment header first. */
211 	kaddr = kmap_local_folio(*out_folio, offset_in_folio(*out_folio, *total_out));
212 	put_unaligned_le32(compressed_size, kaddr);
213 	kunmap_local(kaddr);
214 	ret = write_and_queue_folio(out_bio, out_folio, total_out, LZO_LEN);
215 	if (ret < 0)
216 		return ret;
217 
218 	copy_start = *total_out;
219 
220 	/* Copy compressed data. */
221 	while (*total_out - copy_start < compressed_size) {
222 		u32 copy_len = min_t(u32, sectorsize - *total_out % sectorsize,
223 				     copy_start + compressed_size - *total_out);
224 		u32 foffset = *total_out & (fsize - 1);
225 
226 		/* With the range copied, we're larger than the original range. */
227 		if (((*total_out + copy_len) >> sectorsize_bits) >=
228 		    max_out >> sectorsize_bits)
229 			return -E2BIG;
230 
231 		if (!*out_folio) {
232 			*out_folio = btrfs_alloc_compr_folio(fs_info, GFP_NOFS);
233 			if (!*out_folio)
234 				return -ENOMEM;
235 		}
236 
237 		kaddr = kmap_local_folio(*out_folio, foffset);
238 		memcpy(kaddr, compressed_data + *total_out - copy_start, copy_len);
239 		kunmap_local(kaddr);
240 		ret = write_and_queue_folio(out_bio, out_folio, total_out, copy_len);
241 		if (ret < 0)
242 			return ret;
243 	}
244 
245 	/*
246 	 * Check if we can fit the next segment header into the remaining space
247 	 * of the sector.
248 	 */
249 	sector_bytes_left = round_up(*total_out, sectorsize) - *total_out;
250 	if (sector_bytes_left >= LZO_LEN || sector_bytes_left == 0)
251 		return 0;
252 
253 	ASSERT(*out_folio);
254 
255 	/* The remaining size is not enough, pad it with zeros */
256 	folio_zero_range(*out_folio, offset_in_folio(*out_folio, *total_out), sector_bytes_left);
257 	return write_and_queue_folio(out_bio, out_folio, total_out, sector_bytes_left);
258 }
259 
lzo_compress_bio(struct list_head * ws,struct compressed_bio * cb)260 int lzo_compress_bio(struct list_head *ws, struct compressed_bio *cb)
261 {
262 	struct btrfs_inode *inode = cb->bbio.inode;
263 	struct btrfs_fs_info *fs_info = inode->root->fs_info;
264 	struct workspace *workspace = list_entry(ws, struct workspace, list);
265 	struct bio *bio = &cb->bbio.bio;
266 	const u64 start = cb->start;
267 	const u32 len = cb->len;
268 	const u32 sectorsize = fs_info->sectorsize;
269 	const u32 min_folio_size = btrfs_min_folio_size(fs_info);
270 	struct address_space *mapping = inode->vfs_inode.i_mapping;
271 	struct folio *folio_in = NULL;
272 	struct folio *folio_out = NULL;
273 	char *sizes_ptr;
274 	int ret = 0;
275 	/* Points to the file offset of input data. */
276 	u64 cur_in = start;
277 	/* Points to the current output byte. */
278 	u32 total_out = 0;
279 
280 	ASSERT(bio->bi_iter.bi_size == 0);
281 	ASSERT(len);
282 
283 	folio_out = btrfs_alloc_compr_folio(fs_info, GFP_NOFS);
284 	if (!folio_out)
285 		return -ENOMEM;
286 
287 	/* Queue a segment header first. */
288 	ret = write_and_queue_folio(bio, &folio_out, &total_out, LZO_LEN);
289 	/* The first header should not fail. */
290 	ASSERT(ret == 0);
291 
292 	while (cur_in < start + len) {
293 		char *data_in;
294 		const u32 sectorsize_mask = sectorsize - 1;
295 		u32 sector_off = (cur_in - start) & sectorsize_mask;
296 		u32 in_len;
297 		size_t out_len;
298 
299 		/* Get the input page first. */
300 		if (!folio_in) {
301 			ret = btrfs_compress_filemap_get_folio(mapping, cur_in, &folio_in);
302 			if (ret < 0)
303 				goto out;
304 		}
305 
306 		/* Compress at most one sector of data each time. */
307 		in_len = min_t(u32, start + len - cur_in, sectorsize - sector_off);
308 		ASSERT(in_len);
309 		data_in = kmap_local_folio(folio_in, offset_in_folio(folio_in, cur_in));
310 		ret = lzo1x_1_compress(data_in, in_len, workspace->cbuf, &out_len,
311 				       workspace->mem);
312 		kunmap_local(data_in);
313 		if (unlikely(ret < 0)) {
314 			/* lzo1x_1_compress never fails. */
315 			ret = -EIO;
316 			goto out;
317 		}
318 
319 		ret = copy_compressed_data_to_bio(fs_info, bio, workspace->cbuf, out_len,
320 						  &folio_out, &total_out, len);
321 		if (ret < 0)
322 			goto out;
323 
324 		cur_in += in_len;
325 
326 		/*
327 		 * Check if we're making it bigger after two sectors.  And if
328 		 * it is so, give up.
329 		 */
330 		if (cur_in - start > sectorsize * 2 && cur_in - start < total_out) {
331 			ret = -E2BIG;
332 			goto out;
333 		}
334 
335 		/* Check if we have reached input folio boundary. */
336 		if (IS_ALIGNED(cur_in, min_folio_size)) {
337 			folio_put(folio_in);
338 			folio_in = NULL;
339 		}
340 	}
341 	/*
342 	 * The last folio is already queued. Bio is responsible for freeing
343 	 * those folios now.
344 	 */
345 	folio_out = NULL;
346 
347 	/* Store the size of all chunks of compressed data */
348 	sizes_ptr = kmap_local_folio(bio_first_folio_all(bio), 0);
349 	put_unaligned_le32(total_out, sizes_ptr);
350 	kunmap_local(sizes_ptr);
351 out:
352 	/*
353 	 * We can only free the folio that has no part queued into the bio.
354 	 *
355 	 * As any folio that is already queued into bio will be released by
356 	 * the endio function of bio.
357 	 */
358 	if (folio_out && IS_ALIGNED(total_out, min_folio_size)) {
359 		btrfs_free_compr_folio(folio_out);
360 		folio_out = NULL;
361 	}
362 	if (folio_in)
363 		folio_put(folio_in);
364 	return ret;
365 }
366 
get_current_folio(struct compressed_bio * cb,struct folio_iter * fi,u32 * cur_folio_index,u32 cur_in)367 static struct folio *get_current_folio(struct compressed_bio *cb, struct folio_iter *fi,
368 				       u32 *cur_folio_index, u32 cur_in)
369 {
370 	struct btrfs_fs_info *fs_info = cb_to_fs_info(cb);
371 	const u32 min_folio_shift = PAGE_SHIFT + fs_info->block_min_order;
372 
373 	ASSERT(cur_folio_index);
374 
375 	/* Need to switch to the next folio. */
376 	if (cur_in >> min_folio_shift != *cur_folio_index) {
377 		/* We can only do the switch one folio a time. */
378 		ASSERT(cur_in >> min_folio_shift == *cur_folio_index + 1);
379 
380 		bio_next_folio(fi, &cb->bbio.bio);
381 		(*cur_folio_index)++;
382 	}
383 	return fi->folio;
384 }
385 
386 /*
387  * Copy the compressed segment payload into @dest.
388  *
389  * For the payload there will be no padding, just need to do page switching.
390  */
copy_compressed_segment(struct compressed_bio * cb,struct folio_iter * fi,u32 * cur_folio_index,char * dest,u32 len,u32 * cur_in)391 static void copy_compressed_segment(struct compressed_bio *cb,
392 				    struct folio_iter *fi, u32 *cur_folio_index,
393 				    char *dest, u32 len, u32 *cur_in)
394 {
395 	u32 orig_in = *cur_in;
396 
397 	while (*cur_in < orig_in + len) {
398 		struct folio *cur_folio = get_current_folio(cb, fi, cur_folio_index, *cur_in);
399 		u32 copy_len;
400 
401 		ASSERT(cur_folio);
402 		copy_len = min_t(u32, orig_in + len - *cur_in,
403 				 folio_size(cur_folio) - offset_in_folio(cur_folio, *cur_in));
404 		ASSERT(copy_len);
405 
406 		memcpy_from_folio(dest + *cur_in - orig_in, cur_folio,
407 				  offset_in_folio(cur_folio, *cur_in), copy_len);
408 
409 		*cur_in += copy_len;
410 	}
411 }
412 
lzo_decompress_bio(struct list_head * ws,struct compressed_bio * cb)413 int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
414 {
415 	struct workspace *workspace = list_entry(ws, struct workspace, list);
416 	struct btrfs_fs_info *fs_info = cb->bbio.inode->root->fs_info;
417 	const u32 sectorsize = fs_info->sectorsize;
418 	const u32 compressed_len = bio_get_size(&cb->bbio.bio);
419 	struct folio_iter fi;
420 	char *kaddr;
421 	int ret;
422 	/* Compressed data length, can be unaligned */
423 	u32 len_in;
424 	/* Offset inside the compressed data */
425 	u32 cur_in = 0;
426 	/* Bytes decompressed so far */
427 	u32 cur_out = 0;
428 	/* The current folio index number inside the bio. */
429 	u32 cur_folio_index = 0;
430 
431 	bio_first_folio(&fi, &cb->bbio.bio, 0);
432 	/* There must be a compressed folio and matches the sectorsize. */
433 	if (unlikely(!fi.folio))
434 		return -EINVAL;
435 	ASSERT(folio_size(fi.folio) == btrfs_min_folio_size(fs_info));
436 	kaddr = kmap_local_folio(fi.folio, 0);
437 	len_in = get_unaligned_le32(kaddr);
438 	kunmap_local(kaddr);
439 	cur_in += LZO_LEN;
440 
441 	/*
442 	 * LZO header length check
443 	 *
444 	 * The total length should not exceed the maximum extent length,
445 	 * and all sectors should be used.
446 	 * If this happens, it means the compressed extent is corrupted.
447 	 */
448 	if (unlikely(len_in > min_t(size_t, BTRFS_MAX_COMPRESSED, compressed_len) ||
449 		     round_up(len_in, sectorsize) < compressed_len)) {
450 		struct btrfs_inode *inode = cb->bbio.inode;
451 
452 		btrfs_err(fs_info,
453 "lzo header invalid, root %llu inode %llu offset %llu lzo len %u compressed len %u",
454 			  btrfs_root_id(inode->root), btrfs_ino(inode),
455 			  cb->start, len_in, compressed_len);
456 		return -EUCLEAN;
457 	}
458 
459 	/* Go through each lzo segment */
460 	while (cur_in < len_in) {
461 		struct folio *cur_folio;
462 		/* Length of the compressed segment */
463 		u32 seg_len;
464 		u32 sector_bytes_left;
465 		size_t out_len = lzo1x_worst_compress(sectorsize);
466 
467 		/*
468 		 * We should always have enough space for one segment header
469 		 * inside current sector.
470 		 */
471 		ASSERT(cur_in / sectorsize ==
472 		       (cur_in + LZO_LEN - 1) / sectorsize);
473 		cur_folio = get_current_folio(cb, &fi, &cur_folio_index, cur_in);
474 		ASSERT(cur_folio);
475 		kaddr = kmap_local_folio(cur_folio, 0);
476 		seg_len = get_unaligned_le32(kaddr + offset_in_folio(cur_folio, cur_in));
477 		kunmap_local(kaddr);
478 		cur_in += LZO_LEN;
479 
480 		if (unlikely(seg_len > workspace_cbuf_length(fs_info))) {
481 			struct btrfs_inode *inode = cb->bbio.inode;
482 
483 			/*
484 			 * seg_len shouldn't be larger than we have allocated
485 			 * for workspace->cbuf
486 			 */
487 			btrfs_err(fs_info,
488 			"lzo segment too big, root %llu inode %llu offset %llu len %u",
489 				  btrfs_root_id(inode->root), btrfs_ino(inode),
490 				  cb->start, seg_len);
491 			return -EIO;
492 		}
493 
494 		/* Copy the compressed segment payload into workspace */
495 		copy_compressed_segment(cb, &fi, &cur_folio_index, workspace->cbuf,
496 					seg_len, &cur_in);
497 
498 		/* Decompress the data */
499 		ret = lzo1x_decompress_safe(workspace->cbuf, seg_len,
500 					    workspace->buf, &out_len);
501 		if (unlikely(ret != LZO_E_OK)) {
502 			struct btrfs_inode *inode = cb->bbio.inode;
503 
504 			btrfs_err(fs_info,
505 		"lzo decompression failed, error %d root %llu inode %llu offset %llu",
506 				  ret, btrfs_root_id(inode->root), btrfs_ino(inode),
507 				  cb->start);
508 			return -EIO;
509 		}
510 
511 		/* Copy the data into inode pages */
512 		ret = btrfs_decompress_buf2page(workspace->buf, out_len, cb, cur_out);
513 		cur_out += out_len;
514 
515 		/* All data read, exit */
516 		if (ret == 0)
517 			return 0;
518 		ret = 0;
519 
520 		/* Check if the sector has enough space for a segment header */
521 		sector_bytes_left = sectorsize - (cur_in % sectorsize);
522 		if (sector_bytes_left >= LZO_LEN)
523 			continue;
524 
525 		/* Skip the padding zeros */
526 		cur_in += sector_bytes_left;
527 	}
528 
529 	return 0;
530 }
531 
lzo_decompress(struct list_head * ws,const u8 * data_in,struct folio * dest_folio,unsigned long dest_pgoff,size_t srclen,size_t destlen)532 int lzo_decompress(struct list_head *ws, const u8 *data_in,
533 		struct folio *dest_folio, unsigned long dest_pgoff, size_t srclen,
534 		size_t destlen)
535 {
536 	struct workspace *workspace = list_entry(ws, struct workspace, list);
537 	struct btrfs_fs_info *fs_info = folio_to_fs_info(dest_folio);
538 	const u32 sectorsize = fs_info->sectorsize;
539 	size_t in_len;
540 	size_t out_len;
541 	size_t max_segment_len = workspace_buf_length(fs_info);
542 	int ret;
543 
544 	if (unlikely(srclen < LZO_LEN || srclen > max_segment_len + LZO_LEN * 2))
545 		return -EUCLEAN;
546 
547 	in_len = get_unaligned_le32(data_in);
548 	if (unlikely(in_len != srclen))
549 		return -EUCLEAN;
550 	data_in += LZO_LEN;
551 
552 	in_len = get_unaligned_le32(data_in);
553 	if (unlikely(in_len != srclen - LZO_LEN * 2))
554 		return -EUCLEAN;
555 	data_in += LZO_LEN;
556 
557 	out_len = sectorsize;
558 	ret = lzo1x_decompress_safe(data_in, in_len, workspace->buf, &out_len);
559 	if (unlikely(ret != LZO_E_OK)) {
560 		struct btrfs_inode *inode = folio_to_inode(dest_folio);
561 
562 		btrfs_err(fs_info,
563 		"lzo decompression failed, error %d root %llu inode %llu offset %llu",
564 			  ret, btrfs_root_id(inode->root), btrfs_ino(inode),
565 			  folio_pos(dest_folio));
566 		return -EIO;
567 	}
568 
569 	ASSERT(out_len <= sectorsize);
570 	memcpy_to_folio(dest_folio, dest_pgoff, workspace->buf, out_len);
571 	/* Early end, considered as an error. */
572 	if (unlikely(out_len < destlen)) {
573 		folio_zero_range(dest_folio, dest_pgoff + out_len, destlen - out_len);
574 		return -EIO;
575 	}
576 
577 	return 0;
578 }
579 
580 const struct btrfs_compress_levels  btrfs_lzo_compress = {
581 	.max_level		= 1,
582 	.default_level		= 1,
583 };
584