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