lzo.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2008 Oracle. All rights reserved.
  4. */
  5. #include <linux/kernel.h>
  6. #include <linux/slab.h>
  7. #include <linux/mm.h>
  8. #include <linux/init.h>
  9. #include <linux/err.h>
  10. #include <linux/sched.h>
  11. #include <linux/pagemap.h>
  12. #include <linux/bio.h>
  13. #include <linux/lzo.h>
  14. #include <linux/refcount.h>
  15. #include "messages.h"
  16. #include "compression.h"
  17. #include "ctree.h"
  18. #include "super.h"
  19. #include "btrfs_inode.h"
  20. #define LZO_LEN 4
  21. /*
  22. * Btrfs LZO compression format
  23. *
  24. * Regular and inlined LZO compressed data extents consist of:
  25. *
  26. * 1. Header
  27. * Fixed size. LZO_LEN (4) bytes long, LE32.
  28. * Records the total size (including the header) of compressed data.
  29. *
  30. * 2. Segment(s)
  31. * Variable size. Each segment includes one segment header, followed by data
  32. * payload.
  33. * One regular LZO compressed extent can have one or more segments.
  34. * For inlined LZO compressed extent, only one segment is allowed.
  35. * One segment represents at most one sector of uncompressed data.
  36. *
  37. * 2.1 Segment header
  38. * Fixed size. LZO_LEN (4) bytes long, LE32.
  39. * Records the total size of the segment (not including the header).
  40. * Segment header never crosses sector boundary, thus it's possible to
  41. * have at most 3 padding zeros at the end of the sector.
  42. *
  43. * 2.2 Data Payload
  44. * Variable size. Size up limit should be lzo1x_worst_compress(sectorsize)
  45. * which is 4419 for a 4KiB sectorsize.
  46. *
  47. * Example with 4K sectorsize:
  48. * Page 1:
  49. * 0 0x2 0x4 0x6 0x8 0xa 0xc 0xe 0x10
  50. * 0x0000 | Header | SegHdr 01 | Data payload 01 ... |
  51. * ...
  52. * 0x0ff0 | SegHdr N | Data payload N ... |00|
  53. * ^^ padding zeros
  54. * Page 2:
  55. * 0x1000 | SegHdr N+1| Data payload N+1 ... |
  56. */
  57. #define WORKSPACE_BUF_LENGTH (lzo1x_worst_compress(PAGE_SIZE))
  58. #define WORKSPACE_CBUF_LENGTH (lzo1x_worst_compress(PAGE_SIZE))
  59. struct workspace {
  60. void *mem;
  61. void *buf; /* where decompressed data goes */
  62. void *cbuf; /* where compressed data goes */
  63. struct list_head list;
  64. };
  65. static struct workspace_manager wsm;
  66. void lzo_free_workspace(struct list_head *ws)
  67. {
  68. struct workspace *workspace = list_entry(ws, struct workspace, list);
  69. kvfree(workspace->buf);
  70. kvfree(workspace->cbuf);
  71. kvfree(workspace->mem);
  72. kfree(workspace);
  73. }
  74. struct list_head *lzo_alloc_workspace(unsigned int level)
  75. {
  76. struct workspace *workspace;
  77. workspace = kzalloc(sizeof(*workspace), GFP_KERNEL);
  78. if (!workspace)
  79. return ERR_PTR(-ENOMEM);
  80. workspace->mem = kvmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL | __GFP_NOWARN);
  81. workspace->buf = kvmalloc(WORKSPACE_BUF_LENGTH, GFP_KERNEL | __GFP_NOWARN);
  82. workspace->cbuf = kvmalloc(WORKSPACE_CBUF_LENGTH, GFP_KERNEL | __GFP_NOWARN);
  83. if (!workspace->mem || !workspace->buf || !workspace->cbuf)
  84. goto fail;
  85. INIT_LIST_HEAD(&workspace->list);
  86. return &workspace->list;
  87. fail:
  88. lzo_free_workspace(&workspace->list);
  89. return ERR_PTR(-ENOMEM);
  90. }
  91. static inline void write_compress_length(char *buf, size_t len)
  92. {
  93. __le32 dlen;
  94. dlen = cpu_to_le32(len);
  95. memcpy(buf, &dlen, LZO_LEN);
  96. }
  97. static inline size_t read_compress_length(const char *buf)
  98. {
  99. __le32 dlen;
  100. memcpy(&dlen, buf, LZO_LEN);
  101. return le32_to_cpu(dlen);
  102. }
  103. /*
  104. * Will do:
  105. *
  106. * - Write a segment header into the destination
  107. * - Copy the compressed buffer into the destination
  108. * - Make sure we have enough space in the last sector to fit a segment header
  109. * If not, we will pad at most (LZO_LEN (4)) - 1 bytes of zeros.
  110. *
  111. * Will allocate new pages when needed.
  112. */
  113. static int copy_compressed_data_to_page(char *compressed_data,
  114. size_t compressed_size,
  115. struct folio **out_folios,
  116. unsigned long max_nr_folio,
  117. u32 *cur_out,
  118. const u32 sectorsize)
  119. {
  120. u32 sector_bytes_left;
  121. u32 orig_out;
  122. struct folio *cur_folio;
  123. char *kaddr;
  124. if ((*cur_out / PAGE_SIZE) >= max_nr_folio)
  125. return -E2BIG;
  126. /*
  127. * We never allow a segment header crossing sector boundary, previous
  128. * run should ensure we have enough space left inside the sector.
  129. */
  130. ASSERT((*cur_out / sectorsize) == (*cur_out + LZO_LEN - 1) / sectorsize);
  131. cur_folio = out_folios[*cur_out / PAGE_SIZE];
  132. /* Allocate a new page */
  133. if (!cur_folio) {
  134. cur_folio = btrfs_alloc_compr_folio();
  135. if (!cur_folio)
  136. return -ENOMEM;
  137. out_folios[*cur_out / PAGE_SIZE] = cur_folio;
  138. }
  139. kaddr = kmap_local_folio(cur_folio, 0);
  140. write_compress_length(kaddr + offset_in_page(*cur_out),
  141. compressed_size);
  142. *cur_out += LZO_LEN;
  143. orig_out = *cur_out;
  144. /* Copy compressed data */
  145. while (*cur_out - orig_out < compressed_size) {
  146. u32 copy_len = min_t(u32, sectorsize - *cur_out % sectorsize,
  147. orig_out + compressed_size - *cur_out);
  148. kunmap_local(kaddr);
  149. if ((*cur_out / PAGE_SIZE) >= max_nr_folio)
  150. return -E2BIG;
  151. cur_folio = out_folios[*cur_out / PAGE_SIZE];
  152. /* Allocate a new page */
  153. if (!cur_folio) {
  154. cur_folio = btrfs_alloc_compr_folio();
  155. if (!cur_folio)
  156. return -ENOMEM;
  157. out_folios[*cur_out / PAGE_SIZE] = cur_folio;
  158. }
  159. kaddr = kmap_local_folio(cur_folio, 0);
  160. memcpy(kaddr + offset_in_page(*cur_out),
  161. compressed_data + *cur_out - orig_out, copy_len);
  162. *cur_out += copy_len;
  163. }
  164. /*
  165. * Check if we can fit the next segment header into the remaining space
  166. * of the sector.
  167. */
  168. sector_bytes_left = round_up(*cur_out, sectorsize) - *cur_out;
  169. if (sector_bytes_left >= LZO_LEN || sector_bytes_left == 0)
  170. goto out;
  171. /* The remaining size is not enough, pad it with zeros */
  172. memset(kaddr + offset_in_page(*cur_out), 0,
  173. sector_bytes_left);
  174. *cur_out += sector_bytes_left;
  175. out:
  176. kunmap_local(kaddr);
  177. return 0;
  178. }
  179. int lzo_compress_folios(struct list_head *ws, struct address_space *mapping,
  180. u64 start, struct folio **folios, unsigned long *out_folios,
  181. unsigned long *total_in, unsigned long *total_out)
  182. {
  183. struct workspace *workspace = list_entry(ws, struct workspace, list);
  184. const u32 sectorsize = inode_to_fs_info(mapping->host)->sectorsize;
  185. struct folio *folio_in = NULL;
  186. char *sizes_ptr;
  187. const unsigned long max_nr_folio = *out_folios;
  188. int ret = 0;
  189. /* Points to the file offset of input data */
  190. u64 cur_in = start;
  191. /* Points to the current output byte */
  192. u32 cur_out = 0;
  193. u32 len = *total_out;
  194. ASSERT(max_nr_folio > 0);
  195. *out_folios = 0;
  196. *total_out = 0;
  197. *total_in = 0;
  198. /*
  199. * Skip the header for now, we will later come back and write the total
  200. * compressed size
  201. */
  202. cur_out += LZO_LEN;
  203. while (cur_in < start + len) {
  204. char *data_in;
  205. const u32 sectorsize_mask = sectorsize - 1;
  206. u32 sector_off = (cur_in - start) & sectorsize_mask;
  207. u32 in_len;
  208. size_t out_len;
  209. /* Get the input page first */
  210. if (!folio_in) {
  211. ret = btrfs_compress_filemap_get_folio(mapping, cur_in, &folio_in);
  212. if (ret < 0)
  213. goto out;
  214. }
  215. /* Compress at most one sector of data each time */
  216. in_len = min_t(u32, start + len - cur_in, sectorsize - sector_off);
  217. ASSERT(in_len);
  218. data_in = kmap_local_folio(folio_in, 0);
  219. ret = lzo1x_1_compress(data_in +
  220. offset_in_page(cur_in), in_len,
  221. workspace->cbuf, &out_len,
  222. workspace->mem);
  223. kunmap_local(data_in);
  224. if (unlikely(ret < 0)) {
  225. /* lzo1x_1_compress never fails. */
  226. ret = -EIO;
  227. goto out;
  228. }
  229. ret = copy_compressed_data_to_page(workspace->cbuf, out_len,
  230. folios, max_nr_folio,
  231. &cur_out, sectorsize);
  232. if (ret < 0)
  233. goto out;
  234. cur_in += in_len;
  235. /*
  236. * Check if we're making it bigger after two sectors. And if
  237. * it is so, give up.
  238. */
  239. if (cur_in - start > sectorsize * 2 && cur_in - start < cur_out) {
  240. ret = -E2BIG;
  241. goto out;
  242. }
  243. /* Check if we have reached page boundary */
  244. if (PAGE_ALIGNED(cur_in)) {
  245. folio_put(folio_in);
  246. folio_in = NULL;
  247. }
  248. }
  249. /* Store the size of all chunks of compressed data */
  250. sizes_ptr = kmap_local_folio(folios[0], 0);
  251. write_compress_length(sizes_ptr, cur_out);
  252. kunmap_local(sizes_ptr);
  253. ret = 0;
  254. *total_out = cur_out;
  255. *total_in = cur_in - start;
  256. out:
  257. if (folio_in)
  258. folio_put(folio_in);
  259. *out_folios = DIV_ROUND_UP(cur_out, PAGE_SIZE);
  260. return ret;
  261. }
  262. /*
  263. * Copy the compressed segment payload into @dest.
  264. *
  265. * For the payload there will be no padding, just need to do page switching.
  266. */
  267. static void copy_compressed_segment(struct compressed_bio *cb,
  268. char *dest, u32 len, u32 *cur_in)
  269. {
  270. u32 orig_in = *cur_in;
  271. while (*cur_in < orig_in + len) {
  272. struct folio *cur_folio;
  273. u32 copy_len = min_t(u32, PAGE_SIZE - offset_in_page(*cur_in),
  274. orig_in + len - *cur_in);
  275. ASSERT(copy_len);
  276. cur_folio = cb->compressed_folios[*cur_in / PAGE_SIZE];
  277. memcpy_from_folio(dest + *cur_in - orig_in, cur_folio,
  278. offset_in_folio(cur_folio, *cur_in), copy_len);
  279. *cur_in += copy_len;
  280. }
  281. }
  282. int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
  283. {
  284. struct workspace *workspace = list_entry(ws, struct workspace, list);
  285. const struct btrfs_fs_info *fs_info = cb->bbio.inode->root->fs_info;
  286. const u32 sectorsize = fs_info->sectorsize;
  287. char *kaddr;
  288. int ret;
  289. /* Compressed data length, can be unaligned */
  290. u32 len_in;
  291. /* Offset inside the compressed data */
  292. u32 cur_in = 0;
  293. /* Bytes decompressed so far */
  294. u32 cur_out = 0;
  295. kaddr = kmap_local_folio(cb->compressed_folios[0], 0);
  296. len_in = read_compress_length(kaddr);
  297. kunmap_local(kaddr);
  298. cur_in += LZO_LEN;
  299. /*
  300. * LZO header length check
  301. *
  302. * The total length should not exceed the maximum extent length,
  303. * and all sectors should be used.
  304. * If this happens, it means the compressed extent is corrupted.
  305. */
  306. if (unlikely(len_in > min_t(size_t, BTRFS_MAX_COMPRESSED, cb->compressed_len) ||
  307. round_up(len_in, sectorsize) < cb->compressed_len)) {
  308. struct btrfs_inode *inode = cb->bbio.inode;
  309. btrfs_err(fs_info,
  310. "lzo header invalid, root %llu inode %llu offset %llu lzo len %u compressed len %u",
  311. btrfs_root_id(inode->root), btrfs_ino(inode),
  312. cb->start, len_in, cb->compressed_len);
  313. return -EUCLEAN;
  314. }
  315. /* Go through each lzo segment */
  316. while (cur_in < len_in) {
  317. struct folio *cur_folio;
  318. /* Length of the compressed segment */
  319. u32 seg_len;
  320. u32 sector_bytes_left;
  321. size_t out_len = lzo1x_worst_compress(sectorsize);
  322. /*
  323. * We should always have enough space for one segment header
  324. * inside current sector.
  325. */
  326. ASSERT(cur_in / sectorsize ==
  327. (cur_in + LZO_LEN - 1) / sectorsize);
  328. cur_folio = cb->compressed_folios[cur_in / PAGE_SIZE];
  329. ASSERT(cur_folio);
  330. kaddr = kmap_local_folio(cur_folio, 0);
  331. seg_len = read_compress_length(kaddr + offset_in_page(cur_in));
  332. kunmap_local(kaddr);
  333. cur_in += LZO_LEN;
  334. if (unlikely(seg_len > WORKSPACE_CBUF_LENGTH)) {
  335. struct btrfs_inode *inode = cb->bbio.inode;
  336. /*
  337. * seg_len shouldn't be larger than we have allocated
  338. * for workspace->cbuf
  339. */
  340. btrfs_err(fs_info,
  341. "lzo segment too big, root %llu inode %llu offset %llu len %u",
  342. btrfs_root_id(inode->root), btrfs_ino(inode),
  343. cb->start, seg_len);
  344. return -EIO;
  345. }
  346. /* Copy the compressed segment payload into workspace */
  347. copy_compressed_segment(cb, workspace->cbuf, seg_len, &cur_in);
  348. /* Decompress the data */
  349. ret = lzo1x_decompress_safe(workspace->cbuf, seg_len,
  350. workspace->buf, &out_len);
  351. if (unlikely(ret != LZO_E_OK)) {
  352. struct btrfs_inode *inode = cb->bbio.inode;
  353. btrfs_err(fs_info,
  354. "lzo decompression failed, error %d root %llu inode %llu offset %llu",
  355. ret, btrfs_root_id(inode->root), btrfs_ino(inode),
  356. cb->start);
  357. return -EIO;
  358. }
  359. /* Copy the data into inode pages */
  360. ret = btrfs_decompress_buf2page(workspace->buf, out_len, cb, cur_out);
  361. cur_out += out_len;
  362. /* All data read, exit */
  363. if (ret == 0)
  364. return 0;
  365. ret = 0;
  366. /* Check if the sector has enough space for a segment header */
  367. sector_bytes_left = sectorsize - (cur_in % sectorsize);
  368. if (sector_bytes_left >= LZO_LEN)
  369. continue;
  370. /* Skip the padding zeros */
  371. cur_in += sector_bytes_left;
  372. }
  373. return 0;
  374. }
  375. int lzo_decompress(struct list_head *ws, const u8 *data_in,
  376. struct folio *dest_folio, unsigned long dest_pgoff, size_t srclen,
  377. size_t destlen)
  378. {
  379. struct workspace *workspace = list_entry(ws, struct workspace, list);
  380. struct btrfs_fs_info *fs_info = folio_to_fs_info(dest_folio);
  381. const u32 sectorsize = fs_info->sectorsize;
  382. size_t in_len;
  383. size_t out_len;
  384. size_t max_segment_len = WORKSPACE_BUF_LENGTH;
  385. int ret = 0;
  386. if (srclen < LZO_LEN || srclen > max_segment_len + LZO_LEN * 2)
  387. return -EUCLEAN;
  388. in_len = read_compress_length(data_in);
  389. if (in_len != srclen)
  390. return -EUCLEAN;
  391. data_in += LZO_LEN;
  392. in_len = read_compress_length(data_in);
  393. if (in_len != srclen - LZO_LEN * 2) {
  394. ret = -EUCLEAN;
  395. goto out;
  396. }
  397. data_in += LZO_LEN;
  398. out_len = sectorsize;
  399. ret = lzo1x_decompress_safe(data_in, in_len, workspace->buf, &out_len);
  400. if (unlikely(ret != LZO_E_OK)) {
  401. struct btrfs_inode *inode = folio_to_inode(dest_folio);
  402. btrfs_err(fs_info,
  403. "lzo decompression failed, error %d root %llu inode %llu offset %llu",
  404. ret, btrfs_root_id(inode->root), btrfs_ino(inode),
  405. folio_pos(dest_folio));
  406. ret = -EIO;
  407. goto out;
  408. }
  409. ASSERT(out_len <= sectorsize);
  410. memcpy_to_folio(dest_folio, dest_pgoff, workspace->buf, out_len);
  411. /* Early end, considered as an error. */
  412. if (unlikely(out_len < destlen)) {
  413. ret = -EIO;
  414. folio_zero_range(dest_folio, dest_pgoff + out_len, destlen - out_len);
  415. }
  416. out:
  417. return ret;
  418. }
  419. const struct btrfs_compress_op btrfs_lzo_compress = {
  420. .workspace_manager = &wsm,
  421. .max_level = 1,
  422. .default_level = 1,
  423. };