lzo_wrapper.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Squashfs - a compressed read only filesystem for Linux
  4. *
  5. * Copyright (c) 2010 LG Electronics
  6. * Chan Jeong <[email protected]>
  7. *
  8. * lzo_wrapper.c
  9. */
  10. #include <linux/mutex.h>
  11. #include <linux/bio.h>
  12. #include <linux/slab.h>
  13. #include <linux/vmalloc.h>
  14. #include <linux/lzo.h>
  15. #include "squashfs_fs.h"
  16. #include "squashfs_fs_sb.h"
  17. #include "squashfs.h"
  18. #include "decompressor.h"
  19. #include "page_actor.h"
  20. struct squashfs_lzo {
  21. void *input;
  22. void *output;
  23. };
  24. static void *lzo_init(struct squashfs_sb_info *msblk, void *buff)
  25. {
  26. int block_size = max_t(int, msblk->block_size, SQUASHFS_METADATA_SIZE);
  27. struct squashfs_lzo *stream = kzalloc(sizeof(*stream), GFP_KERNEL);
  28. if (stream == NULL)
  29. goto failed;
  30. stream->input = vmalloc(block_size);
  31. if (stream->input == NULL)
  32. goto failed;
  33. stream->output = vmalloc(block_size);
  34. if (stream->output == NULL)
  35. goto failed2;
  36. return stream;
  37. failed2:
  38. vfree(stream->input);
  39. failed:
  40. ERROR("Failed to allocate lzo workspace\n");
  41. kfree(stream);
  42. return ERR_PTR(-ENOMEM);
  43. }
  44. static void lzo_free(void *strm)
  45. {
  46. struct squashfs_lzo *stream = strm;
  47. if (stream) {
  48. vfree(stream->input);
  49. vfree(stream->output);
  50. }
  51. kfree(stream);
  52. }
  53. static int lzo_uncompress(struct squashfs_sb_info *msblk, void *strm,
  54. struct bio *bio, int offset, int length,
  55. struct squashfs_page_actor *output)
  56. {
  57. struct bvec_iter_all iter_all = {};
  58. struct bio_vec *bvec = bvec_init_iter_all(&iter_all);
  59. struct squashfs_lzo *stream = strm;
  60. void *buff = stream->input, *data;
  61. int bytes = length, res;
  62. size_t out_len = output->length;
  63. while (bio_next_segment(bio, &iter_all)) {
  64. int avail = min(bytes, ((int)bvec->bv_len) - offset);
  65. data = bvec_virt(bvec);
  66. memcpy(buff, data + offset, avail);
  67. buff += avail;
  68. bytes -= avail;
  69. offset = 0;
  70. }
  71. res = lzo1x_decompress_safe(stream->input, (size_t)length,
  72. stream->output, &out_len);
  73. if (res != LZO_E_OK)
  74. goto failed;
  75. res = bytes = (int)out_len;
  76. data = squashfs_first_page(output);
  77. buff = stream->output;
  78. while (data) {
  79. if (bytes <= PAGE_SIZE) {
  80. if (!IS_ERR(data))
  81. memcpy(data, buff, bytes);
  82. break;
  83. } else {
  84. if (!IS_ERR(data))
  85. memcpy(data, buff, PAGE_SIZE);
  86. buff += PAGE_SIZE;
  87. bytes -= PAGE_SIZE;
  88. data = squashfs_next_page(output);
  89. }
  90. }
  91. squashfs_finish_page(output);
  92. return res;
  93. failed:
  94. return -EIO;
  95. }
  96. const struct squashfs_decompressor squashfs_lzo_comp_ops = {
  97. .init = lzo_init,
  98. .free = lzo_free,
  99. .decompress = lzo_uncompress,
  100. .id = LZO_COMPRESSION,
  101. .name = "lzo",
  102. .alloc_buffer = 0,
  103. .supported = 1
  104. };