wok rev 23761
Up linux-cloop (4.12)
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Mon May 04 09:05:12 2020 +0000 (2020-05-04) |
parents | d98ac734626d |
children | cea6e929d21e |
files | fusecloop/stuff/fusecloop.u linux-cloop/receipt linux-cloop/stuff/cloop.u linux64-cloop/receipt linux64-cloop/stuff/cloop.u |
line diff
1.1 --- a/fusecloop/stuff/fusecloop.u Mon May 04 07:56:50 2020 +0100 1.2 +++ b/fusecloop/stuff/fusecloop.u Mon May 04 09:05:12 2020 +0000 1.3 @@ -734,7 +734,7 @@ 1.4 + tail.table_size = ntohl(len); 1.5 + pos += len + sizeof(tail); 1.6 + n = pos & 511; 1.7 -+ if (n) write(STDOUT_FILENO, padding, 512 - n); 1.8 ++ // if (n) write(STDOUT_FILENO, padding, 512 - n); 1.9 + write(STDOUT_FILENO, compressed, len); 1.10 + write(STDOUT_FILENO, &tail, sizeof(tail)); 1.11 + exit(sig != 0);
2.1 --- a/linux-cloop/receipt Mon May 04 07:56:50 2020 +0100 2.2 +++ b/linux-cloop/receipt Mon May 04 09:05:12 2020 +0000 2.3 @@ -2,13 +2,15 @@ 2.4 2.5 PACKAGE="linux-cloop" 2.6 SOURCE="cloop" 2.7 -VERSION="2.639-2" 2.8 +_VERSION="2.639-2" 2.9 +#VERSION="$(sed '/+#define CLOOP_VERSION/!d;s|.* "\(.*\)"|\1|' stuff/cloop.u)" 2.10 +VERSION="4.12" 2.11 CATEGORY="base-system" 2.12 MAINTAINER="pascal.bellard@slitaz.org" 2.13 LICENSE="GPL2" 2.14 SHORT_DESC="The read-only compressed loop device kernel module." 2.15 WEB_SITE="http://knoppix.net/wiki/Cloop" 2.16 -TARBALL="${SOURCE}_${VERSION}.tar.gz" 2.17 +TARBALL="${SOURCE}_${_VERSION}.tar.gz" 2.18 WGET_URL="http://debian-knoppix.alioth.debian.org/packages/$SOURCE/$TARBALL" 2.19 2.20 DEPENDS="linux" 2.21 @@ -19,9 +21,7 @@ 2.22 2.23 compile_rules() 2.24 { 2.25 - patch -p0 < $stuff/cloop.u # 3.2.98 2.26 - sed -i -e 's|file->f_path.mnt, file->f_path.dentry|\&file->f_path|' \ 2.27 - -e 's|bvec->|bvec.|g;s|*bvec|bvec|' cloop.c 2.28 + patch -p0 < $stuff/cloop.u 2.29 make KERNEL_DIR="/usr/src/linux" cloop.ko && xz cloop.ko 2.30 } 2.31
3.1 --- a/linux-cloop/stuff/cloop.u Mon May 04 07:56:50 2020 +0100 3.2 +++ b/linux-cloop/stuff/cloop.u Mon May 04 09:05:12 2020 +0000 3.3 @@ -1,80 +1,221 @@ 3.4 --- cloop.h 3.5 +++ cloop.h 3.6 -@@ -20,6 +20,80 @@ 3.7 +@@ -1,15 +1,50 @@ 3.8 ++#define CLOOP_SIGNATURE "#!/bin/sh" /* @ offset 0 */ 3.9 ++#define CLOOP_SIGNATURE_SIZE 9 3.10 ++#define CLOOP_SIGNATURE_OFFSET 0x0 3.11 ++ 3.12 + #ifndef _COMPRESSED_LOOP_H 3.13 + #define _COMPRESSED_LOOP_H 3.14 + 3.15 +-#define CLOOP_HEADROOM 128 3.16 ++/*************************************************************************\ 3.17 ++* Starting with Format V4.0 (cloop version 4.x), cloop can now have two * 3.18 ++* alternative structures: * 3.19 ++* * 3.20 ++* 1. Header first: "robust" format, handles missing blocks well * 3.21 ++* 2. Footer (header last): "streaming" format, easier to create * 3.22 ++* * 3.23 ++* The cloop kernel module autodetects both formats, and can (currently) * 3.24 ++* still handle the V2.0 format as well. * 3.25 ++* * 3.26 ++* 1. Header first: * 3.27 ++* +---------------------------- FIXED SIZE ---------------------------+ * 3.28 ++* |Signature (128 bytes) | * 3.29 ++* |block_size (32bit number, network order) | * 3.30 ++* |num_blocks (32bit number, network order) | * 3.31 ++* +--------------------------- VARIABLE SIZE -------------------------+ * 3.32 ++* |num_blocks * FlagsOffset (upper 4 bits flags, lower 64 bits offset)| * 3.33 ++* |compressed data blocks of variable size ... | * 3.34 ++* +-------------------------------------------------------------------+ * 3.35 ++* * 3.36 ++* 2. Footer (header last): * 3.37 ++* +--------------------------- VARIABLE SIZE -------------------------+ * 3.38 ++* |compressed data blocks of variable size ... | * 3.39 ++* |num_blocks * FlagsOffset (upper 4 bits flags, lower 64 bits offset)| * 3.40 ++* +---------------------------- FIXED SIZE ---------------------------+ * 3.41 ++* |Signature (128 bytes) | * 3.42 ++* |block_size (32bit number, network order) | * 3.43 ++* |num_blocks (32bit number, network order) | * 3.44 ++* +-------------------------------------------------------------------+ * 3.45 ++* * 3.46 ++* Offsets are always relative to beginning of file, in all formats. * 3.47 ++* The block index contains num_blocks+1 offsets, followed (1) or * 3.48 ++* preceded (2) by the compressed blocks. * 3.49 ++\*************************************************************************/ 3.50 + 3.51 +-/* The cloop header usually looks like this: */ 3.52 +-/* #!/bin/sh */ 3.53 +-/* #V2.00 Format */ 3.54 +-/* ...padding up to CLOOP_HEADROOM... */ 3.55 +-/* block_size (32bit number, network order) */ 3.56 +-/* num_blocks (32bit number, network order) */ 3.57 ++#include <linux/types.h> /* u_int32_t */ 3.58 ++ 3.59 ++#define CLOOP_HEADROOM 128 3.60 + 3.61 ++/* Header of fixed length, can be located at beginning or end of file */ 3.62 + struct cloop_head 3.63 + { 3.64 + char preamble[CLOOP_HEADROOM]; 3.65 +@@ -17,9 +52,163 @@ 3.66 + u_int32_t num_blocks; 3.67 + }; 3.68 + 3.69 ++/************************************************************************\ 3.70 ++* CLOOP4 flags for each compressed block * 3.71 ++* Value Meaning * 3.72 ++* 0 GZIP/7ZIP compression (compatible with V2.0 Format) * 3.73 ++* 1 no compression (incompressible data) * 3.74 ++* 2 xz compression (currently best space saver) * 3.75 ++* 3 lz4 compression * 3.76 ++* 4 lzo compression (fastest) * 3.77 ++\************************************************************************/ 3.78 ++ 3.79 ++typedef uint64_t cloop_block_ptr; 3.80 ++ 3.81 ++/* Get value of first 4 bits */ 3.82 ++#define CLOOP_BLOCK_FLAGS(x) ((unsigned int)(((x) & 0xf000000000000000LLU) >> 60)) 3.83 ++/* Get value of last 60 bits */ 3.84 ++#define CLOOP_BLOCK_OFFSET(x) ((x) & 0x0fffffffffffffffLLU) 3.85 ++ 3.86 ++#define CLOOP_COMPRESSOR_ZLIB 0x0 3.87 ++#define CLOOP_COMPRESSOR_NONE 0x1 3.88 ++#define CLOOP_COMPRESSOR_XZ 0x2 3.89 ++#define CLOOP_COMPRESSOR_LZ4 0x3 3.90 ++#define CLOOP_COMPRESSOR_LZO1X 0x4 3.91 ++ 3.92 ++#define CLOOP_COMPRESSOR_VALID(x) ((x) >= CLOOP_COMPRESSOR_ZLIB && (x) <= CLOOP_COMPRESSOR_LZO1X) 3.93 ++ 3.94 ++#define CLOOP_COMPRESSOR_LINK 0xF 3.95 ++ 3.96 ++ 3.97 /* data_index (num_blocks 64bit pointers, network order)... */ 3.98 /* compressed data (gzip block compressed format)... */ 3.99 3.100 +struct cloop_tail 3.101 +{ 3.102 -+ u_int32_t table_size; 3.103 -+ u_int32_t index_size; 3.104 ++ u_int32_t table_size; 3.105 ++ u_int32_t index_size; /* size:4 comp:3 ctrl-c:1 lastlen:24 */ 3.106 ++#define CLOOP3_INDEX_SIZE(x) ((unsigned int)((x) & 0xF)) 3.107 ++#define CLOOP3_BLOCKS_FLAGS(x) ((unsigned int)((x) & 0x70) >> 4) 3.108 ++#define CLOOP3_TRUNCATED(x) ((unsigned int)((x) & 0x80) >> 7) 3.109 ++#define CLOOP3_LASTLEN(x) (unsigned int)((x) >> 8) 3.110 + u_int32_t num_blocks; 3.111 +}; 3.112 + 3.113 ++#define GZIP_MAX_BUFFER(n) ((n) + (n)/1000 + 12) 3.114 ++ 3.115 +struct block_info 3.116 +{ 3.117 + loff_t offset; /* 64-bit offsets of compressed block */ 3.118 + u_int32_t size; /* 32-bit compressed block size */ 3.119 -+ u_int32_t optidx; /* 32-bit index number */ 3.120 ++ u_int32_t flags; /* 32-bit compression flags */ 3.121 +}; 3.122 + 3.123 -+static inline char *build_index(struct block_info *offsets, unsigned long n) 3.124 ++static inline char *build_index(struct block_info *offsets, unsigned long n, 3.125 ++ unsigned long block_size, unsigned global_flags) 3.126 +{ 3.127 + u_int32_t *ofs32 = (u_int32_t *) offsets; 3.128 + loff_t *ofs64 = (loff_t *) offsets; 3.129 -+ 3.130 ++ 3.131 ++ /* v3 64bits bug: v1 assumed */ 3.132 ++ unsigned long v3_64 = (n+1)/2; 3.133 ++ loff_t prev; 3.134 ++ 3.135 ++ if (ofs32[0] != 0 && ofs32[1] == 0) { 3.136 ++ for (prev=__le64_to_cpu(ofs64[v3_64]); 3.137 ++ v3_64 > 0 && __le64_to_cpu(ofs64[--v3_64]) < prev; 3.138 ++ prev=__le64_to_cpu(ofs64[v3_64])); 3.139 ++ } 3.140 ++ 3.141 + if (ofs32[0] == 0) { 3.142 + if (ofs32[2]) { /* ACCELERATED KNOPPIX V1.0 */ 3.143 + while (n--) { 3.144 + offsets[n].offset = __be64_to_cpu(offsets[n].offset); 3.145 + offsets[n].size = ntohl(offsets[n].size); 3.146 ++ offsets[n].flags = 0; 3.147 + } 3.148 + return (char *) "128BE accelerated knoppix 1.0"; 3.149 + } 3.150 -+ else { /* V2.0 */ 3.151 -+ loff_t last = __be64_to_cpu(ofs64[n - 1]); 3.152 -+ while (n--) { 3.153 ++ else { /* V2.0/V4.0 */ 3.154 ++ loff_t last = CLOOP_BLOCK_OFFSET(__be64_to_cpu(ofs64[n])); 3.155 ++ u_int32_t flags; 3.156 ++ static char v4[11]; 3.157 ++ unsigned long i = n; 3.158 ++ 3.159 ++ for (flags = 0; n-- ;) { 3.160 ++ loff_t data = __be64_to_cpu(ofs64[n]); 3.161 ++ 3.162 + offsets[n].size = last - 3.163 -+ (offsets[n].offset = __be64_to_cpu(ofs64[n])); 3.164 ++ (offsets[n].offset = CLOOP_BLOCK_OFFSET(data)); 3.165 + last = offsets[n].offset; 3.166 ++ offsets[n].flags = CLOOP_BLOCK_FLAGS(data); 3.167 ++ flags |= 1 << offsets[n].flags; 3.168 + } 3.169 -+ return (char *) "64BE v2.0"; 3.170 ++ if (flags < 2) return (char *) "64BE v2.0"; 3.171 ++ while (i--) { 3.172 ++ if (offsets[i].flags == CLOOP_COMPRESSOR_LINK) { 3.173 ++ offsets[i] = offsets[offsets[i].offset]; 3.174 ++ } 3.175 ++ } 3.176 ++ strcpy(v4, (char *) "64BE v4.0a"); 3.177 ++ v4[10] = 'a' + ((flags-1) & 0xF); // compressors used 3.178 ++ if (flags > 0x10) { // with links ? 3.179 ++ v4[10] += 'A' - 'a'; 3.180 ++ } 3.181 ++ return v4; 3.182 + } 3.183 + } 3.184 -+ else if (ofs32[1] == 0) { /* V1.0 */ 3.185 -+ loff_t last = __le64_to_cpu(ofs64[n - 1]); 3.186 ++ else if (ofs32[1] == 0 && v3_64 == 0) { /* V1.0 */ 3.187 ++ loff_t last = __le64_to_cpu(ofs64[n]); 3.188 + while (n--) { 3.189 + offsets[n].size = last - 3.190 + (offsets[n].offset = __le64_to_cpu(ofs64[n])); 3.191 + last = offsets[n].offset; 3.192 ++ offsets[n].flags = 0; 3.193 + } 3.194 + return (char *) "64LE v1.0"; 3.195 + } 3.196 -+ else if (ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */ 3.197 -+ loff_t last = ntohl(ofs32[n - 1]); 3.198 -+ while (n--) { 3.199 -+ offsets[n].size = last - 3.200 -+ (offsets[n].offset = ntohl(ofs32[n])); 3.201 -+ last = offsets[n].offset; 3.202 -+ } 3.203 -+ return (char *) "32BE v0.68"; 3.204 -+ } 3.205 -+ else { /* V3.0 */ 3.206 ++ else { /* V3.0 or V0.68 */ 3.207 + unsigned long i; 3.208 + loff_t j; 3.209 ++ static char v3[11]; 3.210 + 3.211 ++ for (i = 0; i < n && ntohl(ofs32[i]) < ntohl(ofs32[i+1]); i++); 3.212 ++ if (i == n && ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */ 3.213 ++ loff_t last = ntohl(ofs32[n]); 3.214 ++ while (n--) { 3.215 ++ offsets[n].size = last - 3.216 ++ (offsets[n].offset = ntohl(ofs32[n])); 3.217 ++ last = offsets[n].offset; 3.218 ++ offsets[n].flags = 0; 3.219 ++ } 3.220 ++ return (char *) "32BE v0.68"; 3.221 ++ } 3.222 ++ 3.223 ++ v3_64 = (ofs32[1] == 0); 3.224 + for (i = n; i-- != 0; ) 3.225 -+ offsets[i].size = ntohl(ofs32[i]); 3.226 ++ offsets[i].size = ntohl(ofs32[i << v3_64]); 3.227 + for (i = 0, j = sizeof(struct cloop_head); i < n; i++) { 3.228 + offsets[i].offset = j; 3.229 ++ offsets[i].flags = global_flags; 3.230 ++ if (offsets[i].size == 0xFFFFFFFF) { 3.231 ++ offsets[i].flags = CLOOP_COMPRESSOR_NONE; 3.232 ++ offsets[i].size = block_size; 3.233 ++ } 3.234 ++ if ((offsets[i].size & 0x80000000) == 0) { 3.235 ++ j += offsets[i].size; 3.236 ++ } 3.237 ++ } 3.238 ++ for (i = 0; i < n; i++) { 3.239 + if (offsets[i].size & 0x80000000) { 3.240 -+ unsigned long k = offsets[i].size & 0x7FFFFFFF; 3.241 -+ offsets[i].offset = offsets[k].offset; 3.242 -+ offsets[i].size = offsets[k].size; 3.243 ++ offsets[i] = offsets[offsets[i].size & 0x7FFFFFFF]; 3.244 + } 3.245 -+ else j += offsets[i].size; 3.246 + } 3.247 -+ return (char *) "32BE v3.0"; 3.248 ++ strcpy(v3, (char *) (v3_64) ? "64BE v3.0a" : "32BE v3.0a"); 3.249 ++ v3[10] += global_flags; 3.250 ++ return v3; 3.251 + } 3.252 +} 3.253 + 3.254 @@ -83,187 +224,884 @@ 3.255 3.256 --- cloop.c 3.257 +++ cloop.c 3.258 -@@ -5,11 +5,18 @@ 3.259 - * A cloop file looks like this: 3.260 - * [32-bit uncompressed block size: network order] 3.261 - * [32-bit number of blocks (n_blocks): network order] 3.262 +@@ -1,26 +1,23 @@ 3.263 +-/* 3.264 +- * compressed_loop.c: Read-only compressed loop blockdevice 3.265 +- * hacked up by Rusty in 1999, extended and maintained by Klaus Knopper 3.266 +- * 3.267 +- * A cloop file looks like this: 3.268 +- * [32-bit uncompressed block size: network order] 3.269 +- * [32-bit number of blocks (n_blocks): network order] 3.270 - * [64-bit file offsets of start of blocks: network order] 3.271 -+ * [for version < 3] 3.272 -+ * [32-bit, 64-bit or 128-bit file offsets of start of blocks] 3.273 - * ... 3.274 - * (n_blocks + 1). 3.275 - * n_blocks consisting of: 3.276 - * [compressed block] 3.277 -+ * ... 3.278 -+ * [for version >= 3] 3.279 -+ * [compressed list of 32-bit block sizes] 3.280 -+ * [32-bit compressed index size: network order] 3.281 -+ * [32-bit index size = 4: network order] 3.282 -+ * [32-bit number of blocks (n_blocks): network order] 3.283 - * 3.284 - * Every version greatly inspired by code seen in loop.c 3.285 - * by Theodore Ts'o, 3/29/93. 3.286 -@@ -115,7 +122,7 @@ 3.287 +- * ... 3.288 +- * (n_blocks + 1). 3.289 +- * n_blocks consisting of: 3.290 +- * [compressed block] 3.291 +- * 3.292 +- * Every version greatly inspired by code seen in loop.c 3.293 +- * by Theodore Ts'o, 3/29/93. 3.294 +- * 3.295 +- * Copyright 1999-2009 by Paul `Rusty' Russell & Klaus Knopper. 3.296 +- * Redistribution of this file is permitted under the GNU Public License. 3.297 +- * 3.298 +- */ 3.299 ++/************************************************************************\ 3.300 ++* cloop.c: Read-only compressed loop blockdevice * 3.301 ++* hacked up by Rusty in 1999, extended and maintained by Klaus Knopper * 3.302 ++* * 3.303 ++* For all supported cloop file formats, please check the file "cloop.h" * 3.304 ++* New in Version 4: * 3.305 ++* - Header can be first or last in cloop file, * 3.306 ++* - Different compression algorithms supported (compression type * 3.307 ++* encoded in first 4 bytes of block offset address) * 3.308 ++* * 3.309 ++* Every version greatly inspired by code seen in loop.c * 3.310 ++* by Theodore Ts'o, 3/29/93. * 3.311 ++* * 3.312 ++* Copyright 1999-2009 by Paul `Rusty' Russell & Klaus Knopper. * 3.313 ++* Redistribution of this file is permitted under the GNU Public License * 3.314 ++* V2. * 3.315 ++\************************************************************************/ 3.316 + 3.317 + #define CLOOP_NAME "cloop" 3.318 +-#define CLOOP_VERSION "2.639" 3.319 ++#define CLOOP_VERSION "4.12" 3.320 + #define CLOOP_MAX 8 3.321 + 3.322 + #ifndef KBUILD_MODNAME 3.323 +@@ -47,8 +44,27 @@ 3.324 + #include <asm/div64.h> /* do_div() for 64bit division */ 3.325 + #include <asm/uaccess.h> 3.326 + #include <asm/byteorder.h> 3.327 +-/* Use zlib_inflate from lib/zlib_inflate */ 3.328 ++/* Check for ZLIB, LZO1X, LZ4 decompression algorithms in kernel. */ 3.329 ++#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 3.330 + #include <linux/zutil.h> 3.331 ++#endif 3.332 ++#if (defined(CONFIG_LZO_DECOMPRESS) || defined(CONFIG_LZO_DECOMPRESS_MODULE)) 3.333 ++#include <linux/lzo.h> 3.334 ++#endif 3.335 ++#if (defined(CONFIG_DECOMPRESS_LZ4) || defined(CONFIG_DECOMPRESS_LZ4_MODULE)) 3.336 ++#include <linux/lz4.h> 3.337 ++#endif 3.338 ++#if (defined(CONFIG_DECOMPRESS_LZMA) || defined(CONFIG_DECOMPRESS_LZMA_MODULE)) 3.339 ++#include <linux/decompress/unlzma.h> 3.340 ++#endif 3.341 ++#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 3.342 ++#include <linux/xz.h> 3.343 ++#endif 3.344 ++ 3.345 ++#if (!(defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE) || defined(CONFIG_LZO_DECOMPRESS) || defined(CONFIG_LZO_DECOMPRESS_MODULE) || defined(CONFIG_DECOMPRESS_LZ4) || defined(CONFIG_DECOMPRESS_LZ4_MODULE) || defined(CONFIG_DECOMPRESS_LZMA) || defined(CONFIG_DECOMPRESS_LZMA_MODULE) || defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE))) 3.346 ++#error "No decompression library selected in kernel config!" 3.347 ++#endif 3.348 ++ 3.349 + #include <linux/loop.h> 3.350 + #include <linux/kthread.h> 3.351 + #include <linux/compat.h> 3.352 +@@ -92,47 +108,64 @@ 3.353 + #define DEBUGP(format, x...) 3.354 + #endif 3.355 + 3.356 ++/* Default size of buffer to keep some decompressed blocks in memory to speed up access */ 3.357 ++#define BLOCK_BUFFER_MEM (16*65536) 3.358 ++ 3.359 + /* One file can be opened at module insertion time */ 3.360 + /* insmod cloop file=/path/to/file */ 3.361 + static char *file=NULL; 3.362 + static unsigned int preload=0; 3.363 + static unsigned int cloop_max=CLOOP_MAX; 3.364 ++static unsigned int buffers=BLOCK_BUFFER_MEM; 3.365 + module_param(file, charp, 0); 3.366 + module_param(preload, uint, 0); 3.367 + module_param(cloop_max, uint, 0); 3.368 + MODULE_PARM_DESC(file, "Initial cloop image file (full path) for /dev/cloop"); 3.369 + MODULE_PARM_DESC(preload, "Preload n blocks of cloop data into memory"); 3.370 + MODULE_PARM_DESC(cloop_max, "Maximum number of cloop devices (default 8)"); 3.371 ++MODULE_PARM_DESC(buffers, "Size of buffer to keep uncompressed blocks in memory in MiB (default 1)"); 3.372 + 3.373 + static struct file *initial_file=NULL; 3.374 + static int cloop_major=MAJOR_NR; 3.375 + 3.376 +-/* Number of buffered decompressed blocks */ 3.377 +-#define BUFFERED_BLOCKS 8 3.378 + struct cloop_device 3.379 + { 3.380 +- /* Copied straight from the file */ 3.381 ++ /* Header filled from the file */ 3.382 struct cloop_head head; 3.383 ++ int header_first; 3.384 ++ int file_format; 3.385 3.386 - /* An array of offsets of compressed blocks within the file */ 3.387 +- /* An array of offsets of compressed blocks within the file */ 3.388 - loff_t *offsets; 3.389 -+ struct block_info *offsets; 3.390 ++ /* An or'd sum of all flags of each compressed block (v3) */ 3.391 ++ u_int32_t allflags; 3.392 ++ 3.393 ++ /* An array of cloop_ptr flags/offset for compressed blocks within the file */ 3.394 ++ struct block_info *block_ptrs; 3.395 3.396 /* We buffer some uncompressed blocks for performance */ 3.397 - int buffered_blocknum[BUFFERED_BLOCKS]; 3.398 -@@ -256,11 +263,11 @@ 3.399 - return i; 3.400 - } 3.401 +- int buffered_blocknum[BUFFERED_BLOCKS]; 3.402 +- int current_bufnum; 3.403 +- void *buffer[BUFFERED_BLOCKS]; 3.404 +- void *compressed_buffer; 3.405 +- size_t preload_array_size; /* Size of pointer array in blocks */ 3.406 +- size_t preload_size; /* Number of successfully allocated blocks */ 3.407 +- char **preload_cache; /* Pointers to preloaded blocks */ 3.408 ++ size_t num_buffered_blocks; /* how many uncompressed blocks buffered for performance */ 3.409 ++ int *buffered_blocknum; /* list of numbers of uncompressed blocks in buffer */ 3.410 ++ int current_bufnum; /* which block is current */ 3.411 ++ unsigned char **buffer; /* cache space for num_buffered_blocks uncompressed blocks */ 3.412 ++ void *compressed_buffer; /* space for the largest compressed block */ 3.413 ++ size_t preload_array_size; /* Size of pointer array in blocks */ 3.414 ++ size_t preload_size; /* Number of successfully allocated blocks */ 3.415 ++ char **preload_cache; /* Pointers to preloaded blocks */ 3.416 3.417 ++#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 3.418 + z_stream zstream; 3.419 ++#endif 3.420 ++#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 3.421 ++ struct xz_dec *xzdecoderstate; 3.422 ++ struct xz_buf xz_buffer; 3.423 ++#endif 3.424 + 3.425 + struct file *backing_file; /* associated file */ 3.426 + struct inode *backing_inode; /* for bmap */ 3.427 + 3.428 ++ unsigned char *underlying_filename; 3.429 + unsigned long largest_block; 3.430 + unsigned int underlying_blksize; 3.431 ++ loff_t underlying_total_size; 3.432 + int clo_number; 3.433 + int refcnt; 3.434 + struct block_device *bdev; 3.435 +@@ -147,7 +180,6 @@ 3.436 + struct request_queue *clo_queue; 3.437 + struct gendisk *clo_disk; 3.438 + int suspended; 3.439 +- char clo_file_name[LO_NAME_SIZE]; 3.440 + }; 3.441 + 3.442 + /* Changed in 2.639: cloop_dev is now a an array of cloop_dev pointers, 3.443 +@@ -156,52 +188,113 @@ 3.444 + static const char *cloop_name=CLOOP_NAME; 3.445 + static int cloop_count = 0; 3.446 + 3.447 +-#if (!(defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE))) /* Must be compiled into kernel. */ 3.448 +-#error "Invalid Kernel configuration. CONFIG_ZLIB_INFLATE support is needed for cloop." 3.449 +-#endif 3.450 +- 3.451 +-/* Use __get_free_pages instead of vmalloc, allows up to 32 pages, 3.452 +- * 2MB in one piece */ 3.453 + static void *cloop_malloc(size_t size) 3.454 + { 3.455 +- int order = get_order(size); 3.456 +- if(order <= KMALLOC_MAX_ORDER) 3.457 +- return (void *)kmalloc(size, GFP_KERNEL); 3.458 +- else if(order < MAX_ORDER) 3.459 +- return (void *)__get_free_pages(GFP_KERNEL, order); 3.460 ++ /* kmalloc will fail after the system is running for a while, */ 3.461 ++ /* when large orders can't return contiguous memory. */ 3.462 ++ /* Let's just use vmalloc for now. :-/ */ 3.463 ++ /* int order = get_order(size); */ 3.464 ++ /* if(order <= KMALLOC_MAX_ORDER) */ 3.465 ++ /* return (void *)kmalloc(size, GFP_KERNEL); */ 3.466 ++ /* else if(order < MAX_ORDER) */ 3.467 ++ /* return (void *)__get_free_pages(GFP_KERNEL, order); */ 3.468 + return (void *)vmalloc(size); 3.469 + } 3.470 + 3.471 + static void cloop_free(void *mem, size_t size) 3.472 + { 3.473 +- int order = get_order(size); 3.474 +- if(order <= KMALLOC_MAX_ORDER) 3.475 +- kfree(mem); 3.476 +- else if(order < MAX_ORDER) 3.477 +- free_pages((unsigned long)mem, order); 3.478 +- else vfree(mem); 3.479 ++ /* int order = get_order(size); */ 3.480 ++ /* if(order <= KMALLOC_MAX_ORDER) */ 3.481 ++ /* kfree(mem); */ 3.482 ++ /* else if(order < MAX_ORDER) */ 3.483 ++ /* free_pages((unsigned long)mem, order); */ 3.484 ++ /* else */ 3.485 ++ vfree(mem); 3.486 + } 3.487 + 3.488 +-static int uncompress(struct cloop_device *clo, 3.489 +- unsigned char *dest, unsigned long *destLen, 3.490 +- unsigned char *source, unsigned long sourceLen) 3.491 ++static int uncompress(struct cloop_device *clo, unsigned char *dest, unsigned long *destLen, unsigned char *source, unsigned long sourceLen, int flags) 3.492 + { 3.493 +- /* Most of this code can be found in fs/cramfs/uncompress.c */ 3.494 +- int err; 3.495 +- clo->zstream.next_in = source; 3.496 +- clo->zstream.avail_in = sourceLen; 3.497 +- clo->zstream.next_out = dest; 3.498 +- clo->zstream.avail_out = *destLen; 3.499 +- err = zlib_inflateReset(&clo->zstream); 3.500 +- if (err != Z_OK) 3.501 +- { 3.502 +- printk(KERN_ERR "%s: zlib_inflateReset error %d\n", cloop_name, err); 3.503 +- zlib_inflateEnd(&clo->zstream); zlib_inflateInit(&clo->zstream); 3.504 +- } 3.505 +- err = zlib_inflate(&clo->zstream, Z_FINISH); 3.506 +- *destLen = clo->zstream.total_out; 3.507 +- if (err != Z_STREAM_END) return err; 3.508 +- return Z_OK; 3.509 ++ int err = -1; 3.510 ++ switch(flags) 3.511 ++ { 3.512 ++ case CLOOP_COMPRESSOR_NONE: 3.513 ++ memcpy(dest, source, *destLen = sourceLen); 3.514 ++ err = Z_OK; 3.515 ++ break; 3.516 ++#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 3.517 ++ case CLOOP_COMPRESSOR_ZLIB: 3.518 ++ clo->zstream.next_in = source; 3.519 ++ clo->zstream.avail_in = sourceLen; 3.520 ++ clo->zstream.next_out = dest; 3.521 ++ clo->zstream.avail_out = *destLen; 3.522 ++ err = zlib_inflateReset(&clo->zstream); 3.523 ++ if (err != Z_OK) 3.524 ++ { 3.525 ++ printk(KERN_ERR "%s: zlib_inflateReset error %d\n", cloop_name, err); 3.526 ++ zlib_inflateEnd(&clo->zstream); zlib_inflateInit(&clo->zstream); 3.527 ++ } 3.528 ++ err = zlib_inflate(&clo->zstream, Z_FINISH); 3.529 ++ *destLen = clo->zstream.total_out; 3.530 ++ if (err == Z_STREAM_END) err = 0; 3.531 ++ DEBUGP("cloop: zlib decompression done, ret =%d, size =%lu\n", err, *destLen); 3.532 ++ break; 3.533 ++#endif 3.534 ++#if (defined(CONFIG_LZO_DECOMPRESS) || defined(CONFIG_LZO_DECOMPRESS_MODULE)) 3.535 ++ case CLOOP_COMPRESSOR_LZO1X: 3.536 ++ { 3.537 ++ size_t tmp = (size_t) clo->head.block_size; 3.538 ++ err = lzo1x_decompress_safe(source, sourceLen, 3.539 ++ dest, &tmp); 3.540 ++ if (err == LZO_E_OK) *destLen = (u_int32_t) tmp; 3.541 ++ } 3.542 ++ break; 3.543 ++#endif 3.544 ++#if (defined(CONFIG_DECOMPRESS_LZ4) || defined(CONFIG_DECOMPRESS_LZ4_MODULE)) 3.545 ++ case CLOOP_COMPRESSOR_LZ4: 3.546 ++ { 3.547 ++ size_t outputSize = *destLen; 3.548 ++ /* We should adjust outputSize here, in case the last block is smaller than block_size */ 3.549 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) /* field removed */ 3.550 ++ err = lz4_decompress(source, (size_t *) &sourceLen, 3.551 ++ dest, outputSize); 3.552 ++#else 3.553 ++ err = LZ4_decompress_safe(source, 3.554 ++ dest, 3.555 ++ sourceLen, outputSize); 3.556 ++#endif 3.557 ++ if (err >= 0) 3.558 ++ { 3.559 ++ err = 0; 3.560 ++ *destLen = outputSize; 3.561 ++ } 3.562 ++ } 3.563 ++ break; 3.564 ++#endif 3.565 ++#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 3.566 ++ case CLOOP_COMPRESSOR_XZ: 3.567 ++ clo->xz_buffer.in = source; 3.568 ++ clo->xz_buffer.in_pos = 0; 3.569 ++ clo->xz_buffer.in_size = sourceLen; 3.570 ++ clo->xz_buffer.out = dest; 3.571 ++ clo->xz_buffer.out_pos = 0; 3.572 ++ clo->xz_buffer.out_size = *destLen; 3.573 ++ xz_dec_reset(clo->xzdecoderstate); 3.574 ++ err = xz_dec_run(clo->xzdecoderstate, &clo->xz_buffer); 3.575 ++ if (err == XZ_STREAM_END || err == XZ_OK) 3.576 ++ { 3.577 ++ err = 0; 3.578 ++ } 3.579 ++ else 3.580 ++ { 3.581 ++ printk(KERN_ERR "%s: xz_dec_run error %d\n", cloop_name, err); 3.582 ++ err = 1; 3.583 ++ } 3.584 ++ break; 3.585 ++#endif 3.586 ++ default: 3.587 ++ printk(KERN_ERR "%s: compression method is not supported!\n", cloop_name); 3.588 ++ } 3.589 ++ return err; 3.590 + } 3.591 + 3.592 + static ssize_t cloop_read_from_file(struct cloop_device *clo, struct file *f, char *buf, 3.593 +@@ -220,7 +313,7 @@ 3.594 + 3.595 + if(size_read <= 0) 3.596 + { 3.597 +- printk(KERN_ERR "%s: Read error %d at pos %Lu in file %s, " 3.598 ++ printk(KERN_ERR "%s: Read error %d at pos %llu in file %s, " 3.599 + "%d bytes lost.\n", cloop_name, (int)size_read, pos, 3.600 + file, (int)size); 3.601 + memset(buf + buf_len - size, 0, size); 3.602 +@@ -232,72 +325,84 @@ 3.603 + } 3.604 + 3.605 + /* This looks more complicated than it is */ 3.606 +-/* Returns number of block buffer to use for this request */ 3.607 ++/* Returns number of cache block buffer to use for this request */ 3.608 + static int cloop_load_buffer(struct cloop_device *clo, int blocknum) 3.609 + { 3.610 +- unsigned int buf_done = 0; 3.611 +- unsigned long buflen; 3.612 +- unsigned int buf_length; 3.613 ++ loff_t compressed_block_offset; 3.614 ++ long compressed_block_len; 3.615 ++ long uncompressed_block_len=0; 3.616 + int ret; 3.617 + int i; 3.618 +- if(blocknum > ntohl(clo->head.num_blocks) || blocknum < 0) 3.619 +- { 3.620 +- printk(KERN_WARNING "%s: Invalid block number %d requested.\n", 3.621 +- cloop_name, blocknum); 3.622 +- return -1; 3.623 +- } 3.624 ++ if(blocknum > clo->head.num_blocks || blocknum < 0) 3.625 ++ { 3.626 ++ printk(KERN_WARNING "%s: Invalid block number %d requested.\n", 3.627 ++ cloop_name, blocknum); 3.628 ++ return -1; 3.629 ++ } 3.630 + 3.631 + /* Quick return if the block we seek is already in one of the buffers. */ 3.632 + /* Return number of buffer */ 3.633 +- for(i=0; i<BUFFERED_BLOCKS; i++) 3.634 ++ for(i=0; i<clo->num_buffered_blocks; i++) 3.635 + if (blocknum == clo->buffered_blocknum[i]) 3.636 +- { 3.637 +- DEBUGP(KERN_INFO "cloop_load_buffer: Found buffered block %d\n", i); 3.638 +- return i; 3.639 +- } 3.640 +- 3.641 - buf_length = be64_to_cpu(clo->offsets[blocknum+1]) - be64_to_cpu(clo->offsets[blocknum]); 3.642 -+ buf_length = clo->offsets[blocknum].size; 3.643 +- 3.644 +-/* Load one compressed block from the file. */ 3.645 +- cloop_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer, 3.646 +- be64_to_cpu(clo->offsets[blocknum]), buf_length); 3.647 ++ { 3.648 ++ DEBUGP(KERN_INFO "cloop_load_buffer: Found buffered block %d\n", i); 3.649 ++ return i; 3.650 ++ } 3.651 3.652 - /* Load one compressed block from the file. */ 3.653 - cloop_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer, 3.654 -- be64_to_cpu(clo->offsets[blocknum]), buf_length); 3.655 -+ clo->offsets[blocknum].offset, buf_length); 3.656 +- buflen = ntohl(clo->head.block_size); 3.657 ++ compressed_block_offset = clo->block_ptrs[blocknum].offset; 3.658 ++ compressed_block_len = (long) (clo->block_ptrs[blocknum].size) ; 3.659 3.660 - buflen = ntohl(clo->head.block_size); 3.661 +- /* Go to next position in the block ring buffer */ 3.662 +- clo->current_bufnum++; 3.663 +- if(clo->current_bufnum >= BUFFERED_BLOCKS) clo->current_bufnum = 0; 3.664 ++ /* Load one compressed block from the file. */ 3.665 ++ if(compressed_block_offset > 0 && compressed_block_len >= 0) /* sanity check */ 3.666 ++ { 3.667 ++ size_t n = cloop_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer, 3.668 ++ compressed_block_offset, compressed_block_len); 3.669 ++ if (n!= compressed_block_len) 3.670 ++ { 3.671 ++ printk(KERN_ERR "%s: error while reading %lu bytes @ %llu from file %s\n", 3.672 ++ cloop_name, compressed_block_len, clo->block_ptrs[blocknum].offset, clo->underlying_filename); 3.673 ++ /* return -1; */ 3.674 ++ } 3.675 ++ } else { 3.676 ++ printk(KERN_ERR "%s: invalid data block len %ld bytes @ %lld from file %s\n", 3.677 ++ cloop_name, compressed_block_len, clo->block_ptrs[blocknum].offset, clo->underlying_filename); 3.678 ++ return -1; 3.679 ++ } 3.680 ++ 3.681 ++ /* Go to next position in the cache block buffer (which is used as a cyclic buffer) */ 3.682 ++ if(++clo->current_bufnum >= clo->num_buffered_blocks) clo->current_bufnum = 0; 3.683 3.684 -@@ -275,9 +282,9 @@ 3.685 + /* Do the uncompression */ 3.686 +- ret = uncompress(clo, clo->buffer[clo->current_bufnum], &buflen, clo->compressed_buffer, 3.687 +- buf_length); 3.688 ++ uncompressed_block_len = clo->head.block_size; 3.689 ++ ret = uncompress(clo, clo->buffer[clo->current_bufnum], &uncompressed_block_len, 3.690 ++ clo->compressed_buffer, compressed_block_len, clo->block_ptrs[blocknum].flags); 3.691 + /* DEBUGP("cloop: buflen after uncompress: %ld\n",buflen); */ 3.692 if (ret != 0) 3.693 +- { 3.694 +- printk(KERN_ERR "%s: zlib decompression error %i uncompressing block %u %u/%lu/%u/%u " 3.695 +- "%Lu-%Lu\n", cloop_name, ret, blocknum, 3.696 +- ntohl(clo->head.block_size), buflen, buf_length, buf_done, 3.697 +- be64_to_cpu(clo->offsets[blocknum]), be64_to_cpu(clo->offsets[blocknum+1])); 3.698 +- clo->buffered_blocknum[clo->current_bufnum] = -1; 3.699 +- return -1; 3.700 +- } 3.701 ++ { 3.702 ++ printk(KERN_ERR "%s: decompression error %i uncompressing block %u %lu bytes @ %llu, flags %u\n", 3.703 ++ cloop_name, ret, blocknum, 3.704 ++ compressed_block_len, clo->block_ptrs[blocknum].offset, 3.705 ++ clo->block_ptrs[blocknum].flags); 3.706 ++ clo->buffered_blocknum[clo->current_bufnum] = -1; 3.707 ++ return -1; 3.708 ++ } 3.709 + clo->buffered_blocknum[clo->current_bufnum] = blocknum; 3.710 + return clo->current_bufnum; 3.711 + } 3.712 + 3.713 + /* This function does all the real work. */ 3.714 +-/* returns "uptodate" */ 3.715 ++/* returns "uptodate" */ 3.716 + static int cloop_handle_request(struct cloop_device *clo, struct request *req) 3.717 + { 3.718 + int buffered_blocknum = -1; 3.719 + int preloaded = 0; 3.720 + loff_t offset = (loff_t) blk_rq_pos(req)<<9; /* req->sector<<9 */ 3.721 +- struct bio_vec *bvec; 3.722 ++ struct bio_vec bvec; 3.723 + struct req_iterator iter; 3.724 + rq_for_each_segment(bvec, req, iter) 3.725 { 3.726 - printk(KERN_ERR "%s: zlib decompression error %i uncompressing block %u %u/%lu/%u/%u " 3.727 -- "%Lu-%Lu\n", cloop_name, ret, blocknum, 3.728 -+ "%Lu:%u\n", cloop_name, ret, blocknum, 3.729 - ntohl(clo->head.block_size), buflen, buf_length, buf_done, 3.730 -- be64_to_cpu(clo->offsets[blocknum]), be64_to_cpu(clo->offsets[blocknum+1])); 3.731 -+ clo->offsets[blocknum].offset, clo->offsets[blocknum].size); 3.732 - clo->buffered_blocknum[clo->current_bufnum] = -1; 3.733 - return -1; 3.734 +- unsigned long len = bvec->bv_len; 3.735 +- char *to_ptr = kmap(bvec->bv_page) + bvec->bv_offset; 3.736 ++ unsigned long len = bvec.bv_len; 3.737 ++ char *to_ptr = kmap(bvec.bv_page) + bvec.bv_offset; 3.738 + while(len > 0) 3.739 + { 3.740 + u_int32_t length_in_buffer; 3.741 +@@ -308,7 +413,7 @@ 3.742 + /* puts the result in the first argument, i.e. block_offset */ 3.743 + /* becomes the blocknumber to load, and offset_in_buffer the */ 3.744 + /* position in the buffer */ 3.745 +- offset_in_buffer = do_div(block_offset, ntohl(clo->head.block_size)); 3.746 ++ offset_in_buffer = do_div(block_offset, clo->head.block_size); 3.747 + /* Lookup preload cache */ 3.748 + if(block_offset < clo->preload_size && clo->preload_cache != NULL && 3.749 + clo->preload_cache[block_offset] != NULL) 3.750 +@@ -325,7 +430,7 @@ 3.751 + from_ptr = clo->buffer[buffered_blocknum]; 3.752 + } 3.753 + /* Now, at least part of what we want will be in the buffer. */ 3.754 +- length_in_buffer = ntohl(clo->head.block_size) - offset_in_buffer; 3.755 ++ length_in_buffer = clo->head.block_size - offset_in_buffer; 3.756 + if(length_in_buffer > len) 3.757 + { 3.758 + /* DEBUGP("Warning: length_in_buffer=%u > len=%u\n", 3.759 +@@ -337,18 +442,19 @@ 3.760 + len -= length_in_buffer; 3.761 + offset += length_in_buffer; 3.762 + } /* while inner loop */ 3.763 +- kunmap(bvec->bv_page); 3.764 ++ kunmap(bvec.bv_page); 3.765 ++ cond_resched(); 3.766 + } /* end rq_for_each_segment*/ 3.767 + return ((buffered_blocknum!=-1) || preloaded); 3.768 + } 3.769 + 3.770 + /* Adopted from loop.c, a kernel thread to handle physical reads and 3.771 +- * decompression. */ 3.772 ++ decompression. */ 3.773 + static int cloop_thread(void *data) 3.774 + { 3.775 + struct cloop_device *clo = data; 3.776 + current->flags |= PF_NOFREEZE; 3.777 +- set_user_nice(current, -15); 3.778 ++ set_user_nice(current, 10); 3.779 + while (!kthread_should_stop()||!list_empty(&clo->clo_list)) 3.780 + { 3.781 + int err; 3.782 +@@ -390,10 +496,18 @@ 3.783 + int rw; 3.784 + /* quick sanity checks */ 3.785 + /* blk_fs_request() was removed in 2.6.36 */ 3.786 +- if (unlikely(req == NULL || (req->cmd_type != REQ_TYPE_FS))) 3.787 ++ if (unlikely(req == NULL 3.788 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) /* field removed */ 3.789 ++ || (req->cmd_type != REQ_TYPE_FS) 3.790 ++#endif 3.791 ++ )) 3.792 + goto error_continue; 3.793 + rw = rq_data_dir(req); 3.794 +- if (unlikely(rw != READ && rw != READA)) 3.795 ++ if (unlikely(rw != READ 3.796 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) 3.797 ++ && rw != READA 3.798 ++#endif 3.799 ++ )) 3.800 + { 3.801 + DEBUGP("cloop_do_request: bad command\n"); 3.802 + goto error_continue; 3.803 +@@ -409,40 +523,51 @@ 3.804 + continue; /* next request */ 3.805 + error_continue: 3.806 + DEBUGP(KERN_ERR "cloop_do_request: Discarding request %p.\n", req); 3.807 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) 3.808 + req->errors++; 3.809 ++#else 3.810 ++ req->error_count++; 3.811 ++#endif 3.812 + __blk_end_request_all(req, -EIO); 3.813 } 3.814 -@@ -489,30 +496,73 @@ 3.815 - cloop_name, ntohl(clo->head.block_size)); 3.816 - error=-EBADF; goto error_release; 3.817 - } 3.818 + } 3.819 + 3.820 +-/* Read header and offsets from already opened file */ 3.821 +-static int cloop_set_file(int cloop_num, struct file *file, char *filename) 3.822 ++/* Read header, flags and offsets from already opened file */ 3.823 ++static int cloop_set_file(int cloop_num, struct file *file) 3.824 + { 3.825 + struct cloop_device *clo = cloop_dev[cloop_num]; 3.826 + struct inode *inode; 3.827 + char *bbuf=NULL; 3.828 +- unsigned int i, offsets_read, total_offsets; 3.829 +- int isblkdev; 3.830 +- int error = 0; 3.831 ++ unsigned int bbuf_size = 0; 3.832 ++ const unsigned int header_size = sizeof(struct cloop_head); 3.833 ++ unsigned int i, total_offsets=0; 3.834 ++ loff_t fs_read_position = 0, header_pos[2]; 3.835 ++ int flags, isblkdev, bytes_read, error = 0; 3.836 ++ if (clo->suspended) return error; 3.837 ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) 3.838 + inode = file->f_dentry->d_inode; 3.839 ++ clo->underlying_filename = kstrdup(file->f_dentry->d_name.name ? file->f_dentry->d_name.name : (const unsigned char *)"anonymous filename", GFP_KERNEL); 3.840 ++ #else 3.841 ++ inode = file->f_path.dentry->d_inode; 3.842 ++ clo->underlying_filename = kstrdup(file->f_path.dentry->d_name.name ? file->f_path.dentry->d_name.name : (const unsigned char *)"anonymous filename", GFP_KERNEL); 3.843 ++ #endif 3.844 + isblkdev=S_ISBLK(inode->i_mode)?1:0; 3.845 + if(!isblkdev&&!S_ISREG(inode->i_mode)) 3.846 + { 3.847 + printk(KERN_ERR "%s: %s not a regular file or block device\n", 3.848 +- cloop_name, filename); 3.849 ++ cloop_name, clo->underlying_filename); 3.850 + error=-EBADF; goto error_release; 3.851 + } 3.852 + clo->backing_file = file; 3.853 + clo->backing_inode= inode ; 3.854 +- if(!isblkdev&&inode->i_size<sizeof(struct cloop_head)) 3.855 ++ clo->underlying_total_size = (isblkdev) ? inode->i_bdev->bd_inode->i_size : inode->i_size; 3.856 ++ if(clo->underlying_total_size < header_size) 3.857 + { 3.858 +- printk(KERN_ERR "%s: %lu bytes (must be >= %u bytes)\n", 3.859 +- cloop_name, (unsigned long)inode->i_size, 3.860 +- (unsigned)sizeof(struct cloop_head)); 3.861 ++ printk(KERN_ERR "%s: %llu bytes (must be >= %u bytes)\n", 3.862 ++ cloop_name, clo->underlying_total_size, 3.863 ++ (unsigned int)header_size); 3.864 + error=-EBADF; goto error_release; 3.865 + } 3.866 +- /* In suspended mode, we have done all checks necessary - FF */ 3.867 +- if (clo->suspended) 3.868 +- return error; 3.869 + if(isblkdev) 3.870 + { 3.871 + struct request_queue *q = bdev_get_queue(inode->i_bdev); 3.872 +@@ -451,104 +576,225 @@ 3.873 + /* blk_queue_max_hw_segments(clo->clo_queue, queue_max_hw_segments(q)); */ /* Removed in 2.6.34 */ 3.874 + blk_queue_max_segment_size(clo->clo_queue, queue_max_segment_size(q)); 3.875 + blk_queue_segment_boundary(clo->clo_queue, queue_segment_boundary(q)); 3.876 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) 3.877 + blk_queue_merge_bvec(clo->clo_queue, q->merge_bvec_fn); 3.878 ++#endif 3.879 + clo->underlying_blksize = block_size(inode->i_bdev); 3.880 + } 3.881 + else 3.882 + clo->underlying_blksize = PAGE_SIZE; 3.883 +- DEBUGP("Underlying blocksize is %u\n", clo->underlying_blksize); 3.884 +- bbuf = cloop_malloc(clo->underlying_blksize); 3.885 ++ 3.886 ++ DEBUGP(KERN_INFO "Underlying blocksize of %s is %u\n", clo->underlying_filename, clo->underlying_blksize); 3.887 ++ DEBUGP(KERN_INFO "Underlying total size of %s is %llu\n", clo->underlying_filename, clo->underlying_total_size); 3.888 ++ 3.889 ++ /* clo->underlying_blksize should be larger than header_size, even if it's only PAGE_SIZE */ 3.890 ++ bbuf_size = clo->underlying_blksize; 3.891 ++ bbuf = cloop_malloc(bbuf_size); 3.892 + if(!bbuf) 3.893 + { 3.894 +- printk(KERN_ERR "%s: out of kernel mem for block buffer (%lu bytes)\n", 3.895 +- cloop_name, (unsigned long)clo->underlying_blksize); 3.896 ++ printk(KERN_ERR "%s: out of kernel mem for buffer (%u bytes)\n", 3.897 ++ cloop_name, (unsigned int) bbuf_size); 3.898 ++ error=-ENOMEM; goto error_release; 3.899 ++ } 3.900 ++ 3.901 ++ header_pos[0] = 0; /* header first */ 3.902 ++ header_pos[1] = clo->underlying_total_size - sizeof(struct cloop_head); /* header last */ 3.903 ++ for(i=0; i<2; i++) 3.904 ++ { 3.905 ++ /* Check for header */ 3.906 ++ size_t bytes_readable = MIN(clo->underlying_blksize, clo->underlying_total_size - header_pos[i]); 3.907 ++ size_t bytes_read = cloop_read_from_file(clo, file, bbuf, header_pos[i], bytes_readable); 3.908 ++ if(bytes_read != bytes_readable) 3.909 ++ { 3.910 ++ printk(KERN_ERR "%s: Bad file %s, read() of %s %u bytes returned %d.\n", 3.911 ++ cloop_name, clo->underlying_filename, (i==0)?"first":"last", 3.912 ++ (unsigned int)header_size, (int)bytes_read); 3.913 ++ error=-EBADF; 3.914 ++ goto error_release; 3.915 ++ } 3.916 ++ memcpy(&clo->head, bbuf, header_size); 3.917 ++ if (strncmp(bbuf+CLOOP_SIGNATURE_OFFSET, CLOOP_SIGNATURE, CLOOP_SIGNATURE_SIZE)==0) 3.918 ++ { 3.919 ++ clo->file_format++; 3.920 ++ clo->head.block_size=ntohl(clo->head.block_size); 3.921 ++ clo->head.num_blocks=ntohl(clo->head.num_blocks); 3.922 ++ clo->header_first = (i==0) ? 1 : 0; 3.923 ++ printk(KERN_INFO "%s: file %s, %d blocks of %d bytes, header %s.\n", cloop_name, clo->underlying_filename, clo->head.num_blocks, clo->head.block_size, (i==0)?"first":"last"); 3.924 ++ break; 3.925 ++ } 3.926 ++ } 3.927 ++ if (clo->file_format == 0) 3.928 ++ { 3.929 ++ printk(KERN_ERR "%s: Cannot detect %s format.\n", 3.930 ++ cloop_name, cloop_name); 3.931 ++ error=-EBADF; goto error_release; 3.932 ++ } 3.933 ++ if (clo->head.block_size % 512 != 0) 3.934 ++ { 3.935 ++ printk(KERN_ERR "%s: blocksize %u not multiple of 512\n", 3.936 ++ cloop_name, clo->head.block_size); 3.937 ++ error=-EBADF; goto error_release; 3.938 ++ } 3.939 ++ total_offsets=clo->head.num_blocks; 3.940 ++ if (!isblkdev && (sizeof(struct cloop_head)+sizeof(struct block_info)* 3.941 ++ total_offsets > inode->i_size)) 3.942 ++ { 3.943 ++ printk(KERN_ERR "%s: file %s too small for %u blocks\n", 3.944 ++ cloop_name, clo->underlying_filename, clo->head.num_blocks); 3.945 ++ error=-EBADF; goto error_release; 3.946 ++ } 3.947 ++ /* Allocate Memory for decompressors */ 3.948 ++#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 3.949 ++ clo->zstream.workspace = cloop_malloc(zlib_inflate_workspacesize()); 3.950 ++ if(!clo->zstream.workspace) 3.951 ++ { 3.952 ++ printk(KERN_ERR "%s: out of mem for zlib working area %u\n", 3.953 ++ cloop_name, zlib_inflate_workspacesize()); 3.954 + error=-ENOMEM; goto error_release; 3.955 + } 3.956 +- total_offsets = 1; /* Dummy total_offsets: will be filled in first time around */ 3.957 +- for (i = 0, offsets_read = 0; offsets_read < total_offsets; i++) 3.958 ++ zlib_inflateInit(&clo->zstream); 3.959 ++#endif 3.960 ++#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 3.961 ++#if XZ_INTERNAL_CRC32 3.962 ++ /* This must be called before any other xz_* function to initialize the CRC32 lookup table. */ 3.963 ++ xz_crc32_init(void); 3.964 ++#endif 3.965 ++ clo->xzdecoderstate = xz_dec_init(XZ_SINGLE, 0); 3.966 ++#endif 3.967 ++ if (total_offsets + 1 == 0) /* Version 3 */ 3.968 + { 3.969 +- unsigned int offset = 0, num_readable; 3.970 +- size_t bytes_read = cloop_read_from_file(clo, file, bbuf, 3.971 +- i*clo->underlying_blksize, 3.972 +- clo->underlying_blksize); 3.973 +- if(bytes_read != clo->underlying_blksize) 3.974 ++ struct cloop_tail tail; 3.975 ++ if (isblkdev) 3.976 + { 3.977 +- printk(KERN_ERR "%s: Bad file, read() of first %lu bytes returned %d.\n", 3.978 +- cloop_name, (unsigned long)clo->underlying_blksize, (int)bytes_read); 3.979 +- error=-EBADF; 3.980 +- goto error_release; 3.981 ++ /* No end of file: can't find index */ 3.982 ++ printk(KERN_ERR "%s: no V3 support for block device\n", 3.983 ++ cloop_name); 3.984 ++ error=-EBADF; goto error_release; 3.985 + } 3.986 +- /* Header will be in block zero */ 3.987 +- if(i==0) 3.988 ++ bytes_read = cloop_read_from_file(clo, file, (void *) &tail, 3.989 ++ inode->i_size - sizeof(struct cloop_tail), 3.990 ++ sizeof(struct cloop_tail)); 3.991 ++ if (bytes_read == sizeof(struct cloop_tail)) 3.992 + { 3.993 +- memcpy(&clo->head, bbuf, sizeof(struct cloop_head)); 3.994 +- offset = sizeof(struct cloop_head); 3.995 +- if (ntohl(clo->head.block_size) % 512 != 0) 3.996 ++ unsigned long len, zlen; 3.997 ++ int ret; 3.998 ++ void *zbuf; 3.999 ++ clo->head.num_blocks = ntohl(tail.num_blocks); 3.1000 ++ total_offsets = clo->head.num_blocks; 3.1001 ++ clo->block_ptrs = cloop_malloc(sizeof(struct block_info) * total_offsets); 3.1002 ++ zlen = ntohl(tail.table_size); 3.1003 ++ zbuf = cloop_malloc(zlen); 3.1004 ++ if (!clo->block_ptrs || !zbuf) 3.1005 + { 3.1006 +- printk(KERN_ERR "%s: blocksize %u not multiple of 512\n", 3.1007 +- cloop_name, ntohl(clo->head.block_size)); 3.1008 +- error=-EBADF; goto error_release; 3.1009 +- } 3.1010 - if (clo->head.preamble[0x0B]!='V'||clo->head.preamble[0x0C]<'1') 3.1011 - { 3.1012 - printk(KERN_ERR "%s: Cannot read old 32-bit (version 0.68) images, " 3.1013 - "please use an older version of %s for this file.\n", 3.1014 - cloop_name, cloop_name); 3.1015 - error=-EBADF; goto error_release; 3.1016 -- } 3.1017 ++ printk(KERN_ERR "%s: out of kernel mem for index\n", cloop_name); 3.1018 ++ error=-ENOMEM; goto error_release; 3.1019 + } 3.1020 - if (clo->head.preamble[0x0C]<'2') 3.1021 -- { 3.1022 ++ bytes_read = cloop_read_from_file(clo, file, zbuf, 3.1023 ++ inode->i_size - zlen - sizeof(struct cloop_tail), 3.1024 ++ zlen); 3.1025 ++ if (bytes_read != zlen) 3.1026 + { 3.1027 - printk(KERN_ERR "%s: Cannot read old architecture-dependent " 3.1028 - "(format <= 1.0) images, please use an older " 3.1029 - "version of %s for this file.\n", 3.1030 - cloop_name, cloop_name); 3.1031 -- error=-EBADF; goto error_release; 3.1032 -- } 3.1033 ++ printk(KERN_ERR "%s: can't read index\n", cloop_name); 3.1034 + error=-EBADF; goto error_release; 3.1035 + } 3.1036 - total_offsets=ntohl(clo->head.num_blocks)+1; 3.1037 - if (!isblkdev && (sizeof(struct cloop_head)+sizeof(loff_t)* 3.1038 -+ total_offsets=ntohl(clo->head.num_blocks); 3.1039 -+ if (!isblkdev && (sizeof(struct cloop_head)+sizeof(struct block_info)* 3.1040 - total_offsets > inode->i_size)) 3.1041 +- total_offsets > inode->i_size)) 3.1042 ++ len = CLOOP3_INDEX_SIZE(ntohl(tail.index_size)) * total_offsets; 3.1043 ++ flags = CLOOP3_BLOCKS_FLAGS(ntohl(tail.index_size)); 3.1044 ++// May 3 19:45:20 (none) user.info kernel: cloop: uncompress(clo=e0a78000, block_ptrs=e0c9c000, &len(1440)=ddc05e6c, zbuf=e0c9f000, zlen=43, flag=0) 3.1045 ++printk(KERN_INFO "%s: uncompress(clo=%p, block_ptrs=%p, &len(%ld)=%p, zbuf=%p, zlen=%ld, flag=%d)\n", cloop_name, 3.1046 ++ clo, clo->block_ptrs, len, &len, zbuf, zlen, flags); 3.1047 ++ ret = uncompress(clo, (void *) clo->block_ptrs, &len, zbuf, zlen, flags); 3.1048 ++// May 3 19:45:20 (none) user.alert kernel: BUG: unable to handle kernel NULL pointer dereference at (null) 3.1049 ++printk(KERN_INFO "%s: uncompressed !\n", cloop_name); 3.1050 ++ cloop_free(zbuf, zlen); 3.1051 ++ if (ret != 0) 3.1052 { 3.1053 - printk(KERN_ERR "%s: file too small for %u blocks\n", 3.1054 - cloop_name, ntohl(clo->head.num_blocks)); 3.1055 +- printk(KERN_ERR "%s: file too small for %u blocks\n", 3.1056 +- cloop_name, ntohl(clo->head.num_blocks)); 3.1057 ++ printk(KERN_ERR "%s: decompression error %i uncompressing index, flags %u\n", 3.1058 ++ cloop_name, ret, flags); 3.1059 error=-EBADF; goto error_release; 3.1060 } 3.1061 - clo->offsets = cloop_malloc(sizeof(loff_t) * total_offsets); 3.1062 -+ if (total_offsets + 1 == 0) /* Version >= 3.0 */ 3.1063 -+ { 3.1064 -+ struct cloop_tail tail; 3.1065 -+ if(isblkdev) 3.1066 -+ { 3.1067 -+ /* No end of file: can't find index */ 3.1068 -+ printk(KERN_ERR "%s: no V3 support for block device\n", 3.1069 -+ cloop_name); 3.1070 -+ error=-EBADF; goto error_release; 3.1071 -+ } 3.1072 -+ bytes_read = cloop_read_from_file(clo, file, (void *) &tail, 3.1073 -+ inode->i_size - sizeof(struct cloop_tail), 3.1074 -+ sizeof(struct cloop_tail)); 3.1075 -+ if(bytes_read == sizeof(struct cloop_tail)) 3.1076 -+ { 3.1077 -+ unsigned long len, zlen; 3.1078 -+ void *zbuf; 3.1079 -+ clo->head.num_blocks = tail.num_blocks; 3.1080 -+ total_offsets = ntohl(clo->head.num_blocks); 3.1081 -+ clo->offsets = cloop_malloc(sizeof(struct block_info) * total_offsets); 3.1082 -+ if (!clo->offsets) 3.1083 -+ { 3.1084 -+ printk(KERN_ERR "%s: can't alloc index\n", 3.1085 -+ cloop_name); 3.1086 -+ error=-EBADF; goto error_release; 3.1087 -+ } 3.1088 -+ zbuf = &clo->offsets[total_offsets/2]; 3.1089 -+ zlen = ntohl(tail.table_size); 3.1090 -+ len = ntohl(tail.index_size) * total_offsets; 3.1091 -+ bytes_read = cloop_read_from_file(clo, file, zbuf, 3.1092 -+ inode->i_size - zlen - sizeof(struct cloop_tail), 3.1093 -+ zlen); 3.1094 -+ if (bytes_read != zlen) 3.1095 -+ { 3.1096 -+ printk(KERN_ERR "%s: can't read index\n", 3.1097 -+ cloop_name); 3.1098 -+ error=-EBADF; goto error_release; 3.1099 -+ } 3.1100 -+ clo->zstream.workspace = cloop_malloc(zlib_inflate_workspacesize()); 3.1101 -+ if(!clo->zstream.workspace) 3.1102 -+ { 3.1103 -+ printk(KERN_ERR "%s: can't alloc index workspace\n", 3.1104 -+ cloop_name); 3.1105 -+ error=-EBADF; goto error_release; 3.1106 -+ } 3.1107 -+ zlib_inflateInit(&clo->zstream); 3.1108 -+ uncompress(clo, (void *) clo->offsets, &len, zbuf, zlen); 3.1109 -+ cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); 3.1110 -+ clo->zstream.workspace = NULL; 3.1111 -+ break; 3.1112 -+ } 3.1113 -+ else 3.1114 -+ { 3.1115 -+ printk(KERN_ERR "%s: can't find index\n", 3.1116 -+ cloop_name); 3.1117 -+ error=-EBADF; goto error_release; 3.1118 -+ } 3.1119 -+ } 3.1120 -+ clo->offsets = cloop_malloc(sizeof(struct block_info) * total_offsets); 3.1121 - if (!clo->offsets) 3.1122 - { 3.1123 - printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name); 3.1124 -@@ -521,19 +571,22 @@ 3.1125 +- if (!clo->offsets) 3.1126 +- { 3.1127 +- printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name); 3.1128 +- error=-ENOMEM; goto error_release; 3.1129 +- } 3.1130 } 3.1131 - num_readable = MIN(total_offsets - offsets_read, 3.1132 - (clo->underlying_blksize - offset) 3.1133 +- num_readable = MIN(total_offsets - offsets_read, 3.1134 +- (clo->underlying_blksize - offset) 3.1135 - / sizeof(loff_t)); 3.1136 - memcpy(&clo->offsets[offsets_read], bbuf+offset, num_readable * sizeof(loff_t)); 3.1137 -+ / sizeof(struct block_info)); 3.1138 -+ memcpy(&clo->offsets[offsets_read], bbuf+offset, num_readable * sizeof(struct block_info)); 3.1139 - offsets_read += num_readable; 3.1140 - } 3.1141 - { /* Search for largest block rather than estimate. KK. */ 3.1142 - int i; 3.1143 +- offsets_read += num_readable; 3.1144 +- } 3.1145 +- { /* Search for largest block rather than estimate. KK. */ 3.1146 +- int i; 3.1147 - for(i=0;i<total_offsets-1;i++) 3.1148 -+ char *version = build_index(clo->offsets, ntohl(clo->head.num_blocks)); 3.1149 -+ for(i=0,clo->largest_block=0;i<total_offsets;i++) 3.1150 ++ else 3.1151 ++ { 3.1152 ++ printk(KERN_ERR "%s: can't find index\n", cloop_name); 3.1153 ++ error=-ENOMEM; goto error_release; 3.1154 ++ } 3.1155 ++ } 3.1156 ++ else 3.1157 ++ { 3.1158 ++ unsigned int n, total_bytes; 3.1159 ++ flags = 0; 3.1160 ++ clo->block_ptrs = cloop_malloc(sizeof(struct block_info) * total_offsets); 3.1161 ++ if (!clo->block_ptrs) 3.1162 ++ { 3.1163 ++ printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name); 3.1164 ++ error=-ENOMEM; goto error_release; 3.1165 ++ } 3.1166 ++ /* Read them offsets! */ 3.1167 ++ if(clo->header_first) 3.1168 ++ { 3.1169 ++ total_bytes = total_offsets * sizeof(struct block_info); 3.1170 ++ fs_read_position = sizeof(struct cloop_head); 3.1171 ++ } 3.1172 ++ else 3.1173 { 3.1174 - loff_t d=be64_to_cpu(clo->offsets[i+1]) - be64_to_cpu(clo->offsets[i]); 3.1175 - clo->largest_block=MAX(clo->largest_block,d); 3.1176 -+ clo->largest_block=MAX(clo->largest_block,clo->offsets[i].size); 3.1177 ++ total_bytes = total_offsets * sizeof(loff_t); 3.1178 ++ fs_read_position = clo->underlying_total_size - sizeof(struct cloop_head) - total_bytes; 3.1179 ++ } 3.1180 ++ for(n=0;n<total_bytes;) 3.1181 ++ { 3.1182 ++ size_t bytes_readable; 3.1183 ++ bytes_readable = MIN(bbuf_size, clo->underlying_total_size - fs_read_position); 3.1184 ++ if(bytes_readable <= 0) break; /* Done */ 3.1185 ++ bytes_read = cloop_read_from_file(clo, file, bbuf, fs_read_position, bytes_readable); 3.1186 ++ if(bytes_read != bytes_readable) 3.1187 ++ { 3.1188 ++ printk(KERN_ERR "%s: Bad file %s, read() %lu bytes @ %llu returned %d.\n", 3.1189 ++ cloop_name, clo->underlying_filename, (unsigned long)clo->underlying_blksize, fs_read_position, (int)bytes_read); 3.1190 ++ error=-EBADF; 3.1191 ++ goto error_release; 3.1192 ++ } 3.1193 ++ memcpy(((char *)clo->block_ptrs) + n, bbuf, bytes_read); 3.1194 ++ /* remember where to read the next blk from file */ 3.1195 ++ fs_read_position += bytes_read; 3.1196 ++ n += bytes_read; 3.1197 } 3.1198 - printk(KERN_INFO "%s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n", 3.1199 - cloop_name, filename, ntohl(clo->head.num_blocks), 3.1200 -+ i = ntohl(clo->head.block_size); 3.1201 -+ i += i/1000 + 12 + 4; /* max gzip block size */ 3.1202 -+ if (clo->largest_block > i) clo->largest_block = i; /* broken index ? */ 3.1203 -+ printk(KERN_INFO "%s: %s: %s, %u blocks, %u bytes/block, largest block is %lu bytes.\n", 3.1204 -+ cloop_name, filename, version, ntohl(clo->head.num_blocks), 3.1205 - ntohl(clo->head.block_size), clo->largest_block); 3.1206 +- ntohl(clo->head.block_size), clo->largest_block); 3.1207 } 3.1208 - /* Combo kmalloc used too large chunks (>130000). */ 3.1209 -@@ -565,16 +618,6 @@ 3.1210 - error=-ENOMEM; goto error_release_free_all; 3.1211 +-/* Combo kmalloc used too large chunks (>130000). */ 3.1212 + { 3.1213 + int i; 3.1214 +- for(i=0;i<BUFFERED_BLOCKS;i++) 3.1215 +- { 3.1216 +- clo->buffer[i] = cloop_malloc(ntohl(clo->head.block_size)); 3.1217 +- if(!clo->buffer[i]) 3.1218 +- { 3.1219 +- printk(KERN_ERR "%s: out of memory for buffer %lu\n", 3.1220 +- cloop_name, (unsigned long) ntohl(clo->head.block_size)); 3.1221 +- error=-ENOMEM; goto error_release_free; 3.1222 +- } 3.1223 +- } 3.1224 ++ char *version = build_index(clo->block_ptrs, clo->head.num_blocks, clo->head.block_size, flags); 3.1225 ++ clo->largest_block = 0; 3.1226 ++ for (i = 0; i < clo->head.num_blocks; i++) 3.1227 ++ if (clo->block_ptrs[i].size > clo->largest_block) 3.1228 ++ clo->largest_block = clo->block_ptrs[i].size; 3.1229 ++ printk(KERN_INFO "%s: %s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n", 3.1230 ++ cloop_name, clo->underlying_filename, version, clo->head.num_blocks, 3.1231 ++ clo->head.block_size, clo->largest_block); 3.1232 ++ } 3.1233 ++ { 3.1234 ++ int i; 3.1235 ++ clo->num_buffered_blocks = (buffers > 0 && clo->head.block_size >= 512) ? 3.1236 ++ (buffers / clo->head.block_size) : 1; 3.1237 ++ clo->buffered_blocknum = cloop_malloc(clo->num_buffered_blocks * sizeof (u_int32_t)); 3.1238 ++ clo->buffer = cloop_malloc(clo->num_buffered_blocks * sizeof (char*)); 3.1239 ++ if (!clo->buffered_blocknum || !clo->buffer) 3.1240 ++ { 3.1241 ++ printk(KERN_ERR "%s: out of memory for index of cache buffer (%lu bytes)\n", 3.1242 ++ cloop_name, (unsigned long)clo->num_buffered_blocks * sizeof (u_int32_t) + sizeof(char*) ); 3.1243 ++ error=-ENOMEM; goto error_release; 3.1244 ++ } 3.1245 ++ memset(clo->buffer, 0, clo->num_buffered_blocks * sizeof (char*)); 3.1246 ++ for(i=0;i<clo->num_buffered_blocks;i++) 3.1247 ++ { 3.1248 ++ clo->buffered_blocknum[i] = -1; 3.1249 ++ clo->buffer[i] = cloop_malloc(clo->head.block_size); 3.1250 ++ if(!clo->buffer[i]) 3.1251 ++ { 3.1252 ++ printk(KERN_ERR "%s: out of memory for cache buffer %lu\n", 3.1253 ++ cloop_name, (unsigned long) clo->head.block_size); 3.1254 ++ error=-ENOMEM; goto error_release_free; 3.1255 ++ } 3.1256 ++ } 3.1257 ++ clo->current_bufnum = 0; 3.1258 + } 3.1259 + clo->compressed_buffer = cloop_malloc(clo->largest_block); 3.1260 + if(!clo->compressed_buffer) 3.1261 +@@ -557,31 +803,7 @@ 3.1262 + cloop_name, clo->largest_block); 3.1263 + error=-ENOMEM; goto error_release_free_buffer; 3.1264 } 3.1265 - zlib_inflateInit(&clo->zstream); 3.1266 +- clo->zstream.workspace = cloop_malloc(zlib_inflate_workspacesize()); 3.1267 +- if(!clo->zstream.workspace) 3.1268 +- { 3.1269 +- printk(KERN_ERR "%s: out of mem for zlib working area %u\n", 3.1270 +- cloop_name, zlib_inflate_workspacesize()); 3.1271 +- error=-ENOMEM; goto error_release_free_all; 3.1272 +- } 3.1273 +- zlib_inflateInit(&clo->zstream); 3.1274 - if(!isblkdev && 3.1275 - be64_to_cpu(clo->offsets[ntohl(clo->head.num_blocks)]) != inode->i_size) 3.1276 - { 3.1277 @@ -274,15 +1112,264 @@ 3.1278 - cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); clo->zstream.workspace=NULL; 3.1279 - goto error_release_free_all; 3.1280 - } 3.1281 +- { 3.1282 +- int i; 3.1283 +- for(i=0; i<BUFFERED_BLOCKS; i++) clo->buffered_blocknum[i] = -1; 3.1284 +- clo->current_bufnum=0; 3.1285 +- } 3.1286 +- set_capacity(clo->clo_disk, (sector_t)(ntohl(clo->head.num_blocks)* 3.1287 +- (ntohl(clo->head.block_size)>>9))); 3.1288 ++ set_capacity(clo->clo_disk, (sector_t)(clo->head.num_blocks*(clo->head.block_size>>9))); 3.1289 + clo->clo_thread = kthread_create(cloop_thread, clo, "cloop%d", cloop_num); 3.1290 + if(IS_ERR(clo->clo_thread)) 3.1291 + { 3.1292 +@@ -591,17 +813,17 @@ 3.1293 + } 3.1294 + if(preload > 0) 3.1295 + { 3.1296 +- clo->preload_array_size = ((preload<=ntohl(clo->head.num_blocks))?preload:ntohl(clo->head.num_blocks)); 3.1297 ++ clo->preload_array_size = ((preload<=clo->head.num_blocks)?preload:clo->head.num_blocks); 3.1298 + clo->preload_size = 0; 3.1299 + if((clo->preload_cache = cloop_malloc(clo->preload_array_size * sizeof(char *))) != NULL) 3.1300 + { 3.1301 + int i; 3.1302 + for(i=0; i<clo->preload_array_size; i++) 3.1303 + { 3.1304 +- if((clo->preload_cache[i] = cloop_malloc(ntohl(clo->head.block_size))) == NULL) 3.1305 ++ if((clo->preload_cache[i] = cloop_malloc(clo->head.block_size)) == NULL) 3.1306 + { /* Out of memory */ 3.1307 + printk(KERN_WARNING "%s: cloop_malloc(%d) failed for preload_cache[%d] (ignored).\n", 3.1308 +- cloop_name, ntohl(clo->head.block_size), i); 3.1309 ++ cloop_name, clo->head.block_size, i); 3.1310 + break; 3.1311 + } 3.1312 + } 3.1313 +@@ -612,13 +834,13 @@ 3.1314 + if(buffered_blocknum >= 0) 3.1315 + { 3.1316 + memcpy(clo->preload_cache[i], clo->buffer[buffered_blocknum], 3.1317 +- ntohl(clo->head.block_size)); 3.1318 ++ clo->head.block_size); 3.1319 + } 3.1320 + else 3.1321 + { 3.1322 + printk(KERN_WARNING "%s: can't read block %d into preload cache, set to zero.\n", 3.1323 + cloop_name, i); 3.1324 +- memset(clo->preload_cache[i], 0, ntohl(clo->head.block_size)); 3.1325 ++ memset(clo->preload_cache[i], 0, clo->head.block_size); 3.1326 + } 3.1327 + } 3.1328 + printk(KERN_INFO "%s: preloaded %d blocks into cache.\n", cloop_name, 3.1329 +@@ -641,22 +863,19 @@ 3.1330 + cloop_free(clo->compressed_buffer, clo->largest_block); 3.1331 + clo->compressed_buffer=NULL; 3.1332 + error_release_free_buffer: 3.1333 ++ if(clo->buffer) 3.1334 { 3.1335 int i; 3.1336 - for(i=0; i<BUFFERED_BLOCKS; i++) clo->buffered_blocknum[i] = -1; 3.1337 -@@ -653,7 +696,7 @@ 3.1338 - } 3.1339 +- for(i=0; i<BUFFERED_BLOCKS; i++) 3.1340 +- { 3.1341 +- if(clo->buffer[i]) 3.1342 +- { 3.1343 +- cloop_free(clo->buffer[i], ntohl(clo->head.block_size)); 3.1344 +- clo->buffer[i]=NULL; 3.1345 +- } 3.1346 +- } 3.1347 ++ for(i=0; i<clo->num_buffered_blocks; i++) { if(clo->buffer[i]) { cloop_free(clo->buffer[i], clo->head.block_size); clo->buffer[i]=NULL; }} 3.1348 ++ cloop_free(clo->buffer, clo->num_buffered_blocks*sizeof(char*)); clo->buffer=NULL; 3.1349 } 3.1350 ++ if (clo->buffered_blocknum) { cloop_free(clo->buffered_blocknum, sizeof(int)*clo->num_buffered_blocks); clo->buffered_blocknum=NULL; } 3.1351 error_release_free: 3.1352 - cloop_free(clo->offsets, sizeof(loff_t) * total_offsets); 3.1353 -+ cloop_free(clo->offsets, sizeof(struct block_info) * total_offsets); 3.1354 - clo->offsets=NULL; 3.1355 +- clo->offsets=NULL; 3.1356 ++ cloop_free(clo->block_ptrs, sizeof(struct block_info) * total_offsets); 3.1357 ++ clo->block_ptrs=NULL; 3.1358 error_release: 3.1359 if(bbuf) cloop_free(bbuf, clo->underlying_blksize); 3.1360 ++ if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; } 3.1361 + clo->backing_file=NULL; 3.1362 + return error; 3.1363 + } 3.1364 +@@ -673,7 +892,7 @@ 3.1365 + if(clo->backing_file) return -EBUSY; 3.1366 + file = fget(arg); /* get filp struct from ioctl arg fd */ 3.1367 + if(!file) return -EBADF; 3.1368 +- error=cloop_set_file(cloop_num,file,"losetup_file"); 3.1369 ++ error=cloop_set_file(cloop_num,file); 3.1370 + set_device_ro(bdev, 1); 3.1371 + if(error) fput(file); 3.1372 + return error; 3.1373 +@@ -684,29 +903,48 @@ 3.1374 + { 3.1375 + struct cloop_device *clo = cloop_dev[cloop_num]; 3.1376 + struct file *filp = clo->backing_file; 3.1377 +- int i; 3.1378 + if(clo->refcnt > 1) /* we needed one fd for the ioctl */ 3.1379 + return -EBUSY; 3.1380 + if(filp==NULL) return -EINVAL; 3.1381 + if(clo->clo_thread) { kthread_stop(clo->clo_thread); clo->clo_thread=NULL; } 3.1382 +- if(filp!=initial_file) fput(filp); 3.1383 +- else { filp_close(initial_file,0); initial_file=NULL; } 3.1384 ++ if(filp!=initial_file) 3.1385 ++ fput(filp); 3.1386 ++ else 3.1387 ++ { 3.1388 ++ filp_close(initial_file,0); 3.1389 ++ initial_file=NULL; 3.1390 ++ } 3.1391 + clo->backing_file = NULL; 3.1392 + clo->backing_inode = NULL; 3.1393 +- if(clo->offsets) { cloop_free(clo->offsets, clo->underlying_blksize); clo->offsets = NULL; } 3.1394 ++ if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; } 3.1395 ++ if(clo->block_ptrs) { cloop_free(clo->block_ptrs, clo->head.num_blocks); clo->block_ptrs = NULL; } 3.1396 + if(clo->preload_cache) 3.1397 +- { 3.1398 +- for(i=0; i < clo->preload_size; i++) 3.1399 +- cloop_free(clo->preload_cache[i], ntohl(clo->head.block_size)); 3.1400 +- cloop_free(clo->preload_cache, clo->preload_array_size * sizeof(char *)); 3.1401 +- clo->preload_cache = NULL; 3.1402 +- clo->preload_size = clo->preload_array_size = 0; 3.1403 +- } 3.1404 +- for(i=0; i<BUFFERED_BLOCKS; i++) 3.1405 +- if(clo->buffer[i]) { cloop_free(clo->buffer[i], ntohl(clo->head.block_size)); clo->buffer[i]=NULL; } 3.1406 ++ { 3.1407 ++ int i; 3.1408 ++ for(i=0; i < clo->preload_size; i++) 3.1409 ++ cloop_free(clo->preload_cache[i], clo->head.block_size); 3.1410 ++ cloop_free(clo->preload_cache, clo->preload_array_size * sizeof(char *)); 3.1411 ++ clo->preload_cache = NULL; 3.1412 ++ clo->preload_size = clo->preload_array_size = 0; 3.1413 ++ } 3.1414 ++ if (clo->buffered_blocknum) 3.1415 ++ { 3.1416 ++ cloop_free(clo->buffered_blocknum, sizeof(int) * clo->num_buffered_blocks); clo->buffered_blocknum = NULL; 3.1417 ++ } 3.1418 ++ if (clo->buffer) 3.1419 ++ { 3.1420 ++ int i; 3.1421 ++ for(i=0; i<clo->num_buffered_blocks; i++) { if(clo->buffer[i]) cloop_free(clo->buffer[i], clo->head.block_size); } 3.1422 ++ cloop_free(clo->buffer, sizeof(char*) * clo->num_buffered_blocks); clo->buffer = NULL; 3.1423 ++ } 3.1424 + if(clo->compressed_buffer) { cloop_free(clo->compressed_buffer, clo->largest_block); clo->compressed_buffer = NULL; } 3.1425 ++#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 3.1426 + zlib_inflateEnd(&clo->zstream); 3.1427 + if(clo->zstream.workspace) { cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); clo->zstream.workspace = NULL; } 3.1428 ++#endif 3.1429 ++#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 3.1430 ++ xz_dec_end(clo->xzdecoderstate); 3.1431 ++#endif 3.1432 + if(bdev) invalidate_bdev(bdev); 3.1433 + if(clo->clo_disk) set_capacity(clo->clo_disk, 0); 3.1434 + return 0; 3.1435 +@@ -731,8 +969,8 @@ 3.1436 + const struct loop_info64 *info) 3.1437 + { 3.1438 + if (!clo->backing_file) return -ENXIO; 3.1439 +- memcpy(clo->clo_file_name, info->lo_file_name, LO_NAME_SIZE); 3.1440 +- clo->clo_file_name[LO_NAME_SIZE-1] = 0; 3.1441 ++ if(clo->underlying_filename) kfree(clo->underlying_filename); 3.1442 ++ clo->underlying_filename = kstrdup(info->lo_file_name, GFP_KERNEL); 3.1443 + return 0; 3.1444 + } 3.1445 + 3.1446 +@@ -743,7 +981,11 @@ 3.1447 + struct kstat stat; 3.1448 + int err; 3.1449 + if (!file) return -ENXIO; 3.1450 +- err = vfs_getattr(file->f_path.mnt, file->f_path.dentry, &stat); 3.1451 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) 3.1452 ++ err = vfs_getattr(&file->f_path, &stat); 3.1453 ++#else 3.1454 ++ err = vfs_getattr(&file->f_path, &stat, STATX_INO, AT_STATX_SYNC_AS_STAT); 3.1455 ++#endif 3.1456 + if (err) return err; 3.1457 + memset(info, 0, sizeof(*info)); 3.1458 + info->lo_number = clo->clo_number; 3.1459 +@@ -753,7 +995,8 @@ 3.1460 + info->lo_offset = 0; 3.1461 + info->lo_sizelimit = 0; 3.1462 + info->lo_flags = 0; 3.1463 +- memcpy(info->lo_file_name, clo->clo_file_name, LO_NAME_SIZE); 3.1464 ++ strncpy(info->lo_file_name, clo->underlying_filename, LO_NAME_SIZE); 3.1465 ++ info->lo_file_name[LO_NAME_SIZE-1]=0; 3.1466 + return 0; 3.1467 + } 3.1468 + 3.1469 +@@ -833,8 +1076,6 @@ 3.1470 + if (!err && copy_to_user(arg, &info64, sizeof(info64))) err = -EFAULT; 3.1471 + return err; 3.1472 + } 3.1473 +-/* EOF get/set_status */ 3.1474 +- 3.1475 + 3.1476 + static int cloop_ioctl(struct block_device *bdev, fmode_t mode, 3.1477 + unsigned int cmd, unsigned long arg) 3.1478 +@@ -914,21 +1155,20 @@ 3.1479 + /* losetup uses write-open and flags=0x8002 to set a new file */ 3.1480 + if(mode & FMODE_WRITE) 3.1481 + { 3.1482 +- printk(KERN_WARNING "%s: Can't open device read-write in mode 0x%x\n", cloop_name, mode); 3.1483 ++ printk(KERN_INFO "%s: Open in read-write mode 0x%x requested, ignored.\n", cloop_name, mode); 3.1484 + return -EROFS; 3.1485 + } 3.1486 + cloop_dev[cloop_num]->refcnt+=1; 3.1487 + return 0; 3.1488 + } 3.1489 + 3.1490 +-static int cloop_close(struct gendisk *disk, fmode_t mode) 3.1491 ++static void cloop_close(struct gendisk *disk, fmode_t mode) 3.1492 + { 3.1493 +- int cloop_num, err=0; 3.1494 +- if(!disk) return 0; 3.1495 ++ int cloop_num; 3.1496 ++ if(!disk) return; 3.1497 + cloop_num=((struct cloop_device *)disk->private_data)->clo_number; 3.1498 +- if(cloop_num < 0 || cloop_num > (cloop_count-1)) return 0; 3.1499 ++ if(cloop_num < 0 || cloop_num > (cloop_count-1)) return; 3.1500 + cloop_dev[cloop_num]->refcnt-=1; 3.1501 +- return err; 3.1502 + } 3.1503 + 3.1504 + static struct block_device_operations clo_fops = 3.1505 +@@ -973,6 +1213,10 @@ 3.1506 + goto error_out; 3.1507 + } 3.1508 + clo->clo_queue->queuedata = clo; 3.1509 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) 3.1510 ++ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, clo->clo_queue); 3.1511 ++ queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, clo->clo_queue); 3.1512 ++#endif 3.1513 + clo->clo_disk = alloc_disk(1); 3.1514 + if(!clo->clo_disk) 3.1515 + { 3.1516 +@@ -1004,6 +1248,11 @@ 3.1517 + cloop_dev[cloop_num] = NULL; 3.1518 + } 3.1519 + 3.1520 ++/* LZ4 Stuff */ 3.1521 ++#if (defined USE_LZ4_INTERNAL) 3.1522 ++#include "lz4_kmod.c" 3.1523 ++#endif 3.1524 ++ 3.1525 + static int __init cloop_init(void) 3.1526 + { 3.1527 + int error=0; 3.1528 +@@ -1044,7 +1293,7 @@ 3.1529 + initial_file=NULL; /* if IS_ERR, it's NOT open. */ 3.1530 + } 3.1531 + else 3.1532 +- error=cloop_set_file(0,initial_file,file); 3.1533 ++ error=cloop_set_file(0,initial_file); 3.1534 + if(error) 3.1535 + { 3.1536 + printk(KERN_ERR 3.1537 +@@ -1052,9 +1301,6 @@ 3.1538 + cloop_name, file, error); 3.1539 + goto init_out_dealloc; 3.1540 + } 3.1541 +- if(namelen >= LO_NAME_SIZE) namelen = LO_NAME_SIZE-1; 3.1542 +- memcpy(cloop_dev[0]->clo_file_name, file, namelen); 3.1543 +- cloop_dev[0]->clo_file_name[namelen] = 0; 3.1544 + } 3.1545 + return 0; 3.1546 + init_out_dealloc:
4.1 --- a/linux64-cloop/receipt Mon May 04 07:56:50 2020 +0100 4.2 +++ b/linux64-cloop/receipt Mon May 04 09:05:12 2020 +0000 4.3 @@ -2,13 +2,15 @@ 4.4 4.5 PACKAGE="linux64-cloop" 4.6 SOURCE="cloop" 4.7 -VERSION="2.639-2" 4.8 +_VERSION="2.639-2" 4.9 +#VERSION="$(sed '/+#define CLOOP_VERSION/!d;s|.* "\(.*\)"|\1|' stuff/cloop.u)" 4.10 +VERSION="4.12" 4.11 CATEGORY="base-system" 4.12 MAINTAINER="pascal.bellard@slitaz.org" 4.13 LICENSE="GPL2" 4.14 SHORT_DESC="The read-only compressed loop device kernel module." 4.15 WEB_SITE="http://knoppix.net/wiki/Cloop" 4.16 -TARBALL="${SOURCE}_${VERSION}.tar.gz" 4.17 +TARBALL="${SOURCE}_${_VERSION}.tar.gz" 4.18 WGET_URL="http://debian-knoppix.alioth.debian.org/packages/$SOURCE/$TARBALL" 4.19 PROVIDE="linux-cloop:linux64" 4.20 4.21 @@ -22,9 +24,7 @@ 4.22 4.23 compile_rules() 4.24 { 4.25 - patch -p0 < $stuff/cloop.u # 3.2.98 4.26 - sed -i -e 's|file->f_path.mnt, file->f_path.dentry|\&file->f_path|' \ 4.27 - -e 's|bvec->|bvec.|g;s|*bvec|bvec|' cloop.c 4.28 + patch -p0 < $stuff/cloop.u 4.29 make KERNEL_DIR="/usr/src/linux" cloop.ko && xz cloop.ko 4.30 } 4.31
5.1 --- a/linux64-cloop/stuff/cloop.u Mon May 04 07:56:50 2020 +0100 5.2 +++ b/linux64-cloop/stuff/cloop.u Mon May 04 09:05:12 2020 +0000 5.3 @@ -1,80 +1,221 @@ 5.4 --- cloop.h 5.5 +++ cloop.h 5.6 -@@ -20,6 +20,80 @@ 5.7 +@@ -1,15 +1,50 @@ 5.8 ++#define CLOOP_SIGNATURE "#!/bin/sh" /* @ offset 0 */ 5.9 ++#define CLOOP_SIGNATURE_SIZE 9 5.10 ++#define CLOOP_SIGNATURE_OFFSET 0x0 5.11 ++ 5.12 + #ifndef _COMPRESSED_LOOP_H 5.13 + #define _COMPRESSED_LOOP_H 5.14 + 5.15 +-#define CLOOP_HEADROOM 128 5.16 ++/*************************************************************************\ 5.17 ++* Starting with Format V4.0 (cloop version 4.x), cloop can now have two * 5.18 ++* alternative structures: * 5.19 ++* * 5.20 ++* 1. Header first: "robust" format, handles missing blocks well * 5.21 ++* 2. Footer (header last): "streaming" format, easier to create * 5.22 ++* * 5.23 ++* The cloop kernel module autodetects both formats, and can (currently) * 5.24 ++* still handle the V2.0 format as well. * 5.25 ++* * 5.26 ++* 1. Header first: * 5.27 ++* +---------------------------- FIXED SIZE ---------------------------+ * 5.28 ++* |Signature (128 bytes) | * 5.29 ++* |block_size (32bit number, network order) | * 5.30 ++* |num_blocks (32bit number, network order) | * 5.31 ++* +--------------------------- VARIABLE SIZE -------------------------+ * 5.32 ++* |num_blocks * FlagsOffset (upper 4 bits flags, lower 64 bits offset)| * 5.33 ++* |compressed data blocks of variable size ... | * 5.34 ++* +-------------------------------------------------------------------+ * 5.35 ++* * 5.36 ++* 2. Footer (header last): * 5.37 ++* +--------------------------- VARIABLE SIZE -------------------------+ * 5.38 ++* |compressed data blocks of variable size ... | * 5.39 ++* |num_blocks * FlagsOffset (upper 4 bits flags, lower 64 bits offset)| * 5.40 ++* +---------------------------- FIXED SIZE ---------------------------+ * 5.41 ++* |Signature (128 bytes) | * 5.42 ++* |block_size (32bit number, network order) | * 5.43 ++* |num_blocks (32bit number, network order) | * 5.44 ++* +-------------------------------------------------------------------+ * 5.45 ++* * 5.46 ++* Offsets are always relative to beginning of file, in all formats. * 5.47 ++* The block index contains num_blocks+1 offsets, followed (1) or * 5.48 ++* preceded (2) by the compressed blocks. * 5.49 ++\*************************************************************************/ 5.50 + 5.51 +-/* The cloop header usually looks like this: */ 5.52 +-/* #!/bin/sh */ 5.53 +-/* #V2.00 Format */ 5.54 +-/* ...padding up to CLOOP_HEADROOM... */ 5.55 +-/* block_size (32bit number, network order) */ 5.56 +-/* num_blocks (32bit number, network order) */ 5.57 ++#include <linux/types.h> /* u_int32_t */ 5.58 ++ 5.59 ++#define CLOOP_HEADROOM 128 5.60 + 5.61 ++/* Header of fixed length, can be located at beginning or end of file */ 5.62 + struct cloop_head 5.63 + { 5.64 + char preamble[CLOOP_HEADROOM]; 5.65 +@@ -17,9 +52,163 @@ 5.66 + u_int32_t num_blocks; 5.67 + }; 5.68 + 5.69 ++/************************************************************************\ 5.70 ++* CLOOP4 flags for each compressed block * 5.71 ++* Value Meaning * 5.72 ++* 0 GZIP/7ZIP compression (compatible with V2.0 Format) * 5.73 ++* 1 no compression (incompressible data) * 5.74 ++* 2 xz compression (currently best space saver) * 5.75 ++* 3 lz4 compression * 5.76 ++* 4 lzo compression (fastest) * 5.77 ++\************************************************************************/ 5.78 ++ 5.79 ++typedef uint64_t cloop_block_ptr; 5.80 ++ 5.81 ++/* Get value of first 4 bits */ 5.82 ++#define CLOOP_BLOCK_FLAGS(x) ((unsigned int)(((x) & 0xf000000000000000LLU) >> 60)) 5.83 ++/* Get value of last 60 bits */ 5.84 ++#define CLOOP_BLOCK_OFFSET(x) ((x) & 0x0fffffffffffffffLLU) 5.85 ++ 5.86 ++#define CLOOP_COMPRESSOR_ZLIB 0x0 5.87 ++#define CLOOP_COMPRESSOR_NONE 0x1 5.88 ++#define CLOOP_COMPRESSOR_XZ 0x2 5.89 ++#define CLOOP_COMPRESSOR_LZ4 0x3 5.90 ++#define CLOOP_COMPRESSOR_LZO1X 0x4 5.91 ++ 5.92 ++#define CLOOP_COMPRESSOR_VALID(x) ((x) >= CLOOP_COMPRESSOR_ZLIB && (x) <= CLOOP_COMPRESSOR_LZO1X) 5.93 ++ 5.94 ++#define CLOOP_COMPRESSOR_LINK 0xF 5.95 ++ 5.96 ++ 5.97 /* data_index (num_blocks 64bit pointers, network order)... */ 5.98 /* compressed data (gzip block compressed format)... */ 5.99 5.100 +struct cloop_tail 5.101 +{ 5.102 -+ u_int32_t table_size; 5.103 -+ u_int32_t index_size; 5.104 ++ u_int32_t table_size; 5.105 ++ u_int32_t index_size; /* size:4 comp:3 ctrl-c:1 lastlen:24 */ 5.106 ++#define CLOOP3_INDEX_SIZE(x) ((unsigned int)((x) & 0xF)) 5.107 ++#define CLOOP3_BLOCKS_FLAGS(x) ((unsigned int)((x) & 0x70) >> 4) 5.108 ++#define CLOOP3_TRUNCATED(x) ((unsigned int)((x) & 0x80) >> 7) 5.109 ++#define CLOOP3_LASTLEN(x) (unsigned int)((x) >> 8) 5.110 + u_int32_t num_blocks; 5.111 +}; 5.112 + 5.113 ++#define GZIP_MAX_BUFFER(n) ((n) + (n)/1000 + 12) 5.114 ++ 5.115 +struct block_info 5.116 +{ 5.117 + loff_t offset; /* 64-bit offsets of compressed block */ 5.118 + u_int32_t size; /* 32-bit compressed block size */ 5.119 -+ u_int32_t optidx; /* 32-bit index number */ 5.120 ++ u_int32_t flags; /* 32-bit compression flags */ 5.121 +}; 5.122 + 5.123 -+static inline char *build_index(struct block_info *offsets, unsigned long n) 5.124 ++static inline char *build_index(struct block_info *offsets, unsigned long n, 5.125 ++ unsigned long block_size, unsigned global_flags) 5.126 +{ 5.127 + u_int32_t *ofs32 = (u_int32_t *) offsets; 5.128 + loff_t *ofs64 = (loff_t *) offsets; 5.129 -+ 5.130 ++ 5.131 ++ /* v3 64bits bug: v1 assumed */ 5.132 ++ unsigned long v3_64 = (n+1)/2; 5.133 ++ loff_t prev; 5.134 ++ 5.135 ++ if (ofs32[0] != 0 && ofs32[1] == 0) { 5.136 ++ for (prev=__le64_to_cpu(ofs64[v3_64]); 5.137 ++ v3_64 > 0 && __le64_to_cpu(ofs64[--v3_64]) < prev; 5.138 ++ prev=__le64_to_cpu(ofs64[v3_64])); 5.139 ++ } 5.140 ++ 5.141 + if (ofs32[0] == 0) { 5.142 + if (ofs32[2]) { /* ACCELERATED KNOPPIX V1.0 */ 5.143 + while (n--) { 5.144 + offsets[n].offset = __be64_to_cpu(offsets[n].offset); 5.145 + offsets[n].size = ntohl(offsets[n].size); 5.146 ++ offsets[n].flags = 0; 5.147 + } 5.148 + return (char *) "128BE accelerated knoppix 1.0"; 5.149 + } 5.150 -+ else { /* V2.0 */ 5.151 -+ loff_t last = __be64_to_cpu(ofs64[n - 1]); 5.152 -+ while (n--) { 5.153 ++ else { /* V2.0/V4.0 */ 5.154 ++ loff_t last = CLOOP_BLOCK_OFFSET(__be64_to_cpu(ofs64[n])); 5.155 ++ u_int32_t flags; 5.156 ++ static char v4[11]; 5.157 ++ unsigned long i = n; 5.158 ++ 5.159 ++ for (flags = 0; n-- ;) { 5.160 ++ loff_t data = __be64_to_cpu(ofs64[n]); 5.161 ++ 5.162 + offsets[n].size = last - 5.163 -+ (offsets[n].offset = __be64_to_cpu(ofs64[n])); 5.164 ++ (offsets[n].offset = CLOOP_BLOCK_OFFSET(data)); 5.165 + last = offsets[n].offset; 5.166 ++ offsets[n].flags = CLOOP_BLOCK_FLAGS(data); 5.167 ++ flags |= 1 << offsets[n].flags; 5.168 + } 5.169 -+ return (char *) "64BE v2.0"; 5.170 ++ if (flags < 2) return (char *) "64BE v2.0"; 5.171 ++ while (i--) { 5.172 ++ if (offsets[i].flags == CLOOP_COMPRESSOR_LINK) { 5.173 ++ offsets[i] = offsets[offsets[i].offset]; 5.174 ++ } 5.175 ++ } 5.176 ++ strcpy(v4, (char *) "64BE v4.0a"); 5.177 ++ v4[10] = 'a' + ((flags-1) & 0xF); // compressors used 5.178 ++ if (flags > 0x10) { // with links ? 5.179 ++ v4[10] += 'A' - 'a'; 5.180 ++ } 5.181 ++ return v4; 5.182 + } 5.183 + } 5.184 -+ else if (ofs32[1] == 0) { /* V1.0 */ 5.185 -+ loff_t last = __le64_to_cpu(ofs64[n - 1]); 5.186 ++ else if (ofs32[1] == 0 && v3_64 == 0) { /* V1.0 */ 5.187 ++ loff_t last = __le64_to_cpu(ofs64[n]); 5.188 + while (n--) { 5.189 + offsets[n].size = last - 5.190 + (offsets[n].offset = __le64_to_cpu(ofs64[n])); 5.191 + last = offsets[n].offset; 5.192 ++ offsets[n].flags = 0; 5.193 + } 5.194 + return (char *) "64LE v1.0"; 5.195 + } 5.196 -+ else if (ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */ 5.197 -+ loff_t last = ntohl(ofs32[n - 1]); 5.198 -+ while (n--) { 5.199 -+ offsets[n].size = last - 5.200 -+ (offsets[n].offset = ntohl(ofs32[n])); 5.201 -+ last = offsets[n].offset; 5.202 -+ } 5.203 -+ return (char *) "32BE v0.68"; 5.204 -+ } 5.205 -+ else { /* V3.0 */ 5.206 ++ else { /* V3.0 or V0.68 */ 5.207 + unsigned long i; 5.208 + loff_t j; 5.209 ++ static char v3[11]; 5.210 + 5.211 ++ for (i = 0; i < n && ntohl(ofs32[i]) < ntohl(ofs32[i+1]); i++); 5.212 ++ if (i == n && ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */ 5.213 ++ loff_t last = ntohl(ofs32[n]); 5.214 ++ while (n--) { 5.215 ++ offsets[n].size = last - 5.216 ++ (offsets[n].offset = ntohl(ofs32[n])); 5.217 ++ last = offsets[n].offset; 5.218 ++ offsets[n].flags = 0; 5.219 ++ } 5.220 ++ return (char *) "32BE v0.68"; 5.221 ++ } 5.222 ++ 5.223 ++ v3_64 = (ofs32[1] == 0); 5.224 + for (i = n; i-- != 0; ) 5.225 -+ offsets[i].size = ntohl(ofs32[i]); 5.226 ++ offsets[i].size = ntohl(ofs32[i << v3_64]); 5.227 + for (i = 0, j = sizeof(struct cloop_head); i < n; i++) { 5.228 + offsets[i].offset = j; 5.229 ++ offsets[i].flags = global_flags; 5.230 ++ if (offsets[i].size == 0xFFFFFFFF) { 5.231 ++ offsets[i].flags = CLOOP_COMPRESSOR_NONE; 5.232 ++ offsets[i].size = block_size; 5.233 ++ } 5.234 ++ if ((offsets[i].size & 0x80000000) == 0) { 5.235 ++ j += offsets[i].size; 5.236 ++ } 5.237 ++ } 5.238 ++ for (i = 0; i < n; i++) { 5.239 + if (offsets[i].size & 0x80000000) { 5.240 -+ unsigned long k = offsets[i].size & 0x7FFFFFFF; 5.241 -+ offsets[i].offset = offsets[k].offset; 5.242 -+ offsets[i].size = offsets[k].size; 5.243 ++ offsets[i] = offsets[offsets[i].size & 0x7FFFFFFF]; 5.244 + } 5.245 -+ else j += offsets[i].size; 5.246 + } 5.247 -+ return (char *) "32BE v3.0"; 5.248 ++ strcpy(v3, (char *) (v3_64) ? "64BE v3.0a" : "32BE v3.0a"); 5.249 ++ v3[10] += global_flags; 5.250 ++ return v3; 5.251 + } 5.252 +} 5.253 + 5.254 @@ -83,187 +224,884 @@ 5.255 5.256 --- cloop.c 5.257 +++ cloop.c 5.258 -@@ -5,11 +5,18 @@ 5.259 - * A cloop file looks like this: 5.260 - * [32-bit uncompressed block size: network order] 5.261 - * [32-bit number of blocks (n_blocks): network order] 5.262 +@@ -1,26 +1,23 @@ 5.263 +-/* 5.264 +- * compressed_loop.c: Read-only compressed loop blockdevice 5.265 +- * hacked up by Rusty in 1999, extended and maintained by Klaus Knopper 5.266 +- * 5.267 +- * A cloop file looks like this: 5.268 +- * [32-bit uncompressed block size: network order] 5.269 +- * [32-bit number of blocks (n_blocks): network order] 5.270 - * [64-bit file offsets of start of blocks: network order] 5.271 -+ * [for version < 3] 5.272 -+ * [32-bit, 64-bit or 128-bit file offsets of start of blocks] 5.273 - * ... 5.274 - * (n_blocks + 1). 5.275 - * n_blocks consisting of: 5.276 - * [compressed block] 5.277 -+ * ... 5.278 -+ * [for version >= 3] 5.279 -+ * [compressed list of 32-bit block sizes] 5.280 -+ * [32-bit compressed index size: network order] 5.281 -+ * [32-bit index size = 4: network order] 5.282 -+ * [32-bit number of blocks (n_blocks): network order] 5.283 - * 5.284 - * Every version greatly inspired by code seen in loop.c 5.285 - * by Theodore Ts'o, 3/29/93. 5.286 -@@ -115,7 +122,7 @@ 5.287 +- * ... 5.288 +- * (n_blocks + 1). 5.289 +- * n_blocks consisting of: 5.290 +- * [compressed block] 5.291 +- * 5.292 +- * Every version greatly inspired by code seen in loop.c 5.293 +- * by Theodore Ts'o, 3/29/93. 5.294 +- * 5.295 +- * Copyright 1999-2009 by Paul `Rusty' Russell & Klaus Knopper. 5.296 +- * Redistribution of this file is permitted under the GNU Public License. 5.297 +- * 5.298 +- */ 5.299 ++/************************************************************************\ 5.300 ++* cloop.c: Read-only compressed loop blockdevice * 5.301 ++* hacked up by Rusty in 1999, extended and maintained by Klaus Knopper * 5.302 ++* * 5.303 ++* For all supported cloop file formats, please check the file "cloop.h" * 5.304 ++* New in Version 4: * 5.305 ++* - Header can be first or last in cloop file, * 5.306 ++* - Different compression algorithms supported (compression type * 5.307 ++* encoded in first 4 bytes of block offset address) * 5.308 ++* * 5.309 ++* Every version greatly inspired by code seen in loop.c * 5.310 ++* by Theodore Ts'o, 3/29/93. * 5.311 ++* * 5.312 ++* Copyright 1999-2009 by Paul `Rusty' Russell & Klaus Knopper. * 5.313 ++* Redistribution of this file is permitted under the GNU Public License * 5.314 ++* V2. * 5.315 ++\************************************************************************/ 5.316 + 5.317 + #define CLOOP_NAME "cloop" 5.318 +-#define CLOOP_VERSION "2.639" 5.319 ++#define CLOOP_VERSION "4.12" 5.320 + #define CLOOP_MAX 8 5.321 + 5.322 + #ifndef KBUILD_MODNAME 5.323 +@@ -47,8 +44,27 @@ 5.324 + #include <asm/div64.h> /* do_div() for 64bit division */ 5.325 + #include <asm/uaccess.h> 5.326 + #include <asm/byteorder.h> 5.327 +-/* Use zlib_inflate from lib/zlib_inflate */ 5.328 ++/* Check for ZLIB, LZO1X, LZ4 decompression algorithms in kernel. */ 5.329 ++#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 5.330 + #include <linux/zutil.h> 5.331 ++#endif 5.332 ++#if (defined(CONFIG_LZO_DECOMPRESS) || defined(CONFIG_LZO_DECOMPRESS_MODULE)) 5.333 ++#include <linux/lzo.h> 5.334 ++#endif 5.335 ++#if (defined(CONFIG_DECOMPRESS_LZ4) || defined(CONFIG_DECOMPRESS_LZ4_MODULE)) 5.336 ++#include <linux/lz4.h> 5.337 ++#endif 5.338 ++#if (defined(CONFIG_DECOMPRESS_LZMA) || defined(CONFIG_DECOMPRESS_LZMA_MODULE)) 5.339 ++#include <linux/decompress/unlzma.h> 5.340 ++#endif 5.341 ++#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 5.342 ++#include <linux/xz.h> 5.343 ++#endif 5.344 ++ 5.345 ++#if (!(defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE) || defined(CONFIG_LZO_DECOMPRESS) || defined(CONFIG_LZO_DECOMPRESS_MODULE) || defined(CONFIG_DECOMPRESS_LZ4) || defined(CONFIG_DECOMPRESS_LZ4_MODULE) || defined(CONFIG_DECOMPRESS_LZMA) || defined(CONFIG_DECOMPRESS_LZMA_MODULE) || defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE))) 5.346 ++#error "No decompression library selected in kernel config!" 5.347 ++#endif 5.348 ++ 5.349 + #include <linux/loop.h> 5.350 + #include <linux/kthread.h> 5.351 + #include <linux/compat.h> 5.352 +@@ -92,47 +108,64 @@ 5.353 + #define DEBUGP(format, x...) 5.354 + #endif 5.355 + 5.356 ++/* Default size of buffer to keep some decompressed blocks in memory to speed up access */ 5.357 ++#define BLOCK_BUFFER_MEM (16*65536) 5.358 ++ 5.359 + /* One file can be opened at module insertion time */ 5.360 + /* insmod cloop file=/path/to/file */ 5.361 + static char *file=NULL; 5.362 + static unsigned int preload=0; 5.363 + static unsigned int cloop_max=CLOOP_MAX; 5.364 ++static unsigned int buffers=BLOCK_BUFFER_MEM; 5.365 + module_param(file, charp, 0); 5.366 + module_param(preload, uint, 0); 5.367 + module_param(cloop_max, uint, 0); 5.368 + MODULE_PARM_DESC(file, "Initial cloop image file (full path) for /dev/cloop"); 5.369 + MODULE_PARM_DESC(preload, "Preload n blocks of cloop data into memory"); 5.370 + MODULE_PARM_DESC(cloop_max, "Maximum number of cloop devices (default 8)"); 5.371 ++MODULE_PARM_DESC(buffers, "Size of buffer to keep uncompressed blocks in memory in MiB (default 1)"); 5.372 + 5.373 + static struct file *initial_file=NULL; 5.374 + static int cloop_major=MAJOR_NR; 5.375 + 5.376 +-/* Number of buffered decompressed blocks */ 5.377 +-#define BUFFERED_BLOCKS 8 5.378 + struct cloop_device 5.379 + { 5.380 +- /* Copied straight from the file */ 5.381 ++ /* Header filled from the file */ 5.382 struct cloop_head head; 5.383 ++ int header_first; 5.384 ++ int file_format; 5.385 5.386 - /* An array of offsets of compressed blocks within the file */ 5.387 +- /* An array of offsets of compressed blocks within the file */ 5.388 - loff_t *offsets; 5.389 -+ struct block_info *offsets; 5.390 ++ /* An or'd sum of all flags of each compressed block (v3) */ 5.391 ++ u_int32_t allflags; 5.392 ++ 5.393 ++ /* An array of cloop_ptr flags/offset for compressed blocks within the file */ 5.394 ++ struct block_info *block_ptrs; 5.395 5.396 /* We buffer some uncompressed blocks for performance */ 5.397 - int buffered_blocknum[BUFFERED_BLOCKS]; 5.398 -@@ -256,11 +263,11 @@ 5.399 - return i; 5.400 - } 5.401 +- int buffered_blocknum[BUFFERED_BLOCKS]; 5.402 +- int current_bufnum; 5.403 +- void *buffer[BUFFERED_BLOCKS]; 5.404 +- void *compressed_buffer; 5.405 +- size_t preload_array_size; /* Size of pointer array in blocks */ 5.406 +- size_t preload_size; /* Number of successfully allocated blocks */ 5.407 +- char **preload_cache; /* Pointers to preloaded blocks */ 5.408 ++ size_t num_buffered_blocks; /* how many uncompressed blocks buffered for performance */ 5.409 ++ int *buffered_blocknum; /* list of numbers of uncompressed blocks in buffer */ 5.410 ++ int current_bufnum; /* which block is current */ 5.411 ++ unsigned char **buffer; /* cache space for num_buffered_blocks uncompressed blocks */ 5.412 ++ void *compressed_buffer; /* space for the largest compressed block */ 5.413 ++ size_t preload_array_size; /* Size of pointer array in blocks */ 5.414 ++ size_t preload_size; /* Number of successfully allocated blocks */ 5.415 ++ char **preload_cache; /* Pointers to preloaded blocks */ 5.416 5.417 ++#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 5.418 + z_stream zstream; 5.419 ++#endif 5.420 ++#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 5.421 ++ struct xz_dec *xzdecoderstate; 5.422 ++ struct xz_buf xz_buffer; 5.423 ++#endif 5.424 + 5.425 + struct file *backing_file; /* associated file */ 5.426 + struct inode *backing_inode; /* for bmap */ 5.427 + 5.428 ++ unsigned char *underlying_filename; 5.429 + unsigned long largest_block; 5.430 + unsigned int underlying_blksize; 5.431 ++ loff_t underlying_total_size; 5.432 + int clo_number; 5.433 + int refcnt; 5.434 + struct block_device *bdev; 5.435 +@@ -147,7 +180,6 @@ 5.436 + struct request_queue *clo_queue; 5.437 + struct gendisk *clo_disk; 5.438 + int suspended; 5.439 +- char clo_file_name[LO_NAME_SIZE]; 5.440 + }; 5.441 + 5.442 + /* Changed in 2.639: cloop_dev is now a an array of cloop_dev pointers, 5.443 +@@ -156,52 +188,113 @@ 5.444 + static const char *cloop_name=CLOOP_NAME; 5.445 + static int cloop_count = 0; 5.446 + 5.447 +-#if (!(defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE))) /* Must be compiled into kernel. */ 5.448 +-#error "Invalid Kernel configuration. CONFIG_ZLIB_INFLATE support is needed for cloop." 5.449 +-#endif 5.450 +- 5.451 +-/* Use __get_free_pages instead of vmalloc, allows up to 32 pages, 5.452 +- * 2MB in one piece */ 5.453 + static void *cloop_malloc(size_t size) 5.454 + { 5.455 +- int order = get_order(size); 5.456 +- if(order <= KMALLOC_MAX_ORDER) 5.457 +- return (void *)kmalloc(size, GFP_KERNEL); 5.458 +- else if(order < MAX_ORDER) 5.459 +- return (void *)__get_free_pages(GFP_KERNEL, order); 5.460 ++ /* kmalloc will fail after the system is running for a while, */ 5.461 ++ /* when large orders can't return contiguous memory. */ 5.462 ++ /* Let's just use vmalloc for now. :-/ */ 5.463 ++ /* int order = get_order(size); */ 5.464 ++ /* if(order <= KMALLOC_MAX_ORDER) */ 5.465 ++ /* return (void *)kmalloc(size, GFP_KERNEL); */ 5.466 ++ /* else if(order < MAX_ORDER) */ 5.467 ++ /* return (void *)__get_free_pages(GFP_KERNEL, order); */ 5.468 + return (void *)vmalloc(size); 5.469 + } 5.470 + 5.471 + static void cloop_free(void *mem, size_t size) 5.472 + { 5.473 +- int order = get_order(size); 5.474 +- if(order <= KMALLOC_MAX_ORDER) 5.475 +- kfree(mem); 5.476 +- else if(order < MAX_ORDER) 5.477 +- free_pages((unsigned long)mem, order); 5.478 +- else vfree(mem); 5.479 ++ /* int order = get_order(size); */ 5.480 ++ /* if(order <= KMALLOC_MAX_ORDER) */ 5.481 ++ /* kfree(mem); */ 5.482 ++ /* else if(order < MAX_ORDER) */ 5.483 ++ /* free_pages((unsigned long)mem, order); */ 5.484 ++ /* else */ 5.485 ++ vfree(mem); 5.486 + } 5.487 + 5.488 +-static int uncompress(struct cloop_device *clo, 5.489 +- unsigned char *dest, unsigned long *destLen, 5.490 +- unsigned char *source, unsigned long sourceLen) 5.491 ++static int uncompress(struct cloop_device *clo, unsigned char *dest, unsigned long *destLen, unsigned char *source, unsigned long sourceLen, int flags) 5.492 + { 5.493 +- /* Most of this code can be found in fs/cramfs/uncompress.c */ 5.494 +- int err; 5.495 +- clo->zstream.next_in = source; 5.496 +- clo->zstream.avail_in = sourceLen; 5.497 +- clo->zstream.next_out = dest; 5.498 +- clo->zstream.avail_out = *destLen; 5.499 +- err = zlib_inflateReset(&clo->zstream); 5.500 +- if (err != Z_OK) 5.501 +- { 5.502 +- printk(KERN_ERR "%s: zlib_inflateReset error %d\n", cloop_name, err); 5.503 +- zlib_inflateEnd(&clo->zstream); zlib_inflateInit(&clo->zstream); 5.504 +- } 5.505 +- err = zlib_inflate(&clo->zstream, Z_FINISH); 5.506 +- *destLen = clo->zstream.total_out; 5.507 +- if (err != Z_STREAM_END) return err; 5.508 +- return Z_OK; 5.509 ++ int err = -1; 5.510 ++ switch(flags) 5.511 ++ { 5.512 ++ case CLOOP_COMPRESSOR_NONE: 5.513 ++ memcpy(dest, source, *destLen = sourceLen); 5.514 ++ err = Z_OK; 5.515 ++ break; 5.516 ++#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 5.517 ++ case CLOOP_COMPRESSOR_ZLIB: 5.518 ++ clo->zstream.next_in = source; 5.519 ++ clo->zstream.avail_in = sourceLen; 5.520 ++ clo->zstream.next_out = dest; 5.521 ++ clo->zstream.avail_out = *destLen; 5.522 ++ err = zlib_inflateReset(&clo->zstream); 5.523 ++ if (err != Z_OK) 5.524 ++ { 5.525 ++ printk(KERN_ERR "%s: zlib_inflateReset error %d\n", cloop_name, err); 5.526 ++ zlib_inflateEnd(&clo->zstream); zlib_inflateInit(&clo->zstream); 5.527 ++ } 5.528 ++ err = zlib_inflate(&clo->zstream, Z_FINISH); 5.529 ++ *destLen = clo->zstream.total_out; 5.530 ++ if (err == Z_STREAM_END) err = 0; 5.531 ++ DEBUGP("cloop: zlib decompression done, ret =%d, size =%lu\n", err, *destLen); 5.532 ++ break; 5.533 ++#endif 5.534 ++#if (defined(CONFIG_LZO_DECOMPRESS) || defined(CONFIG_LZO_DECOMPRESS_MODULE)) 5.535 ++ case CLOOP_COMPRESSOR_LZO1X: 5.536 ++ { 5.537 ++ size_t tmp = (size_t) clo->head.block_size; 5.538 ++ err = lzo1x_decompress_safe(source, sourceLen, 5.539 ++ dest, &tmp); 5.540 ++ if (err == LZO_E_OK) *destLen = (u_int32_t) tmp; 5.541 ++ } 5.542 ++ break; 5.543 ++#endif 5.544 ++#if (defined(CONFIG_DECOMPRESS_LZ4) || defined(CONFIG_DECOMPRESS_LZ4_MODULE)) 5.545 ++ case CLOOP_COMPRESSOR_LZ4: 5.546 ++ { 5.547 ++ size_t outputSize = *destLen; 5.548 ++ /* We should adjust outputSize here, in case the last block is smaller than block_size */ 5.549 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) /* field removed */ 5.550 ++ err = lz4_decompress(source, (size_t *) &sourceLen, 5.551 ++ dest, outputSize); 5.552 ++#else 5.553 ++ err = LZ4_decompress_safe(source, 5.554 ++ dest, 5.555 ++ sourceLen, outputSize); 5.556 ++#endif 5.557 ++ if (err >= 0) 5.558 ++ { 5.559 ++ err = 0; 5.560 ++ *destLen = outputSize; 5.561 ++ } 5.562 ++ } 5.563 ++ break; 5.564 ++#endif 5.565 ++#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 5.566 ++ case CLOOP_COMPRESSOR_XZ: 5.567 ++ clo->xz_buffer.in = source; 5.568 ++ clo->xz_buffer.in_pos = 0; 5.569 ++ clo->xz_buffer.in_size = sourceLen; 5.570 ++ clo->xz_buffer.out = dest; 5.571 ++ clo->xz_buffer.out_pos = 0; 5.572 ++ clo->xz_buffer.out_size = *destLen; 5.573 ++ xz_dec_reset(clo->xzdecoderstate); 5.574 ++ err = xz_dec_run(clo->xzdecoderstate, &clo->xz_buffer); 5.575 ++ if (err == XZ_STREAM_END || err == XZ_OK) 5.576 ++ { 5.577 ++ err = 0; 5.578 ++ } 5.579 ++ else 5.580 ++ { 5.581 ++ printk(KERN_ERR "%s: xz_dec_run error %d\n", cloop_name, err); 5.582 ++ err = 1; 5.583 ++ } 5.584 ++ break; 5.585 ++#endif 5.586 ++ default: 5.587 ++ printk(KERN_ERR "%s: compression method is not supported!\n", cloop_name); 5.588 ++ } 5.589 ++ return err; 5.590 + } 5.591 + 5.592 + static ssize_t cloop_read_from_file(struct cloop_device *clo, struct file *f, char *buf, 5.593 +@@ -220,7 +313,7 @@ 5.594 + 5.595 + if(size_read <= 0) 5.596 + { 5.597 +- printk(KERN_ERR "%s: Read error %d at pos %Lu in file %s, " 5.598 ++ printk(KERN_ERR "%s: Read error %d at pos %llu in file %s, " 5.599 + "%d bytes lost.\n", cloop_name, (int)size_read, pos, 5.600 + file, (int)size); 5.601 + memset(buf + buf_len - size, 0, size); 5.602 +@@ -232,72 +325,84 @@ 5.603 + } 5.604 + 5.605 + /* This looks more complicated than it is */ 5.606 +-/* Returns number of block buffer to use for this request */ 5.607 ++/* Returns number of cache block buffer to use for this request */ 5.608 + static int cloop_load_buffer(struct cloop_device *clo, int blocknum) 5.609 + { 5.610 +- unsigned int buf_done = 0; 5.611 +- unsigned long buflen; 5.612 +- unsigned int buf_length; 5.613 ++ loff_t compressed_block_offset; 5.614 ++ long compressed_block_len; 5.615 ++ long uncompressed_block_len=0; 5.616 + int ret; 5.617 + int i; 5.618 +- if(blocknum > ntohl(clo->head.num_blocks) || blocknum < 0) 5.619 +- { 5.620 +- printk(KERN_WARNING "%s: Invalid block number %d requested.\n", 5.621 +- cloop_name, blocknum); 5.622 +- return -1; 5.623 +- } 5.624 ++ if(blocknum > clo->head.num_blocks || blocknum < 0) 5.625 ++ { 5.626 ++ printk(KERN_WARNING "%s: Invalid block number %d requested.\n", 5.627 ++ cloop_name, blocknum); 5.628 ++ return -1; 5.629 ++ } 5.630 + 5.631 + /* Quick return if the block we seek is already in one of the buffers. */ 5.632 + /* Return number of buffer */ 5.633 +- for(i=0; i<BUFFERED_BLOCKS; i++) 5.634 ++ for(i=0; i<clo->num_buffered_blocks; i++) 5.635 + if (blocknum == clo->buffered_blocknum[i]) 5.636 +- { 5.637 +- DEBUGP(KERN_INFO "cloop_load_buffer: Found buffered block %d\n", i); 5.638 +- return i; 5.639 +- } 5.640 +- 5.641 - buf_length = be64_to_cpu(clo->offsets[blocknum+1]) - be64_to_cpu(clo->offsets[blocknum]); 5.642 -+ buf_length = clo->offsets[blocknum].size; 5.643 +- 5.644 +-/* Load one compressed block from the file. */ 5.645 +- cloop_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer, 5.646 +- be64_to_cpu(clo->offsets[blocknum]), buf_length); 5.647 ++ { 5.648 ++ DEBUGP(KERN_INFO "cloop_load_buffer: Found buffered block %d\n", i); 5.649 ++ return i; 5.650 ++ } 5.651 5.652 - /* Load one compressed block from the file. */ 5.653 - cloop_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer, 5.654 -- be64_to_cpu(clo->offsets[blocknum]), buf_length); 5.655 -+ clo->offsets[blocknum].offset, buf_length); 5.656 +- buflen = ntohl(clo->head.block_size); 5.657 ++ compressed_block_offset = clo->block_ptrs[blocknum].offset; 5.658 ++ compressed_block_len = (long) (clo->block_ptrs[blocknum].size) ; 5.659 5.660 - buflen = ntohl(clo->head.block_size); 5.661 +- /* Go to next position in the block ring buffer */ 5.662 +- clo->current_bufnum++; 5.663 +- if(clo->current_bufnum >= BUFFERED_BLOCKS) clo->current_bufnum = 0; 5.664 ++ /* Load one compressed block from the file. */ 5.665 ++ if(compressed_block_offset > 0 && compressed_block_len >= 0) /* sanity check */ 5.666 ++ { 5.667 ++ size_t n = cloop_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer, 5.668 ++ compressed_block_offset, compressed_block_len); 5.669 ++ if (n!= compressed_block_len) 5.670 ++ { 5.671 ++ printk(KERN_ERR "%s: error while reading %lu bytes @ %llu from file %s\n", 5.672 ++ cloop_name, compressed_block_len, clo->block_ptrs[blocknum].offset, clo->underlying_filename); 5.673 ++ /* return -1; */ 5.674 ++ } 5.675 ++ } else { 5.676 ++ printk(KERN_ERR "%s: invalid data block len %ld bytes @ %lld from file %s\n", 5.677 ++ cloop_name, compressed_block_len, clo->block_ptrs[blocknum].offset, clo->underlying_filename); 5.678 ++ return -1; 5.679 ++ } 5.680 ++ 5.681 ++ /* Go to next position in the cache block buffer (which is used as a cyclic buffer) */ 5.682 ++ if(++clo->current_bufnum >= clo->num_buffered_blocks) clo->current_bufnum = 0; 5.683 5.684 -@@ -275,9 +282,9 @@ 5.685 + /* Do the uncompression */ 5.686 +- ret = uncompress(clo, clo->buffer[clo->current_bufnum], &buflen, clo->compressed_buffer, 5.687 +- buf_length); 5.688 ++ uncompressed_block_len = clo->head.block_size; 5.689 ++ ret = uncompress(clo, clo->buffer[clo->current_bufnum], &uncompressed_block_len, 5.690 ++ clo->compressed_buffer, compressed_block_len, clo->block_ptrs[blocknum].flags); 5.691 + /* DEBUGP("cloop: buflen after uncompress: %ld\n",buflen); */ 5.692 if (ret != 0) 5.693 +- { 5.694 +- printk(KERN_ERR "%s: zlib decompression error %i uncompressing block %u %u/%lu/%u/%u " 5.695 +- "%Lu-%Lu\n", cloop_name, ret, blocknum, 5.696 +- ntohl(clo->head.block_size), buflen, buf_length, buf_done, 5.697 +- be64_to_cpu(clo->offsets[blocknum]), be64_to_cpu(clo->offsets[blocknum+1])); 5.698 +- clo->buffered_blocknum[clo->current_bufnum] = -1; 5.699 +- return -1; 5.700 +- } 5.701 ++ { 5.702 ++ printk(KERN_ERR "%s: decompression error %i uncompressing block %u %lu bytes @ %llu, flags %u\n", 5.703 ++ cloop_name, ret, blocknum, 5.704 ++ compressed_block_len, clo->block_ptrs[blocknum].offset, 5.705 ++ clo->block_ptrs[blocknum].flags); 5.706 ++ clo->buffered_blocknum[clo->current_bufnum] = -1; 5.707 ++ return -1; 5.708 ++ } 5.709 + clo->buffered_blocknum[clo->current_bufnum] = blocknum; 5.710 + return clo->current_bufnum; 5.711 + } 5.712 + 5.713 + /* This function does all the real work. */ 5.714 +-/* returns "uptodate" */ 5.715 ++/* returns "uptodate" */ 5.716 + static int cloop_handle_request(struct cloop_device *clo, struct request *req) 5.717 + { 5.718 + int buffered_blocknum = -1; 5.719 + int preloaded = 0; 5.720 + loff_t offset = (loff_t) blk_rq_pos(req)<<9; /* req->sector<<9 */ 5.721 +- struct bio_vec *bvec; 5.722 ++ struct bio_vec bvec; 5.723 + struct req_iterator iter; 5.724 + rq_for_each_segment(bvec, req, iter) 5.725 { 5.726 - printk(KERN_ERR "%s: zlib decompression error %i uncompressing block %u %u/%lu/%u/%u " 5.727 -- "%Lu-%Lu\n", cloop_name, ret, blocknum, 5.728 -+ "%Lu:%u\n", cloop_name, ret, blocknum, 5.729 - ntohl(clo->head.block_size), buflen, buf_length, buf_done, 5.730 -- be64_to_cpu(clo->offsets[blocknum]), be64_to_cpu(clo->offsets[blocknum+1])); 5.731 -+ clo->offsets[blocknum].offset, clo->offsets[blocknum].size); 5.732 - clo->buffered_blocknum[clo->current_bufnum] = -1; 5.733 - return -1; 5.734 +- unsigned long len = bvec->bv_len; 5.735 +- char *to_ptr = kmap(bvec->bv_page) + bvec->bv_offset; 5.736 ++ unsigned long len = bvec.bv_len; 5.737 ++ char *to_ptr = kmap(bvec.bv_page) + bvec.bv_offset; 5.738 + while(len > 0) 5.739 + { 5.740 + u_int32_t length_in_buffer; 5.741 +@@ -308,7 +413,7 @@ 5.742 + /* puts the result in the first argument, i.e. block_offset */ 5.743 + /* becomes the blocknumber to load, and offset_in_buffer the */ 5.744 + /* position in the buffer */ 5.745 +- offset_in_buffer = do_div(block_offset, ntohl(clo->head.block_size)); 5.746 ++ offset_in_buffer = do_div(block_offset, clo->head.block_size); 5.747 + /* Lookup preload cache */ 5.748 + if(block_offset < clo->preload_size && clo->preload_cache != NULL && 5.749 + clo->preload_cache[block_offset] != NULL) 5.750 +@@ -325,7 +430,7 @@ 5.751 + from_ptr = clo->buffer[buffered_blocknum]; 5.752 + } 5.753 + /* Now, at least part of what we want will be in the buffer. */ 5.754 +- length_in_buffer = ntohl(clo->head.block_size) - offset_in_buffer; 5.755 ++ length_in_buffer = clo->head.block_size - offset_in_buffer; 5.756 + if(length_in_buffer > len) 5.757 + { 5.758 + /* DEBUGP("Warning: length_in_buffer=%u > len=%u\n", 5.759 +@@ -337,18 +442,19 @@ 5.760 + len -= length_in_buffer; 5.761 + offset += length_in_buffer; 5.762 + } /* while inner loop */ 5.763 +- kunmap(bvec->bv_page); 5.764 ++ kunmap(bvec.bv_page); 5.765 ++ cond_resched(); 5.766 + } /* end rq_for_each_segment*/ 5.767 + return ((buffered_blocknum!=-1) || preloaded); 5.768 + } 5.769 + 5.770 + /* Adopted from loop.c, a kernel thread to handle physical reads and 5.771 +- * decompression. */ 5.772 ++ decompression. */ 5.773 + static int cloop_thread(void *data) 5.774 + { 5.775 + struct cloop_device *clo = data; 5.776 + current->flags |= PF_NOFREEZE; 5.777 +- set_user_nice(current, -15); 5.778 ++ set_user_nice(current, 10); 5.779 + while (!kthread_should_stop()||!list_empty(&clo->clo_list)) 5.780 + { 5.781 + int err; 5.782 +@@ -390,10 +496,18 @@ 5.783 + int rw; 5.784 + /* quick sanity checks */ 5.785 + /* blk_fs_request() was removed in 2.6.36 */ 5.786 +- if (unlikely(req == NULL || (req->cmd_type != REQ_TYPE_FS))) 5.787 ++ if (unlikely(req == NULL 5.788 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) /* field removed */ 5.789 ++ || (req->cmd_type != REQ_TYPE_FS) 5.790 ++#endif 5.791 ++ )) 5.792 + goto error_continue; 5.793 + rw = rq_data_dir(req); 5.794 +- if (unlikely(rw != READ && rw != READA)) 5.795 ++ if (unlikely(rw != READ 5.796 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) 5.797 ++ && rw != READA 5.798 ++#endif 5.799 ++ )) 5.800 + { 5.801 + DEBUGP("cloop_do_request: bad command\n"); 5.802 + goto error_continue; 5.803 +@@ -409,40 +523,51 @@ 5.804 + continue; /* next request */ 5.805 + error_continue: 5.806 + DEBUGP(KERN_ERR "cloop_do_request: Discarding request %p.\n", req); 5.807 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) 5.808 + req->errors++; 5.809 ++#else 5.810 ++ req->error_count++; 5.811 ++#endif 5.812 + __blk_end_request_all(req, -EIO); 5.813 } 5.814 -@@ -489,30 +496,73 @@ 5.815 - cloop_name, ntohl(clo->head.block_size)); 5.816 - error=-EBADF; goto error_release; 5.817 - } 5.818 + } 5.819 + 5.820 +-/* Read header and offsets from already opened file */ 5.821 +-static int cloop_set_file(int cloop_num, struct file *file, char *filename) 5.822 ++/* Read header, flags and offsets from already opened file */ 5.823 ++static int cloop_set_file(int cloop_num, struct file *file) 5.824 + { 5.825 + struct cloop_device *clo = cloop_dev[cloop_num]; 5.826 + struct inode *inode; 5.827 + char *bbuf=NULL; 5.828 +- unsigned int i, offsets_read, total_offsets; 5.829 +- int isblkdev; 5.830 +- int error = 0; 5.831 ++ unsigned int bbuf_size = 0; 5.832 ++ const unsigned int header_size = sizeof(struct cloop_head); 5.833 ++ unsigned int i, total_offsets=0; 5.834 ++ loff_t fs_read_position = 0, header_pos[2]; 5.835 ++ int flags, isblkdev, bytes_read, error = 0; 5.836 ++ if (clo->suspended) return error; 5.837 ++ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) 5.838 + inode = file->f_dentry->d_inode; 5.839 ++ clo->underlying_filename = kstrdup(file->f_dentry->d_name.name ? file->f_dentry->d_name.name : (const unsigned char *)"anonymous filename", GFP_KERNEL); 5.840 ++ #else 5.841 ++ inode = file->f_path.dentry->d_inode; 5.842 ++ clo->underlying_filename = kstrdup(file->f_path.dentry->d_name.name ? file->f_path.dentry->d_name.name : (const unsigned char *)"anonymous filename", GFP_KERNEL); 5.843 ++ #endif 5.844 + isblkdev=S_ISBLK(inode->i_mode)?1:0; 5.845 + if(!isblkdev&&!S_ISREG(inode->i_mode)) 5.846 + { 5.847 + printk(KERN_ERR "%s: %s not a regular file or block device\n", 5.848 +- cloop_name, filename); 5.849 ++ cloop_name, clo->underlying_filename); 5.850 + error=-EBADF; goto error_release; 5.851 + } 5.852 + clo->backing_file = file; 5.853 + clo->backing_inode= inode ; 5.854 +- if(!isblkdev&&inode->i_size<sizeof(struct cloop_head)) 5.855 ++ clo->underlying_total_size = (isblkdev) ? inode->i_bdev->bd_inode->i_size : inode->i_size; 5.856 ++ if(clo->underlying_total_size < header_size) 5.857 + { 5.858 +- printk(KERN_ERR "%s: %lu bytes (must be >= %u bytes)\n", 5.859 +- cloop_name, (unsigned long)inode->i_size, 5.860 +- (unsigned)sizeof(struct cloop_head)); 5.861 ++ printk(KERN_ERR "%s: %llu bytes (must be >= %u bytes)\n", 5.862 ++ cloop_name, clo->underlying_total_size, 5.863 ++ (unsigned int)header_size); 5.864 + error=-EBADF; goto error_release; 5.865 + } 5.866 +- /* In suspended mode, we have done all checks necessary - FF */ 5.867 +- if (clo->suspended) 5.868 +- return error; 5.869 + if(isblkdev) 5.870 + { 5.871 + struct request_queue *q = bdev_get_queue(inode->i_bdev); 5.872 +@@ -451,104 +576,225 @@ 5.873 + /* blk_queue_max_hw_segments(clo->clo_queue, queue_max_hw_segments(q)); */ /* Removed in 2.6.34 */ 5.874 + blk_queue_max_segment_size(clo->clo_queue, queue_max_segment_size(q)); 5.875 + blk_queue_segment_boundary(clo->clo_queue, queue_segment_boundary(q)); 5.876 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) 5.877 + blk_queue_merge_bvec(clo->clo_queue, q->merge_bvec_fn); 5.878 ++#endif 5.879 + clo->underlying_blksize = block_size(inode->i_bdev); 5.880 + } 5.881 + else 5.882 + clo->underlying_blksize = PAGE_SIZE; 5.883 +- DEBUGP("Underlying blocksize is %u\n", clo->underlying_blksize); 5.884 +- bbuf = cloop_malloc(clo->underlying_blksize); 5.885 ++ 5.886 ++ DEBUGP(KERN_INFO "Underlying blocksize of %s is %u\n", clo->underlying_filename, clo->underlying_blksize); 5.887 ++ DEBUGP(KERN_INFO "Underlying total size of %s is %llu\n", clo->underlying_filename, clo->underlying_total_size); 5.888 ++ 5.889 ++ /* clo->underlying_blksize should be larger than header_size, even if it's only PAGE_SIZE */ 5.890 ++ bbuf_size = clo->underlying_blksize; 5.891 ++ bbuf = cloop_malloc(bbuf_size); 5.892 + if(!bbuf) 5.893 + { 5.894 +- printk(KERN_ERR "%s: out of kernel mem for block buffer (%lu bytes)\n", 5.895 +- cloop_name, (unsigned long)clo->underlying_blksize); 5.896 ++ printk(KERN_ERR "%s: out of kernel mem for buffer (%u bytes)\n", 5.897 ++ cloop_name, (unsigned int) bbuf_size); 5.898 ++ error=-ENOMEM; goto error_release; 5.899 ++ } 5.900 ++ 5.901 ++ header_pos[0] = 0; /* header first */ 5.902 ++ header_pos[1] = clo->underlying_total_size - sizeof(struct cloop_head); /* header last */ 5.903 ++ for(i=0; i<2; i++) 5.904 ++ { 5.905 ++ /* Check for header */ 5.906 ++ size_t bytes_readable = MIN(clo->underlying_blksize, clo->underlying_total_size - header_pos[i]); 5.907 ++ size_t bytes_read = cloop_read_from_file(clo, file, bbuf, header_pos[i], bytes_readable); 5.908 ++ if(bytes_read != bytes_readable) 5.909 ++ { 5.910 ++ printk(KERN_ERR "%s: Bad file %s, read() of %s %u bytes returned %d.\n", 5.911 ++ cloop_name, clo->underlying_filename, (i==0)?"first":"last", 5.912 ++ (unsigned int)header_size, (int)bytes_read); 5.913 ++ error=-EBADF; 5.914 ++ goto error_release; 5.915 ++ } 5.916 ++ memcpy(&clo->head, bbuf, header_size); 5.917 ++ if (strncmp(bbuf+CLOOP_SIGNATURE_OFFSET, CLOOP_SIGNATURE, CLOOP_SIGNATURE_SIZE)==0) 5.918 ++ { 5.919 ++ clo->file_format++; 5.920 ++ clo->head.block_size=ntohl(clo->head.block_size); 5.921 ++ clo->head.num_blocks=ntohl(clo->head.num_blocks); 5.922 ++ clo->header_first = (i==0) ? 1 : 0; 5.923 ++ printk(KERN_INFO "%s: file %s, %d blocks of %d bytes, header %s.\n", cloop_name, clo->underlying_filename, clo->head.num_blocks, clo->head.block_size, (i==0)?"first":"last"); 5.924 ++ break; 5.925 ++ } 5.926 ++ } 5.927 ++ if (clo->file_format == 0) 5.928 ++ { 5.929 ++ printk(KERN_ERR "%s: Cannot detect %s format.\n", 5.930 ++ cloop_name, cloop_name); 5.931 ++ error=-EBADF; goto error_release; 5.932 ++ } 5.933 ++ if (clo->head.block_size % 512 != 0) 5.934 ++ { 5.935 ++ printk(KERN_ERR "%s: blocksize %u not multiple of 512\n", 5.936 ++ cloop_name, clo->head.block_size); 5.937 ++ error=-EBADF; goto error_release; 5.938 ++ } 5.939 ++ total_offsets=clo->head.num_blocks; 5.940 ++ if (!isblkdev && (sizeof(struct cloop_head)+sizeof(struct block_info)* 5.941 ++ total_offsets > inode->i_size)) 5.942 ++ { 5.943 ++ printk(KERN_ERR "%s: file %s too small for %u blocks\n", 5.944 ++ cloop_name, clo->underlying_filename, clo->head.num_blocks); 5.945 ++ error=-EBADF; goto error_release; 5.946 ++ } 5.947 ++ /* Allocate Memory for decompressors */ 5.948 ++#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 5.949 ++ clo->zstream.workspace = cloop_malloc(zlib_inflate_workspacesize()); 5.950 ++ if(!clo->zstream.workspace) 5.951 ++ { 5.952 ++ printk(KERN_ERR "%s: out of mem for zlib working area %u\n", 5.953 ++ cloop_name, zlib_inflate_workspacesize()); 5.954 + error=-ENOMEM; goto error_release; 5.955 + } 5.956 +- total_offsets = 1; /* Dummy total_offsets: will be filled in first time around */ 5.957 +- for (i = 0, offsets_read = 0; offsets_read < total_offsets; i++) 5.958 ++ zlib_inflateInit(&clo->zstream); 5.959 ++#endif 5.960 ++#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 5.961 ++#if XZ_INTERNAL_CRC32 5.962 ++ /* This must be called before any other xz_* function to initialize the CRC32 lookup table. */ 5.963 ++ xz_crc32_init(void); 5.964 ++#endif 5.965 ++ clo->xzdecoderstate = xz_dec_init(XZ_SINGLE, 0); 5.966 ++#endif 5.967 ++ if (total_offsets + 1 == 0) /* Version 3 */ 5.968 + { 5.969 +- unsigned int offset = 0, num_readable; 5.970 +- size_t bytes_read = cloop_read_from_file(clo, file, bbuf, 5.971 +- i*clo->underlying_blksize, 5.972 +- clo->underlying_blksize); 5.973 +- if(bytes_read != clo->underlying_blksize) 5.974 ++ struct cloop_tail tail; 5.975 ++ if (isblkdev) 5.976 + { 5.977 +- printk(KERN_ERR "%s: Bad file, read() of first %lu bytes returned %d.\n", 5.978 +- cloop_name, (unsigned long)clo->underlying_blksize, (int)bytes_read); 5.979 +- error=-EBADF; 5.980 +- goto error_release; 5.981 ++ /* No end of file: can't find index */ 5.982 ++ printk(KERN_ERR "%s: no V3 support for block device\n", 5.983 ++ cloop_name); 5.984 ++ error=-EBADF; goto error_release; 5.985 + } 5.986 +- /* Header will be in block zero */ 5.987 +- if(i==0) 5.988 ++ bytes_read = cloop_read_from_file(clo, file, (void *) &tail, 5.989 ++ inode->i_size - sizeof(struct cloop_tail), 5.990 ++ sizeof(struct cloop_tail)); 5.991 ++ if (bytes_read == sizeof(struct cloop_tail)) 5.992 + { 5.993 +- memcpy(&clo->head, bbuf, sizeof(struct cloop_head)); 5.994 +- offset = sizeof(struct cloop_head); 5.995 +- if (ntohl(clo->head.block_size) % 512 != 0) 5.996 ++ unsigned long len, zlen; 5.997 ++ int ret; 5.998 ++ void *zbuf; 5.999 ++ clo->head.num_blocks = ntohl(tail.num_blocks); 5.1000 ++ total_offsets = clo->head.num_blocks; 5.1001 ++ clo->block_ptrs = cloop_malloc(sizeof(struct block_info) * total_offsets); 5.1002 ++ zlen = ntohl(tail.table_size); 5.1003 ++ zbuf = cloop_malloc(zlen); 5.1004 ++ if (!clo->block_ptrs || !zbuf) 5.1005 + { 5.1006 +- printk(KERN_ERR "%s: blocksize %u not multiple of 512\n", 5.1007 +- cloop_name, ntohl(clo->head.block_size)); 5.1008 +- error=-EBADF; goto error_release; 5.1009 +- } 5.1010 - if (clo->head.preamble[0x0B]!='V'||clo->head.preamble[0x0C]<'1') 5.1011 - { 5.1012 - printk(KERN_ERR "%s: Cannot read old 32-bit (version 0.68) images, " 5.1013 - "please use an older version of %s for this file.\n", 5.1014 - cloop_name, cloop_name); 5.1015 - error=-EBADF; goto error_release; 5.1016 -- } 5.1017 ++ printk(KERN_ERR "%s: out of kernel mem for index\n", cloop_name); 5.1018 ++ error=-ENOMEM; goto error_release; 5.1019 + } 5.1020 - if (clo->head.preamble[0x0C]<'2') 5.1021 -- { 5.1022 ++ bytes_read = cloop_read_from_file(clo, file, zbuf, 5.1023 ++ inode->i_size - zlen - sizeof(struct cloop_tail), 5.1024 ++ zlen); 5.1025 ++ if (bytes_read != zlen) 5.1026 + { 5.1027 - printk(KERN_ERR "%s: Cannot read old architecture-dependent " 5.1028 - "(format <= 1.0) images, please use an older " 5.1029 - "version of %s for this file.\n", 5.1030 - cloop_name, cloop_name); 5.1031 -- error=-EBADF; goto error_release; 5.1032 -- } 5.1033 ++ printk(KERN_ERR "%s: can't read index\n", cloop_name); 5.1034 + error=-EBADF; goto error_release; 5.1035 + } 5.1036 - total_offsets=ntohl(clo->head.num_blocks)+1; 5.1037 - if (!isblkdev && (sizeof(struct cloop_head)+sizeof(loff_t)* 5.1038 -+ total_offsets=ntohl(clo->head.num_blocks); 5.1039 -+ if (!isblkdev && (sizeof(struct cloop_head)+sizeof(struct block_info)* 5.1040 - total_offsets > inode->i_size)) 5.1041 +- total_offsets > inode->i_size)) 5.1042 ++ len = CLOOP3_INDEX_SIZE(ntohl(tail.index_size)) * total_offsets; 5.1043 ++ flags = CLOOP3_BLOCKS_FLAGS(ntohl(tail.index_size)); 5.1044 ++// May 3 19:45:20 (none) user.info kernel: cloop: uncompress(clo=e0a78000, block_ptrs=e0c9c000, &len(1440)=ddc05e6c, zbuf=e0c9f000, zlen=43, flag=0) 5.1045 ++printk(KERN_INFO "%s: uncompress(clo=%p, block_ptrs=%p, &len(%ld)=%p, zbuf=%p, zlen=%ld, flag=%d)\n", cloop_name, 5.1046 ++ clo, clo->block_ptrs, len, &len, zbuf, zlen, flags); 5.1047 ++ ret = uncompress(clo, (void *) clo->block_ptrs, &len, zbuf, zlen, flags); 5.1048 ++// May 3 19:45:20 (none) user.alert kernel: BUG: unable to handle kernel NULL pointer dereference at (null) 5.1049 ++printk(KERN_INFO "%s: uncompressed !\n", cloop_name); 5.1050 ++ cloop_free(zbuf, zlen); 5.1051 ++ if (ret != 0) 5.1052 { 5.1053 - printk(KERN_ERR "%s: file too small for %u blocks\n", 5.1054 - cloop_name, ntohl(clo->head.num_blocks)); 5.1055 +- printk(KERN_ERR "%s: file too small for %u blocks\n", 5.1056 +- cloop_name, ntohl(clo->head.num_blocks)); 5.1057 ++ printk(KERN_ERR "%s: decompression error %i uncompressing index, flags %u\n", 5.1058 ++ cloop_name, ret, flags); 5.1059 error=-EBADF; goto error_release; 5.1060 } 5.1061 - clo->offsets = cloop_malloc(sizeof(loff_t) * total_offsets); 5.1062 -+ if (total_offsets + 1 == 0) /* Version >= 3.0 */ 5.1063 -+ { 5.1064 -+ struct cloop_tail tail; 5.1065 -+ if(isblkdev) 5.1066 -+ { 5.1067 -+ /* No end of file: can't find index */ 5.1068 -+ printk(KERN_ERR "%s: no V3 support for block device\n", 5.1069 -+ cloop_name); 5.1070 -+ error=-EBADF; goto error_release; 5.1071 -+ } 5.1072 -+ bytes_read = cloop_read_from_file(clo, file, (void *) &tail, 5.1073 -+ inode->i_size - sizeof(struct cloop_tail), 5.1074 -+ sizeof(struct cloop_tail)); 5.1075 -+ if(bytes_read == sizeof(struct cloop_tail)) 5.1076 -+ { 5.1077 -+ unsigned long len, zlen; 5.1078 -+ void *zbuf; 5.1079 -+ clo->head.num_blocks = tail.num_blocks; 5.1080 -+ total_offsets = ntohl(clo->head.num_blocks); 5.1081 -+ clo->offsets = cloop_malloc(sizeof(struct block_info) * total_offsets); 5.1082 -+ if (!clo->offsets) 5.1083 -+ { 5.1084 -+ printk(KERN_ERR "%s: can't alloc index\n", 5.1085 -+ cloop_name); 5.1086 -+ error=-EBADF; goto error_release; 5.1087 -+ } 5.1088 -+ zbuf = &clo->offsets[total_offsets/2]; 5.1089 -+ zlen = ntohl(tail.table_size); 5.1090 -+ len = ntohl(tail.index_size) * total_offsets; 5.1091 -+ bytes_read = cloop_read_from_file(clo, file, zbuf, 5.1092 -+ inode->i_size - zlen - sizeof(struct cloop_tail), 5.1093 -+ zlen); 5.1094 -+ if (bytes_read != zlen) 5.1095 -+ { 5.1096 -+ printk(KERN_ERR "%s: can't read index\n", 5.1097 -+ cloop_name); 5.1098 -+ error=-EBADF; goto error_release; 5.1099 -+ } 5.1100 -+ clo->zstream.workspace = cloop_malloc(zlib_inflate_workspacesize()); 5.1101 -+ if(!clo->zstream.workspace) 5.1102 -+ { 5.1103 -+ printk(KERN_ERR "%s: can't alloc index workspace\n", 5.1104 -+ cloop_name); 5.1105 -+ error=-EBADF; goto error_release; 5.1106 -+ } 5.1107 -+ zlib_inflateInit(&clo->zstream); 5.1108 -+ uncompress(clo, (void *) clo->offsets, &len, zbuf, zlen); 5.1109 -+ cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); 5.1110 -+ clo->zstream.workspace = NULL; 5.1111 -+ break; 5.1112 -+ } 5.1113 -+ else 5.1114 -+ { 5.1115 -+ printk(KERN_ERR "%s: can't find index\n", 5.1116 -+ cloop_name); 5.1117 -+ error=-EBADF; goto error_release; 5.1118 -+ } 5.1119 -+ } 5.1120 -+ clo->offsets = cloop_malloc(sizeof(struct block_info) * total_offsets); 5.1121 - if (!clo->offsets) 5.1122 - { 5.1123 - printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name); 5.1124 -@@ -521,19 +571,22 @@ 5.1125 +- if (!clo->offsets) 5.1126 +- { 5.1127 +- printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name); 5.1128 +- error=-ENOMEM; goto error_release; 5.1129 +- } 5.1130 } 5.1131 - num_readable = MIN(total_offsets - offsets_read, 5.1132 - (clo->underlying_blksize - offset) 5.1133 +- num_readable = MIN(total_offsets - offsets_read, 5.1134 +- (clo->underlying_blksize - offset) 5.1135 - / sizeof(loff_t)); 5.1136 - memcpy(&clo->offsets[offsets_read], bbuf+offset, num_readable * sizeof(loff_t)); 5.1137 -+ / sizeof(struct block_info)); 5.1138 -+ memcpy(&clo->offsets[offsets_read], bbuf+offset, num_readable * sizeof(struct block_info)); 5.1139 - offsets_read += num_readable; 5.1140 - } 5.1141 - { /* Search for largest block rather than estimate. KK. */ 5.1142 - int i; 5.1143 +- offsets_read += num_readable; 5.1144 +- } 5.1145 +- { /* Search for largest block rather than estimate. KK. */ 5.1146 +- int i; 5.1147 - for(i=0;i<total_offsets-1;i++) 5.1148 -+ char *version = build_index(clo->offsets, ntohl(clo->head.num_blocks)); 5.1149 -+ for(i=0,clo->largest_block=0;i<total_offsets;i++) 5.1150 ++ else 5.1151 ++ { 5.1152 ++ printk(KERN_ERR "%s: can't find index\n", cloop_name); 5.1153 ++ error=-ENOMEM; goto error_release; 5.1154 ++ } 5.1155 ++ } 5.1156 ++ else 5.1157 ++ { 5.1158 ++ unsigned int n, total_bytes; 5.1159 ++ flags = 0; 5.1160 ++ clo->block_ptrs = cloop_malloc(sizeof(struct block_info) * total_offsets); 5.1161 ++ if (!clo->block_ptrs) 5.1162 ++ { 5.1163 ++ printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name); 5.1164 ++ error=-ENOMEM; goto error_release; 5.1165 ++ } 5.1166 ++ /* Read them offsets! */ 5.1167 ++ if(clo->header_first) 5.1168 ++ { 5.1169 ++ total_bytes = total_offsets * sizeof(struct block_info); 5.1170 ++ fs_read_position = sizeof(struct cloop_head); 5.1171 ++ } 5.1172 ++ else 5.1173 { 5.1174 - loff_t d=be64_to_cpu(clo->offsets[i+1]) - be64_to_cpu(clo->offsets[i]); 5.1175 - clo->largest_block=MAX(clo->largest_block,d); 5.1176 -+ clo->largest_block=MAX(clo->largest_block,clo->offsets[i].size); 5.1177 ++ total_bytes = total_offsets * sizeof(loff_t); 5.1178 ++ fs_read_position = clo->underlying_total_size - sizeof(struct cloop_head) - total_bytes; 5.1179 ++ } 5.1180 ++ for(n=0;n<total_bytes;) 5.1181 ++ { 5.1182 ++ size_t bytes_readable; 5.1183 ++ bytes_readable = MIN(bbuf_size, clo->underlying_total_size - fs_read_position); 5.1184 ++ if(bytes_readable <= 0) break; /* Done */ 5.1185 ++ bytes_read = cloop_read_from_file(clo, file, bbuf, fs_read_position, bytes_readable); 5.1186 ++ if(bytes_read != bytes_readable) 5.1187 ++ { 5.1188 ++ printk(KERN_ERR "%s: Bad file %s, read() %lu bytes @ %llu returned %d.\n", 5.1189 ++ cloop_name, clo->underlying_filename, (unsigned long)clo->underlying_blksize, fs_read_position, (int)bytes_read); 5.1190 ++ error=-EBADF; 5.1191 ++ goto error_release; 5.1192 ++ } 5.1193 ++ memcpy(((char *)clo->block_ptrs) + n, bbuf, bytes_read); 5.1194 ++ /* remember where to read the next blk from file */ 5.1195 ++ fs_read_position += bytes_read; 5.1196 ++ n += bytes_read; 5.1197 } 5.1198 - printk(KERN_INFO "%s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n", 5.1199 - cloop_name, filename, ntohl(clo->head.num_blocks), 5.1200 -+ i = ntohl(clo->head.block_size); 5.1201 -+ i += i/1000 + 12 + 4; /* max gzip block size */ 5.1202 -+ if (clo->largest_block > i) clo->largest_block = i; /* broken index ? */ 5.1203 -+ printk(KERN_INFO "%s: %s: %s, %u blocks, %u bytes/block, largest block is %lu bytes.\n", 5.1204 -+ cloop_name, filename, version, ntohl(clo->head.num_blocks), 5.1205 - ntohl(clo->head.block_size), clo->largest_block); 5.1206 +- ntohl(clo->head.block_size), clo->largest_block); 5.1207 } 5.1208 - /* Combo kmalloc used too large chunks (>130000). */ 5.1209 -@@ -565,16 +618,6 @@ 5.1210 - error=-ENOMEM; goto error_release_free_all; 5.1211 +-/* Combo kmalloc used too large chunks (>130000). */ 5.1212 + { 5.1213 + int i; 5.1214 +- for(i=0;i<BUFFERED_BLOCKS;i++) 5.1215 +- { 5.1216 +- clo->buffer[i] = cloop_malloc(ntohl(clo->head.block_size)); 5.1217 +- if(!clo->buffer[i]) 5.1218 +- { 5.1219 +- printk(KERN_ERR "%s: out of memory for buffer %lu\n", 5.1220 +- cloop_name, (unsigned long) ntohl(clo->head.block_size)); 5.1221 +- error=-ENOMEM; goto error_release_free; 5.1222 +- } 5.1223 +- } 5.1224 ++ char *version = build_index(clo->block_ptrs, clo->head.num_blocks, clo->head.block_size, flags); 5.1225 ++ clo->largest_block = 0; 5.1226 ++ for (i = 0; i < clo->head.num_blocks; i++) 5.1227 ++ if (clo->block_ptrs[i].size > clo->largest_block) 5.1228 ++ clo->largest_block = clo->block_ptrs[i].size; 5.1229 ++ printk(KERN_INFO "%s: %s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n", 5.1230 ++ cloop_name, clo->underlying_filename, version, clo->head.num_blocks, 5.1231 ++ clo->head.block_size, clo->largest_block); 5.1232 ++ } 5.1233 ++ { 5.1234 ++ int i; 5.1235 ++ clo->num_buffered_blocks = (buffers > 0 && clo->head.block_size >= 512) ? 5.1236 ++ (buffers / clo->head.block_size) : 1; 5.1237 ++ clo->buffered_blocknum = cloop_malloc(clo->num_buffered_blocks * sizeof (u_int32_t)); 5.1238 ++ clo->buffer = cloop_malloc(clo->num_buffered_blocks * sizeof (char*)); 5.1239 ++ if (!clo->buffered_blocknum || !clo->buffer) 5.1240 ++ { 5.1241 ++ printk(KERN_ERR "%s: out of memory for index of cache buffer (%lu bytes)\n", 5.1242 ++ cloop_name, (unsigned long)clo->num_buffered_blocks * sizeof (u_int32_t) + sizeof(char*) ); 5.1243 ++ error=-ENOMEM; goto error_release; 5.1244 ++ } 5.1245 ++ memset(clo->buffer, 0, clo->num_buffered_blocks * sizeof (char*)); 5.1246 ++ for(i=0;i<clo->num_buffered_blocks;i++) 5.1247 ++ { 5.1248 ++ clo->buffered_blocknum[i] = -1; 5.1249 ++ clo->buffer[i] = cloop_malloc(clo->head.block_size); 5.1250 ++ if(!clo->buffer[i]) 5.1251 ++ { 5.1252 ++ printk(KERN_ERR "%s: out of memory for cache buffer %lu\n", 5.1253 ++ cloop_name, (unsigned long) clo->head.block_size); 5.1254 ++ error=-ENOMEM; goto error_release_free; 5.1255 ++ } 5.1256 ++ } 5.1257 ++ clo->current_bufnum = 0; 5.1258 + } 5.1259 + clo->compressed_buffer = cloop_malloc(clo->largest_block); 5.1260 + if(!clo->compressed_buffer) 5.1261 +@@ -557,31 +803,7 @@ 5.1262 + cloop_name, clo->largest_block); 5.1263 + error=-ENOMEM; goto error_release_free_buffer; 5.1264 } 5.1265 - zlib_inflateInit(&clo->zstream); 5.1266 +- clo->zstream.workspace = cloop_malloc(zlib_inflate_workspacesize()); 5.1267 +- if(!clo->zstream.workspace) 5.1268 +- { 5.1269 +- printk(KERN_ERR "%s: out of mem for zlib working area %u\n", 5.1270 +- cloop_name, zlib_inflate_workspacesize()); 5.1271 +- error=-ENOMEM; goto error_release_free_all; 5.1272 +- } 5.1273 +- zlib_inflateInit(&clo->zstream); 5.1274 - if(!isblkdev && 5.1275 - be64_to_cpu(clo->offsets[ntohl(clo->head.num_blocks)]) != inode->i_size) 5.1276 - { 5.1277 @@ -274,15 +1112,264 @@ 5.1278 - cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); clo->zstream.workspace=NULL; 5.1279 - goto error_release_free_all; 5.1280 - } 5.1281 +- { 5.1282 +- int i; 5.1283 +- for(i=0; i<BUFFERED_BLOCKS; i++) clo->buffered_blocknum[i] = -1; 5.1284 +- clo->current_bufnum=0; 5.1285 +- } 5.1286 +- set_capacity(clo->clo_disk, (sector_t)(ntohl(clo->head.num_blocks)* 5.1287 +- (ntohl(clo->head.block_size)>>9))); 5.1288 ++ set_capacity(clo->clo_disk, (sector_t)(clo->head.num_blocks*(clo->head.block_size>>9))); 5.1289 + clo->clo_thread = kthread_create(cloop_thread, clo, "cloop%d", cloop_num); 5.1290 + if(IS_ERR(clo->clo_thread)) 5.1291 + { 5.1292 +@@ -591,17 +813,17 @@ 5.1293 + } 5.1294 + if(preload > 0) 5.1295 + { 5.1296 +- clo->preload_array_size = ((preload<=ntohl(clo->head.num_blocks))?preload:ntohl(clo->head.num_blocks)); 5.1297 ++ clo->preload_array_size = ((preload<=clo->head.num_blocks)?preload:clo->head.num_blocks); 5.1298 + clo->preload_size = 0; 5.1299 + if((clo->preload_cache = cloop_malloc(clo->preload_array_size * sizeof(char *))) != NULL) 5.1300 + { 5.1301 + int i; 5.1302 + for(i=0; i<clo->preload_array_size; i++) 5.1303 + { 5.1304 +- if((clo->preload_cache[i] = cloop_malloc(ntohl(clo->head.block_size))) == NULL) 5.1305 ++ if((clo->preload_cache[i] = cloop_malloc(clo->head.block_size)) == NULL) 5.1306 + { /* Out of memory */ 5.1307 + printk(KERN_WARNING "%s: cloop_malloc(%d) failed for preload_cache[%d] (ignored).\n", 5.1308 +- cloop_name, ntohl(clo->head.block_size), i); 5.1309 ++ cloop_name, clo->head.block_size, i); 5.1310 + break; 5.1311 + } 5.1312 + } 5.1313 +@@ -612,13 +834,13 @@ 5.1314 + if(buffered_blocknum >= 0) 5.1315 + { 5.1316 + memcpy(clo->preload_cache[i], clo->buffer[buffered_blocknum], 5.1317 +- ntohl(clo->head.block_size)); 5.1318 ++ clo->head.block_size); 5.1319 + } 5.1320 + else 5.1321 + { 5.1322 + printk(KERN_WARNING "%s: can't read block %d into preload cache, set to zero.\n", 5.1323 + cloop_name, i); 5.1324 +- memset(clo->preload_cache[i], 0, ntohl(clo->head.block_size)); 5.1325 ++ memset(clo->preload_cache[i], 0, clo->head.block_size); 5.1326 + } 5.1327 + } 5.1328 + printk(KERN_INFO "%s: preloaded %d blocks into cache.\n", cloop_name, 5.1329 +@@ -641,22 +863,19 @@ 5.1330 + cloop_free(clo->compressed_buffer, clo->largest_block); 5.1331 + clo->compressed_buffer=NULL; 5.1332 + error_release_free_buffer: 5.1333 ++ if(clo->buffer) 5.1334 { 5.1335 int i; 5.1336 - for(i=0; i<BUFFERED_BLOCKS; i++) clo->buffered_blocknum[i] = -1; 5.1337 -@@ -653,7 +696,7 @@ 5.1338 - } 5.1339 +- for(i=0; i<BUFFERED_BLOCKS; i++) 5.1340 +- { 5.1341 +- if(clo->buffer[i]) 5.1342 +- { 5.1343 +- cloop_free(clo->buffer[i], ntohl(clo->head.block_size)); 5.1344 +- clo->buffer[i]=NULL; 5.1345 +- } 5.1346 +- } 5.1347 ++ for(i=0; i<clo->num_buffered_blocks; i++) { if(clo->buffer[i]) { cloop_free(clo->buffer[i], clo->head.block_size); clo->buffer[i]=NULL; }} 5.1348 ++ cloop_free(clo->buffer, clo->num_buffered_blocks*sizeof(char*)); clo->buffer=NULL; 5.1349 } 5.1350 ++ if (clo->buffered_blocknum) { cloop_free(clo->buffered_blocknum, sizeof(int)*clo->num_buffered_blocks); clo->buffered_blocknum=NULL; } 5.1351 error_release_free: 5.1352 - cloop_free(clo->offsets, sizeof(loff_t) * total_offsets); 5.1353 -+ cloop_free(clo->offsets, sizeof(struct block_info) * total_offsets); 5.1354 - clo->offsets=NULL; 5.1355 +- clo->offsets=NULL; 5.1356 ++ cloop_free(clo->block_ptrs, sizeof(struct block_info) * total_offsets); 5.1357 ++ clo->block_ptrs=NULL; 5.1358 error_release: 5.1359 if(bbuf) cloop_free(bbuf, clo->underlying_blksize); 5.1360 ++ if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; } 5.1361 + clo->backing_file=NULL; 5.1362 + return error; 5.1363 + } 5.1364 +@@ -673,7 +892,7 @@ 5.1365 + if(clo->backing_file) return -EBUSY; 5.1366 + file = fget(arg); /* get filp struct from ioctl arg fd */ 5.1367 + if(!file) return -EBADF; 5.1368 +- error=cloop_set_file(cloop_num,file,"losetup_file"); 5.1369 ++ error=cloop_set_file(cloop_num,file); 5.1370 + set_device_ro(bdev, 1); 5.1371 + if(error) fput(file); 5.1372 + return error; 5.1373 +@@ -684,29 +903,48 @@ 5.1374 + { 5.1375 + struct cloop_device *clo = cloop_dev[cloop_num]; 5.1376 + struct file *filp = clo->backing_file; 5.1377 +- int i; 5.1378 + if(clo->refcnt > 1) /* we needed one fd for the ioctl */ 5.1379 + return -EBUSY; 5.1380 + if(filp==NULL) return -EINVAL; 5.1381 + if(clo->clo_thread) { kthread_stop(clo->clo_thread); clo->clo_thread=NULL; } 5.1382 +- if(filp!=initial_file) fput(filp); 5.1383 +- else { filp_close(initial_file,0); initial_file=NULL; } 5.1384 ++ if(filp!=initial_file) 5.1385 ++ fput(filp); 5.1386 ++ else 5.1387 ++ { 5.1388 ++ filp_close(initial_file,0); 5.1389 ++ initial_file=NULL; 5.1390 ++ } 5.1391 + clo->backing_file = NULL; 5.1392 + clo->backing_inode = NULL; 5.1393 +- if(clo->offsets) { cloop_free(clo->offsets, clo->underlying_blksize); clo->offsets = NULL; } 5.1394 ++ if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; } 5.1395 ++ if(clo->block_ptrs) { cloop_free(clo->block_ptrs, clo->head.num_blocks); clo->block_ptrs = NULL; } 5.1396 + if(clo->preload_cache) 5.1397 +- { 5.1398 +- for(i=0; i < clo->preload_size; i++) 5.1399 +- cloop_free(clo->preload_cache[i], ntohl(clo->head.block_size)); 5.1400 +- cloop_free(clo->preload_cache, clo->preload_array_size * sizeof(char *)); 5.1401 +- clo->preload_cache = NULL; 5.1402 +- clo->preload_size = clo->preload_array_size = 0; 5.1403 +- } 5.1404 +- for(i=0; i<BUFFERED_BLOCKS; i++) 5.1405 +- if(clo->buffer[i]) { cloop_free(clo->buffer[i], ntohl(clo->head.block_size)); clo->buffer[i]=NULL; } 5.1406 ++ { 5.1407 ++ int i; 5.1408 ++ for(i=0; i < clo->preload_size; i++) 5.1409 ++ cloop_free(clo->preload_cache[i], clo->head.block_size); 5.1410 ++ cloop_free(clo->preload_cache, clo->preload_array_size * sizeof(char *)); 5.1411 ++ clo->preload_cache = NULL; 5.1412 ++ clo->preload_size = clo->preload_array_size = 0; 5.1413 ++ } 5.1414 ++ if (clo->buffered_blocknum) 5.1415 ++ { 5.1416 ++ cloop_free(clo->buffered_blocknum, sizeof(int) * clo->num_buffered_blocks); clo->buffered_blocknum = NULL; 5.1417 ++ } 5.1418 ++ if (clo->buffer) 5.1419 ++ { 5.1420 ++ int i; 5.1421 ++ for(i=0; i<clo->num_buffered_blocks; i++) { if(clo->buffer[i]) cloop_free(clo->buffer[i], clo->head.block_size); } 5.1422 ++ cloop_free(clo->buffer, sizeof(char*) * clo->num_buffered_blocks); clo->buffer = NULL; 5.1423 ++ } 5.1424 + if(clo->compressed_buffer) { cloop_free(clo->compressed_buffer, clo->largest_block); clo->compressed_buffer = NULL; } 5.1425 ++#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 5.1426 + zlib_inflateEnd(&clo->zstream); 5.1427 + if(clo->zstream.workspace) { cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); clo->zstream.workspace = NULL; } 5.1428 ++#endif 5.1429 ++#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 5.1430 ++ xz_dec_end(clo->xzdecoderstate); 5.1431 ++#endif 5.1432 + if(bdev) invalidate_bdev(bdev); 5.1433 + if(clo->clo_disk) set_capacity(clo->clo_disk, 0); 5.1434 + return 0; 5.1435 +@@ -731,8 +969,8 @@ 5.1436 + const struct loop_info64 *info) 5.1437 + { 5.1438 + if (!clo->backing_file) return -ENXIO; 5.1439 +- memcpy(clo->clo_file_name, info->lo_file_name, LO_NAME_SIZE); 5.1440 +- clo->clo_file_name[LO_NAME_SIZE-1] = 0; 5.1441 ++ if(clo->underlying_filename) kfree(clo->underlying_filename); 5.1442 ++ clo->underlying_filename = kstrdup(info->lo_file_name, GFP_KERNEL); 5.1443 + return 0; 5.1444 + } 5.1445 + 5.1446 +@@ -743,7 +981,11 @@ 5.1447 + struct kstat stat; 5.1448 + int err; 5.1449 + if (!file) return -ENXIO; 5.1450 +- err = vfs_getattr(file->f_path.mnt, file->f_path.dentry, &stat); 5.1451 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) 5.1452 ++ err = vfs_getattr(&file->f_path, &stat); 5.1453 ++#else 5.1454 ++ err = vfs_getattr(&file->f_path, &stat, STATX_INO, AT_STATX_SYNC_AS_STAT); 5.1455 ++#endif 5.1456 + if (err) return err; 5.1457 + memset(info, 0, sizeof(*info)); 5.1458 + info->lo_number = clo->clo_number; 5.1459 +@@ -753,7 +995,8 @@ 5.1460 + info->lo_offset = 0; 5.1461 + info->lo_sizelimit = 0; 5.1462 + info->lo_flags = 0; 5.1463 +- memcpy(info->lo_file_name, clo->clo_file_name, LO_NAME_SIZE); 5.1464 ++ strncpy(info->lo_file_name, clo->underlying_filename, LO_NAME_SIZE); 5.1465 ++ info->lo_file_name[LO_NAME_SIZE-1]=0; 5.1466 + return 0; 5.1467 + } 5.1468 + 5.1469 +@@ -833,8 +1076,6 @@ 5.1470 + if (!err && copy_to_user(arg, &info64, sizeof(info64))) err = -EFAULT; 5.1471 + return err; 5.1472 + } 5.1473 +-/* EOF get/set_status */ 5.1474 +- 5.1475 + 5.1476 + static int cloop_ioctl(struct block_device *bdev, fmode_t mode, 5.1477 + unsigned int cmd, unsigned long arg) 5.1478 +@@ -914,21 +1155,20 @@ 5.1479 + /* losetup uses write-open and flags=0x8002 to set a new file */ 5.1480 + if(mode & FMODE_WRITE) 5.1481 + { 5.1482 +- printk(KERN_WARNING "%s: Can't open device read-write in mode 0x%x\n", cloop_name, mode); 5.1483 ++ printk(KERN_INFO "%s: Open in read-write mode 0x%x requested, ignored.\n", cloop_name, mode); 5.1484 + return -EROFS; 5.1485 + } 5.1486 + cloop_dev[cloop_num]->refcnt+=1; 5.1487 + return 0; 5.1488 + } 5.1489 + 5.1490 +-static int cloop_close(struct gendisk *disk, fmode_t mode) 5.1491 ++static void cloop_close(struct gendisk *disk, fmode_t mode) 5.1492 + { 5.1493 +- int cloop_num, err=0; 5.1494 +- if(!disk) return 0; 5.1495 ++ int cloop_num; 5.1496 ++ if(!disk) return; 5.1497 + cloop_num=((struct cloop_device *)disk->private_data)->clo_number; 5.1498 +- if(cloop_num < 0 || cloop_num > (cloop_count-1)) return 0; 5.1499 ++ if(cloop_num < 0 || cloop_num > (cloop_count-1)) return; 5.1500 + cloop_dev[cloop_num]->refcnt-=1; 5.1501 +- return err; 5.1502 + } 5.1503 + 5.1504 + static struct block_device_operations clo_fops = 5.1505 +@@ -973,6 +1213,10 @@ 5.1506 + goto error_out; 5.1507 + } 5.1508 + clo->clo_queue->queuedata = clo; 5.1509 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) 5.1510 ++ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, clo->clo_queue); 5.1511 ++ queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, clo->clo_queue); 5.1512 ++#endif 5.1513 + clo->clo_disk = alloc_disk(1); 5.1514 + if(!clo->clo_disk) 5.1515 + { 5.1516 +@@ -1004,6 +1248,11 @@ 5.1517 + cloop_dev[cloop_num] = NULL; 5.1518 + } 5.1519 + 5.1520 ++/* LZ4 Stuff */ 5.1521 ++#if (defined USE_LZ4_INTERNAL) 5.1522 ++#include "lz4_kmod.c" 5.1523 ++#endif 5.1524 ++ 5.1525 + static int __init cloop_init(void) 5.1526 + { 5.1527 + int error=0; 5.1528 +@@ -1044,7 +1293,7 @@ 5.1529 + initial_file=NULL; /* if IS_ERR, it's NOT open. */ 5.1530 + } 5.1531 + else 5.1532 +- error=cloop_set_file(0,initial_file,file); 5.1533 ++ error=cloop_set_file(0,initial_file); 5.1534 + if(error) 5.1535 + { 5.1536 + printk(KERN_ERR 5.1537 +@@ -1052,9 +1301,6 @@ 5.1538 + cloop_name, file, error); 5.1539 + goto init_out_dealloc; 5.1540 + } 5.1541 +- if(namelen >= LO_NAME_SIZE) namelen = LO_NAME_SIZE-1; 5.1542 +- memcpy(cloop_dev[0]->clo_file_name, file, namelen); 5.1543 +- cloop_dev[0]->clo_file_name[namelen] = 0; 5.1544 + } 5.1545 + return 0; 5.1546 + init_out_dealloc: