wok-current rev 24983
Up xcursor-comix (0.9.2)
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Sun May 08 16:45:21 2022 +0000 (2022-05-08) |
parents | 0f92b8cc8086 |
children | 2b0142c9f248 |
files | linux-cloop/receipt linux-cloop/stuff/cloop.u linux64-cloop/receipt linux64-cloop/stuff/cloop.u wbar/receipt xa/receipt xautomation/receipt xcursor-aero/receipt xcursor-comix/receipt |
line diff
1.1 --- a/linux-cloop/receipt Sun May 08 13:06:36 2022 +0000 1.2 +++ b/linux-cloop/receipt Sun May 08 16:45:21 2022 +0000 1.3 @@ -2,16 +2,15 @@ 1.4 1.5 PACKAGE="linux-cloop" 1.6 SOURCE="cloop" 1.7 -_VERSION="2.639-2" 1.8 -#VERSION="$(sed '/+#define CLOOP_VERSION/!d;s|.* "\(.*\)"|\1|' stuff/cloop.u)" 1.9 +_VERSION="3.14.1.3" 1.10 VERSION="4.12" 1.11 CATEGORY="base-system" 1.12 MAINTAINER="pascal.bellard@slitaz.org" 1.13 LICENSE="GPL2" 1.14 SHORT_DESC="The read-only compressed loop device kernel module." 1.15 WEB_SITE="http://knoppix.net/wiki/Cloop" 1.16 -TARBALL="${SOURCE}_${_VERSION}.tar.gz" 1.17 -WGET_URL="http://debian-knoppix.alioth.debian.org/packages/$SOURCE/$TARBALL" 1.18 +TARBALL="${SOURCE}_${_VERSION}.tar.xz" 1.19 +WGET_URL="http://deb.debian.org/debian/pool/main/c/$SOURCE/$TARBALL" 1.20 1.21 DEPENDS="linux" 1.22 BUILD_DEPENDS="linux-module-headers xz" 1.23 @@ -23,6 +22,7 @@ 1.24 { 1.25 patch -p0 < $stuff/cloop.u 1.26 make ARCH=i386 KERNEL_DIR="/usr/src/linux" cloop.ko && xz cloop.ko 1.27 + make cloop_suspend 1.28 } 1.29 1.30 # Rules to gen a SliTaz package suitable for Tazpkg.
2.1 --- a/linux-cloop/stuff/cloop.u Sun May 08 13:06:36 2022 +0000 2.2 +++ b/linux-cloop/stuff/cloop.u Sun May 08 16:45:21 2022 +0000 2.3 @@ -1,6 +1,6 @@ 2.4 --- cloop.h 2.5 +++ cloop.h 2.6 -@@ -1,15 +1,50 @@ 2.7 +@@ -1,3 +1,7 @@ 2.8 +#define CLOOP_SIGNATURE "#!/bin/sh" /* @ offset 0 */ 2.9 +#define CLOOP_SIGNATURE_SIZE 9 2.10 +#define CLOOP_SIGNATURE_OFFSET 0x0 2.11 @@ -8,99 +8,46 @@ 2.12 #ifndef _COMPRESSED_LOOP_H 2.13 #define _COMPRESSED_LOOP_H 2.14 2.15 --#define CLOOP_HEADROOM 128 2.16 -+/*************************************************************************\ 2.17 -+* Starting with Format V4.0 (cloop version 4.x), cloop can now have two * 2.18 -+* alternative structures: * 2.19 -+* * 2.20 -+* 1. Header first: "robust" format, handles missing blocks well * 2.21 -+* 2. Footer (header last): "streaming" format, easier to create * 2.22 -+* * 2.23 -+* The cloop kernel module autodetects both formats, and can (currently) * 2.24 -+* still handle the V2.0 format as well. * 2.25 -+* * 2.26 -+* 1. Header first: * 2.27 -+* +---------------------------- FIXED SIZE ---------------------------+ * 2.28 -+* |Signature (128 bytes) | * 2.29 -+* |block_size (32bit number, network order) | * 2.30 -+* |num_blocks (32bit number, network order) | * 2.31 -+* +--------------------------- VARIABLE SIZE -------------------------+ * 2.32 -+* |num_blocks * FlagsOffset (upper 4 bits flags, lower 64 bits offset)| * 2.33 -+* |compressed data blocks of variable size ... | * 2.34 -+* +-------------------------------------------------------------------+ * 2.35 -+* * 2.36 -+* 2. Footer (header last): * 2.37 -+* +--------------------------- VARIABLE SIZE -------------------------+ * 2.38 -+* |compressed data blocks of variable size ... | * 2.39 -+* |num_blocks * FlagsOffset (upper 4 bits flags, lower 64 bits offset)| * 2.40 -+* +---------------------------- FIXED SIZE ---------------------------+ * 2.41 -+* |Signature (128 bytes) | * 2.42 -+* |block_size (32bit number, network order) | * 2.43 -+* |num_blocks (32bit number, network order) | * 2.44 -+* +-------------------------------------------------------------------+ * 2.45 -+* * 2.46 -+* Offsets are always relative to beginning of file, in all formats. * 2.47 -+* The block index contains num_blocks+1 offsets, followed (1) or * 2.48 -+* preceded (2) by the compressed blocks. * 2.49 -+\*************************************************************************/ 2.50 +@@ -38,10 +42,6 @@ 2.51 2.52 --/* The cloop header usually looks like this: */ 2.53 --/* #!/bin/sh */ 2.54 --/* #V2.00 Format */ 2.55 --/* ...padding up to CLOOP_HEADROOM... */ 2.56 --/* block_size (32bit number, network order) */ 2.57 --/* num_blocks (32bit number, network order) */ 2.58 -+#include <linux/types.h> /* u_int32_t */ 2.59 -+ 2.60 -+#define CLOOP_HEADROOM 128 2.61 + #include <linux/types.h> /* u_int32_t */ 2.62 2.63 -+/* Header of fixed length, can be located at beginning or end of file */ 2.64 - struct cloop_head 2.65 - { 2.66 - char preamble[CLOOP_HEADROOM]; 2.67 -@@ -17,9 +52,163 @@ 2.68 +-#ifndef __KERNEL__ 2.69 +-#include <stdint.h> /* regular uint64_t */ 2.70 +-#endif 2.71 +- 2.72 + #define CLOOP_HEADROOM 128 2.73 + 2.74 + /* Header of fixed length, can be located at beginning or end of file */ 2.75 +@@ -52,13 +52,6 @@ 2.76 u_int32_t num_blocks; 2.77 }; 2.78 2.79 -+/************************************************************************\ 2.80 -+* CLOOP4 flags for each compressed block * 2.81 -+* Value Meaning * 2.82 -+* 0 GZIP/7ZIP compression (compatible with V2.0 Format) * 2.83 -+* 1 no compression (incompressible data) * 2.84 -+* 2 xz compression (currently best space saver) * 2.85 -+* 3 lz4 compression * 2.86 -+* 4 lzo compression (fastest) * 2.87 -+\************************************************************************/ 2.88 -+ 2.89 -+typedef uint64_t cloop_block_ptr; 2.90 -+ 2.91 -+/* Get value of first 4 bits */ 2.92 -+#define CLOOP_BLOCK_FLAGS(x) ((unsigned int)(((x) & 0xf000000000000000LLU) >> 60)) 2.93 -+/* Get value of last 60 bits */ 2.94 -+#define CLOOP_BLOCK_OFFSET(x) ((x) & 0x0fffffffffffffffLLU) 2.95 -+ 2.96 -+#define CLOOP_COMPRESSOR_ZLIB 0x0 2.97 -+#define CLOOP_COMPRESSOR_NONE 0x1 2.98 -+#define CLOOP_COMPRESSOR_XZ 0x2 2.99 -+#define CLOOP_COMPRESSOR_LZ4 0x3 2.100 -+#define CLOOP_COMPRESSOR_LZO1X 0x4 2.101 -+ 2.102 -+#define CLOOP_COMPRESSOR_VALID(x) ((x) >= CLOOP_COMPRESSOR_ZLIB && (x) <= CLOOP_COMPRESSOR_LZO1X) 2.103 -+ 2.104 +-#define CLOOP2_SIGNATURE "V2.0" /* @ offset 0x0b */ 2.105 +-#define CLOOP2_SIGNATURE_SIZE 4 2.106 +-#define CLOOP2_SIGNATURE_OFFSET 0x0b 2.107 +-#define CLOOP4_SIGNATURE "V4.0" /* @ offset 0x0b */ 2.108 +-#define CLOOP4_SIGNATURE_SIZE 4 2.109 +-#define CLOOP4_SIGNATURE_OFFSET 0x0b 2.110 +- 2.111 + /************************************************************************\ 2.112 + * CLOOP4 flags for each compressed block * 2.113 + * Value Meaning * 2.114 +@@ -84,6 +77,134 @@ 2.115 + 2.116 + #define CLOOP_COMPRESSOR_VALID(x) ((x) >= CLOOP_COMPRESSOR_ZLIB && (x) <= CLOOP_COMPRESSOR_LZO1X) 2.117 + 2.118 +#define CLOOP_COMPRESSOR_LINK 0xF 2.119 + 2.120 + 2.121 - /* data_index (num_blocks 64bit pointers, network order)... */ 2.122 - /* compressed data (gzip block compressed format)... */ 2.123 - 2.124 ++/* data_index (num_blocks 64bit pointers, network order)... */ 2.125 ++/* compressed data (gzip block compressed format)... */ 2.126 ++ 2.127 +struct cloop_tail 2.128 +{ 2.129 + u_int32_t table_size; 2.130 -+ u_int32_t index_size; /* size:4 comp:3 ctrl-c:1 lastlen:24 */ 2.131 ++ u_int32_t index_size; /* size:4 unused:3 ctrl-c:1 lastlen:24 */ 2.132 +#define CLOOP3_INDEX_SIZE(x) ((unsigned int)((x) & 0xF)) 2.133 -+#define CLOOP3_BLOCKS_FLAGS(x) ((unsigned int)((x) & 0x70) >> 4) 2.134 -+#define CLOOP3_TRUNCATED(x) ((unsigned int)((x) & 0x80) >> 7) 2.135 -+#define CLOOP3_LASTLEN(x) (unsigned int)((x) >> 8) 2.136 + u_int32_t num_blocks; 2.137 +}; 2.138 + 2.139 @@ -114,8 +61,10 @@ 2.140 +}; 2.141 + 2.142 +static inline char *build_index(struct block_info *offsets, unsigned long n, 2.143 -+ unsigned long block_size, unsigned global_flags) 2.144 ++ unsigned long block_size) 2.145 +{ 2.146 ++ static char v[11]; 2.147 ++ u_int32_t flags = 0; 2.148 + u_int32_t *ofs32 = (u_int32_t *) offsets; 2.149 + loff_t *ofs64 = (loff_t *) offsets; 2.150 + 2.151 @@ -140,8 +89,6 @@ 2.152 + } 2.153 + else { /* V2.0/V4.0 */ 2.154 + loff_t last = CLOOP_BLOCK_OFFSET(__be64_to_cpu(ofs64[n])); 2.155 -+ u_int32_t flags; 2.156 -+ static char v4[11]; 2.157 + unsigned long i = n; 2.158 + 2.159 + for (flags = 0; n-- ;) { 2.160 @@ -159,12 +106,7 @@ 2.161 + offsets[i] = offsets[offsets[i].offset]; 2.162 + } 2.163 + } 2.164 -+ strcpy(v4, (char *) "64BE v4.0a"); 2.165 -+ v4[10] = 'a' + ((flags-1) & 0xF); // compressors used 2.166 -+ if (flags > 0x10) { // with links ? 2.167 -+ v4[10] += 'A' - 'a'; 2.168 -+ } 2.169 -+ return v4; 2.170 ++ strcpy(v, (char *) "64BE v4.0a"); 2.171 + } 2.172 + } 2.173 + else if (ofs32[1] == 0 && v3_64 == 0) { /* V1.0 */ 2.174 @@ -180,7 +122,6 @@ 2.175 + else { /* V3.0 or V0.68 */ 2.176 + unsigned long i; 2.177 + loff_t j; 2.178 -+ static char v3[11]; 2.179 + 2.180 + for (i = 0; i < n && ntohl(ofs32[i]) < ntohl(ofs32[i+1]); i++); 2.181 + if (i == n && ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */ 2.182 @@ -195,28 +136,33 @@ 2.183 + } 2.184 + 2.185 + v3_64 = (ofs32[1] == 0); 2.186 -+ for (i = n; i-- != 0; ) 2.187 ++ for (i = n; i-- != 0; ) { 2.188 + offsets[i].size = ntohl(ofs32[i << v3_64]); 2.189 ++ if (offsets[i].size == 0xFFFFFFFF) { 2.190 ++ offsets[i].size = 0x10000000 | block_size; 2.191 ++ } 2.192 ++ offsets[i].flags = (offsets[i].size >> 28); 2.193 ++ offsets[i].size &= 0x0FFFFFFF; 2.194 ++ } 2.195 + for (i = 0, j = sizeof(struct cloop_head); i < n; i++) { 2.196 + offsets[i].offset = j; 2.197 -+ offsets[i].flags = global_flags; 2.198 -+ if (offsets[i].size == 0xFFFFFFFF) { 2.199 -+ offsets[i].flags = CLOOP_COMPRESSOR_NONE; 2.200 -+ offsets[i].size = block_size; 2.201 -+ } 2.202 -+ if ((offsets[i].size & 0x80000000) == 0) { 2.203 ++ if (offsets[i].flags < 8) { 2.204 + j += offsets[i].size; 2.205 + } 2.206 + } 2.207 + for (i = 0; i < n; i++) { 2.208 -+ if (offsets[i].size & 0x80000000) { 2.209 -+ offsets[i] = offsets[offsets[i].size & 0x7FFFFFFF]; 2.210 ++ flags |= 1 << offsets[i].flags; 2.211 ++ if (offsets[i].flags >= 8) { 2.212 ++ offsets[i] = offsets[offsets[i].size]; 2.213 + } 2.214 + } 2.215 -+ strcpy(v3, (char *) (v3_64) ? "64BE v3.0a" : "32BE v3.0a"); 2.216 -+ v3[10] += global_flags; 2.217 -+ return v3; 2.218 ++ strcpy(v, (char *) (v3_64) ? "64BE v3.0a" : "32BE v3.0a"); 2.219 + } 2.220 ++ v[10] = 'a' + ((flags-1) & 0xF); // compressors used 2.221 ++ if (flags > 0x10) { // with links ? 2.222 ++ v[10] += 'A' - 'a'; 2.223 ++ } 2.224 ++ return v; 2.225 +} 2.226 + 2.227 /* Cloop suspend IOCTL */ 2.228 @@ -224,661 +170,538 @@ 2.229 2.230 --- cloop.c 2.231 +++ cloop.c 2.232 -@@ -1,26 +1,23 @@ 2.233 --/* 2.234 -- * compressed_loop.c: Read-only compressed loop blockdevice 2.235 -- * hacked up by Rusty in 1999, extended and maintained by Klaus Knopper 2.236 -- * 2.237 -- * A cloop file looks like this: 2.238 -- * [32-bit uncompressed block size: network order] 2.239 -- * [32-bit number of blocks (n_blocks): network order] 2.240 -- * [64-bit file offsets of start of blocks: network order] 2.241 -- * ... 2.242 -- * (n_blocks + 1). 2.243 -- * n_blocks consisting of: 2.244 -- * [compressed block] 2.245 -- * 2.246 -- * Every version greatly inspired by code seen in loop.c 2.247 -- * by Theodore Ts'o, 3/29/93. 2.248 -- * 2.249 -- * Copyright 1999-2009 by Paul `Rusty' Russell & Klaus Knopper. 2.250 -- * Redistribution of this file is permitted under the GNU Public License. 2.251 -- * 2.252 -- */ 2.253 -+/************************************************************************\ 2.254 -+* cloop.c: Read-only compressed loop blockdevice * 2.255 -+* hacked up by Rusty in 1999, extended and maintained by Klaus Knopper * 2.256 -+* * 2.257 -+* For all supported cloop file formats, please check the file "cloop.h" * 2.258 -+* New in Version 4: * 2.259 -+* - Header can be first or last in cloop file, * 2.260 -+* - Different compression algorithms supported (compression type * 2.261 -+* encoded in first 4 bytes of block offset address) * 2.262 -+* * 2.263 -+* Every version greatly inspired by code seen in loop.c * 2.264 -+* by Theodore Ts'o, 3/29/93. * 2.265 -+* * 2.266 -+* Copyright 1999-2009 by Paul `Rusty' Russell & Klaus Knopper. * 2.267 -+* Redistribution of this file is permitted under the GNU Public License * 2.268 -+* V2. * 2.269 -+\************************************************************************/ 2.270 +@@ -17,7 +17,7 @@ 2.271 + \************************************************************************/ 2.272 2.273 #define CLOOP_NAME "cloop" 2.274 --#define CLOOP_VERSION "2.639" 2.275 +-#define CLOOP_VERSION "5.3" 2.276 +#define CLOOP_VERSION "4.12" 2.277 #define CLOOP_MAX 8 2.278 2.279 #ifndef KBUILD_MODNAME 2.280 -@@ -47,8 +44,27 @@ 2.281 - #include <asm/div64.h> /* do_div() for 64bit division */ 2.282 - #include <asm/uaccess.h> 2.283 - #include <asm/byteorder.h> 2.284 --/* Use zlib_inflate from lib/zlib_inflate */ 2.285 -+/* Check for ZLIB, LZO1X, LZ4 decompression algorithms in kernel. */ 2.286 -+#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 2.287 - #include <linux/zutil.h> 2.288 -+#endif 2.289 -+#if (defined(CONFIG_LZO_DECOMPRESS) || defined(CONFIG_LZO_DECOMPRESS_MODULE)) 2.290 -+#include <linux/lzo.h> 2.291 -+#endif 2.292 -+#if (defined(CONFIG_DECOMPRESS_LZ4) || defined(CONFIG_DECOMPRESS_LZ4_MODULE)) 2.293 -+#include <linux/lz4.h> 2.294 -+#endif 2.295 -+#if (defined(CONFIG_DECOMPRESS_LZMA) || defined(CONFIG_DECOMPRESS_LZMA_MODULE)) 2.296 -+#include <linux/decompress/unlzma.h> 2.297 -+#endif 2.298 -+#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 2.299 -+#include <linux/xz.h> 2.300 -+#endif 2.301 -+ 2.302 -+#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))) 2.303 -+#error "No decompression library selected in kernel config!" 2.304 -+#endif 2.305 -+ 2.306 +@@ -68,7 +68,6 @@ 2.307 #include <linux/loop.h> 2.308 #include <linux/kthread.h> 2.309 #include <linux/compat.h> 2.310 -@@ -92,47 +108,64 @@ 2.311 - #define DEBUGP(format, x...) 2.312 - #endif 2.313 +-#include <linux/blk-mq.h> /* new multiqueue infrastructure */ 2.314 + #include "cloop.h" 2.315 2.316 -+/* Default size of buffer to keep some decompressed blocks in memory to speed up access */ 2.317 -+#define BLOCK_BUFFER_MEM (16*65536) 2.318 -+ 2.319 - /* One file can be opened at module insertion time */ 2.320 - /* insmod cloop file=/path/to/file */ 2.321 - static char *file=NULL; 2.322 - static unsigned int preload=0; 2.323 - static unsigned int cloop_max=CLOOP_MAX; 2.324 -+static unsigned int buffers=BLOCK_BUFFER_MEM; 2.325 - module_param(file, charp, 0); 2.326 - module_param(preload, uint, 0); 2.327 - module_param(cloop_max, uint, 0); 2.328 - MODULE_PARM_DESC(file, "Initial cloop image file (full path) for /dev/cloop"); 2.329 - MODULE_PARM_DESC(preload, "Preload n blocks of cloop data into memory"); 2.330 - MODULE_PARM_DESC(cloop_max, "Maximum number of cloop devices (default 8)"); 2.331 -+MODULE_PARM_DESC(buffers, "Size of buffer to keep uncompressed blocks in memory in MiB (default 1)"); 2.332 + /* New License scheme */ 2.333 +@@ -93,10 +92,7 @@ 2.334 + /* Use experimental major for now */ 2.335 + #define MAJOR_NR 240 2.336 2.337 - static struct file *initial_file=NULL; 2.338 - static int cloop_major=MAJOR_NR; 2.339 +-#ifndef DEVICE_NAME 2.340 +-#define DEVICE_NAME CLOOP_NAME 2.341 +-#endif 2.342 +- 2.343 ++/* #define DEVICE_NAME CLOOP_NAME */ 2.344 + /* #define DEVICE_NR(device) (MINOR(device)) */ 2.345 + /* #define DEVICE_ON(device) */ 2.346 + /* #define DEVICE_OFF(device) */ 2.347 +@@ -143,7 +139,7 @@ 2.348 + u_int32_t allflags; 2.349 2.350 --/* Number of buffered decompressed blocks */ 2.351 --#define BUFFERED_BLOCKS 8 2.352 - struct cloop_device 2.353 - { 2.354 -- /* Copied straight from the file */ 2.355 -+ /* Header filled from the file */ 2.356 - struct cloop_head head; 2.357 -+ int header_first; 2.358 -+ int file_format; 2.359 - 2.360 -- /* An array of offsets of compressed blocks within the file */ 2.361 -- loff_t *offsets; 2.362 -+ /* An or'd sum of all flags of each compressed block (v3) */ 2.363 -+ u_int32_t allflags; 2.364 -+ 2.365 -+ /* An array of cloop_ptr flags/offset for compressed blocks within the file */ 2.366 + /* An array of cloop_ptr flags/offset for compressed blocks within the file */ 2.367 +- cloop_block_ptr *block_ptrs; 2.368 + struct block_info *block_ptrs; 2.369 2.370 /* We buffer some uncompressed blocks for performance */ 2.371 -- int buffered_blocknum[BUFFERED_BLOCKS]; 2.372 -- int current_bufnum; 2.373 -- void *buffer[BUFFERED_BLOCKS]; 2.374 -- void *compressed_buffer; 2.375 -- size_t preload_array_size; /* Size of pointer array in blocks */ 2.376 -- size_t preload_size; /* Number of successfully allocated blocks */ 2.377 -- char **preload_cache; /* Pointers to preloaded blocks */ 2.378 -+ size_t num_buffered_blocks; /* how many uncompressed blocks buffered for performance */ 2.379 -+ int *buffered_blocknum; /* list of numbers of uncompressed blocks in buffer */ 2.380 -+ int current_bufnum; /* which block is current */ 2.381 -+ unsigned char **buffer; /* cache space for num_buffered_blocks uncompressed blocks */ 2.382 -+ void *compressed_buffer; /* space for the largest compressed block */ 2.383 -+ size_t preload_array_size; /* Size of pointer array in blocks */ 2.384 -+ size_t preload_size; /* Number of successfully allocated blocks */ 2.385 -+ char **preload_cache; /* Pointers to preloaded blocks */ 2.386 - 2.387 -+#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 2.388 - z_stream zstream; 2.389 -+#endif 2.390 -+#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 2.391 -+ struct xz_dec *xzdecoderstate; 2.392 -+ struct xz_buf xz_buffer; 2.393 -+#endif 2.394 - 2.395 - struct file *backing_file; /* associated file */ 2.396 - struct inode *backing_inode; /* for bmap */ 2.397 - 2.398 -+ unsigned char *underlying_filename; 2.399 - unsigned long largest_block; 2.400 - unsigned int underlying_blksize; 2.401 -+ loff_t underlying_total_size; 2.402 - int clo_number; 2.403 - int refcnt; 2.404 - struct block_device *bdev; 2.405 -@@ -147,7 +180,6 @@ 2.406 + size_t num_buffered_blocks; /* how many uncompressed blocks buffered for performance */ 2.407 +@@ -178,14 +174,16 @@ 2.408 + spinlock_t queue_lock; 2.409 + /* mutex for ioctl() */ 2.410 + struct mutex clo_ctl_mutex; 2.411 +- /* mutex for request */ 2.412 +- struct mutex clo_rq_mutex; 2.413 ++ struct list_head clo_list; 2.414 ++ struct task_struct *clo_thread; 2.415 ++ wait_queue_head_t clo_event; 2.416 struct request_queue *clo_queue; 2.417 struct gendisk *clo_disk; 2.418 +- struct blk_mq_tag_set tag_set; 2.419 int suspended; 2.420 -- char clo_file_name[LO_NAME_SIZE]; 2.421 }; 2.422 2.423 - /* Changed in 2.639: cloop_dev is now a an array of cloop_dev pointers, 2.424 -@@ -156,52 +188,113 @@ 2.425 ++/* Changed in 2.639: cloop_dev is now a an array of cloop_dev pointers, 2.426 ++ so we can specify how many devices we need via parameters. */ 2.427 + static struct cloop_device **cloop_dev; 2.428 static const char *cloop_name=CLOOP_NAME; 2.429 static int cloop_count = 0; 2.430 - 2.431 --#if (!(defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE))) /* Must be compiled into kernel. */ 2.432 --#error "Invalid Kernel configuration. CONFIG_ZLIB_INFLATE support is needed for cloop." 2.433 --#endif 2.434 -- 2.435 --/* Use __get_free_pages instead of vmalloc, allows up to 32 pages, 2.436 -- * 2MB in one piece */ 2.437 - static void *cloop_malloc(size_t size) 2.438 - { 2.439 -- int order = get_order(size); 2.440 -- if(order <= KMALLOC_MAX_ORDER) 2.441 -- return (void *)kmalloc(size, GFP_KERNEL); 2.442 -- else if(order < MAX_ORDER) 2.443 -- return (void *)__get_free_pages(GFP_KERNEL, order); 2.444 -+ /* kmalloc will fail after the system is running for a while, */ 2.445 -+ /* when large orders can't return contiguous memory. */ 2.446 -+ /* Let's just use vmalloc for now. :-/ */ 2.447 -+ /* int order = get_order(size); */ 2.448 -+ /* if(order <= KMALLOC_MAX_ORDER) */ 2.449 -+ /* return (void *)kmalloc(size, GFP_KERNEL); */ 2.450 -+ /* else if(order < MAX_ORDER) */ 2.451 -+ /* return (void *)__get_free_pages(GFP_KERNEL, order); */ 2.452 - return (void *)vmalloc(size); 2.453 +@@ -214,24 +212,21 @@ 2.454 + vfree(mem); 2.455 } 2.456 2.457 - static void cloop_free(void *mem, size_t size) 2.458 - { 2.459 -- int order = get_order(size); 2.460 -- if(order <= KMALLOC_MAX_ORDER) 2.461 -- kfree(mem); 2.462 -- else if(order < MAX_ORDER) 2.463 -- free_pages((unsigned long)mem, order); 2.464 -- else vfree(mem); 2.465 -+ /* int order = get_order(size); */ 2.466 -+ /* if(order <= KMALLOC_MAX_ORDER) */ 2.467 -+ /* kfree(mem); */ 2.468 -+ /* else if(order < MAX_ORDER) */ 2.469 -+ /* free_pages((unsigned long)mem, order); */ 2.470 -+ /* else */ 2.471 -+ vfree(mem); 2.472 - } 2.473 - 2.474 --static int uncompress(struct cloop_device *clo, 2.475 -- unsigned char *dest, unsigned long *destLen, 2.476 -- unsigned char *source, unsigned long sourceLen) 2.477 +-/* static int uncompress(struct cloop_device *clo, unsigned char *dest, unsigned long *destLen, unsigned char *source, unsigned long sourceLen) */ 2.478 +-static int uncompress(struct cloop_device *clo, u_int32_t block_num, u_int32_t compressed_length, unsigned long *uncompressed_length) 2.479 +static int uncompress(struct cloop_device *clo, unsigned char *dest, unsigned long *destLen, unsigned char *source, unsigned long sourceLen, int flags) 2.480 { 2.481 -- /* Most of this code can be found in fs/cramfs/uncompress.c */ 2.482 -- int err; 2.483 -- clo->zstream.next_in = source; 2.484 -- clo->zstream.avail_in = sourceLen; 2.485 -- clo->zstream.next_out = dest; 2.486 -- clo->zstream.avail_out = *destLen; 2.487 -- err = zlib_inflateReset(&clo->zstream); 2.488 -- if (err != Z_OK) 2.489 -- { 2.490 -- printk(KERN_ERR "%s: zlib_inflateReset error %d\n", cloop_name, err); 2.491 -- zlib_inflateEnd(&clo->zstream); zlib_inflateInit(&clo->zstream); 2.492 -- } 2.493 -- err = zlib_inflate(&clo->zstream, Z_FINISH); 2.494 -- *destLen = clo->zstream.total_out; 2.495 -- if (err != Z_STREAM_END) return err; 2.496 -- return Z_OK; 2.497 -+ int err = -1; 2.498 -+ switch(flags) 2.499 -+ { 2.500 -+ case CLOOP_COMPRESSOR_NONE: 2.501 + int err = -1; 2.502 +- int flags = CLOOP_BLOCK_FLAGS(clo->block_ptrs[block_num]); 2.503 + switch(flags) 2.504 + { 2.505 + case CLOOP_COMPRESSOR_NONE: 2.506 +- /* block is umcompressed, swap pointers only! */ 2.507 +- { char *tmp = clo->compressed_buffer; clo->compressed_buffer = clo->buffer[clo->current_bufnum]; clo->buffer[clo->current_bufnum] = tmp; } 2.508 +- DEBUGP("cloop: block %d is uncompressed (flags=%d), just swapping %u bytes\n", block_num, flags, compressed_length); 2.509 + memcpy(dest, source, *destLen = sourceLen); 2.510 + err = Z_OK; 2.511 -+ break; 2.512 -+#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 2.513 -+ case CLOOP_COMPRESSOR_ZLIB: 2.514 + break; 2.515 + #if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 2.516 + case CLOOP_COMPRESSOR_ZLIB: 2.517 +- clo->zstream.next_in = clo->compressed_buffer; 2.518 +- clo->zstream.avail_in = compressed_length; 2.519 +- clo->zstream.next_out = clo->buffer[clo->current_bufnum]; 2.520 +- clo->zstream.avail_out = clo->head.block_size; 2.521 + clo->zstream.next_in = source; 2.522 + clo->zstream.avail_in = sourceLen; 2.523 + clo->zstream.next_out = dest; 2.524 + clo->zstream.avail_out = *destLen; 2.525 -+ err = zlib_inflateReset(&clo->zstream); 2.526 -+ if (err != Z_OK) 2.527 -+ { 2.528 -+ printk(KERN_ERR "%s: zlib_inflateReset error %d\n", cloop_name, err); 2.529 -+ zlib_inflateEnd(&clo->zstream); zlib_inflateInit(&clo->zstream); 2.530 -+ } 2.531 -+ err = zlib_inflate(&clo->zstream, Z_FINISH); 2.532 + err = zlib_inflateReset(&clo->zstream); 2.533 + if (err != Z_OK) 2.534 + { 2.535 +@@ -239,50 +234,50 @@ 2.536 + zlib_inflateEnd(&clo->zstream); zlib_inflateInit(&clo->zstream); 2.537 + } 2.538 + err = zlib_inflate(&clo->zstream, Z_FINISH); 2.539 +- *uncompressed_length = clo->zstream.total_out; 2.540 + *destLen = clo->zstream.total_out; 2.541 -+ if (err == Z_STREAM_END) err = 0; 2.542 + if (err == Z_STREAM_END) err = 0; 2.543 +- DEBUGP("cloop: zlib decompression done, ret =%d, size =%lu\n", err, *uncompressed_length); 2.544 + DEBUGP("cloop: zlib decompression done, ret =%d, size =%lu\n", err, *destLen); 2.545 -+ break; 2.546 -+#endif 2.547 -+#if (defined(CONFIG_LZO_DECOMPRESS) || defined(CONFIG_LZO_DECOMPRESS_MODULE)) 2.548 -+ case CLOOP_COMPRESSOR_LZO1X: 2.549 -+ { 2.550 -+ size_t tmp = (size_t) clo->head.block_size; 2.551 + break; 2.552 + #endif 2.553 + #if (defined(CONFIG_LZO_DECOMPRESS) || defined(CONFIG_LZO_DECOMPRESS_MODULE)) 2.554 + case CLOOP_COMPRESSOR_LZO1X: 2.555 + { 2.556 + size_t tmp = (size_t) clo->head.block_size; 2.557 +- err = lzo1x_decompress_safe(clo->compressed_buffer, compressed_length, 2.558 +- clo->buffer[clo->current_bufnum], &tmp); 2.559 +- if (err == LZO_E_OK) *uncompressed_length = (u_int32_t) tmp; 2.560 + err = lzo1x_decompress_safe(source, sourceLen, 2.561 + dest, &tmp); 2.562 + if (err == LZO_E_OK) *destLen = (u_int32_t) tmp; 2.563 -+ } 2.564 -+ break; 2.565 -+#endif 2.566 -+#if (defined(CONFIG_DECOMPRESS_LZ4) || defined(CONFIG_DECOMPRESS_LZ4_MODULE)) 2.567 -+ case CLOOP_COMPRESSOR_LZ4: 2.568 -+ { 2.569 + } 2.570 + break; 2.571 + #endif 2.572 + #if (defined(CONFIG_DECOMPRESS_LZ4) || defined(CONFIG_DECOMPRESS_LZ4_MODULE)) 2.573 + case CLOOP_COMPRESSOR_LZ4: 2.574 + { 2.575 +- size_t outputSize = clo->head.block_size; 2.576 + size_t outputSize = *destLen; 2.577 -+ /* We should adjust outputSize here, in case the last block is smaller than block_size */ 2.578 -+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) /* field removed */ 2.579 + /* We should adjust outputSize here, in case the last block is smaller than block_size */ 2.580 + #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) /* field removed */ 2.581 +- err = lz4_decompress(clo->compressed_buffer, (size_t *) &compressed_length, 2.582 +- clo->buffer[clo->current_bufnum], outputSize); 2.583 + err = lz4_decompress(source, (size_t *) &sourceLen, 2.584 + dest, outputSize); 2.585 -+#else 2.586 + #else 2.587 +- err = LZ4_decompress_safe(clo->compressed_buffer, 2.588 +- clo->buffer[clo->current_bufnum], 2.589 +- compressed_length, outputSize); 2.590 + err = LZ4_decompress_safe(source, 2.591 + dest, 2.592 + sourceLen, outputSize); 2.593 -+#endif 2.594 -+ if (err >= 0) 2.595 -+ { 2.596 -+ err = 0; 2.597 + #endif 2.598 + if (err >= 0) 2.599 + { 2.600 + err = 0; 2.601 +- *uncompressed_length = outputSize; 2.602 + *destLen = outputSize; 2.603 -+ } 2.604 -+ } 2.605 -+ break; 2.606 -+#endif 2.607 -+#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 2.608 -+ case CLOOP_COMPRESSOR_XZ: 2.609 + } 2.610 + } 2.611 + break; 2.612 + #endif 2.613 + #if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 2.614 + case CLOOP_COMPRESSOR_XZ: 2.615 +- clo->xz_buffer.in = clo->compressed_buffer; 2.616 + clo->xz_buffer.in = source; 2.617 -+ clo->xz_buffer.in_pos = 0; 2.618 + clo->xz_buffer.in_pos = 0; 2.619 +- clo->xz_buffer.in_size = compressed_length; 2.620 +- clo->xz_buffer.out = clo->buffer[clo->current_bufnum]; 2.621 + clo->xz_buffer.in_size = sourceLen; 2.622 + clo->xz_buffer.out = dest; 2.623 -+ clo->xz_buffer.out_pos = 0; 2.624 + clo->xz_buffer.out_pos = 0; 2.625 +- clo->xz_buffer.out_size = clo->head.block_size; 2.626 + clo->xz_buffer.out_size = *destLen; 2.627 -+ xz_dec_reset(clo->xzdecoderstate); 2.628 -+ err = xz_dec_run(clo->xzdecoderstate, &clo->xz_buffer); 2.629 -+ if (err == XZ_STREAM_END || err == XZ_OK) 2.630 -+ { 2.631 -+ err = 0; 2.632 -+ } 2.633 -+ else 2.634 -+ { 2.635 -+ printk(KERN_ERR "%s: xz_dec_run error %d\n", cloop_name, err); 2.636 -+ err = 1; 2.637 -+ } 2.638 -+ break; 2.639 -+#endif 2.640 -+ default: 2.641 -+ printk(KERN_ERR "%s: compression method is not supported!\n", cloop_name); 2.642 -+ } 2.643 -+ return err; 2.644 - } 2.645 - 2.646 - static ssize_t cloop_read_from_file(struct cloop_device *clo, struct file *f, char *buf, 2.647 -@@ -220,7 +313,7 @@ 2.648 + xz_dec_reset(clo->xzdecoderstate); 2.649 + err = xz_dec_run(clo->xzdecoderstate, &clo->xz_buffer); 2.650 + if (err == XZ_STREAM_END || err == XZ_OK) 2.651 +@@ -309,16 +304,12 @@ 2.652 + while (buf_done < buf_len) 2.653 + { 2.654 + size_t size = buf_len - buf_done, size_read; 2.655 +- mm_segment_t old_fs; 2.656 + /* kernel_read() only supports 32 bit offsets, so we use vfs_read() instead. */ 2.657 + /* int size_read = kernel_read(f, pos, buf + buf_done, size); */ 2.658 +- 2.659 +- // mutex_lock(&clo->clo_rq_mutex); 2.660 +- old_fs = get_fs(); 2.661 +- set_fs(KERNEL_DS); 2.662 ++ mm_segment_t old_fs = get_fs(); 2.663 ++ set_fs(get_ds()); 2.664 + size_read = vfs_read(f, (void __user *)(buf + buf_done), size, &pos); 2.665 + set_fs(old_fs); 2.666 +- // mutex_unlock(&clo->clo_rq_mutex); 2.667 2.668 if(size_read <= 0) 2.669 { 2.670 -- printk(KERN_ERR "%s: Read error %d at pos %Lu in file %s, " 2.671 -+ printk(KERN_ERR "%s: Read error %d at pos %llu in file %s, " 2.672 - "%d bytes lost.\n", cloop_name, (int)size_read, pos, 2.673 - file, (int)size); 2.674 - memset(buf + buf_len - size, 0, size); 2.675 -@@ -232,72 +325,84 @@ 2.676 - } 2.677 +@@ -358,8 +349,8 @@ 2.678 + return i; 2.679 + } 2.680 2.681 - /* This looks more complicated than it is */ 2.682 --/* Returns number of block buffer to use for this request */ 2.683 -+/* Returns number of cache block buffer to use for this request */ 2.684 - static int cloop_load_buffer(struct cloop_device *clo, int blocknum) 2.685 - { 2.686 -- unsigned int buf_done = 0; 2.687 -- unsigned long buflen; 2.688 -- unsigned int buf_length; 2.689 -+ loff_t compressed_block_offset; 2.690 -+ long compressed_block_len; 2.691 -+ long uncompressed_block_len=0; 2.692 - int ret; 2.693 - int i; 2.694 -- if(blocknum > ntohl(clo->head.num_blocks) || blocknum < 0) 2.695 -- { 2.696 -- printk(KERN_WARNING "%s: Invalid block number %d requested.\n", 2.697 -- cloop_name, blocknum); 2.698 -- return -1; 2.699 -- } 2.700 -+ if(blocknum > clo->head.num_blocks || blocknum < 0) 2.701 -+ { 2.702 -+ printk(KERN_WARNING "%s: Invalid block number %d requested.\n", 2.703 -+ cloop_name, blocknum); 2.704 -+ return -1; 2.705 -+ } 2.706 - 2.707 - /* Quick return if the block we seek is already in one of the buffers. */ 2.708 - /* Return number of buffer */ 2.709 -- for(i=0; i<BUFFERED_BLOCKS; i++) 2.710 -+ for(i=0; i<clo->num_buffered_blocks; i++) 2.711 - if (blocknum == clo->buffered_blocknum[i]) 2.712 -- { 2.713 -- DEBUGP(KERN_INFO "cloop_load_buffer: Found buffered block %d\n", i); 2.714 -- return i; 2.715 -- } 2.716 -- 2.717 -- buf_length = be64_to_cpu(clo->offsets[blocknum+1]) - be64_to_cpu(clo->offsets[blocknum]); 2.718 -- 2.719 --/* Load one compressed block from the file. */ 2.720 -- cloop_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer, 2.721 -- be64_to_cpu(clo->offsets[blocknum]), buf_length); 2.722 -+ { 2.723 -+ DEBUGP(KERN_INFO "cloop_load_buffer: Found buffered block %d\n", i); 2.724 -+ return i; 2.725 -+ } 2.726 - 2.727 -- buflen = ntohl(clo->head.block_size); 2.728 +- compressed_block_offset = CLOOP_BLOCK_OFFSET(clo->block_ptrs[blocknum]); 2.729 +- compressed_block_len = (long) (CLOOP_BLOCK_OFFSET(clo->block_ptrs[blocknum+1]) - compressed_block_offset) ; 2.730 + compressed_block_offset = clo->block_ptrs[blocknum].offset; 2.731 + compressed_block_len = (long) (clo->block_ptrs[blocknum].size) ; 2.732 2.733 -- /* Go to next position in the block ring buffer */ 2.734 -- clo->current_bufnum++; 2.735 -- if(clo->current_bufnum >= BUFFERED_BLOCKS) clo->current_bufnum = 0; 2.736 -+ /* Load one compressed block from the file. */ 2.737 -+ if(compressed_block_offset > 0 && compressed_block_len >= 0) /* sanity check */ 2.738 -+ { 2.739 -+ size_t n = cloop_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer, 2.740 -+ compressed_block_offset, compressed_block_len); 2.741 -+ if (n!= compressed_block_len) 2.742 -+ { 2.743 -+ printk(KERN_ERR "%s: error while reading %lu bytes @ %llu from file %s\n", 2.744 + /* Load one compressed block from the file. */ 2.745 + if(compressed_block_offset > 0 && compressed_block_len >= 0) /* sanity check */ 2.746 +@@ -369,12 +360,12 @@ 2.747 + if (n!= compressed_block_len) 2.748 + { 2.749 + printk(KERN_ERR "%s: error while reading %lu bytes @ %llu from file %s\n", 2.750 +- cloop_name, compressed_block_len, clo->block_ptrs[blocknum], clo->underlying_filename); 2.751 + cloop_name, compressed_block_len, clo->block_ptrs[blocknum].offset, clo->underlying_filename); 2.752 -+ /* return -1; */ 2.753 -+ } 2.754 -+ } else { 2.755 -+ printk(KERN_ERR "%s: invalid data block len %ld bytes @ %lld from file %s\n", 2.756 + /* return -1; */ 2.757 + } 2.758 + } else { 2.759 + printk(KERN_ERR "%s: invalid data block len %ld bytes @ %lld from file %s\n", 2.760 +- cloop_name, compressed_block_len, clo->block_ptrs[blocknum], clo->underlying_filename); 2.761 + cloop_name, compressed_block_len, clo->block_ptrs[blocknum].offset, clo->underlying_filename); 2.762 -+ return -1; 2.763 -+ } 2.764 -+ 2.765 -+ /* Go to next position in the cache block buffer (which is used as a cyclic buffer) */ 2.766 -+ if(++clo->current_bufnum >= clo->num_buffered_blocks) clo->current_bufnum = 0; 2.767 + return -1; 2.768 + } 2.769 + 2.770 +@@ -382,14 +373,16 @@ 2.771 + if(++clo->current_bufnum >= clo->num_buffered_blocks) clo->current_bufnum = 0; 2.772 2.773 /* Do the uncompression */ 2.774 -- ret = uncompress(clo, clo->buffer[clo->current_bufnum], &buflen, clo->compressed_buffer, 2.775 -- buf_length); 2.776 +- ret = uncompress(clo, blocknum, compressed_block_len, &uncompressed_block_len); 2.777 + uncompressed_block_len = clo->head.block_size; 2.778 + ret = uncompress(clo, clo->buffer[clo->current_bufnum], &uncompressed_block_len, 2.779 + clo->compressed_buffer, compressed_block_len, clo->block_ptrs[blocknum].flags); 2.780 /* DEBUGP("cloop: buflen after uncompress: %ld\n",buflen); */ 2.781 if (ret != 0) 2.782 -- { 2.783 -- printk(KERN_ERR "%s: zlib decompression error %i uncompressing block %u %u/%lu/%u/%u " 2.784 -- "%Lu-%Lu\n", cloop_name, ret, blocknum, 2.785 -- ntohl(clo->head.block_size), buflen, buf_length, buf_done, 2.786 -- be64_to_cpu(clo->offsets[blocknum]), be64_to_cpu(clo->offsets[blocknum+1])); 2.787 -- clo->buffered_blocknum[clo->current_bufnum] = -1; 2.788 -- return -1; 2.789 -- } 2.790 -+ { 2.791 -+ printk(KERN_ERR "%s: decompression error %i uncompressing block %u %lu bytes @ %llu, flags %u\n", 2.792 -+ cloop_name, ret, blocknum, 2.793 + { 2.794 + printk(KERN_ERR "%s: decompression error %i uncompressing block %u %lu bytes @ %llu, flags %u\n", 2.795 + cloop_name, ret, blocknum, 2.796 +- compressed_block_len, CLOOP_BLOCK_OFFSET(clo->block_ptrs[blocknum]), 2.797 +- CLOOP_BLOCK_FLAGS(clo->block_ptrs[blocknum])); 2.798 + compressed_block_len, clo->block_ptrs[blocknum].offset, 2.799 + clo->block_ptrs[blocknum].flags); 2.800 -+ clo->buffered_blocknum[clo->current_bufnum] = -1; 2.801 -+ return -1; 2.802 -+ } 2.803 - clo->buffered_blocknum[clo->current_bufnum] = blocknum; 2.804 + clo->buffered_blocknum[clo->current_bufnum] = -1; 2.805 + return -1; 2.806 + } 2.807 +@@ -397,107 +390,146 @@ 2.808 return clo->current_bufnum; 2.809 } 2.810 2.811 - /* This function does all the real work. */ 2.812 --/* returns "uptodate" */ 2.813 +-static blk_status_t cloop_handle_request(struct cloop_device *clo, struct request *req) 2.814 ++/* This function does all the real work. */ 2.815 +/* returns "uptodate" */ 2.816 - static int cloop_handle_request(struct cloop_device *clo, struct request *req) 2.817 ++static int cloop_handle_request(struct cloop_device *clo, struct request *req) 2.818 { 2.819 int buffered_blocknum = -1; 2.820 int preloaded = 0; 2.821 - loff_t offset = (loff_t) blk_rq_pos(req)<<9; /* req->sector<<9 */ 2.822 -- struct bio_vec *bvec; 2.823 -+ struct bio_vec bvec; 2.824 +- loff_t offset = (loff_t) blk_rq_pos(req)<<9; 2.825 ++ loff_t offset = (loff_t) blk_rq_pos(req)<<9; /* req->sector<<9 */ 2.826 + struct bio_vec bvec; 2.827 struct req_iterator iter; 2.828 +- blk_status_t ret = BLK_STS_OK; 2.829 +- 2.830 +- if (unlikely(req_op(req) != REQ_OP_READ )) 2.831 +- { 2.832 +- blk_dump_rq_flags(req, DEVICE_NAME " bad request"); 2.833 +- return BLK_STS_IOERR; 2.834 +- } 2.835 +- 2.836 +- if (unlikely(!clo->backing_file && !clo->suspended)) 2.837 +- { 2.838 +- DEBUGP("cloop_handle_request: not connected to a file\n"); 2.839 +- return BLK_STS_IOERR; 2.840 +- } 2.841 +- 2.842 rq_for_each_segment(bvec, req, iter) 2.843 +- { 2.844 +- unsigned long len = bvec.bv_len; 2.845 +- loff_t to_offset = bvec.bv_offset; 2.846 +- 2.847 +- while(len > 0) 2.848 { 2.849 -- unsigned long len = bvec->bv_len; 2.850 -- char *to_ptr = kmap(bvec->bv_page) + bvec->bv_offset; 2.851 +- u_int32_t length_in_buffer; 2.852 +- loff_t block_offset = offset; 2.853 +- u_int32_t offset_in_buffer; 2.854 +- char *from_ptr, *to_ptr; 2.855 +- /* do_div (div64.h) returns the 64bit division remainder and */ 2.856 +- /* puts the result in the first argument, i.e. block_offset */ 2.857 +- /* becomes the blocknumber to load, and offset_in_buffer the */ 2.858 +- /* position in the buffer */ 2.859 +- offset_in_buffer = do_div(block_offset, clo->head.block_size); 2.860 +- /* Lookup preload cache */ 2.861 +- if(block_offset < clo->preload_size && clo->preload_cache != NULL && clo->preload_cache[block_offset] != NULL) 2.862 +- { /* Copy from cache */ 2.863 +- preloaded = 1; 2.864 +- from_ptr = clo->preload_cache[block_offset]; 2.865 +- } 2.866 +- else 2.867 +- { 2.868 +- preloaded = 0; 2.869 +- buffered_blocknum = cloop_load_buffer(clo,block_offset); 2.870 +- if(buffered_blocknum == -1) 2.871 + unsigned long len = bvec.bv_len; 2.872 + char *to_ptr = kmap(bvec.bv_page) + bvec.bv_offset; 2.873 - while(len > 0) 2.874 ++ while(len > 0) 2.875 { 2.876 - u_int32_t length_in_buffer; 2.877 -@@ -308,7 +413,7 @@ 2.878 - /* puts the result in the first argument, i.e. block_offset */ 2.879 - /* becomes the blocknumber to load, and offset_in_buffer the */ 2.880 - /* position in the buffer */ 2.881 -- offset_in_buffer = do_div(block_offset, ntohl(clo->head.block_size)); 2.882 +- ret = BLK_STS_IOERR; 2.883 +- break; /* invalid data, leave inner loop */ 2.884 ++ u_int32_t length_in_buffer; 2.885 ++ loff_t block_offset = offset; 2.886 ++ u_int32_t offset_in_buffer; 2.887 ++ char *from_ptr; 2.888 ++ /* do_div (div64.h) returns the 64bit division remainder and */ 2.889 ++ /* puts the result in the first argument, i.e. block_offset */ 2.890 ++ /* becomes the blocknumber to load, and offset_in_buffer the */ 2.891 ++ /* position in the buffer */ 2.892 + offset_in_buffer = do_div(block_offset, clo->head.block_size); 2.893 - /* Lookup preload cache */ 2.894 - if(block_offset < clo->preload_size && clo->preload_cache != NULL && 2.895 - clo->preload_cache[block_offset] != NULL) 2.896 -@@ -325,7 +430,7 @@ 2.897 - from_ptr = clo->buffer[buffered_blocknum]; 2.898 - } 2.899 - /* Now, at least part of what we want will be in the buffer. */ 2.900 -- length_in_buffer = ntohl(clo->head.block_size) - offset_in_buffer; 2.901 ++ /* Lookup preload cache */ 2.902 ++ if(block_offset < clo->preload_size && clo->preload_cache != NULL && 2.903 ++ clo->preload_cache[block_offset] != NULL) 2.904 ++ { /* Copy from cache */ 2.905 ++ preloaded = 1; 2.906 ++ from_ptr = clo->preload_cache[block_offset]; 2.907 ++ } 2.908 ++ else 2.909 ++ { 2.910 ++ preloaded = 0; 2.911 ++ buffered_blocknum = cloop_load_buffer(clo,block_offset); 2.912 ++ if(buffered_blocknum == -1) break; /* invalid data, leave inner loop */ 2.913 ++ /* Copy from buffer */ 2.914 ++ from_ptr = clo->buffer[buffered_blocknum]; 2.915 ++ } 2.916 ++ /* Now, at least part of what we want will be in the buffer. */ 2.917 + length_in_buffer = clo->head.block_size - offset_in_buffer; 2.918 - if(length_in_buffer > len) 2.919 - { 2.920 - /* DEBUGP("Warning: length_in_buffer=%u > len=%u\n", 2.921 -@@ -337,18 +442,19 @@ 2.922 - len -= length_in_buffer; 2.923 - offset += length_in_buffer; 2.924 - } /* while inner loop */ 2.925 -- kunmap(bvec->bv_page); 2.926 ++ if(length_in_buffer > len) 2.927 ++ { 2.928 ++/* DEBUGP("Warning: length_in_buffer=%u > len=%u\n", 2.929 ++ length_in_buffer,len); */ 2.930 ++ length_in_buffer = len; 2.931 ++ } 2.932 ++ memcpy(to_ptr, from_ptr + offset_in_buffer, length_in_buffer); 2.933 ++ to_ptr += length_in_buffer; 2.934 ++ len -= length_in_buffer; 2.935 ++ offset += length_in_buffer; 2.936 ++ } /* while inner loop */ 2.937 + kunmap(bvec.bv_page); 2.938 + cond_resched(); 2.939 - } /* end rq_for_each_segment*/ 2.940 - return ((buffered_blocknum!=-1) || preloaded); 2.941 - } 2.942 - 2.943 - /* Adopted from loop.c, a kernel thread to handle physical reads and 2.944 -- * decompression. */ 2.945 ++ } /* end rq_for_each_segment*/ 2.946 ++ return ((buffered_blocknum!=-1) || preloaded); 2.947 ++} 2.948 ++ 2.949 ++/* Adopted from loop.c, a kernel thread to handle physical reads and 2.950 + decompression. */ 2.951 - static int cloop_thread(void *data) 2.952 - { 2.953 - struct cloop_device *clo = data; 2.954 - current->flags |= PF_NOFREEZE; 2.955 -- set_user_nice(current, -15); 2.956 ++static int cloop_thread(void *data) 2.957 ++{ 2.958 ++ struct cloop_device *clo = data; 2.959 ++ current->flags |= PF_NOFREEZE; 2.960 + set_user_nice(current, 10); 2.961 - while (!kthread_should_stop()||!list_empty(&clo->clo_list)) 2.962 - { 2.963 - int err; 2.964 -@@ -390,10 +496,18 @@ 2.965 - int rw; 2.966 - /* quick sanity checks */ 2.967 - /* blk_fs_request() was removed in 2.6.36 */ 2.968 -- if (unlikely(req == NULL || (req->cmd_type != REQ_TYPE_FS))) 2.969 ++ while (!kthread_should_stop()||!list_empty(&clo->clo_list)) 2.970 ++ { 2.971 ++ int err; 2.972 ++ err = wait_event_interruptible(clo->clo_event, !list_empty(&clo->clo_list) || 2.973 ++ kthread_should_stop()); 2.974 ++ if(unlikely(err)) 2.975 ++ { 2.976 ++ DEBUGP(KERN_ERR "cloop thread activated on error!? Continuing.\n"); 2.977 ++ continue; 2.978 + } 2.979 +- /* Copy from buffer */ 2.980 +- from_ptr = clo->buffer[buffered_blocknum]; 2.981 +- } 2.982 +- /* Now, at least part of what we want will be in the buffer. */ 2.983 +- length_in_buffer = clo->head.block_size - offset_in_buffer; 2.984 +- if(length_in_buffer > len) 2.985 +- { 2.986 +- /* DEBUGP("Warning: length_in_buffer=%u > len=%u\n", length_in_buffer,len); */ 2.987 +- length_in_buffer = len; 2.988 +- } 2.989 +- to_ptr = kmap_atomic(bvec.bv_page); 2.990 +- memcpy(to_ptr + to_offset, from_ptr + offset_in_buffer, length_in_buffer); 2.991 +- kunmap_atomic(to_ptr); 2.992 +- to_offset += length_in_buffer; 2.993 +- len -= length_in_buffer; 2.994 +- offset += length_in_buffer; 2.995 +- } /* while inner loop */ 2.996 +- } /* rq_for_each_segment */ 2.997 +- return ret; 2.998 +-} 2.999 +- 2.1000 +-static blk_status_t cloop_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) 2.1001 +-{ 2.1002 +-// struct request_queue *q = hctx->queue; 2.1003 +-// struct cloop_device *clo = q->queuedata; 2.1004 +- struct request *req = bd->rq; 2.1005 +- struct cloop_device *clo = req->rq_disk->private_data; 2.1006 +- blk_status_t ret = BLK_STS_OK; 2.1007 +- 2.1008 +-#if 1 /* Does it work when loading libraries? */ 2.1009 +- /* Since we have a buffered block list as well as data to read */ 2.1010 +- /* from disk (slow), and are (probably) never called from an */ 2.1011 +- /* interrupt, we use a simple mutex lock right here to ensure */ 2.1012 +- /* consistency. */ 2.1013 +- mutex_lock(&clo->clo_rq_mutex); 2.1014 +- #else 2.1015 +- spin_lock_irq(&clo->queue_lock); 2.1016 +- #endif 2.1017 +- blk_mq_start_request(req); 2.1018 +- do { 2.1019 +- ret = cloop_handle_request(clo, req); 2.1020 +- } while(blk_update_request(req, ret, blk_rq_cur_bytes(req))); 2.1021 +- blk_mq_end_request(req, ret); 2.1022 +- #if 1 /* See above */ 2.1023 +- mutex_unlock(&clo->clo_rq_mutex); 2.1024 +- #else 2.1025 +- spin_unlock_irq(&clo->queue_lock); 2.1026 +- #endif 2.1027 +- return ret; 2.1028 ++ if(!list_empty(&clo->clo_list)) 2.1029 ++ { 2.1030 ++ struct request *req; 2.1031 ++ unsigned long flags; 2.1032 ++ int uptodate; 2.1033 ++ spin_lock_irq(&clo->queue_lock); 2.1034 ++ req = list_entry(clo->clo_list.next, struct request, queuelist); 2.1035 ++ list_del_init(&req->queuelist); 2.1036 ++ spin_unlock_irq(&clo->queue_lock); 2.1037 ++ uptodate = cloop_handle_request(clo, req); 2.1038 ++ spin_lock_irqsave(&clo->queue_lock, flags); 2.1039 ++ __blk_end_request_all(req, uptodate ? 0 : -EIO); 2.1040 ++ spin_unlock_irqrestore(&clo->queue_lock, flags); 2.1041 ++ } 2.1042 ++ } 2.1043 ++ DEBUGP(KERN_ERR "cloop_thread exited.\n"); 2.1044 ++ return 0; 2.1045 ++} 2.1046 ++ 2.1047 ++/* This is called by the kernel block queue management every now and then, 2.1048 ++ * with successive read requests qeued and sorted in a (hopefully) 2.1049 ++ * "most efficient way". spin_lock_irq() is being held by the kernel. */ 2.1050 ++static void cloop_do_request(struct request_queue *q) 2.1051 ++{ 2.1052 ++ struct request *req; 2.1053 ++ while((req = blk_fetch_request(q)) != NULL) 2.1054 ++ { 2.1055 ++ struct cloop_device *clo; 2.1056 ++ int rw; 2.1057 ++ /* quick sanity checks */ 2.1058 ++ /* blk_fs_request() was removed in 2.6.36 */ 2.1059 + if (unlikely(req == NULL 2.1060 +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) /* field removed */ 2.1061 + || (req->cmd_type != REQ_TYPE_FS) 2.1062 +#endif 2.1063 + )) 2.1064 - goto error_continue; 2.1065 - rw = rq_data_dir(req); 2.1066 -- if (unlikely(rw != READ && rw != READA)) 2.1067 ++ goto error_continue; 2.1068 ++ rw = rq_data_dir(req); 2.1069 + if (unlikely(rw != READ 2.1070 +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) 2.1071 + && rw != READA 2.1072 +#endif 2.1073 + )) 2.1074 - { 2.1075 - DEBUGP("cloop_do_request: bad command\n"); 2.1076 - goto error_continue; 2.1077 -@@ -409,40 +523,51 @@ 2.1078 - continue; /* next request */ 2.1079 - error_continue: 2.1080 - DEBUGP(KERN_ERR "cloop_do_request: Discarding request %p.\n", req); 2.1081 ++ { 2.1082 ++ DEBUGP("cloop_do_request: bad command\n"); 2.1083 ++ goto error_continue; 2.1084 ++ } 2.1085 ++ clo = req->rq_disk->private_data; 2.1086 ++ if (unlikely(!clo->backing_file && !clo->suspended)) 2.1087 ++ { 2.1088 ++ DEBUGP("cloop_do_request: not connected to a file\n"); 2.1089 ++ goto error_continue; 2.1090 ++ } 2.1091 ++ list_add_tail(&req->queuelist, &clo->clo_list); /* Add to working list for thread */ 2.1092 ++ wake_up(&clo->clo_event); /* Wake up cloop_thread */ 2.1093 ++ continue; /* next request */ 2.1094 ++ error_continue: 2.1095 ++ DEBUGP(KERN_ERR "cloop_do_request: Discarding request %p.\n", req); 2.1096 +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) 2.1097 - req->errors++; 2.1098 ++ req->errors++; 2.1099 +#else 2.1100 + req->error_count++; 2.1101 +#endif 2.1102 - __blk_end_request_all(req, -EIO); 2.1103 - } 2.1104 ++ __blk_end_request_all(req, -EIO); 2.1105 ++ } 2.1106 } 2.1107 2.1108 --/* Read header and offsets from already opened file */ 2.1109 --static int cloop_set_file(int cloop_num, struct file *file, char *filename) 2.1110 -+/* Read header, flags and offsets from already opened file */ 2.1111 -+static int cloop_set_file(int cloop_num, struct file *file) 2.1112 - { 2.1113 - struct cloop_device *clo = cloop_dev[cloop_num]; 2.1114 - struct inode *inode; 2.1115 + /* Read header, flags and offsets from already opened file */ 2.1116 +@@ -508,7 +540,7 @@ 2.1117 char *bbuf=NULL; 2.1118 -- unsigned int i, offsets_read, total_offsets; 2.1119 -- int isblkdev; 2.1120 -- int error = 0; 2.1121 -+ unsigned int bbuf_size = 0; 2.1122 -+ const unsigned int header_size = sizeof(struct cloop_head); 2.1123 + unsigned int bbuf_size = 0; 2.1124 + const unsigned int header_size = sizeof(struct cloop_head); 2.1125 +- unsigned int i, offsets_read=0, total_offsets=0; 2.1126 + unsigned int i, total_offsets=0; 2.1127 -+ loff_t fs_read_position = 0, header_pos[2]; 2.1128 -+ int flags, isblkdev, bytes_read, error = 0; 2.1129 -+ if (clo->suspended) return error; 2.1130 -+ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) 2.1131 - inode = file->f_dentry->d_inode; 2.1132 -+ clo->underlying_filename = kstrdup(file->f_dentry->d_name.name ? file->f_dentry->d_name.name : (const unsigned char *)"anonymous filename", GFP_KERNEL); 2.1133 -+ #else 2.1134 -+ inode = file->f_path.dentry->d_inode; 2.1135 -+ 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); 2.1136 -+ #endif 2.1137 - isblkdev=S_ISBLK(inode->i_mode)?1:0; 2.1138 - if(!isblkdev&&!S_ISREG(inode->i_mode)) 2.1139 + loff_t fs_read_position = 0, header_pos[2]; 2.1140 + int isblkdev, bytes_read, error = 0; 2.1141 + if (clo->suspended) return error; 2.1142 +@@ -581,29 +613,19 @@ 2.1143 + goto error_release; 2.1144 + } 2.1145 + memcpy(&clo->head, bbuf, header_size); 2.1146 +- if (strncmp(bbuf+CLOOP4_SIGNATURE_OFFSET, CLOOP4_SIGNATURE, CLOOP4_SIGNATURE_SIZE)==0) 2.1147 ++ if (strncmp(bbuf+CLOOP_SIGNATURE_OFFSET, CLOOP_SIGNATURE, CLOOP_SIGNATURE_SIZE)==0) 2.1148 + { 2.1149 +- clo->file_format=4; 2.1150 ++ clo->file_format++; 2.1151 + clo->head.block_size=ntohl(clo->head.block_size); 2.1152 + clo->head.num_blocks=ntohl(clo->head.num_blocks); 2.1153 + clo->header_first = (i==0) ? 1 : 0; 2.1154 +- printk(KERN_INFO "%s: file %s version %d, %d blocks of %d bytes, header %s.\n", cloop_name, clo->underlying_filename, clo->file_format, clo->head.num_blocks, clo->head.block_size, (i==0)?"first":"last"); 2.1155 +- break; 2.1156 +- } 2.1157 +- else if (strncmp(bbuf+CLOOP2_SIGNATURE_OFFSET, CLOOP2_SIGNATURE, CLOOP2_SIGNATURE_SIZE)==0) 2.1158 +- { 2.1159 +- clo->file_format=2; 2.1160 +- clo->head.block_size=ntohl(clo->head.block_size); 2.1161 +- clo->head.num_blocks=ntohl(clo->head.num_blocks); 2.1162 +- clo->header_first = (i==0) ? 1 : 0; 2.1163 +- printk(KERN_INFO "%s: file %s version %d, %d blocks of %d bytes, header %s.\n", cloop_name, clo->underlying_filename, clo->file_format, clo->head.num_blocks, clo->head.block_size, (i==0)?"first":"last"); 2.1164 ++ 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"); 2.1165 + break; 2.1166 + } 2.1167 + } 2.1168 + if (clo->file_format == 0) 2.1169 { 2.1170 - printk(KERN_ERR "%s: %s not a regular file or block device\n", 2.1171 -- cloop_name, filename); 2.1172 -+ cloop_name, clo->underlying_filename); 2.1173 +- printk(KERN_ERR "%s: Cannot read old 32-bit (version 0.68) images, " 2.1174 +- "please use an older version of %s for this file.\n", 2.1175 ++ printk(KERN_ERR "%s: Cannot detect %s format.\n", 2.1176 + cloop_name, cloop_name); 2.1177 + error=-EBADF; goto error_release; 2.1178 + } 2.1179 +@@ -613,67 +635,133 @@ 2.1180 + cloop_name, clo->head.block_size); 2.1181 error=-EBADF; goto error_release; 2.1182 } 2.1183 - clo->backing_file = file; 2.1184 - clo->backing_inode= inode ; 2.1185 -- if(!isblkdev&&inode->i_size<sizeof(struct cloop_head)) 2.1186 -+ clo->underlying_total_size = (isblkdev) ? inode->i_bdev->bd_inode->i_size : inode->i_size; 2.1187 -+ if(clo->underlying_total_size < header_size) 2.1188 +- total_offsets=clo->head.num_blocks+1; 2.1189 +- if (!isblkdev && (sizeof(struct cloop_head)+sizeof(loff_t)* 2.1190 ++ total_offsets=clo->head.num_blocks; 2.1191 ++ if (!isblkdev && (sizeof(struct cloop_head)+sizeof(struct block_info)* 2.1192 + total_offsets > inode->i_size)) 2.1193 { 2.1194 -- printk(KERN_ERR "%s: %lu bytes (must be >= %u bytes)\n", 2.1195 -- cloop_name, (unsigned long)inode->i_size, 2.1196 -- (unsigned)sizeof(struct cloop_head)); 2.1197 -+ printk(KERN_ERR "%s: %llu bytes (must be >= %u bytes)\n", 2.1198 -+ cloop_name, clo->underlying_total_size, 2.1199 -+ (unsigned int)header_size); 2.1200 + printk(KERN_ERR "%s: file %s too small for %u blocks\n", 2.1201 + cloop_name, clo->underlying_filename, clo->head.num_blocks); 2.1202 error=-EBADF; goto error_release; 2.1203 } 2.1204 -- /* In suspended mode, we have done all checks necessary - FF */ 2.1205 -- if (clo->suspended) 2.1206 -- return error; 2.1207 - if(isblkdev) 2.1208 - { 2.1209 - struct request_queue *q = bdev_get_queue(inode->i_bdev); 2.1210 -@@ -451,104 +576,225 @@ 2.1211 - /* blk_queue_max_hw_segments(clo->clo_queue, queue_max_hw_segments(q)); */ /* Removed in 2.6.34 */ 2.1212 - blk_queue_max_segment_size(clo->clo_queue, queue_max_segment_size(q)); 2.1213 - blk_queue_segment_boundary(clo->clo_queue, queue_segment_boundary(q)); 2.1214 -+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) 2.1215 - blk_queue_merge_bvec(clo->clo_queue, q->merge_bvec_fn); 2.1216 -+#endif 2.1217 - clo->underlying_blksize = block_size(inode->i_bdev); 2.1218 - } 2.1219 - else 2.1220 - clo->underlying_blksize = PAGE_SIZE; 2.1221 -- DEBUGP("Underlying blocksize is %u\n", clo->underlying_blksize); 2.1222 -- bbuf = cloop_malloc(clo->underlying_blksize); 2.1223 -+ 2.1224 -+ DEBUGP(KERN_INFO "Underlying blocksize of %s is %u\n", clo->underlying_filename, clo->underlying_blksize); 2.1225 -+ DEBUGP(KERN_INFO "Underlying total size of %s is %llu\n", clo->underlying_filename, clo->underlying_total_size); 2.1226 -+ 2.1227 -+ /* clo->underlying_blksize should be larger than header_size, even if it's only PAGE_SIZE */ 2.1228 -+ bbuf_size = clo->underlying_blksize; 2.1229 -+ bbuf = cloop_malloc(bbuf_size); 2.1230 - if(!bbuf) 2.1231 - { 2.1232 -- printk(KERN_ERR "%s: out of kernel mem for block buffer (%lu bytes)\n", 2.1233 -- cloop_name, (unsigned long)clo->underlying_blksize); 2.1234 -+ printk(KERN_ERR "%s: out of kernel mem for buffer (%u bytes)\n", 2.1235 -+ cloop_name, (unsigned int) bbuf_size); 2.1236 -+ error=-ENOMEM; goto error_release; 2.1237 -+ } 2.1238 -+ 2.1239 -+ header_pos[0] = 0; /* header first */ 2.1240 -+ header_pos[1] = clo->underlying_total_size - sizeof(struct cloop_head); /* header last */ 2.1241 -+ for(i=0; i<2; i++) 2.1242 -+ { 2.1243 -+ /* Check for header */ 2.1244 -+ size_t bytes_readable = MIN(clo->underlying_blksize, clo->underlying_total_size - header_pos[i]); 2.1245 -+ size_t bytes_read = cloop_read_from_file(clo, file, bbuf, header_pos[i], bytes_readable); 2.1246 -+ if(bytes_read != bytes_readable) 2.1247 -+ { 2.1248 -+ printk(KERN_ERR "%s: Bad file %s, read() of %s %u bytes returned %d.\n", 2.1249 -+ cloop_name, clo->underlying_filename, (i==0)?"first":"last", 2.1250 -+ (unsigned int)header_size, (int)bytes_read); 2.1251 -+ error=-EBADF; 2.1252 -+ goto error_release; 2.1253 -+ } 2.1254 -+ memcpy(&clo->head, bbuf, header_size); 2.1255 -+ if (strncmp(bbuf+CLOOP_SIGNATURE_OFFSET, CLOOP_SIGNATURE, CLOOP_SIGNATURE_SIZE)==0) 2.1256 -+ { 2.1257 -+ clo->file_format++; 2.1258 -+ clo->head.block_size=ntohl(clo->head.block_size); 2.1259 -+ clo->head.num_blocks=ntohl(clo->head.num_blocks); 2.1260 -+ clo->header_first = (i==0) ? 1 : 0; 2.1261 -+ 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"); 2.1262 -+ break; 2.1263 -+ } 2.1264 -+ } 2.1265 -+ if (clo->file_format == 0) 2.1266 -+ { 2.1267 -+ printk(KERN_ERR "%s: Cannot detect %s format.\n", 2.1268 -+ cloop_name, cloop_name); 2.1269 -+ error=-EBADF; goto error_release; 2.1270 -+ } 2.1271 -+ if (clo->head.block_size % 512 != 0) 2.1272 -+ { 2.1273 -+ printk(KERN_ERR "%s: blocksize %u not multiple of 512\n", 2.1274 -+ cloop_name, clo->head.block_size); 2.1275 -+ error=-EBADF; goto error_release; 2.1276 -+ } 2.1277 -+ total_offsets=clo->head.num_blocks; 2.1278 -+ if (!isblkdev && (sizeof(struct cloop_head)+sizeof(struct block_info)* 2.1279 -+ total_offsets > inode->i_size)) 2.1280 -+ { 2.1281 -+ printk(KERN_ERR "%s: file %s too small for %u blocks\n", 2.1282 -+ cloop_name, clo->underlying_filename, clo->head.num_blocks); 2.1283 -+ error=-EBADF; goto error_release; 2.1284 -+ } 2.1285 +- clo->block_ptrs = cloop_malloc(sizeof(cloop_block_ptr) * total_offsets); 2.1286 +- if (!clo->block_ptrs) 2.1287 + /* Allocate Memory for decompressors */ 2.1288 +#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 2.1289 + clo->zstream.workspace = cloop_malloc(zlib_inflate_workspacesize()); 2.1290 + if(!clo->zstream.workspace) 2.1291 -+ { 2.1292 + { 2.1293 +- printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name); 2.1294 + printk(KERN_ERR "%s: out of mem for zlib working area %u\n", 2.1295 + cloop_name, zlib_inflate_workspacesize()); 2.1296 error=-ENOMEM; goto error_release; 2.1297 } 2.1298 -- total_offsets = 1; /* Dummy total_offsets: will be filled in first time around */ 2.1299 -- for (i = 0, offsets_read = 0; offsets_read < total_offsets; i++) 2.1300 +- /* Read them offsets! */ 2.1301 +- if(clo->header_first) 2.1302 + zlib_inflateInit(&clo->zstream); 2.1303 +#endif 2.1304 +#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 2.1305 @@ -890,33 +713,20 @@ 2.1306 +#endif 2.1307 + if (total_offsets + 1 == 0) /* Version 3 */ 2.1308 { 2.1309 -- unsigned int offset = 0, num_readable; 2.1310 -- size_t bytes_read = cloop_read_from_file(clo, file, bbuf, 2.1311 -- i*clo->underlying_blksize, 2.1312 -- clo->underlying_blksize); 2.1313 -- if(bytes_read != clo->underlying_blksize) 2.1314 +- fs_read_position = sizeof(struct cloop_head); 2.1315 + struct cloop_tail tail; 2.1316 + if (isblkdev) 2.1317 - { 2.1318 -- printk(KERN_ERR "%s: Bad file, read() of first %lu bytes returned %d.\n", 2.1319 -- cloop_name, (unsigned long)clo->underlying_blksize, (int)bytes_read); 2.1320 -- error=-EBADF; 2.1321 -- goto error_release; 2.1322 ++ { 2.1323 + /* No end of file: can't find index */ 2.1324 + printk(KERN_ERR "%s: no V3 support for block device\n", 2.1325 + cloop_name); 2.1326 + error=-EBADF; goto error_release; 2.1327 - } 2.1328 -- /* Header will be in block zero */ 2.1329 -- if(i==0) 2.1330 ++ } 2.1331 + bytes_read = cloop_read_from_file(clo, file, (void *) &tail, 2.1332 + inode->i_size - sizeof(struct cloop_tail), 2.1333 + sizeof(struct cloop_tail)); 2.1334 + if (bytes_read == sizeof(struct cloop_tail)) 2.1335 - { 2.1336 -- memcpy(&clo->head, bbuf, sizeof(struct cloop_head)); 2.1337 -- offset = sizeof(struct cloop_head); 2.1338 -- if (ntohl(clo->head.block_size) % 512 != 0) 2.1339 ++ { 2.1340 + unsigned long len, zlen; 2.1341 + int ret; 2.1342 + void *zbuf; 2.1343 @@ -926,79 +736,47 @@ 2.1344 + zlen = ntohl(tail.table_size); 2.1345 + zbuf = cloop_malloc(zlen); 2.1346 + if (!clo->block_ptrs || !zbuf) 2.1347 - { 2.1348 -- printk(KERN_ERR "%s: blocksize %u not multiple of 512\n", 2.1349 -- cloop_name, ntohl(clo->head.block_size)); 2.1350 -- error=-EBADF; goto error_release; 2.1351 -- } 2.1352 -- if (clo->head.preamble[0x0B]!='V'||clo->head.preamble[0x0C]<'1') 2.1353 -- { 2.1354 -- printk(KERN_ERR "%s: Cannot read old 32-bit (version 0.68) images, " 2.1355 -- "please use an older version of %s for this file.\n", 2.1356 -- cloop_name, cloop_name); 2.1357 -- error=-EBADF; goto error_release; 2.1358 ++ { 2.1359 + printk(KERN_ERR "%s: out of kernel mem for index\n", cloop_name); 2.1360 + error=-ENOMEM; goto error_release; 2.1361 - } 2.1362 -- if (clo->head.preamble[0x0C]<'2') 2.1363 ++ } 2.1364 + bytes_read = cloop_read_from_file(clo, file, zbuf, 2.1365 + inode->i_size - zlen - sizeof(struct cloop_tail), 2.1366 + zlen); 2.1367 + if (bytes_read != zlen) 2.1368 - { 2.1369 -- printk(KERN_ERR "%s: Cannot read old architecture-dependent " 2.1370 -- "(format <= 1.0) images, please use an older " 2.1371 -- "version of %s for this file.\n", 2.1372 -- cloop_name, cloop_name); 2.1373 ++ { 2.1374 + printk(KERN_ERR "%s: can't read index\n", cloop_name); 2.1375 - error=-EBADF; goto error_release; 2.1376 - } 2.1377 -- total_offsets=ntohl(clo->head.num_blocks)+1; 2.1378 -- if (!isblkdev && (sizeof(struct cloop_head)+sizeof(loff_t)* 2.1379 -- total_offsets > inode->i_size)) 2.1380 ++ error=-EBADF; goto error_release; 2.1381 ++ } 2.1382 + len = CLOOP3_INDEX_SIZE(ntohl(tail.index_size)) * total_offsets; 2.1383 -+ flags = CLOOP3_BLOCKS_FLAGS(ntohl(tail.index_size)); 2.1384 -+// 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) 2.1385 -+printk(KERN_INFO "%s: uncompress(clo=%p, block_ptrs=%p, &len(%ld)=%p, zbuf=%p, zlen=%ld, flag=%d)\n", cloop_name, 2.1386 -+ clo, clo->block_ptrs, len, &len, zbuf, zlen, flags); 2.1387 -+ ret = uncompress(clo, (void *) clo->block_ptrs, &len, zbuf, zlen, flags); 2.1388 -+// May 3 19:45:20 (none) user.alert kernel: BUG: unable to handle kernel NULL pointer dereference at (null) 2.1389 -+printk(KERN_INFO "%s: uncompressed !\n", cloop_name); 2.1390 ++ ret = uncompress(clo, (void *) clo->block_ptrs, &len, zbuf, zlen, CLOOP_COMPRESSOR_ZLIB); 2.1391 + cloop_free(zbuf, zlen); 2.1392 + if (ret != 0) 2.1393 - { 2.1394 -- printk(KERN_ERR "%s: file too small for %u blocks\n", 2.1395 -- cloop_name, ntohl(clo->head.num_blocks)); 2.1396 -+ printk(KERN_ERR "%s: decompression error %i uncompressing index, flags %u\n", 2.1397 -+ cloop_name, ret, flags); 2.1398 - error=-EBADF; goto error_release; 2.1399 - } 2.1400 -- clo->offsets = cloop_malloc(sizeof(loff_t) * total_offsets); 2.1401 -- if (!clo->offsets) 2.1402 -- { 2.1403 -- printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name); 2.1404 -- error=-ENOMEM; goto error_release; 2.1405 -- } 2.1406 - } 2.1407 -- num_readable = MIN(total_offsets - offsets_read, 2.1408 -- (clo->underlying_blksize - offset) 2.1409 -- / sizeof(loff_t)); 2.1410 -- memcpy(&clo->offsets[offsets_read], bbuf+offset, num_readable * sizeof(loff_t)); 2.1411 -- offsets_read += num_readable; 2.1412 -- } 2.1413 -- { /* Search for largest block rather than estimate. KK. */ 2.1414 -- int i; 2.1415 -- for(i=0;i<total_offsets-1;i++) 2.1416 ++ { 2.1417 ++ printk(KERN_ERR "%s: decompression error %i uncompressing index\n", 2.1418 ++ cloop_name, ret); 2.1419 ++ error=-EBADF; goto error_release; 2.1420 ++ } 2.1421 ++ } 2.1422 + else 2.1423 + { 2.1424 + printk(KERN_ERR "%s: can't find index\n", cloop_name); 2.1425 + error=-ENOMEM; goto error_release; 2.1426 + } 2.1427 -+ } 2.1428 -+ else 2.1429 -+ { 2.1430 + } 2.1431 + else 2.1432 + { 2.1433 +- fs_read_position = clo->underlying_total_size - sizeof(struct cloop_head) - total_offsets * sizeof(loff_t); 2.1434 +- } 2.1435 +- for(offsets_read=0;offsets_read<total_offsets;) 2.1436 +- { 2.1437 +- size_t bytes_readable; 2.1438 +- unsigned int num_readable, offset = 0; 2.1439 +- bytes_readable = MIN(bbuf_size, clo->underlying_total_size - fs_read_position); 2.1440 +- if(bytes_readable <= 0) break; /* Done */ 2.1441 +- bytes_read = cloop_read_from_file(clo, file, bbuf, fs_read_position, bytes_readable); 2.1442 +- if(bytes_read != bytes_readable) 2.1443 + unsigned int n, total_bytes; 2.1444 -+ flags = 0; 2.1445 + clo->block_ptrs = cloop_malloc(sizeof(struct block_info) * total_offsets); 2.1446 + if (!clo->block_ptrs) 2.1447 + { 2.1448 @@ -1007,14 +785,26 @@ 2.1449 + } 2.1450 + /* Read them offsets! */ 2.1451 + if(clo->header_first) 2.1452 -+ { 2.1453 + { 2.1454 +- printk(KERN_ERR "%s: Bad file %s, read() %lu bytes @ %llu returned %d.\n", 2.1455 +- cloop_name, clo->underlying_filename, (unsigned long)clo->underlying_blksize, fs_read_position, (int)bytes_read); 2.1456 +- error=-EBADF; 2.1457 +- goto error_release; 2.1458 + total_bytes = total_offsets * sizeof(struct block_info); 2.1459 + fs_read_position = sizeof(struct cloop_head); 2.1460 -+ } 2.1461 + } 2.1462 +- /* remember where to read the next blk from file */ 2.1463 +- fs_read_position += bytes_read; 2.1464 +- /* calculate how many offsets can be taken from current bbuf */ 2.1465 +- num_readable = MIN(total_offsets - offsets_read, 2.1466 +- bytes_read / sizeof(loff_t)); 2.1467 +- DEBUGP(KERN_INFO "cloop: parsing %d offsets %d to %d\n", num_readable, offsets_read, offsets_read+num_readable-1); 2.1468 +- for (i=0,offset=0; i<num_readable; i++) 2.1469 + else 2.1470 { 2.1471 -- loff_t d=be64_to_cpu(clo->offsets[i+1]) - be64_to_cpu(clo->offsets[i]); 2.1472 -- clo->largest_block=MAX(clo->largest_block,d); 2.1473 +- loff_t tmp = be64_to_cpu( *(loff_t*) (bbuf+offset) ); 2.1474 +- if (i%50==0) DEBUGP(KERN_INFO "cloop: offset %03d: %llu\n", offsets_read, tmp); 2.1475 +- if(offsets_read > 0) 2.1476 + total_bytes = total_offsets * sizeof(loff_t); 2.1477 + fs_read_position = clo->underlying_total_size - sizeof(struct cloop_head) - total_bytes; 2.1478 + } 2.1479 @@ -1025,35 +815,28 @@ 2.1480 + if(bytes_readable <= 0) break; /* Done */ 2.1481 + bytes_read = cloop_read_from_file(clo, file, bbuf, fs_read_position, bytes_readable); 2.1482 + if(bytes_read != bytes_readable) 2.1483 -+ { 2.1484 + { 2.1485 +- loff_t d = CLOOP_BLOCK_OFFSET(tmp) - CLOOP_BLOCK_OFFSET(clo->block_ptrs[offsets_read-1]); 2.1486 +- if(d > clo->largest_block) clo->largest_block = d; 2.1487 + printk(KERN_ERR "%s: Bad file %s, read() %lu bytes @ %llu returned %d.\n", 2.1488 + cloop_name, clo->underlying_filename, (unsigned long)clo->underlying_blksize, fs_read_position, (int)bytes_read); 2.1489 + error=-EBADF; 2.1490 + goto error_release; 2.1491 -+ } 2.1492 + } 2.1493 +- clo->block_ptrs[offsets_read++] = tmp; 2.1494 +- offset += sizeof(loff_t); 2.1495 + memcpy(((char *)clo->block_ptrs) + n, bbuf, bytes_read); 2.1496 + /* remember where to read the next blk from file */ 2.1497 + fs_read_position += bytes_read; 2.1498 + n += bytes_read; 2.1499 } 2.1500 -- printk(KERN_INFO "%s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n", 2.1501 -- cloop_name, filename, ntohl(clo->head.num_blocks), 2.1502 -- ntohl(clo->head.block_size), clo->largest_block); 2.1503 } 2.1504 --/* Combo kmalloc used too large chunks (>130000). */ 2.1505 +- printk(KERN_INFO "%s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n", 2.1506 +- cloop_name, clo->underlying_filename, clo->head.num_blocks, 2.1507 +- clo->head.block_size, clo->largest_block); 2.1508 { 2.1509 int i; 2.1510 -- for(i=0;i<BUFFERED_BLOCKS;i++) 2.1511 -- { 2.1512 -- clo->buffer[i] = cloop_malloc(ntohl(clo->head.block_size)); 2.1513 -- if(!clo->buffer[i]) 2.1514 -- { 2.1515 -- printk(KERN_ERR "%s: out of memory for buffer %lu\n", 2.1516 -- cloop_name, (unsigned long) ntohl(clo->head.block_size)); 2.1517 -- error=-ENOMEM; goto error_release_free; 2.1518 -- } 2.1519 -- } 2.1520 -+ char *version = build_index(clo->block_ptrs, clo->head.num_blocks, clo->head.block_size, flags); 2.1521 ++ char *version = build_index(clo->block_ptrs, clo->head.num_blocks, clo->head.block_size); 2.1522 + clo->largest_block = 0; 2.1523 + for (i = 0; i < clo->head.num_blocks; i++) 2.1524 + if (clo->block_ptrs[i].size > clo->largest_block) 2.1525 @@ -1061,39 +844,15 @@ 2.1526 + printk(KERN_INFO "%s: %s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n", 2.1527 + cloop_name, clo->underlying_filename, version, clo->head.num_blocks, 2.1528 + clo->head.block_size, clo->largest_block); 2.1529 -+ } 2.1530 -+ { 2.1531 -+ int i; 2.1532 -+ clo->num_buffered_blocks = (buffers > 0 && clo->head.block_size >= 512) ? 2.1533 -+ (buffers / clo->head.block_size) : 1; 2.1534 -+ clo->buffered_blocknum = cloop_malloc(clo->num_buffered_blocks * sizeof (u_int32_t)); 2.1535 -+ clo->buffer = cloop_malloc(clo->num_buffered_blocks * sizeof (char*)); 2.1536 -+ if (!clo->buffered_blocknum || !clo->buffer) 2.1537 -+ { 2.1538 -+ printk(KERN_ERR "%s: out of memory for index of cache buffer (%lu bytes)\n", 2.1539 -+ cloop_name, (unsigned long)clo->num_buffered_blocks * sizeof (u_int32_t) + sizeof(char*) ); 2.1540 -+ error=-ENOMEM; goto error_release; 2.1541 -+ } 2.1542 -+ memset(clo->buffer, 0, clo->num_buffered_blocks * sizeof (char*)); 2.1543 -+ for(i=0;i<clo->num_buffered_blocks;i++) 2.1544 -+ { 2.1545 -+ clo->buffered_blocknum[i] = -1; 2.1546 -+ clo->buffer[i] = cloop_malloc(clo->head.block_size); 2.1547 -+ if(!clo->buffer[i]) 2.1548 -+ { 2.1549 -+ printk(KERN_ERR "%s: out of memory for cache buffer %lu\n", 2.1550 -+ cloop_name, (unsigned long) clo->head.block_size); 2.1551 -+ error=-ENOMEM; goto error_release_free; 2.1552 -+ } 2.1553 -+ } 2.1554 -+ clo->current_bufnum = 0; 2.1555 - } 2.1556 - clo->compressed_buffer = cloop_malloc(clo->largest_block); 2.1557 - if(!clo->compressed_buffer) 2.1558 -@@ -557,31 +803,7 @@ 2.1559 + clo->num_buffered_blocks = (buffers > 0 && clo->head.block_size >= 512) ? 2.1560 + (buffers / clo->head.block_size) : 1; 2.1561 + clo->buffered_blocknum = cloop_malloc(clo->num_buffered_blocks * sizeof (u_int32_t)); 2.1562 +@@ -705,36 +793,14 @@ 2.1563 cloop_name, clo->largest_block); 2.1564 error=-ENOMEM; goto error_release_free_buffer; 2.1565 } 2.1566 +- /* Allocate Memory for decompressors */ 2.1567 +-#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 2.1568 - clo->zstream.workspace = cloop_malloc(zlib_inflate_workspacesize()); 2.1569 - if(!clo->zstream.workspace) 2.1570 - { 2.1571 @@ -1102,443 +861,48 @@ 2.1572 - error=-ENOMEM; goto error_release_free_all; 2.1573 - } 2.1574 - zlib_inflateInit(&clo->zstream); 2.1575 -- if(!isblkdev && 2.1576 -- be64_to_cpu(clo->offsets[ntohl(clo->head.num_blocks)]) != inode->i_size) 2.1577 -- { 2.1578 -- printk(KERN_ERR "%s: final offset wrong (%Lu not %Lu)\n", 2.1579 +-#endif 2.1580 +-#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 2.1581 +-#if XZ_INTERNAL_CRC32 2.1582 +- /* This must be called before any other xz_* function to initialize the CRC32 lookup table. */ 2.1583 +- xz_crc32_init(void); 2.1584 +-#endif 2.1585 +- clo->xzdecoderstate = xz_dec_init(XZ_SINGLE, 0); 2.1586 +-#endif 2.1587 +- if(CLOOP_BLOCK_OFFSET(clo->block_ptrs[clo->head.num_blocks]) > clo->underlying_total_size) 2.1588 ++ set_capacity(clo->clo_disk, (sector_t)(clo->head.num_blocks*(clo->head.block_size>>9))); 2.1589 ++ clo->clo_thread = kthread_create(cloop_thread, clo, "cloop%d", cloop_num); 2.1590 ++ if(IS_ERR(clo->clo_thread)) 2.1591 + { 2.1592 +- printk(KERN_ERR "%s: final offset wrong (%llu > %llu)\n", 2.1593 - cloop_name, 2.1594 -- be64_to_cpu(clo->offsets[ntohl(clo->head.num_blocks)]), 2.1595 -- inode->i_size); 2.1596 +- CLOOP_BLOCK_OFFSET(clo->block_ptrs[clo->head.num_blocks]), 2.1597 +- clo->underlying_total_size); 2.1598 +-#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 2.1599 - cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); clo->zstream.workspace=NULL; 2.1600 -- goto error_release_free_all; 2.1601 -- } 2.1602 -- { 2.1603 -- int i; 2.1604 -- for(i=0; i<BUFFERED_BLOCKS; i++) clo->buffered_blocknum[i] = -1; 2.1605 -- clo->current_bufnum=0; 2.1606 -- } 2.1607 -- set_capacity(clo->clo_disk, (sector_t)(ntohl(clo->head.num_blocks)* 2.1608 -- (ntohl(clo->head.block_size)>>9))); 2.1609 -+ set_capacity(clo->clo_disk, (sector_t)(clo->head.num_blocks*(clo->head.block_size>>9))); 2.1610 - clo->clo_thread = kthread_create(cloop_thread, clo, "cloop%d", cloop_num); 2.1611 - if(IS_ERR(clo->clo_thread)) 2.1612 - { 2.1613 -@@ -591,17 +813,17 @@ 2.1614 +-#endif 2.1615 ++ error = PTR_ERR(clo->clo_thread); 2.1616 ++ clo->clo_thread=NULL; 2.1617 + goto error_release_free_all; 2.1618 } 2.1619 +- set_capacity(clo->clo_disk, (sector_t)(clo->head.num_blocks*(clo->head.block_size>>9))); 2.1620 if(preload > 0) 2.1621 { 2.1622 -- clo->preload_array_size = ((preload<=ntohl(clo->head.num_blocks))?preload:ntohl(clo->head.num_blocks)); 2.1623 -+ clo->preload_array_size = ((preload<=clo->head.num_blocks)?preload:clo->head.num_blocks); 2.1624 - clo->preload_size = 0; 2.1625 - if((clo->preload_cache = cloop_malloc(clo->preload_array_size * sizeof(char *))) != NULL) 2.1626 - { 2.1627 - int i; 2.1628 - for(i=0; i<clo->preload_array_size; i++) 2.1629 - { 2.1630 -- if((clo->preload_cache[i] = cloop_malloc(ntohl(clo->head.block_size))) == NULL) 2.1631 -+ if((clo->preload_cache[i] = cloop_malloc(clo->head.block_size)) == NULL) 2.1632 - { /* Out of memory */ 2.1633 - printk(KERN_WARNING "%s: cloop_malloc(%d) failed for preload_cache[%d] (ignored).\n", 2.1634 -- cloop_name, ntohl(clo->head.block_size), i); 2.1635 -+ cloop_name, clo->head.block_size, i); 2.1636 - break; 2.1637 - } 2.1638 - } 2.1639 -@@ -612,13 +834,13 @@ 2.1640 - if(buffered_blocknum >= 0) 2.1641 - { 2.1642 - memcpy(clo->preload_cache[i], clo->buffer[buffered_blocknum], 2.1643 -- ntohl(clo->head.block_size)); 2.1644 -+ clo->head.block_size); 2.1645 - } 2.1646 - else 2.1647 - { 2.1648 - printk(KERN_WARNING "%s: can't read block %d into preload cache, set to zero.\n", 2.1649 - cloop_name, i); 2.1650 -- memset(clo->preload_cache[i], 0, ntohl(clo->head.block_size)); 2.1651 -+ memset(clo->preload_cache[i], 0, clo->head.block_size); 2.1652 - } 2.1653 - } 2.1654 - printk(KERN_INFO "%s: preloaded %d blocks into cache.\n", cloop_name, 2.1655 -@@ -641,22 +863,19 @@ 2.1656 - cloop_free(clo->compressed_buffer, clo->largest_block); 2.1657 - clo->compressed_buffer=NULL; 2.1658 - error_release_free_buffer: 2.1659 -+ if(clo->buffer) 2.1660 - { 2.1661 - int i; 2.1662 -- for(i=0; i<BUFFERED_BLOCKS; i++) 2.1663 -- { 2.1664 -- if(clo->buffer[i]) 2.1665 -- { 2.1666 -- cloop_free(clo->buffer[i], ntohl(clo->head.block_size)); 2.1667 -- clo->buffer[i]=NULL; 2.1668 -- } 2.1669 -- } 2.1670 -+ 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; }} 2.1671 -+ cloop_free(clo->buffer, clo->num_buffered_blocks*sizeof(char*)); clo->buffer=NULL; 2.1672 + clo->preload_array_size = ((preload<=clo->head.num_blocks)?preload:clo->head.num_blocks); 2.1673 +@@ -780,6 +846,7 @@ 2.1674 + clo->preload_array_size = clo->preload_size = 0; 2.1675 + } 2.1676 + } 2.1677 ++ wake_up_process(clo->clo_thread); 2.1678 + /* Uncheck */ 2.1679 + return error; 2.1680 + error_release_free_all: 2.1681 +@@ -794,9 +861,13 @@ 2.1682 } 2.1683 -+ if (clo->buffered_blocknum) { cloop_free(clo->buffered_blocknum, sizeof(int)*clo->num_buffered_blocks); clo->buffered_blocknum=NULL; } 2.1684 + if (clo->buffered_blocknum) { cloop_free(clo->buffered_blocknum, sizeof(int)*clo->num_buffered_blocks); clo->buffered_blocknum=NULL; } 2.1685 error_release_free: 2.1686 -- cloop_free(clo->offsets, sizeof(loff_t) * total_offsets); 2.1687 -- clo->offsets=NULL; 2.1688 +- cloop_free(clo->block_ptrs, sizeof(cloop_block_ptr) * total_offsets); 2.1689 + cloop_free(clo->block_ptrs, sizeof(struct block_info) * total_offsets); 2.1690 -+ clo->block_ptrs=NULL; 2.1691 - error_release: 2.1692 - if(bbuf) cloop_free(bbuf, clo->underlying_blksize); 2.1693 -+ if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; } 2.1694 - clo->backing_file=NULL; 2.1695 - return error; 2.1696 - } 2.1697 -@@ -673,7 +892,7 @@ 2.1698 - if(clo->backing_file) return -EBUSY; 2.1699 - file = fget(arg); /* get filp struct from ioctl arg fd */ 2.1700 - if(!file) return -EBADF; 2.1701 -- error=cloop_set_file(cloop_num,file,"losetup_file"); 2.1702 -+ error=cloop_set_file(cloop_num,file); 2.1703 - set_device_ro(bdev, 1); 2.1704 - if(error) fput(file); 2.1705 - return error; 2.1706 -@@ -684,29 +903,48 @@ 2.1707 - { 2.1708 - struct cloop_device *clo = cloop_dev[cloop_num]; 2.1709 - struct file *filp = clo->backing_file; 2.1710 -- int i; 2.1711 - if(clo->refcnt > 1) /* we needed one fd for the ioctl */ 2.1712 - return -EBUSY; 2.1713 - if(filp==NULL) return -EINVAL; 2.1714 - if(clo->clo_thread) { kthread_stop(clo->clo_thread); clo->clo_thread=NULL; } 2.1715 -- if(filp!=initial_file) fput(filp); 2.1716 -- else { filp_close(initial_file,0); initial_file=NULL; } 2.1717 -+ if(filp!=initial_file) 2.1718 -+ fput(filp); 2.1719 -+ else 2.1720 -+ { 2.1721 -+ filp_close(initial_file,0); 2.1722 -+ initial_file=NULL; 2.1723 -+ } 2.1724 - clo->backing_file = NULL; 2.1725 - clo->backing_inode = NULL; 2.1726 -- if(clo->offsets) { cloop_free(clo->offsets, clo->underlying_blksize); clo->offsets = NULL; } 2.1727 -+ if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; } 2.1728 -+ if(clo->block_ptrs) { cloop_free(clo->block_ptrs, clo->head.num_blocks); clo->block_ptrs = NULL; } 2.1729 - if(clo->preload_cache) 2.1730 -- { 2.1731 -- for(i=0; i < clo->preload_size; i++) 2.1732 -- cloop_free(clo->preload_cache[i], ntohl(clo->head.block_size)); 2.1733 -- cloop_free(clo->preload_cache, clo->preload_array_size * sizeof(char *)); 2.1734 -- clo->preload_cache = NULL; 2.1735 -- clo->preload_size = clo->preload_array_size = 0; 2.1736 -- } 2.1737 -- for(i=0; i<BUFFERED_BLOCKS; i++) 2.1738 -- if(clo->buffer[i]) { cloop_free(clo->buffer[i], ntohl(clo->head.block_size)); clo->buffer[i]=NULL; } 2.1739 -+ { 2.1740 -+ int i; 2.1741 -+ for(i=0; i < clo->preload_size; i++) 2.1742 -+ cloop_free(clo->preload_cache[i], clo->head.block_size); 2.1743 -+ cloop_free(clo->preload_cache, clo->preload_array_size * sizeof(char *)); 2.1744 -+ clo->preload_cache = NULL; 2.1745 -+ clo->preload_size = clo->preload_array_size = 0; 2.1746 -+ } 2.1747 -+ if (clo->buffered_blocknum) 2.1748 -+ { 2.1749 -+ cloop_free(clo->buffered_blocknum, sizeof(int) * clo->num_buffered_blocks); clo->buffered_blocknum = NULL; 2.1750 -+ } 2.1751 -+ if (clo->buffer) 2.1752 -+ { 2.1753 -+ int i; 2.1754 -+ for(i=0; i<clo->num_buffered_blocks; i++) { if(clo->buffer[i]) cloop_free(clo->buffer[i], clo->head.block_size); } 2.1755 -+ cloop_free(clo->buffer, sizeof(char*) * clo->num_buffered_blocks); clo->buffer = NULL; 2.1756 -+ } 2.1757 - if(clo->compressed_buffer) { cloop_free(clo->compressed_buffer, clo->largest_block); clo->compressed_buffer = NULL; } 2.1758 -+#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 2.1759 - zlib_inflateEnd(&clo->zstream); 2.1760 - if(clo->zstream.workspace) { cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); clo->zstream.workspace = NULL; } 2.1761 -+#endif 2.1762 -+#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 2.1763 -+ xz_dec_end(clo->xzdecoderstate); 2.1764 -+#endif 2.1765 - if(bdev) invalidate_bdev(bdev); 2.1766 - if(clo->clo_disk) set_capacity(clo->clo_disk, 0); 2.1767 - return 0; 2.1768 -@@ -731,8 +969,8 @@ 2.1769 - const struct loop_info64 *info) 2.1770 - { 2.1771 - if (!clo->backing_file) return -ENXIO; 2.1772 -- memcpy(clo->clo_file_name, info->lo_file_name, LO_NAME_SIZE); 2.1773 -- clo->clo_file_name[LO_NAME_SIZE-1] = 0; 2.1774 -+ if(clo->underlying_filename) kfree(clo->underlying_filename); 2.1775 -+ clo->underlying_filename = kstrdup(info->lo_file_name, GFP_KERNEL); 2.1776 - return 0; 2.1777 - } 2.1778 - 2.1779 -@@ -743,7 +981,11 @@ 2.1780 - struct kstat stat; 2.1781 - int err; 2.1782 - if (!file) return -ENXIO; 2.1783 -- err = vfs_getattr(file->f_path.mnt, file->f_path.dentry, &stat); 2.1784 -+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) 2.1785 -+ err = vfs_getattr(&file->f_path, &stat); 2.1786 -+#else 2.1787 -+ err = vfs_getattr(&file->f_path, &stat, STATX_INO, AT_STATX_SYNC_AS_STAT); 2.1788 -+#endif 2.1789 - if (err) return err; 2.1790 - memset(info, 0, sizeof(*info)); 2.1791 - info->lo_number = clo->clo_number; 2.1792 -@@ -753,7 +995,8 @@ 2.1793 - info->lo_offset = 0; 2.1794 - info->lo_sizelimit = 0; 2.1795 - info->lo_flags = 0; 2.1796 -- memcpy(info->lo_file_name, clo->clo_file_name, LO_NAME_SIZE); 2.1797 -+ strncpy(info->lo_file_name, clo->underlying_filename, LO_NAME_SIZE); 2.1798 -+ info->lo_file_name[LO_NAME_SIZE-1]=0; 2.1799 - return 0; 2.1800 - } 2.1801 - 2.1802 -@@ -833,8 +1076,6 @@ 2.1803 - if (!err && copy_to_user(arg, &info64, sizeof(info64))) err = -EFAULT; 2.1804 - return err; 2.1805 - } 2.1806 --/* EOF get/set_status */ 2.1807 -- 2.1808 - 2.1809 - static int cloop_ioctl(struct block_device *bdev, fmode_t mode, 2.1810 - unsigned int cmd, unsigned long arg) 2.1811 -@@ -914,21 +1155,20 @@ 2.1812 - /* losetup uses write-open and flags=0x8002 to set a new file */ 2.1813 - if(mode & FMODE_WRITE) 2.1814 - { 2.1815 -- printk(KERN_WARNING "%s: Can't open device read-write in mode 0x%x\n", cloop_name, mode); 2.1816 -+ printk(KERN_INFO "%s: Open in read-write mode 0x%x requested, ignored.\n", cloop_name, mode); 2.1817 - return -EROFS; 2.1818 - } 2.1819 - cloop_dev[cloop_num]->refcnt+=1; 2.1820 - return 0; 2.1821 - } 2.1822 - 2.1823 --static int cloop_close(struct gendisk *disk, fmode_t mode) 2.1824 -+static void cloop_close(struct gendisk *disk, fmode_t mode) 2.1825 - { 2.1826 -- int cloop_num, err=0; 2.1827 -- if(!disk) return 0; 2.1828 -+ int cloop_num; 2.1829 -+ if(!disk) return; 2.1830 - cloop_num=((struct cloop_device *)disk->private_data)->clo_number; 2.1831 -- if(cloop_num < 0 || cloop_num > (cloop_count-1)) return 0; 2.1832 -+ if(cloop_num < 0 || cloop_num > (cloop_count-1)) return; 2.1833 - cloop_dev[cloop_num]->refcnt-=1; 2.1834 -- return err; 2.1835 - } 2.1836 - 2.1837 - static struct block_device_operations clo_fops = 2.1838 -@@ -973,6 +1213,10 @@ 2.1839 - goto error_out; 2.1840 - } 2.1841 - clo->clo_queue->queuedata = clo; 2.1842 -+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) 2.1843 -+ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, clo->clo_queue); 2.1844 -+ queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, clo->clo_queue); 2.1845 -+#endif 2.1846 - clo->clo_disk = alloc_disk(1); 2.1847 - if(!clo->clo_disk) 2.1848 - { 2.1849 -@@ -1004,6 +1248,11 @@ 2.1850 - cloop_dev[cloop_num] = NULL; 2.1851 - } 2.1852 - 2.1853 -+/* LZ4 Stuff */ 2.1854 -+#if (defined USE_LZ4_INTERNAL) 2.1855 -+#include "lz4_kmod.c" 2.1856 -+#endif 2.1857 -+ 2.1858 - static int __init cloop_init(void) 2.1859 - { 2.1860 - int error=0; 2.1861 -@@ -1044,7 +1293,7 @@ 2.1862 - initial_file=NULL; /* if IS_ERR, it's NOT open. */ 2.1863 - } 2.1864 - else 2.1865 -- error=cloop_set_file(0,initial_file,file); 2.1866 -+ error=cloop_set_file(0,initial_file); 2.1867 - if(error) 2.1868 - { 2.1869 - printk(KERN_ERR 2.1870 -@@ -1052,9 +1301,6 @@ 2.1871 - cloop_name, file, error); 2.1872 - goto init_out_dealloc; 2.1873 - } 2.1874 -- if(namelen >= LO_NAME_SIZE) namelen = LO_NAME_SIZE-1; 2.1875 -- memcpy(cloop_dev[0]->clo_file_name, file, namelen); 2.1876 -- cloop_dev[0]->clo_file_name[namelen] = 0; 2.1877 - } 2.1878 - return 0; 2.1879 - init_out_dealloc: 2.1880 ---- cloop.h 2.1881 -+++ cloop.h 2.1882 -@@ -86,11 +86,8 @@ 2.1883 - struct cloop_tail 2.1884 - { 2.1885 - u_int32_t table_size; 2.1886 -- u_int32_t index_size; /* size:4 comp:3 ctrl-c:1 lastlen:24 */ 2.1887 -+ u_int32_t index_size; /* size:4 unused:3 ctrl-c:1 lastlen:24 */ 2.1888 - #define CLOOP3_INDEX_SIZE(x) ((unsigned int)((x) & 0xF)) 2.1889 --#define CLOOP3_BLOCKS_FLAGS(x) ((unsigned int)((x) & 0x70) >> 4) 2.1890 --#define CLOOP3_TRUNCATED(x) ((unsigned int)((x) & 0x80) >> 7) 2.1891 --#define CLOOP3_LASTLEN(x) (unsigned int)((x) >> 8) 2.1892 - u_int32_t num_blocks; 2.1893 - }; 2.1894 - 2.1895 -@@ -104,8 +101,10 @@ 2.1896 - }; 2.1897 - 2.1898 - static inline char *build_index(struct block_info *offsets, unsigned long n, 2.1899 -- unsigned long block_size, unsigned global_flags) 2.1900 -+ unsigned long block_size) 2.1901 - { 2.1902 -+ static char v[11]; 2.1903 -+ u_int32_t flags = 0; 2.1904 - u_int32_t *ofs32 = (u_int32_t *) offsets; 2.1905 - loff_t *ofs64 = (loff_t *) offsets; 2.1906 - 2.1907 -@@ -130,8 +129,6 @@ 2.1908 - } 2.1909 - else { /* V2.0/V4.0 */ 2.1910 - loff_t last = CLOOP_BLOCK_OFFSET(__be64_to_cpu(ofs64[n])); 2.1911 -- u_int32_t flags; 2.1912 -- static char v4[11]; 2.1913 - unsigned long i = n; 2.1914 - 2.1915 - for (flags = 0; n-- ;) { 2.1916 -@@ -149,12 +146,7 @@ 2.1917 - offsets[i] = offsets[offsets[i].offset]; 2.1918 - } 2.1919 - } 2.1920 -- strcpy(v4, (char *) "64BE v4.0a"); 2.1921 -- v4[10] = 'a' + ((flags-1) & 0xF); // compressors used 2.1922 -- if (flags > 0x10) { // with links ? 2.1923 -- v4[10] += 'A' - 'a'; 2.1924 -- } 2.1925 -- return v4; 2.1926 -+ strcpy(v, (char *) "64BE v4.0a"); 2.1927 - } 2.1928 - } 2.1929 - else if (ofs32[1] == 0 && v3_64 == 0) { /* V1.0 */ 2.1930 -@@ -170,7 +162,6 @@ 2.1931 - else { /* V3.0 or V0.68 */ 2.1932 - unsigned long i; 2.1933 - loff_t j; 2.1934 -- static char v3[11]; 2.1935 - 2.1936 - for (i = 0; i < n && ntohl(ofs32[i]) < ntohl(ofs32[i+1]); i++); 2.1937 - if (i == n && ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */ 2.1938 -@@ -185,28 +176,33 @@ 2.1939 - } 2.1940 - 2.1941 - v3_64 = (ofs32[1] == 0); 2.1942 -- for (i = n; i-- != 0; ) 2.1943 -+ for (i = n; i-- != 0; ) { 2.1944 - offsets[i].size = ntohl(ofs32[i << v3_64]); 2.1945 -- for (i = 0, j = sizeof(struct cloop_head); i < n; i++) { 2.1946 -- offsets[i].offset = j; 2.1947 -- offsets[i].flags = global_flags; 2.1948 - if (offsets[i].size == 0xFFFFFFFF) { 2.1949 -- offsets[i].flags = CLOOP_COMPRESSOR_NONE; 2.1950 -- offsets[i].size = block_size; 2.1951 -+ offsets[i].size = 0x10000000 | block_size; 2.1952 - } 2.1953 -- if ((offsets[i].size & 0x80000000) == 0) { 2.1954 -+ offsets[i].flags = (offsets[i].size >> 28); 2.1955 -+ offsets[i].size &= 0x0FFFFFFF; 2.1956 -+ } 2.1957 -+ for (i = 0, j = sizeof(struct cloop_head); i < n; i++) { 2.1958 -+ offsets[i].offset = j; 2.1959 -+ if (offsets[i].flags < 8) { 2.1960 - j += offsets[i].size; 2.1961 - } 2.1962 - } 2.1963 - for (i = 0; i < n; i++) { 2.1964 -- if (offsets[i].size & 0x80000000) { 2.1965 -- offsets[i] = offsets[offsets[i].size & 0x7FFFFFFF]; 2.1966 -+ flags |= 1 << offsets[i].flags; 2.1967 -+ if (offsets[i].flags >= 8) { 2.1968 -+ offsets[i] = offsets[offsets[i].size]; 2.1969 - } 2.1970 - } 2.1971 -- strcpy(v3, (char *) (v3_64) ? "64BE v3.0a" : "32BE v3.0a"); 2.1972 -- v3[10] += global_flags; 2.1973 -- return v3; 2.1974 -+ strcpy(v, (char *) (v3_64) ? "64BE v3.0a" : "32BE v3.0a"); 2.1975 -+ } 2.1976 -+ v[10] = 'a' + ((flags-1) & 0xF); // compressors used 2.1977 -+ if (flags > 0x10) { // with links ? 2.1978 -+ v[10] += 'A' - 'a'; 2.1979 - } 2.1980 -+ return v; 2.1981 - } 2.1982 - 2.1983 - /* Cloop suspend IOCTL */ 2.1984 ---- cloop.c 2.1985 -+++ cloop.c 2.1986 -@@ -542,7 +542,7 @@ 2.1987 - const unsigned int header_size = sizeof(struct cloop_head); 2.1988 - unsigned int i, total_offsets=0; 2.1989 - loff_t fs_read_position = 0, header_pos[2]; 2.1990 -- int flags, isblkdev, bytes_read, error = 0; 2.1991 -+ int isblkdev, bytes_read, error = 0; 2.1992 - if (clo->suspended) return error; 2.1993 - #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) 2.1994 - inode = file->f_dentry->d_inode; 2.1995 -@@ -698,18 +698,12 @@ 2.1996 - error=-EBADF; goto error_release; 2.1997 - } 2.1998 - len = CLOOP3_INDEX_SIZE(ntohl(tail.index_size)) * total_offsets; 2.1999 -- flags = CLOOP3_BLOCKS_FLAGS(ntohl(tail.index_size)); 2.2000 --// 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) 2.2001 --printk(KERN_INFO "%s: uncompress(clo=%p, block_ptrs=%p, &len(%ld)=%p, zbuf=%p, zlen=%ld, flag=%d)\n", cloop_name, 2.2002 -- clo, clo->block_ptrs, len, &len, zbuf, zlen, flags); 2.2003 -- ret = uncompress(clo, (void *) clo->block_ptrs, &len, zbuf, zlen, flags); 2.2004 --// May 3 19:45:20 (none) user.alert kernel: BUG: unable to handle kernel NULL pointer dereference at (null) 2.2005 --printk(KERN_INFO "%s: uncompressed !\n", cloop_name); 2.2006 -+ ret = uncompress(clo, (void *) clo->block_ptrs, &len, zbuf, zlen, CLOOP_COMPRESSOR_ZLIB); 2.2007 - cloop_free(zbuf, zlen); 2.2008 - if (ret != 0) 2.2009 - { 2.2010 -- printk(KERN_ERR "%s: decompression error %i uncompressing index, flags %u\n", 2.2011 -- cloop_name, ret, flags); 2.2012 -+ printk(KERN_ERR "%s: decompression error %i uncompressing index\n", 2.2013 -+ cloop_name, ret); 2.2014 - error=-EBADF; goto error_release; 2.2015 - } 2.2016 - } 2.2017 -@@ -722,7 +716,6 @@ 2.2018 - else 2.2019 - { 2.2020 - unsigned int n, total_bytes; 2.2021 -- flags = 0; 2.2022 - clo->block_ptrs = cloop_malloc(sizeof(struct block_info) * total_offsets); 2.2023 - if (!clo->block_ptrs) 2.2024 - { 2.2025 -@@ -761,7 +754,7 @@ 2.2026 - } 2.2027 - { 2.2028 - int i; 2.2029 -- char *version = build_index(clo->block_ptrs, clo->head.num_blocks, clo->head.block_size, flags); 2.2030 -+ char *version = build_index(clo->block_ptrs, clo->head.num_blocks, clo->head.block_size); 2.2031 - clo->largest_block = 0; 2.2032 - for (i = 0; i < clo->head.num_blocks; i++) 2.2033 - if (clo->block_ptrs[i].size > clo->largest_block) 2.2034 -@@ -769,9 +762,6 @@ 2.2035 - printk(KERN_INFO "%s: %s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n", 2.2036 - cloop_name, clo->underlying_filename, version, clo->head.num_blocks, 2.2037 - clo->head.block_size, clo->largest_block); 2.2038 -- } 2.2039 -- { 2.2040 -- int i; 2.2041 - clo->num_buffered_blocks = (buffers > 0 && clo->head.block_size >= 512) ? 2.2042 - (buffers / clo->head.block_size) : 1; 2.2043 - clo->buffered_blocknum = cloop_malloc(clo->num_buffered_blocks * sizeof (u_int32_t)); 2.2044 -@@ -874,6 +864,10 @@ 2.2045 - cloop_free(clo->block_ptrs, sizeof(struct block_info) * total_offsets); 2.2046 clo->block_ptrs=NULL; 2.2047 error_release: 2.2048 +#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 2.2049 @@ -1548,3 +912,146 @@ 2.2050 if(bbuf) cloop_free(bbuf, clo->underlying_blksize); 2.2051 if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; } 2.2052 clo->backing_file=NULL; 2.2053 +@@ -829,6 +900,7 @@ 2.2054 + if(clo->refcnt > 1) /* we needed one fd for the ioctl */ 2.2055 + return -EBUSY; 2.2056 + if(filp==NULL) return -EINVAL; 2.2057 ++ if(clo->clo_thread) { kthread_stop(clo->clo_thread); clo->clo_thread=NULL; } 2.2058 + if(filp!=initial_file) 2.2059 + fput(filp); 2.2060 + else 2.2061 +@@ -839,7 +911,7 @@ 2.2062 + clo->backing_file = NULL; 2.2063 + clo->backing_inode = NULL; 2.2064 + if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; } 2.2065 +- if(clo->block_ptrs) { cloop_free(clo->block_ptrs, clo->head.num_blocks+1); clo->block_ptrs = NULL; } 2.2066 ++ if(clo->block_ptrs) { cloop_free(clo->block_ptrs, clo->head.num_blocks); clo->block_ptrs = NULL; } 2.2067 + if(clo->preload_cache) 2.2068 + { 2.2069 + int i; 2.2070 +@@ -1054,15 +1126,15 @@ 2.2071 + case LOOP_CLR_FD: /* Change arg */ 2.2072 + case LOOP_GET_STATUS64: /* Change arg */ 2.2073 + case LOOP_SET_STATUS64: /* Change arg */ 2.2074 +- return cloop_ioctl(bdev, mode, cmd, (unsigned long) compat_ptr(arg)); 2.2075 ++ arg = (unsigned long) compat_ptr(arg); 2.2076 + case LOOP_SET_STATUS: /* unchanged */ 2.2077 + case LOOP_GET_STATUS: /* unchanged */ 2.2078 + case LOOP_SET_FD: /* unchanged */ 2.2079 + case LOOP_CHANGE_FD: /* unchanged */ 2.2080 +- return cloop_ioctl(bdev, mode, cmd, arg); 2.2081 +- default: 2.2082 +- return -ENOIOCTLCMD; 2.2083 ++ return cloop_ioctl(bdev, mode, cmd, arg); 2.2084 ++ break; 2.2085 + } 2.2086 ++ return -ENOIOCTLCMD; 2.2087 + } 2.2088 + #endif 2.2089 + 2.2090 +@@ -1093,7 +1165,7 @@ 2.2091 + cloop_dev[cloop_num]->refcnt-=1; 2.2092 + } 2.2093 + 2.2094 +-static const struct block_device_operations clo_fops = 2.2095 ++static struct block_device_operations clo_fops = 2.2096 + { 2.2097 + owner: THIS_MODULE, 2.2098 + open: cloop_open, 2.2099 +@@ -1105,12 +1177,6 @@ 2.2100 + /* locked_ioctl ceased to exist in 2.6.36 */ 2.2101 + }; 2.2102 + 2.2103 +-static const struct blk_mq_ops cloop_mq_ops = { 2.2104 +- .queue_rq = cloop_queue_rq, 2.2105 +-/* .init_request = cloop_init_request, */ 2.2106 +-/* .complete = cloop_complete_rq, */ 2.2107 +-}; 2.2108 +- 2.2109 + static int cloop_register_blkdev(int major_nr) 2.2110 + { 2.2111 + return register_blkdev(major_nr, cloop_name); 2.2112 +@@ -1124,37 +1190,33 @@ 2.2113 + 2.2114 + static int cloop_alloc(int cloop_num) 2.2115 + { 2.2116 +- struct cloop_device *clo = (struct cloop_device *) cloop_malloc(sizeof(struct cloop_device)); 2.2117 ++ struct cloop_device *clo = (struct cloop_device *) cloop_malloc(sizeof(struct cloop_device));; 2.2118 + if(clo == NULL) goto error_out; 2.2119 + cloop_dev[cloop_num] = clo; 2.2120 + memset(clo, 0, sizeof(struct cloop_device)); 2.2121 + clo->clo_number = cloop_num; 2.2122 +- clo->tag_set.ops = &cloop_mq_ops; 2.2123 +- clo->tag_set.nr_hw_queues = 1; 2.2124 +- clo->tag_set.queue_depth = 128; 2.2125 +- clo->tag_set.numa_node = NUMA_NO_NODE; 2.2126 +- clo->tag_set.cmd_size = 0; /* No extra data needed */ 2.2127 +- /* BLK_MQ_F_BLOCKING is extremely important if we want to call blocking functions like vfs_read */ 2.2128 +- clo->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING; 2.2129 +- clo->tag_set.driver_data = clo; 2.2130 +- if(blk_mq_alloc_tag_set(&clo->tag_set)) goto error_out_free_clo; 2.2131 +- clo->clo_queue = blk_mq_init_queue(&clo->tag_set); 2.2132 +- if(IS_ERR(clo->clo_queue)) 2.2133 ++ clo->clo_thread = NULL; 2.2134 ++ init_waitqueue_head(&clo->clo_event); 2.2135 ++ spin_lock_init(&clo->queue_lock); 2.2136 ++ mutex_init(&clo->clo_ctl_mutex); 2.2137 ++ INIT_LIST_HEAD(&clo->clo_list); 2.2138 ++ clo->clo_queue = blk_init_queue(cloop_do_request, &clo->queue_lock); 2.2139 ++ if(!clo->clo_queue) 2.2140 + { 2.2141 + printk(KERN_ERR "%s: Unable to alloc queue[%d]\n", cloop_name, cloop_num); 2.2142 +- goto error_out_free_tags; 2.2143 ++ goto error_out; 2.2144 + } 2.2145 + clo->clo_queue->queuedata = clo; 2.2146 +- blk_queue_max_hw_sectors(clo->clo_queue, BLK_DEF_MAX_SECTORS); 2.2147 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) 2.2148 ++ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, clo->clo_queue); 2.2149 ++ queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, clo->clo_queue); 2.2150 ++#endif 2.2151 + clo->clo_disk = alloc_disk(1); 2.2152 + if(!clo->clo_disk) 2.2153 + { 2.2154 + printk(KERN_ERR "%s: Unable to alloc disk[%d]\n", cloop_name, cloop_num); 2.2155 +- goto error_out_free_queue; 2.2156 ++ goto error_disk; 2.2157 + } 2.2158 +- spin_lock_init(&clo->queue_lock); 2.2159 +- mutex_init(&clo->clo_ctl_mutex); 2.2160 +- mutex_init(&clo->clo_rq_mutex); 2.2161 + clo->clo_disk->major = cloop_major; 2.2162 + clo->clo_disk->first_minor = cloop_num; 2.2163 + clo->clo_disk->fops = &clo_fops; 2.2164 +@@ -1163,12 +1225,8 @@ 2.2165 + sprintf(clo->clo_disk->disk_name, "%s%d", cloop_name, cloop_num); 2.2166 + add_disk(clo->clo_disk); 2.2167 + return 0; 2.2168 +-error_out_free_queue: 2.2169 ++error_disk: 2.2170 + blk_cleanup_queue(clo->clo_queue); 2.2171 +-error_out_free_tags: 2.2172 +- blk_mq_free_tag_set(&clo->tag_set); 2.2173 +-error_out_free_clo: 2.2174 +- cloop_free(clo, sizeof(struct cloop_device)); 2.2175 + error_out: 2.2176 + return -ENOMEM; 2.2177 + } 2.2178 +@@ -1179,7 +1237,6 @@ 2.2179 + if(clo == NULL) return; 2.2180 + del_gendisk(clo->clo_disk); 2.2181 + blk_cleanup_queue(clo->clo_queue); 2.2182 +- blk_mq_free_tag_set(&clo->tag_set); 2.2183 + put_disk(clo->clo_disk); 2.2184 + cloop_free(clo, sizeof(struct cloop_device)); 2.2185 + cloop_dev[cloop_num] = NULL; 2.2186 +--- cloop_suspend.c 2.2187 ++++ cloop_suspend.c 2.2188 +@@ -14,6 +14,7 @@ 2.2189 + #include <fcntl.h> 2.2190 + #include <unistd.h> 2.2191 + #include <stdio.h> 2.2192 ++#include <stdint.h> 2.2193 + 2.2194 + /* We don't use the structure, so that define does not hurt */ 2.2195 + #define dev_t int
3.1 --- a/linux64-cloop/receipt Sun May 08 13:06:36 2022 +0000 3.2 +++ b/linux64-cloop/receipt Sun May 08 16:45:21 2022 +0000 3.3 @@ -2,16 +2,15 @@ 3.4 3.5 PACKAGE="linux64-cloop" 3.6 SOURCE="cloop" 3.7 -_VERSION="2.639-2" 3.8 -#VERSION="$(sed '/+#define CLOOP_VERSION/!d;s|.* "\(.*\)"|\1|' stuff/cloop.u)" 3.9 +_VERSION="3.14.1.3" 3.10 VERSION="4.12" 3.11 CATEGORY="base-system" 3.12 MAINTAINER="pascal.bellard@slitaz.org" 3.13 LICENSE="GPL2" 3.14 SHORT_DESC="The read-only compressed loop device kernel module." 3.15 WEB_SITE="http://knoppix.net/wiki/Cloop" 3.16 -TARBALL="${SOURCE}_${_VERSION}.tar.gz" 3.17 -WGET_URL="http://debian-knoppix.alioth.debian.org/packages/$SOURCE/$TARBALL" 3.18 +TARBALL="${SOURCE}_${_VERSION}.tar.xz" 3.19 +WGET_URL="http://deb.debian.org/debian/pool/main/c/$SOURCE/$TARBALL" 3.20 PROVIDE="linux-cloop:linux64" 3.21 3.22 DEPENDS="linux64" 3.23 @@ -26,6 +25,7 @@ 3.24 { 3.25 patch -p0 < $stuff/cloop.u 3.26 make ARCH=x86_64 KERNEL_DIR="/usr/src/linux" cloop.ko && xz cloop.ko 3.27 + make cloop_suspend 3.28 } 3.29 3.30 # Rules to gen a SliTaz package suitable for Tazpkg.
4.1 --- a/linux64-cloop/stuff/cloop.u Sun May 08 13:06:36 2022 +0000 4.2 +++ b/linux64-cloop/stuff/cloop.u Sun May 08 16:45:21 2022 +0000 4.3 @@ -1,6 +1,6 @@ 4.4 --- cloop.h 4.5 +++ cloop.h 4.6 -@@ -1,15 +1,50 @@ 4.7 +@@ -1,3 +1,7 @@ 4.8 +#define CLOOP_SIGNATURE "#!/bin/sh" /* @ offset 0 */ 4.9 +#define CLOOP_SIGNATURE_SIZE 9 4.10 +#define CLOOP_SIGNATURE_OFFSET 0x0 4.11 @@ -8,99 +8,46 @@ 4.12 #ifndef _COMPRESSED_LOOP_H 4.13 #define _COMPRESSED_LOOP_H 4.14 4.15 --#define CLOOP_HEADROOM 128 4.16 -+/*************************************************************************\ 4.17 -+* Starting with Format V4.0 (cloop version 4.x), cloop can now have two * 4.18 -+* alternative structures: * 4.19 -+* * 4.20 -+* 1. Header first: "robust" format, handles missing blocks well * 4.21 -+* 2. Footer (header last): "streaming" format, easier to create * 4.22 -+* * 4.23 -+* The cloop kernel module autodetects both formats, and can (currently) * 4.24 -+* still handle the V2.0 format as well. * 4.25 -+* * 4.26 -+* 1. Header first: * 4.27 -+* +---------------------------- FIXED SIZE ---------------------------+ * 4.28 -+* |Signature (128 bytes) | * 4.29 -+* |block_size (32bit number, network order) | * 4.30 -+* |num_blocks (32bit number, network order) | * 4.31 -+* +--------------------------- VARIABLE SIZE -------------------------+ * 4.32 -+* |num_blocks * FlagsOffset (upper 4 bits flags, lower 64 bits offset)| * 4.33 -+* |compressed data blocks of variable size ... | * 4.34 -+* +-------------------------------------------------------------------+ * 4.35 -+* * 4.36 -+* 2. Footer (header last): * 4.37 -+* +--------------------------- VARIABLE SIZE -------------------------+ * 4.38 -+* |compressed data blocks of variable size ... | * 4.39 -+* |num_blocks * FlagsOffset (upper 4 bits flags, lower 64 bits offset)| * 4.40 -+* +---------------------------- FIXED SIZE ---------------------------+ * 4.41 -+* |Signature (128 bytes) | * 4.42 -+* |block_size (32bit number, network order) | * 4.43 -+* |num_blocks (32bit number, network order) | * 4.44 -+* +-------------------------------------------------------------------+ * 4.45 -+* * 4.46 -+* Offsets are always relative to beginning of file, in all formats. * 4.47 -+* The block index contains num_blocks+1 offsets, followed (1) or * 4.48 -+* preceded (2) by the compressed blocks. * 4.49 -+\*************************************************************************/ 4.50 +@@ -38,10 +42,6 @@ 4.51 4.52 --/* The cloop header usually looks like this: */ 4.53 --/* #!/bin/sh */ 4.54 --/* #V2.00 Format */ 4.55 --/* ...padding up to CLOOP_HEADROOM... */ 4.56 --/* block_size (32bit number, network order) */ 4.57 --/* num_blocks (32bit number, network order) */ 4.58 -+#include <linux/types.h> /* u_int32_t */ 4.59 -+ 4.60 -+#define CLOOP_HEADROOM 128 4.61 + #include <linux/types.h> /* u_int32_t */ 4.62 4.63 -+/* Header of fixed length, can be located at beginning or end of file */ 4.64 - struct cloop_head 4.65 - { 4.66 - char preamble[CLOOP_HEADROOM]; 4.67 -@@ -17,9 +52,163 @@ 4.68 +-#ifndef __KERNEL__ 4.69 +-#include <stdint.h> /* regular uint64_t */ 4.70 +-#endif 4.71 +- 4.72 + #define CLOOP_HEADROOM 128 4.73 + 4.74 + /* Header of fixed length, can be located at beginning or end of file */ 4.75 +@@ -52,13 +52,6 @@ 4.76 u_int32_t num_blocks; 4.77 }; 4.78 4.79 -+/************************************************************************\ 4.80 -+* CLOOP4 flags for each compressed block * 4.81 -+* Value Meaning * 4.82 -+* 0 GZIP/7ZIP compression (compatible with V2.0 Format) * 4.83 -+* 1 no compression (incompressible data) * 4.84 -+* 2 xz compression (currently best space saver) * 4.85 -+* 3 lz4 compression * 4.86 -+* 4 lzo compression (fastest) * 4.87 -+\************************************************************************/ 4.88 -+ 4.89 -+typedef uint64_t cloop_block_ptr; 4.90 -+ 4.91 -+/* Get value of first 4 bits */ 4.92 -+#define CLOOP_BLOCK_FLAGS(x) ((unsigned int)(((x) & 0xf000000000000000LLU) >> 60)) 4.93 -+/* Get value of last 60 bits */ 4.94 -+#define CLOOP_BLOCK_OFFSET(x) ((x) & 0x0fffffffffffffffLLU) 4.95 -+ 4.96 -+#define CLOOP_COMPRESSOR_ZLIB 0x0 4.97 -+#define CLOOP_COMPRESSOR_NONE 0x1 4.98 -+#define CLOOP_COMPRESSOR_XZ 0x2 4.99 -+#define CLOOP_COMPRESSOR_LZ4 0x3 4.100 -+#define CLOOP_COMPRESSOR_LZO1X 0x4 4.101 -+ 4.102 -+#define CLOOP_COMPRESSOR_VALID(x) ((x) >= CLOOP_COMPRESSOR_ZLIB && (x) <= CLOOP_COMPRESSOR_LZO1X) 4.103 -+ 4.104 +-#define CLOOP2_SIGNATURE "V2.0" /* @ offset 0x0b */ 4.105 +-#define CLOOP2_SIGNATURE_SIZE 4 4.106 +-#define CLOOP2_SIGNATURE_OFFSET 0x0b 4.107 +-#define CLOOP4_SIGNATURE "V4.0" /* @ offset 0x0b */ 4.108 +-#define CLOOP4_SIGNATURE_SIZE 4 4.109 +-#define CLOOP4_SIGNATURE_OFFSET 0x0b 4.110 +- 4.111 + /************************************************************************\ 4.112 + * CLOOP4 flags for each compressed block * 4.113 + * Value Meaning * 4.114 +@@ -84,6 +77,134 @@ 4.115 + 4.116 + #define CLOOP_COMPRESSOR_VALID(x) ((x) >= CLOOP_COMPRESSOR_ZLIB && (x) <= CLOOP_COMPRESSOR_LZO1X) 4.117 + 4.118 +#define CLOOP_COMPRESSOR_LINK 0xF 4.119 + 4.120 + 4.121 - /* data_index (num_blocks 64bit pointers, network order)... */ 4.122 - /* compressed data (gzip block compressed format)... */ 4.123 - 4.124 ++/* data_index (num_blocks 64bit pointers, network order)... */ 4.125 ++/* compressed data (gzip block compressed format)... */ 4.126 ++ 4.127 +struct cloop_tail 4.128 +{ 4.129 + u_int32_t table_size; 4.130 -+ u_int32_t index_size; /* size:4 comp:3 ctrl-c:1 lastlen:24 */ 4.131 ++ u_int32_t index_size; /* size:4 unused:3 ctrl-c:1 lastlen:24 */ 4.132 +#define CLOOP3_INDEX_SIZE(x) ((unsigned int)((x) & 0xF)) 4.133 -+#define CLOOP3_BLOCKS_FLAGS(x) ((unsigned int)((x) & 0x70) >> 4) 4.134 -+#define CLOOP3_TRUNCATED(x) ((unsigned int)((x) & 0x80) >> 7) 4.135 -+#define CLOOP3_LASTLEN(x) (unsigned int)((x) >> 8) 4.136 + u_int32_t num_blocks; 4.137 +}; 4.138 + 4.139 @@ -114,8 +61,10 @@ 4.140 +}; 4.141 + 4.142 +static inline char *build_index(struct block_info *offsets, unsigned long n, 4.143 -+ unsigned long block_size, unsigned global_flags) 4.144 ++ unsigned long block_size) 4.145 +{ 4.146 ++ static char v[11]; 4.147 ++ u_int32_t flags = 0; 4.148 + u_int32_t *ofs32 = (u_int32_t *) offsets; 4.149 + loff_t *ofs64 = (loff_t *) offsets; 4.150 + 4.151 @@ -140,8 +89,6 @@ 4.152 + } 4.153 + else { /* V2.0/V4.0 */ 4.154 + loff_t last = CLOOP_BLOCK_OFFSET(__be64_to_cpu(ofs64[n])); 4.155 -+ u_int32_t flags; 4.156 -+ static char v4[11]; 4.157 + unsigned long i = n; 4.158 + 4.159 + for (flags = 0; n-- ;) { 4.160 @@ -159,12 +106,7 @@ 4.161 + offsets[i] = offsets[offsets[i].offset]; 4.162 + } 4.163 + } 4.164 -+ strcpy(v4, (char *) "64BE v4.0a"); 4.165 -+ v4[10] = 'a' + ((flags-1) & 0xF); // compressors used 4.166 -+ if (flags > 0x10) { // with links ? 4.167 -+ v4[10] += 'A' - 'a'; 4.168 -+ } 4.169 -+ return v4; 4.170 ++ strcpy(v, (char *) "64BE v4.0a"); 4.171 + } 4.172 + } 4.173 + else if (ofs32[1] == 0 && v3_64 == 0) { /* V1.0 */ 4.174 @@ -180,7 +122,6 @@ 4.175 + else { /* V3.0 or V0.68 */ 4.176 + unsigned long i; 4.177 + loff_t j; 4.178 -+ static char v3[11]; 4.179 + 4.180 + for (i = 0; i < n && ntohl(ofs32[i]) < ntohl(ofs32[i+1]); i++); 4.181 + if (i == n && ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */ 4.182 @@ -195,28 +136,33 @@ 4.183 + } 4.184 + 4.185 + v3_64 = (ofs32[1] == 0); 4.186 -+ for (i = n; i-- != 0; ) 4.187 ++ for (i = n; i-- != 0; ) { 4.188 + offsets[i].size = ntohl(ofs32[i << v3_64]); 4.189 ++ if (offsets[i].size == 0xFFFFFFFF) { 4.190 ++ offsets[i].size = 0x10000000 | block_size; 4.191 ++ } 4.192 ++ offsets[i].flags = (offsets[i].size >> 28); 4.193 ++ offsets[i].size &= 0x0FFFFFFF; 4.194 ++ } 4.195 + for (i = 0, j = sizeof(struct cloop_head); i < n; i++) { 4.196 + offsets[i].offset = j; 4.197 -+ offsets[i].flags = global_flags; 4.198 -+ if (offsets[i].size == 0xFFFFFFFF) { 4.199 -+ offsets[i].flags = CLOOP_COMPRESSOR_NONE; 4.200 -+ offsets[i].size = block_size; 4.201 -+ } 4.202 -+ if ((offsets[i].size & 0x80000000) == 0) { 4.203 ++ if (offsets[i].flags < 8) { 4.204 + j += offsets[i].size; 4.205 + } 4.206 + } 4.207 + for (i = 0; i < n; i++) { 4.208 -+ if (offsets[i].size & 0x80000000) { 4.209 -+ offsets[i] = offsets[offsets[i].size & 0x7FFFFFFF]; 4.210 ++ flags |= 1 << offsets[i].flags; 4.211 ++ if (offsets[i].flags >= 8) { 4.212 ++ offsets[i] = offsets[offsets[i].size]; 4.213 + } 4.214 + } 4.215 -+ strcpy(v3, (char *) (v3_64) ? "64BE v3.0a" : "32BE v3.0a"); 4.216 -+ v3[10] += global_flags; 4.217 -+ return v3; 4.218 ++ strcpy(v, (char *) (v3_64) ? "64BE v3.0a" : "32BE v3.0a"); 4.219 + } 4.220 ++ v[10] = 'a' + ((flags-1) & 0xF); // compressors used 4.221 ++ if (flags > 0x10) { // with links ? 4.222 ++ v[10] += 'A' - 'a'; 4.223 ++ } 4.224 ++ return v; 4.225 +} 4.226 + 4.227 /* Cloop suspend IOCTL */ 4.228 @@ -224,661 +170,538 @@ 4.229 4.230 --- cloop.c 4.231 +++ cloop.c 4.232 -@@ -1,26 +1,23 @@ 4.233 --/* 4.234 -- * compressed_loop.c: Read-only compressed loop blockdevice 4.235 -- * hacked up by Rusty in 1999, extended and maintained by Klaus Knopper 4.236 -- * 4.237 -- * A cloop file looks like this: 4.238 -- * [32-bit uncompressed block size: network order] 4.239 -- * [32-bit number of blocks (n_blocks): network order] 4.240 -- * [64-bit file offsets of start of blocks: network order] 4.241 -- * ... 4.242 -- * (n_blocks + 1). 4.243 -- * n_blocks consisting of: 4.244 -- * [compressed block] 4.245 -- * 4.246 -- * Every version greatly inspired by code seen in loop.c 4.247 -- * by Theodore Ts'o, 3/29/93. 4.248 -- * 4.249 -- * Copyright 1999-2009 by Paul `Rusty' Russell & Klaus Knopper. 4.250 -- * Redistribution of this file is permitted under the GNU Public License. 4.251 -- * 4.252 -- */ 4.253 -+/************************************************************************\ 4.254 -+* cloop.c: Read-only compressed loop blockdevice * 4.255 -+* hacked up by Rusty in 1999, extended and maintained by Klaus Knopper * 4.256 -+* * 4.257 -+* For all supported cloop file formats, please check the file "cloop.h" * 4.258 -+* New in Version 4: * 4.259 -+* - Header can be first or last in cloop file, * 4.260 -+* - Different compression algorithms supported (compression type * 4.261 -+* encoded in first 4 bytes of block offset address) * 4.262 -+* * 4.263 -+* Every version greatly inspired by code seen in loop.c * 4.264 -+* by Theodore Ts'o, 3/29/93. * 4.265 -+* * 4.266 -+* Copyright 1999-2009 by Paul `Rusty' Russell & Klaus Knopper. * 4.267 -+* Redistribution of this file is permitted under the GNU Public License * 4.268 -+* V2. * 4.269 -+\************************************************************************/ 4.270 +@@ -17,7 +17,7 @@ 4.271 + \************************************************************************/ 4.272 4.273 #define CLOOP_NAME "cloop" 4.274 --#define CLOOP_VERSION "2.639" 4.275 +-#define CLOOP_VERSION "5.3" 4.276 +#define CLOOP_VERSION "4.12" 4.277 #define CLOOP_MAX 8 4.278 4.279 #ifndef KBUILD_MODNAME 4.280 -@@ -47,8 +44,27 @@ 4.281 - #include <asm/div64.h> /* do_div() for 64bit division */ 4.282 - #include <asm/uaccess.h> 4.283 - #include <asm/byteorder.h> 4.284 --/* Use zlib_inflate from lib/zlib_inflate */ 4.285 -+/* Check for ZLIB, LZO1X, LZ4 decompression algorithms in kernel. */ 4.286 -+#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 4.287 - #include <linux/zutil.h> 4.288 -+#endif 4.289 -+#if (defined(CONFIG_LZO_DECOMPRESS) || defined(CONFIG_LZO_DECOMPRESS_MODULE)) 4.290 -+#include <linux/lzo.h> 4.291 -+#endif 4.292 -+#if (defined(CONFIG_DECOMPRESS_LZ4) || defined(CONFIG_DECOMPRESS_LZ4_MODULE)) 4.293 -+#include <linux/lz4.h> 4.294 -+#endif 4.295 -+#if (defined(CONFIG_DECOMPRESS_LZMA) || defined(CONFIG_DECOMPRESS_LZMA_MODULE)) 4.296 -+#include <linux/decompress/unlzma.h> 4.297 -+#endif 4.298 -+#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 4.299 -+#include <linux/xz.h> 4.300 -+#endif 4.301 -+ 4.302 -+#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))) 4.303 -+#error "No decompression library selected in kernel config!" 4.304 -+#endif 4.305 -+ 4.306 +@@ -68,7 +68,6 @@ 4.307 #include <linux/loop.h> 4.308 #include <linux/kthread.h> 4.309 #include <linux/compat.h> 4.310 -@@ -92,47 +108,64 @@ 4.311 - #define DEBUGP(format, x...) 4.312 - #endif 4.313 +-#include <linux/blk-mq.h> /* new multiqueue infrastructure */ 4.314 + #include "cloop.h" 4.315 4.316 -+/* Default size of buffer to keep some decompressed blocks in memory to speed up access */ 4.317 -+#define BLOCK_BUFFER_MEM (16*65536) 4.318 -+ 4.319 - /* One file can be opened at module insertion time */ 4.320 - /* insmod cloop file=/path/to/file */ 4.321 - static char *file=NULL; 4.322 - static unsigned int preload=0; 4.323 - static unsigned int cloop_max=CLOOP_MAX; 4.324 -+static unsigned int buffers=BLOCK_BUFFER_MEM; 4.325 - module_param(file, charp, 0); 4.326 - module_param(preload, uint, 0); 4.327 - module_param(cloop_max, uint, 0); 4.328 - MODULE_PARM_DESC(file, "Initial cloop image file (full path) for /dev/cloop"); 4.329 - MODULE_PARM_DESC(preload, "Preload n blocks of cloop data into memory"); 4.330 - MODULE_PARM_DESC(cloop_max, "Maximum number of cloop devices (default 8)"); 4.331 -+MODULE_PARM_DESC(buffers, "Size of buffer to keep uncompressed blocks in memory in MiB (default 1)"); 4.332 + /* New License scheme */ 4.333 +@@ -93,10 +92,7 @@ 4.334 + /* Use experimental major for now */ 4.335 + #define MAJOR_NR 240 4.336 4.337 - static struct file *initial_file=NULL; 4.338 - static int cloop_major=MAJOR_NR; 4.339 +-#ifndef DEVICE_NAME 4.340 +-#define DEVICE_NAME CLOOP_NAME 4.341 +-#endif 4.342 +- 4.343 ++/* #define DEVICE_NAME CLOOP_NAME */ 4.344 + /* #define DEVICE_NR(device) (MINOR(device)) */ 4.345 + /* #define DEVICE_ON(device) */ 4.346 + /* #define DEVICE_OFF(device) */ 4.347 +@@ -143,7 +139,7 @@ 4.348 + u_int32_t allflags; 4.349 4.350 --/* Number of buffered decompressed blocks */ 4.351 --#define BUFFERED_BLOCKS 8 4.352 - struct cloop_device 4.353 - { 4.354 -- /* Copied straight from the file */ 4.355 -+ /* Header filled from the file */ 4.356 - struct cloop_head head; 4.357 -+ int header_first; 4.358 -+ int file_format; 4.359 - 4.360 -- /* An array of offsets of compressed blocks within the file */ 4.361 -- loff_t *offsets; 4.362 -+ /* An or'd sum of all flags of each compressed block (v3) */ 4.363 -+ u_int32_t allflags; 4.364 -+ 4.365 -+ /* An array of cloop_ptr flags/offset for compressed blocks within the file */ 4.366 + /* An array of cloop_ptr flags/offset for compressed blocks within the file */ 4.367 +- cloop_block_ptr *block_ptrs; 4.368 + struct block_info *block_ptrs; 4.369 4.370 /* We buffer some uncompressed blocks for performance */ 4.371 -- int buffered_blocknum[BUFFERED_BLOCKS]; 4.372 -- int current_bufnum; 4.373 -- void *buffer[BUFFERED_BLOCKS]; 4.374 -- void *compressed_buffer; 4.375 -- size_t preload_array_size; /* Size of pointer array in blocks */ 4.376 -- size_t preload_size; /* Number of successfully allocated blocks */ 4.377 -- char **preload_cache; /* Pointers to preloaded blocks */ 4.378 -+ size_t num_buffered_blocks; /* how many uncompressed blocks buffered for performance */ 4.379 -+ int *buffered_blocknum; /* list of numbers of uncompressed blocks in buffer */ 4.380 -+ int current_bufnum; /* which block is current */ 4.381 -+ unsigned char **buffer; /* cache space for num_buffered_blocks uncompressed blocks */ 4.382 -+ void *compressed_buffer; /* space for the largest compressed block */ 4.383 -+ size_t preload_array_size; /* Size of pointer array in blocks */ 4.384 -+ size_t preload_size; /* Number of successfully allocated blocks */ 4.385 -+ char **preload_cache; /* Pointers to preloaded blocks */ 4.386 - 4.387 -+#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 4.388 - z_stream zstream; 4.389 -+#endif 4.390 -+#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 4.391 -+ struct xz_dec *xzdecoderstate; 4.392 -+ struct xz_buf xz_buffer; 4.393 -+#endif 4.394 - 4.395 - struct file *backing_file; /* associated file */ 4.396 - struct inode *backing_inode; /* for bmap */ 4.397 - 4.398 -+ unsigned char *underlying_filename; 4.399 - unsigned long largest_block; 4.400 - unsigned int underlying_blksize; 4.401 -+ loff_t underlying_total_size; 4.402 - int clo_number; 4.403 - int refcnt; 4.404 - struct block_device *bdev; 4.405 -@@ -147,7 +180,6 @@ 4.406 + size_t num_buffered_blocks; /* how many uncompressed blocks buffered for performance */ 4.407 +@@ -178,14 +174,16 @@ 4.408 + spinlock_t queue_lock; 4.409 + /* mutex for ioctl() */ 4.410 + struct mutex clo_ctl_mutex; 4.411 +- /* mutex for request */ 4.412 +- struct mutex clo_rq_mutex; 4.413 ++ struct list_head clo_list; 4.414 ++ struct task_struct *clo_thread; 4.415 ++ wait_queue_head_t clo_event; 4.416 struct request_queue *clo_queue; 4.417 struct gendisk *clo_disk; 4.418 +- struct blk_mq_tag_set tag_set; 4.419 int suspended; 4.420 -- char clo_file_name[LO_NAME_SIZE]; 4.421 }; 4.422 4.423 - /* Changed in 2.639: cloop_dev is now a an array of cloop_dev pointers, 4.424 -@@ -156,52 +188,113 @@ 4.425 ++/* Changed in 2.639: cloop_dev is now a an array of cloop_dev pointers, 4.426 ++ so we can specify how many devices we need via parameters. */ 4.427 + static struct cloop_device **cloop_dev; 4.428 static const char *cloop_name=CLOOP_NAME; 4.429 static int cloop_count = 0; 4.430 - 4.431 --#if (!(defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE))) /* Must be compiled into kernel. */ 4.432 --#error "Invalid Kernel configuration. CONFIG_ZLIB_INFLATE support is needed for cloop." 4.433 --#endif 4.434 -- 4.435 --/* Use __get_free_pages instead of vmalloc, allows up to 32 pages, 4.436 -- * 2MB in one piece */ 4.437 - static void *cloop_malloc(size_t size) 4.438 - { 4.439 -- int order = get_order(size); 4.440 -- if(order <= KMALLOC_MAX_ORDER) 4.441 -- return (void *)kmalloc(size, GFP_KERNEL); 4.442 -- else if(order < MAX_ORDER) 4.443 -- return (void *)__get_free_pages(GFP_KERNEL, order); 4.444 -+ /* kmalloc will fail after the system is running for a while, */ 4.445 -+ /* when large orders can't return contiguous memory. */ 4.446 -+ /* Let's just use vmalloc for now. :-/ */ 4.447 -+ /* int order = get_order(size); */ 4.448 -+ /* if(order <= KMALLOC_MAX_ORDER) */ 4.449 -+ /* return (void *)kmalloc(size, GFP_KERNEL); */ 4.450 -+ /* else if(order < MAX_ORDER) */ 4.451 -+ /* return (void *)__get_free_pages(GFP_KERNEL, order); */ 4.452 - return (void *)vmalloc(size); 4.453 +@@ -214,24 +212,21 @@ 4.454 + vfree(mem); 4.455 } 4.456 4.457 - static void cloop_free(void *mem, size_t size) 4.458 - { 4.459 -- int order = get_order(size); 4.460 -- if(order <= KMALLOC_MAX_ORDER) 4.461 -- kfree(mem); 4.462 -- else if(order < MAX_ORDER) 4.463 -- free_pages((unsigned long)mem, order); 4.464 -- else vfree(mem); 4.465 -+ /* int order = get_order(size); */ 4.466 -+ /* if(order <= KMALLOC_MAX_ORDER) */ 4.467 -+ /* kfree(mem); */ 4.468 -+ /* else if(order < MAX_ORDER) */ 4.469 -+ /* free_pages((unsigned long)mem, order); */ 4.470 -+ /* else */ 4.471 -+ vfree(mem); 4.472 - } 4.473 - 4.474 --static int uncompress(struct cloop_device *clo, 4.475 -- unsigned char *dest, unsigned long *destLen, 4.476 -- unsigned char *source, unsigned long sourceLen) 4.477 +-/* static int uncompress(struct cloop_device *clo, unsigned char *dest, unsigned long *destLen, unsigned char *source, unsigned long sourceLen) */ 4.478 +-static int uncompress(struct cloop_device *clo, u_int32_t block_num, u_int32_t compressed_length, unsigned long *uncompressed_length) 4.479 +static int uncompress(struct cloop_device *clo, unsigned char *dest, unsigned long *destLen, unsigned char *source, unsigned long sourceLen, int flags) 4.480 { 4.481 -- /* Most of this code can be found in fs/cramfs/uncompress.c */ 4.482 -- int err; 4.483 -- clo->zstream.next_in = source; 4.484 -- clo->zstream.avail_in = sourceLen; 4.485 -- clo->zstream.next_out = dest; 4.486 -- clo->zstream.avail_out = *destLen; 4.487 -- err = zlib_inflateReset(&clo->zstream); 4.488 -- if (err != Z_OK) 4.489 -- { 4.490 -- printk(KERN_ERR "%s: zlib_inflateReset error %d\n", cloop_name, err); 4.491 -- zlib_inflateEnd(&clo->zstream); zlib_inflateInit(&clo->zstream); 4.492 -- } 4.493 -- err = zlib_inflate(&clo->zstream, Z_FINISH); 4.494 -- *destLen = clo->zstream.total_out; 4.495 -- if (err != Z_STREAM_END) return err; 4.496 -- return Z_OK; 4.497 -+ int err = -1; 4.498 -+ switch(flags) 4.499 -+ { 4.500 -+ case CLOOP_COMPRESSOR_NONE: 4.501 + int err = -1; 4.502 +- int flags = CLOOP_BLOCK_FLAGS(clo->block_ptrs[block_num]); 4.503 + switch(flags) 4.504 + { 4.505 + case CLOOP_COMPRESSOR_NONE: 4.506 +- /* block is umcompressed, swap pointers only! */ 4.507 +- { char *tmp = clo->compressed_buffer; clo->compressed_buffer = clo->buffer[clo->current_bufnum]; clo->buffer[clo->current_bufnum] = tmp; } 4.508 +- DEBUGP("cloop: block %d is uncompressed (flags=%d), just swapping %u bytes\n", block_num, flags, compressed_length); 4.509 + memcpy(dest, source, *destLen = sourceLen); 4.510 + err = Z_OK; 4.511 -+ break; 4.512 -+#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 4.513 -+ case CLOOP_COMPRESSOR_ZLIB: 4.514 + break; 4.515 + #if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 4.516 + case CLOOP_COMPRESSOR_ZLIB: 4.517 +- clo->zstream.next_in = clo->compressed_buffer; 4.518 +- clo->zstream.avail_in = compressed_length; 4.519 +- clo->zstream.next_out = clo->buffer[clo->current_bufnum]; 4.520 +- clo->zstream.avail_out = clo->head.block_size; 4.521 + clo->zstream.next_in = source; 4.522 + clo->zstream.avail_in = sourceLen; 4.523 + clo->zstream.next_out = dest; 4.524 + clo->zstream.avail_out = *destLen; 4.525 -+ err = zlib_inflateReset(&clo->zstream); 4.526 -+ if (err != Z_OK) 4.527 -+ { 4.528 -+ printk(KERN_ERR "%s: zlib_inflateReset error %d\n", cloop_name, err); 4.529 -+ zlib_inflateEnd(&clo->zstream); zlib_inflateInit(&clo->zstream); 4.530 -+ } 4.531 -+ err = zlib_inflate(&clo->zstream, Z_FINISH); 4.532 + err = zlib_inflateReset(&clo->zstream); 4.533 + if (err != Z_OK) 4.534 + { 4.535 +@@ -239,50 +234,50 @@ 4.536 + zlib_inflateEnd(&clo->zstream); zlib_inflateInit(&clo->zstream); 4.537 + } 4.538 + err = zlib_inflate(&clo->zstream, Z_FINISH); 4.539 +- *uncompressed_length = clo->zstream.total_out; 4.540 + *destLen = clo->zstream.total_out; 4.541 -+ if (err == Z_STREAM_END) err = 0; 4.542 + if (err == Z_STREAM_END) err = 0; 4.543 +- DEBUGP("cloop: zlib decompression done, ret =%d, size =%lu\n", err, *uncompressed_length); 4.544 + DEBUGP("cloop: zlib decompression done, ret =%d, size =%lu\n", err, *destLen); 4.545 -+ break; 4.546 -+#endif 4.547 -+#if (defined(CONFIG_LZO_DECOMPRESS) || defined(CONFIG_LZO_DECOMPRESS_MODULE)) 4.548 -+ case CLOOP_COMPRESSOR_LZO1X: 4.549 -+ { 4.550 -+ size_t tmp = (size_t) clo->head.block_size; 4.551 + break; 4.552 + #endif 4.553 + #if (defined(CONFIG_LZO_DECOMPRESS) || defined(CONFIG_LZO_DECOMPRESS_MODULE)) 4.554 + case CLOOP_COMPRESSOR_LZO1X: 4.555 + { 4.556 + size_t tmp = (size_t) clo->head.block_size; 4.557 +- err = lzo1x_decompress_safe(clo->compressed_buffer, compressed_length, 4.558 +- clo->buffer[clo->current_bufnum], &tmp); 4.559 +- if (err == LZO_E_OK) *uncompressed_length = (u_int32_t) tmp; 4.560 + err = lzo1x_decompress_safe(source, sourceLen, 4.561 + dest, &tmp); 4.562 + if (err == LZO_E_OK) *destLen = (u_int32_t) tmp; 4.563 -+ } 4.564 -+ break; 4.565 -+#endif 4.566 -+#if (defined(CONFIG_DECOMPRESS_LZ4) || defined(CONFIG_DECOMPRESS_LZ4_MODULE)) 4.567 -+ case CLOOP_COMPRESSOR_LZ4: 4.568 -+ { 4.569 + } 4.570 + break; 4.571 + #endif 4.572 + #if (defined(CONFIG_DECOMPRESS_LZ4) || defined(CONFIG_DECOMPRESS_LZ4_MODULE)) 4.573 + case CLOOP_COMPRESSOR_LZ4: 4.574 + { 4.575 +- size_t outputSize = clo->head.block_size; 4.576 + size_t outputSize = *destLen; 4.577 -+ /* We should adjust outputSize here, in case the last block is smaller than block_size */ 4.578 -+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) /* field removed */ 4.579 + /* We should adjust outputSize here, in case the last block is smaller than block_size */ 4.580 + #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) /* field removed */ 4.581 +- err = lz4_decompress(clo->compressed_buffer, (size_t *) &compressed_length, 4.582 +- clo->buffer[clo->current_bufnum], outputSize); 4.583 + err = lz4_decompress(source, (size_t *) &sourceLen, 4.584 + dest, outputSize); 4.585 -+#else 4.586 + #else 4.587 +- err = LZ4_decompress_safe(clo->compressed_buffer, 4.588 +- clo->buffer[clo->current_bufnum], 4.589 +- compressed_length, outputSize); 4.590 + err = LZ4_decompress_safe(source, 4.591 + dest, 4.592 + sourceLen, outputSize); 4.593 -+#endif 4.594 -+ if (err >= 0) 4.595 -+ { 4.596 -+ err = 0; 4.597 + #endif 4.598 + if (err >= 0) 4.599 + { 4.600 + err = 0; 4.601 +- *uncompressed_length = outputSize; 4.602 + *destLen = outputSize; 4.603 -+ } 4.604 -+ } 4.605 -+ break; 4.606 -+#endif 4.607 -+#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 4.608 -+ case CLOOP_COMPRESSOR_XZ: 4.609 + } 4.610 + } 4.611 + break; 4.612 + #endif 4.613 + #if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 4.614 + case CLOOP_COMPRESSOR_XZ: 4.615 +- clo->xz_buffer.in = clo->compressed_buffer; 4.616 + clo->xz_buffer.in = source; 4.617 -+ clo->xz_buffer.in_pos = 0; 4.618 + clo->xz_buffer.in_pos = 0; 4.619 +- clo->xz_buffer.in_size = compressed_length; 4.620 +- clo->xz_buffer.out = clo->buffer[clo->current_bufnum]; 4.621 + clo->xz_buffer.in_size = sourceLen; 4.622 + clo->xz_buffer.out = dest; 4.623 -+ clo->xz_buffer.out_pos = 0; 4.624 + clo->xz_buffer.out_pos = 0; 4.625 +- clo->xz_buffer.out_size = clo->head.block_size; 4.626 + clo->xz_buffer.out_size = *destLen; 4.627 -+ xz_dec_reset(clo->xzdecoderstate); 4.628 -+ err = xz_dec_run(clo->xzdecoderstate, &clo->xz_buffer); 4.629 -+ if (err == XZ_STREAM_END || err == XZ_OK) 4.630 -+ { 4.631 -+ err = 0; 4.632 -+ } 4.633 -+ else 4.634 -+ { 4.635 -+ printk(KERN_ERR "%s: xz_dec_run error %d\n", cloop_name, err); 4.636 -+ err = 1; 4.637 -+ } 4.638 -+ break; 4.639 -+#endif 4.640 -+ default: 4.641 -+ printk(KERN_ERR "%s: compression method is not supported!\n", cloop_name); 4.642 -+ } 4.643 -+ return err; 4.644 - } 4.645 - 4.646 - static ssize_t cloop_read_from_file(struct cloop_device *clo, struct file *f, char *buf, 4.647 -@@ -220,7 +313,7 @@ 4.648 + xz_dec_reset(clo->xzdecoderstate); 4.649 + err = xz_dec_run(clo->xzdecoderstate, &clo->xz_buffer); 4.650 + if (err == XZ_STREAM_END || err == XZ_OK) 4.651 +@@ -309,16 +304,12 @@ 4.652 + while (buf_done < buf_len) 4.653 + { 4.654 + size_t size = buf_len - buf_done, size_read; 4.655 +- mm_segment_t old_fs; 4.656 + /* kernel_read() only supports 32 bit offsets, so we use vfs_read() instead. */ 4.657 + /* int size_read = kernel_read(f, pos, buf + buf_done, size); */ 4.658 +- 4.659 +- // mutex_lock(&clo->clo_rq_mutex); 4.660 +- old_fs = get_fs(); 4.661 +- set_fs(KERNEL_DS); 4.662 ++ mm_segment_t old_fs = get_fs(); 4.663 ++ set_fs(get_ds()); 4.664 + size_read = vfs_read(f, (void __user *)(buf + buf_done), size, &pos); 4.665 + set_fs(old_fs); 4.666 +- // mutex_unlock(&clo->clo_rq_mutex); 4.667 4.668 if(size_read <= 0) 4.669 { 4.670 -- printk(KERN_ERR "%s: Read error %d at pos %Lu in file %s, " 4.671 -+ printk(KERN_ERR "%s: Read error %d at pos %llu in file %s, " 4.672 - "%d bytes lost.\n", cloop_name, (int)size_read, pos, 4.673 - file, (int)size); 4.674 - memset(buf + buf_len - size, 0, size); 4.675 -@@ -232,72 +325,84 @@ 4.676 - } 4.677 +@@ -358,8 +349,8 @@ 4.678 + return i; 4.679 + } 4.680 4.681 - /* This looks more complicated than it is */ 4.682 --/* Returns number of block buffer to use for this request */ 4.683 -+/* Returns number of cache block buffer to use for this request */ 4.684 - static int cloop_load_buffer(struct cloop_device *clo, int blocknum) 4.685 - { 4.686 -- unsigned int buf_done = 0; 4.687 -- unsigned long buflen; 4.688 -- unsigned int buf_length; 4.689 -+ loff_t compressed_block_offset; 4.690 -+ long compressed_block_len; 4.691 -+ long uncompressed_block_len=0; 4.692 - int ret; 4.693 - int i; 4.694 -- if(blocknum > ntohl(clo->head.num_blocks) || blocknum < 0) 4.695 -- { 4.696 -- printk(KERN_WARNING "%s: Invalid block number %d requested.\n", 4.697 -- cloop_name, blocknum); 4.698 -- return -1; 4.699 -- } 4.700 -+ if(blocknum > clo->head.num_blocks || blocknum < 0) 4.701 -+ { 4.702 -+ printk(KERN_WARNING "%s: Invalid block number %d requested.\n", 4.703 -+ cloop_name, blocknum); 4.704 -+ return -1; 4.705 -+ } 4.706 - 4.707 - /* Quick return if the block we seek is already in one of the buffers. */ 4.708 - /* Return number of buffer */ 4.709 -- for(i=0; i<BUFFERED_BLOCKS; i++) 4.710 -+ for(i=0; i<clo->num_buffered_blocks; i++) 4.711 - if (blocknum == clo->buffered_blocknum[i]) 4.712 -- { 4.713 -- DEBUGP(KERN_INFO "cloop_load_buffer: Found buffered block %d\n", i); 4.714 -- return i; 4.715 -- } 4.716 -- 4.717 -- buf_length = be64_to_cpu(clo->offsets[blocknum+1]) - be64_to_cpu(clo->offsets[blocknum]); 4.718 -- 4.719 --/* Load one compressed block from the file. */ 4.720 -- cloop_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer, 4.721 -- be64_to_cpu(clo->offsets[blocknum]), buf_length); 4.722 -+ { 4.723 -+ DEBUGP(KERN_INFO "cloop_load_buffer: Found buffered block %d\n", i); 4.724 -+ return i; 4.725 -+ } 4.726 - 4.727 -- buflen = ntohl(clo->head.block_size); 4.728 +- compressed_block_offset = CLOOP_BLOCK_OFFSET(clo->block_ptrs[blocknum]); 4.729 +- compressed_block_len = (long) (CLOOP_BLOCK_OFFSET(clo->block_ptrs[blocknum+1]) - compressed_block_offset) ; 4.730 + compressed_block_offset = clo->block_ptrs[blocknum].offset; 4.731 + compressed_block_len = (long) (clo->block_ptrs[blocknum].size) ; 4.732 4.733 -- /* Go to next position in the block ring buffer */ 4.734 -- clo->current_bufnum++; 4.735 -- if(clo->current_bufnum >= BUFFERED_BLOCKS) clo->current_bufnum = 0; 4.736 -+ /* Load one compressed block from the file. */ 4.737 -+ if(compressed_block_offset > 0 && compressed_block_len >= 0) /* sanity check */ 4.738 -+ { 4.739 -+ size_t n = cloop_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer, 4.740 -+ compressed_block_offset, compressed_block_len); 4.741 -+ if (n!= compressed_block_len) 4.742 -+ { 4.743 -+ printk(KERN_ERR "%s: error while reading %lu bytes @ %llu from file %s\n", 4.744 + /* Load one compressed block from the file. */ 4.745 + if(compressed_block_offset > 0 && compressed_block_len >= 0) /* sanity check */ 4.746 +@@ -369,12 +360,12 @@ 4.747 + if (n!= compressed_block_len) 4.748 + { 4.749 + printk(KERN_ERR "%s: error while reading %lu bytes @ %llu from file %s\n", 4.750 +- cloop_name, compressed_block_len, clo->block_ptrs[blocknum], clo->underlying_filename); 4.751 + cloop_name, compressed_block_len, clo->block_ptrs[blocknum].offset, clo->underlying_filename); 4.752 -+ /* return -1; */ 4.753 -+ } 4.754 -+ } else { 4.755 -+ printk(KERN_ERR "%s: invalid data block len %ld bytes @ %lld from file %s\n", 4.756 + /* return -1; */ 4.757 + } 4.758 + } else { 4.759 + printk(KERN_ERR "%s: invalid data block len %ld bytes @ %lld from file %s\n", 4.760 +- cloop_name, compressed_block_len, clo->block_ptrs[blocknum], clo->underlying_filename); 4.761 + cloop_name, compressed_block_len, clo->block_ptrs[blocknum].offset, clo->underlying_filename); 4.762 -+ return -1; 4.763 -+ } 4.764 -+ 4.765 -+ /* Go to next position in the cache block buffer (which is used as a cyclic buffer) */ 4.766 -+ if(++clo->current_bufnum >= clo->num_buffered_blocks) clo->current_bufnum = 0; 4.767 + return -1; 4.768 + } 4.769 + 4.770 +@@ -382,14 +373,16 @@ 4.771 + if(++clo->current_bufnum >= clo->num_buffered_blocks) clo->current_bufnum = 0; 4.772 4.773 /* Do the uncompression */ 4.774 -- ret = uncompress(clo, clo->buffer[clo->current_bufnum], &buflen, clo->compressed_buffer, 4.775 -- buf_length); 4.776 +- ret = uncompress(clo, blocknum, compressed_block_len, &uncompressed_block_len); 4.777 + uncompressed_block_len = clo->head.block_size; 4.778 + ret = uncompress(clo, clo->buffer[clo->current_bufnum], &uncompressed_block_len, 4.779 + clo->compressed_buffer, compressed_block_len, clo->block_ptrs[blocknum].flags); 4.780 /* DEBUGP("cloop: buflen after uncompress: %ld\n",buflen); */ 4.781 if (ret != 0) 4.782 -- { 4.783 -- printk(KERN_ERR "%s: zlib decompression error %i uncompressing block %u %u/%lu/%u/%u " 4.784 -- "%Lu-%Lu\n", cloop_name, ret, blocknum, 4.785 -- ntohl(clo->head.block_size), buflen, buf_length, buf_done, 4.786 -- be64_to_cpu(clo->offsets[blocknum]), be64_to_cpu(clo->offsets[blocknum+1])); 4.787 -- clo->buffered_blocknum[clo->current_bufnum] = -1; 4.788 -- return -1; 4.789 -- } 4.790 -+ { 4.791 -+ printk(KERN_ERR "%s: decompression error %i uncompressing block %u %lu bytes @ %llu, flags %u\n", 4.792 -+ cloop_name, ret, blocknum, 4.793 + { 4.794 + printk(KERN_ERR "%s: decompression error %i uncompressing block %u %lu bytes @ %llu, flags %u\n", 4.795 + cloop_name, ret, blocknum, 4.796 +- compressed_block_len, CLOOP_BLOCK_OFFSET(clo->block_ptrs[blocknum]), 4.797 +- CLOOP_BLOCK_FLAGS(clo->block_ptrs[blocknum])); 4.798 + compressed_block_len, clo->block_ptrs[blocknum].offset, 4.799 + clo->block_ptrs[blocknum].flags); 4.800 -+ clo->buffered_blocknum[clo->current_bufnum] = -1; 4.801 -+ return -1; 4.802 -+ } 4.803 - clo->buffered_blocknum[clo->current_bufnum] = blocknum; 4.804 + clo->buffered_blocknum[clo->current_bufnum] = -1; 4.805 + return -1; 4.806 + } 4.807 +@@ -397,107 +390,146 @@ 4.808 return clo->current_bufnum; 4.809 } 4.810 4.811 - /* This function does all the real work. */ 4.812 --/* returns "uptodate" */ 4.813 +-static blk_status_t cloop_handle_request(struct cloop_device *clo, struct request *req) 4.814 ++/* This function does all the real work. */ 4.815 +/* returns "uptodate" */ 4.816 - static int cloop_handle_request(struct cloop_device *clo, struct request *req) 4.817 ++static int cloop_handle_request(struct cloop_device *clo, struct request *req) 4.818 { 4.819 int buffered_blocknum = -1; 4.820 int preloaded = 0; 4.821 - loff_t offset = (loff_t) blk_rq_pos(req)<<9; /* req->sector<<9 */ 4.822 -- struct bio_vec *bvec; 4.823 -+ struct bio_vec bvec; 4.824 +- loff_t offset = (loff_t) blk_rq_pos(req)<<9; 4.825 ++ loff_t offset = (loff_t) blk_rq_pos(req)<<9; /* req->sector<<9 */ 4.826 + struct bio_vec bvec; 4.827 struct req_iterator iter; 4.828 +- blk_status_t ret = BLK_STS_OK; 4.829 +- 4.830 +- if (unlikely(req_op(req) != REQ_OP_READ )) 4.831 +- { 4.832 +- blk_dump_rq_flags(req, DEVICE_NAME " bad request"); 4.833 +- return BLK_STS_IOERR; 4.834 +- } 4.835 +- 4.836 +- if (unlikely(!clo->backing_file && !clo->suspended)) 4.837 +- { 4.838 +- DEBUGP("cloop_handle_request: not connected to a file\n"); 4.839 +- return BLK_STS_IOERR; 4.840 +- } 4.841 +- 4.842 rq_for_each_segment(bvec, req, iter) 4.843 +- { 4.844 +- unsigned long len = bvec.bv_len; 4.845 +- loff_t to_offset = bvec.bv_offset; 4.846 +- 4.847 +- while(len > 0) 4.848 { 4.849 -- unsigned long len = bvec->bv_len; 4.850 -- char *to_ptr = kmap(bvec->bv_page) + bvec->bv_offset; 4.851 +- u_int32_t length_in_buffer; 4.852 +- loff_t block_offset = offset; 4.853 +- u_int32_t offset_in_buffer; 4.854 +- char *from_ptr, *to_ptr; 4.855 +- /* do_div (div64.h) returns the 64bit division remainder and */ 4.856 +- /* puts the result in the first argument, i.e. block_offset */ 4.857 +- /* becomes the blocknumber to load, and offset_in_buffer the */ 4.858 +- /* position in the buffer */ 4.859 +- offset_in_buffer = do_div(block_offset, clo->head.block_size); 4.860 +- /* Lookup preload cache */ 4.861 +- if(block_offset < clo->preload_size && clo->preload_cache != NULL && clo->preload_cache[block_offset] != NULL) 4.862 +- { /* Copy from cache */ 4.863 +- preloaded = 1; 4.864 +- from_ptr = clo->preload_cache[block_offset]; 4.865 +- } 4.866 +- else 4.867 +- { 4.868 +- preloaded = 0; 4.869 +- buffered_blocknum = cloop_load_buffer(clo,block_offset); 4.870 +- if(buffered_blocknum == -1) 4.871 + unsigned long len = bvec.bv_len; 4.872 + char *to_ptr = kmap(bvec.bv_page) + bvec.bv_offset; 4.873 - while(len > 0) 4.874 ++ while(len > 0) 4.875 { 4.876 - u_int32_t length_in_buffer; 4.877 -@@ -308,7 +413,7 @@ 4.878 - /* puts the result in the first argument, i.e. block_offset */ 4.879 - /* becomes the blocknumber to load, and offset_in_buffer the */ 4.880 - /* position in the buffer */ 4.881 -- offset_in_buffer = do_div(block_offset, ntohl(clo->head.block_size)); 4.882 +- ret = BLK_STS_IOERR; 4.883 +- break; /* invalid data, leave inner loop */ 4.884 ++ u_int32_t length_in_buffer; 4.885 ++ loff_t block_offset = offset; 4.886 ++ u_int32_t offset_in_buffer; 4.887 ++ char *from_ptr; 4.888 ++ /* do_div (div64.h) returns the 64bit division remainder and */ 4.889 ++ /* puts the result in the first argument, i.e. block_offset */ 4.890 ++ /* becomes the blocknumber to load, and offset_in_buffer the */ 4.891 ++ /* position in the buffer */ 4.892 + offset_in_buffer = do_div(block_offset, clo->head.block_size); 4.893 - /* Lookup preload cache */ 4.894 - if(block_offset < clo->preload_size && clo->preload_cache != NULL && 4.895 - clo->preload_cache[block_offset] != NULL) 4.896 -@@ -325,7 +430,7 @@ 4.897 - from_ptr = clo->buffer[buffered_blocknum]; 4.898 - } 4.899 - /* Now, at least part of what we want will be in the buffer. */ 4.900 -- length_in_buffer = ntohl(clo->head.block_size) - offset_in_buffer; 4.901 ++ /* Lookup preload cache */ 4.902 ++ if(block_offset < clo->preload_size && clo->preload_cache != NULL && 4.903 ++ clo->preload_cache[block_offset] != NULL) 4.904 ++ { /* Copy from cache */ 4.905 ++ preloaded = 1; 4.906 ++ from_ptr = clo->preload_cache[block_offset]; 4.907 ++ } 4.908 ++ else 4.909 ++ { 4.910 ++ preloaded = 0; 4.911 ++ buffered_blocknum = cloop_load_buffer(clo,block_offset); 4.912 ++ if(buffered_blocknum == -1) break; /* invalid data, leave inner loop */ 4.913 ++ /* Copy from buffer */ 4.914 ++ from_ptr = clo->buffer[buffered_blocknum]; 4.915 ++ } 4.916 ++ /* Now, at least part of what we want will be in the buffer. */ 4.917 + length_in_buffer = clo->head.block_size - offset_in_buffer; 4.918 - if(length_in_buffer > len) 4.919 - { 4.920 - /* DEBUGP("Warning: length_in_buffer=%u > len=%u\n", 4.921 -@@ -337,18 +442,19 @@ 4.922 - len -= length_in_buffer; 4.923 - offset += length_in_buffer; 4.924 - } /* while inner loop */ 4.925 -- kunmap(bvec->bv_page); 4.926 ++ if(length_in_buffer > len) 4.927 ++ { 4.928 ++/* DEBUGP("Warning: length_in_buffer=%u > len=%u\n", 4.929 ++ length_in_buffer,len); */ 4.930 ++ length_in_buffer = len; 4.931 ++ } 4.932 ++ memcpy(to_ptr, from_ptr + offset_in_buffer, length_in_buffer); 4.933 ++ to_ptr += length_in_buffer; 4.934 ++ len -= length_in_buffer; 4.935 ++ offset += length_in_buffer; 4.936 ++ } /* while inner loop */ 4.937 + kunmap(bvec.bv_page); 4.938 + cond_resched(); 4.939 - } /* end rq_for_each_segment*/ 4.940 - return ((buffered_blocknum!=-1) || preloaded); 4.941 - } 4.942 - 4.943 - /* Adopted from loop.c, a kernel thread to handle physical reads and 4.944 -- * decompression. */ 4.945 ++ } /* end rq_for_each_segment*/ 4.946 ++ return ((buffered_blocknum!=-1) || preloaded); 4.947 ++} 4.948 ++ 4.949 ++/* Adopted from loop.c, a kernel thread to handle physical reads and 4.950 + decompression. */ 4.951 - static int cloop_thread(void *data) 4.952 - { 4.953 - struct cloop_device *clo = data; 4.954 - current->flags |= PF_NOFREEZE; 4.955 -- set_user_nice(current, -15); 4.956 ++static int cloop_thread(void *data) 4.957 ++{ 4.958 ++ struct cloop_device *clo = data; 4.959 ++ current->flags |= PF_NOFREEZE; 4.960 + set_user_nice(current, 10); 4.961 - while (!kthread_should_stop()||!list_empty(&clo->clo_list)) 4.962 - { 4.963 - int err; 4.964 -@@ -390,10 +496,18 @@ 4.965 - int rw; 4.966 - /* quick sanity checks */ 4.967 - /* blk_fs_request() was removed in 2.6.36 */ 4.968 -- if (unlikely(req == NULL || (req->cmd_type != REQ_TYPE_FS))) 4.969 ++ while (!kthread_should_stop()||!list_empty(&clo->clo_list)) 4.970 ++ { 4.971 ++ int err; 4.972 ++ err = wait_event_interruptible(clo->clo_event, !list_empty(&clo->clo_list) || 4.973 ++ kthread_should_stop()); 4.974 ++ if(unlikely(err)) 4.975 ++ { 4.976 ++ DEBUGP(KERN_ERR "cloop thread activated on error!? Continuing.\n"); 4.977 ++ continue; 4.978 + } 4.979 +- /* Copy from buffer */ 4.980 +- from_ptr = clo->buffer[buffered_blocknum]; 4.981 +- } 4.982 +- /* Now, at least part of what we want will be in the buffer. */ 4.983 +- length_in_buffer = clo->head.block_size - offset_in_buffer; 4.984 +- if(length_in_buffer > len) 4.985 +- { 4.986 +- /* DEBUGP("Warning: length_in_buffer=%u > len=%u\n", length_in_buffer,len); */ 4.987 +- length_in_buffer = len; 4.988 +- } 4.989 +- to_ptr = kmap_atomic(bvec.bv_page); 4.990 +- memcpy(to_ptr + to_offset, from_ptr + offset_in_buffer, length_in_buffer); 4.991 +- kunmap_atomic(to_ptr); 4.992 +- to_offset += length_in_buffer; 4.993 +- len -= length_in_buffer; 4.994 +- offset += length_in_buffer; 4.995 +- } /* while inner loop */ 4.996 +- } /* rq_for_each_segment */ 4.997 +- return ret; 4.998 +-} 4.999 +- 4.1000 +-static blk_status_t cloop_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) 4.1001 +-{ 4.1002 +-// struct request_queue *q = hctx->queue; 4.1003 +-// struct cloop_device *clo = q->queuedata; 4.1004 +- struct request *req = bd->rq; 4.1005 +- struct cloop_device *clo = req->rq_disk->private_data; 4.1006 +- blk_status_t ret = BLK_STS_OK; 4.1007 +- 4.1008 +-#if 1 /* Does it work when loading libraries? */ 4.1009 +- /* Since we have a buffered block list as well as data to read */ 4.1010 +- /* from disk (slow), and are (probably) never called from an */ 4.1011 +- /* interrupt, we use a simple mutex lock right here to ensure */ 4.1012 +- /* consistency. */ 4.1013 +- mutex_lock(&clo->clo_rq_mutex); 4.1014 +- #else 4.1015 +- spin_lock_irq(&clo->queue_lock); 4.1016 +- #endif 4.1017 +- blk_mq_start_request(req); 4.1018 +- do { 4.1019 +- ret = cloop_handle_request(clo, req); 4.1020 +- } while(blk_update_request(req, ret, blk_rq_cur_bytes(req))); 4.1021 +- blk_mq_end_request(req, ret); 4.1022 +- #if 1 /* See above */ 4.1023 +- mutex_unlock(&clo->clo_rq_mutex); 4.1024 +- #else 4.1025 +- spin_unlock_irq(&clo->queue_lock); 4.1026 +- #endif 4.1027 +- return ret; 4.1028 ++ if(!list_empty(&clo->clo_list)) 4.1029 ++ { 4.1030 ++ struct request *req; 4.1031 ++ unsigned long flags; 4.1032 ++ int uptodate; 4.1033 ++ spin_lock_irq(&clo->queue_lock); 4.1034 ++ req = list_entry(clo->clo_list.next, struct request, queuelist); 4.1035 ++ list_del_init(&req->queuelist); 4.1036 ++ spin_unlock_irq(&clo->queue_lock); 4.1037 ++ uptodate = cloop_handle_request(clo, req); 4.1038 ++ spin_lock_irqsave(&clo->queue_lock, flags); 4.1039 ++ __blk_end_request_all(req, uptodate ? 0 : -EIO); 4.1040 ++ spin_unlock_irqrestore(&clo->queue_lock, flags); 4.1041 ++ } 4.1042 ++ } 4.1043 ++ DEBUGP(KERN_ERR "cloop_thread exited.\n"); 4.1044 ++ return 0; 4.1045 ++} 4.1046 ++ 4.1047 ++/* This is called by the kernel block queue management every now and then, 4.1048 ++ * with successive read requests qeued and sorted in a (hopefully) 4.1049 ++ * "most efficient way". spin_lock_irq() is being held by the kernel. */ 4.1050 ++static void cloop_do_request(struct request_queue *q) 4.1051 ++{ 4.1052 ++ struct request *req; 4.1053 ++ while((req = blk_fetch_request(q)) != NULL) 4.1054 ++ { 4.1055 ++ struct cloop_device *clo; 4.1056 ++ int rw; 4.1057 ++ /* quick sanity checks */ 4.1058 ++ /* blk_fs_request() was removed in 2.6.36 */ 4.1059 + if (unlikely(req == NULL 4.1060 +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) /* field removed */ 4.1061 + || (req->cmd_type != REQ_TYPE_FS) 4.1062 +#endif 4.1063 + )) 4.1064 - goto error_continue; 4.1065 - rw = rq_data_dir(req); 4.1066 -- if (unlikely(rw != READ && rw != READA)) 4.1067 ++ goto error_continue; 4.1068 ++ rw = rq_data_dir(req); 4.1069 + if (unlikely(rw != READ 4.1070 +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) 4.1071 + && rw != READA 4.1072 +#endif 4.1073 + )) 4.1074 - { 4.1075 - DEBUGP("cloop_do_request: bad command\n"); 4.1076 - goto error_continue; 4.1077 -@@ -409,40 +523,51 @@ 4.1078 - continue; /* next request */ 4.1079 - error_continue: 4.1080 - DEBUGP(KERN_ERR "cloop_do_request: Discarding request %p.\n", req); 4.1081 ++ { 4.1082 ++ DEBUGP("cloop_do_request: bad command\n"); 4.1083 ++ goto error_continue; 4.1084 ++ } 4.1085 ++ clo = req->rq_disk->private_data; 4.1086 ++ if (unlikely(!clo->backing_file && !clo->suspended)) 4.1087 ++ { 4.1088 ++ DEBUGP("cloop_do_request: not connected to a file\n"); 4.1089 ++ goto error_continue; 4.1090 ++ } 4.1091 ++ list_add_tail(&req->queuelist, &clo->clo_list); /* Add to working list for thread */ 4.1092 ++ wake_up(&clo->clo_event); /* Wake up cloop_thread */ 4.1093 ++ continue; /* next request */ 4.1094 ++ error_continue: 4.1095 ++ DEBUGP(KERN_ERR "cloop_do_request: Discarding request %p.\n", req); 4.1096 +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) 4.1097 - req->errors++; 4.1098 ++ req->errors++; 4.1099 +#else 4.1100 + req->error_count++; 4.1101 +#endif 4.1102 - __blk_end_request_all(req, -EIO); 4.1103 - } 4.1104 ++ __blk_end_request_all(req, -EIO); 4.1105 ++ } 4.1106 } 4.1107 4.1108 --/* Read header and offsets from already opened file */ 4.1109 --static int cloop_set_file(int cloop_num, struct file *file, char *filename) 4.1110 -+/* Read header, flags and offsets from already opened file */ 4.1111 -+static int cloop_set_file(int cloop_num, struct file *file) 4.1112 - { 4.1113 - struct cloop_device *clo = cloop_dev[cloop_num]; 4.1114 - struct inode *inode; 4.1115 + /* Read header, flags and offsets from already opened file */ 4.1116 +@@ -508,7 +540,7 @@ 4.1117 char *bbuf=NULL; 4.1118 -- unsigned int i, offsets_read, total_offsets; 4.1119 -- int isblkdev; 4.1120 -- int error = 0; 4.1121 -+ unsigned int bbuf_size = 0; 4.1122 -+ const unsigned int header_size = sizeof(struct cloop_head); 4.1123 + unsigned int bbuf_size = 0; 4.1124 + const unsigned int header_size = sizeof(struct cloop_head); 4.1125 +- unsigned int i, offsets_read=0, total_offsets=0; 4.1126 + unsigned int i, total_offsets=0; 4.1127 -+ loff_t fs_read_position = 0, header_pos[2]; 4.1128 -+ int flags, isblkdev, bytes_read, error = 0; 4.1129 -+ if (clo->suspended) return error; 4.1130 -+ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) 4.1131 - inode = file->f_dentry->d_inode; 4.1132 -+ clo->underlying_filename = kstrdup(file->f_dentry->d_name.name ? file->f_dentry->d_name.name : (const unsigned char *)"anonymous filename", GFP_KERNEL); 4.1133 -+ #else 4.1134 -+ inode = file->f_path.dentry->d_inode; 4.1135 -+ 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); 4.1136 -+ #endif 4.1137 - isblkdev=S_ISBLK(inode->i_mode)?1:0; 4.1138 - if(!isblkdev&&!S_ISREG(inode->i_mode)) 4.1139 + loff_t fs_read_position = 0, header_pos[2]; 4.1140 + int isblkdev, bytes_read, error = 0; 4.1141 + if (clo->suspended) return error; 4.1142 +@@ -581,29 +613,19 @@ 4.1143 + goto error_release; 4.1144 + } 4.1145 + memcpy(&clo->head, bbuf, header_size); 4.1146 +- if (strncmp(bbuf+CLOOP4_SIGNATURE_OFFSET, CLOOP4_SIGNATURE, CLOOP4_SIGNATURE_SIZE)==0) 4.1147 ++ if (strncmp(bbuf+CLOOP_SIGNATURE_OFFSET, CLOOP_SIGNATURE, CLOOP_SIGNATURE_SIZE)==0) 4.1148 + { 4.1149 +- clo->file_format=4; 4.1150 ++ clo->file_format++; 4.1151 + clo->head.block_size=ntohl(clo->head.block_size); 4.1152 + clo->head.num_blocks=ntohl(clo->head.num_blocks); 4.1153 + clo->header_first = (i==0) ? 1 : 0; 4.1154 +- printk(KERN_INFO "%s: file %s version %d, %d blocks of %d bytes, header %s.\n", cloop_name, clo->underlying_filename, clo->file_format, clo->head.num_blocks, clo->head.block_size, (i==0)?"first":"last"); 4.1155 +- break; 4.1156 +- } 4.1157 +- else if (strncmp(bbuf+CLOOP2_SIGNATURE_OFFSET, CLOOP2_SIGNATURE, CLOOP2_SIGNATURE_SIZE)==0) 4.1158 +- { 4.1159 +- clo->file_format=2; 4.1160 +- clo->head.block_size=ntohl(clo->head.block_size); 4.1161 +- clo->head.num_blocks=ntohl(clo->head.num_blocks); 4.1162 +- clo->header_first = (i==0) ? 1 : 0; 4.1163 +- printk(KERN_INFO "%s: file %s version %d, %d blocks of %d bytes, header %s.\n", cloop_name, clo->underlying_filename, clo->file_format, clo->head.num_blocks, clo->head.block_size, (i==0)?"first":"last"); 4.1164 ++ 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"); 4.1165 + break; 4.1166 + } 4.1167 + } 4.1168 + if (clo->file_format == 0) 4.1169 { 4.1170 - printk(KERN_ERR "%s: %s not a regular file or block device\n", 4.1171 -- cloop_name, filename); 4.1172 -+ cloop_name, clo->underlying_filename); 4.1173 +- printk(KERN_ERR "%s: Cannot read old 32-bit (version 0.68) images, " 4.1174 +- "please use an older version of %s for this file.\n", 4.1175 ++ printk(KERN_ERR "%s: Cannot detect %s format.\n", 4.1176 + cloop_name, cloop_name); 4.1177 + error=-EBADF; goto error_release; 4.1178 + } 4.1179 +@@ -613,67 +635,133 @@ 4.1180 + cloop_name, clo->head.block_size); 4.1181 error=-EBADF; goto error_release; 4.1182 } 4.1183 - clo->backing_file = file; 4.1184 - clo->backing_inode= inode ; 4.1185 -- if(!isblkdev&&inode->i_size<sizeof(struct cloop_head)) 4.1186 -+ clo->underlying_total_size = (isblkdev) ? inode->i_bdev->bd_inode->i_size : inode->i_size; 4.1187 -+ if(clo->underlying_total_size < header_size) 4.1188 +- total_offsets=clo->head.num_blocks+1; 4.1189 +- if (!isblkdev && (sizeof(struct cloop_head)+sizeof(loff_t)* 4.1190 ++ total_offsets=clo->head.num_blocks; 4.1191 ++ if (!isblkdev && (sizeof(struct cloop_head)+sizeof(struct block_info)* 4.1192 + total_offsets > inode->i_size)) 4.1193 { 4.1194 -- printk(KERN_ERR "%s: %lu bytes (must be >= %u bytes)\n", 4.1195 -- cloop_name, (unsigned long)inode->i_size, 4.1196 -- (unsigned)sizeof(struct cloop_head)); 4.1197 -+ printk(KERN_ERR "%s: %llu bytes (must be >= %u bytes)\n", 4.1198 -+ cloop_name, clo->underlying_total_size, 4.1199 -+ (unsigned int)header_size); 4.1200 + printk(KERN_ERR "%s: file %s too small for %u blocks\n", 4.1201 + cloop_name, clo->underlying_filename, clo->head.num_blocks); 4.1202 error=-EBADF; goto error_release; 4.1203 } 4.1204 -- /* In suspended mode, we have done all checks necessary - FF */ 4.1205 -- if (clo->suspended) 4.1206 -- return error; 4.1207 - if(isblkdev) 4.1208 - { 4.1209 - struct request_queue *q = bdev_get_queue(inode->i_bdev); 4.1210 -@@ -451,104 +576,225 @@ 4.1211 - /* blk_queue_max_hw_segments(clo->clo_queue, queue_max_hw_segments(q)); */ /* Removed in 2.6.34 */ 4.1212 - blk_queue_max_segment_size(clo->clo_queue, queue_max_segment_size(q)); 4.1213 - blk_queue_segment_boundary(clo->clo_queue, queue_segment_boundary(q)); 4.1214 -+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) 4.1215 - blk_queue_merge_bvec(clo->clo_queue, q->merge_bvec_fn); 4.1216 -+#endif 4.1217 - clo->underlying_blksize = block_size(inode->i_bdev); 4.1218 - } 4.1219 - else 4.1220 - clo->underlying_blksize = PAGE_SIZE; 4.1221 -- DEBUGP("Underlying blocksize is %u\n", clo->underlying_blksize); 4.1222 -- bbuf = cloop_malloc(clo->underlying_blksize); 4.1223 -+ 4.1224 -+ DEBUGP(KERN_INFO "Underlying blocksize of %s is %u\n", clo->underlying_filename, clo->underlying_blksize); 4.1225 -+ DEBUGP(KERN_INFO "Underlying total size of %s is %llu\n", clo->underlying_filename, clo->underlying_total_size); 4.1226 -+ 4.1227 -+ /* clo->underlying_blksize should be larger than header_size, even if it's only PAGE_SIZE */ 4.1228 -+ bbuf_size = clo->underlying_blksize; 4.1229 -+ bbuf = cloop_malloc(bbuf_size); 4.1230 - if(!bbuf) 4.1231 - { 4.1232 -- printk(KERN_ERR "%s: out of kernel mem for block buffer (%lu bytes)\n", 4.1233 -- cloop_name, (unsigned long)clo->underlying_blksize); 4.1234 -+ printk(KERN_ERR "%s: out of kernel mem for buffer (%u bytes)\n", 4.1235 -+ cloop_name, (unsigned int) bbuf_size); 4.1236 -+ error=-ENOMEM; goto error_release; 4.1237 -+ } 4.1238 -+ 4.1239 -+ header_pos[0] = 0; /* header first */ 4.1240 -+ header_pos[1] = clo->underlying_total_size - sizeof(struct cloop_head); /* header last */ 4.1241 -+ for(i=0; i<2; i++) 4.1242 -+ { 4.1243 -+ /* Check for header */ 4.1244 -+ size_t bytes_readable = MIN(clo->underlying_blksize, clo->underlying_total_size - header_pos[i]); 4.1245 -+ size_t bytes_read = cloop_read_from_file(clo, file, bbuf, header_pos[i], bytes_readable); 4.1246 -+ if(bytes_read != bytes_readable) 4.1247 -+ { 4.1248 -+ printk(KERN_ERR "%s: Bad file %s, read() of %s %u bytes returned %d.\n", 4.1249 -+ cloop_name, clo->underlying_filename, (i==0)?"first":"last", 4.1250 -+ (unsigned int)header_size, (int)bytes_read); 4.1251 -+ error=-EBADF; 4.1252 -+ goto error_release; 4.1253 -+ } 4.1254 -+ memcpy(&clo->head, bbuf, header_size); 4.1255 -+ if (strncmp(bbuf+CLOOP_SIGNATURE_OFFSET, CLOOP_SIGNATURE, CLOOP_SIGNATURE_SIZE)==0) 4.1256 -+ { 4.1257 -+ clo->file_format++; 4.1258 -+ clo->head.block_size=ntohl(clo->head.block_size); 4.1259 -+ clo->head.num_blocks=ntohl(clo->head.num_blocks); 4.1260 -+ clo->header_first = (i==0) ? 1 : 0; 4.1261 -+ 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"); 4.1262 -+ break; 4.1263 -+ } 4.1264 -+ } 4.1265 -+ if (clo->file_format == 0) 4.1266 -+ { 4.1267 -+ printk(KERN_ERR "%s: Cannot detect %s format.\n", 4.1268 -+ cloop_name, cloop_name); 4.1269 -+ error=-EBADF; goto error_release; 4.1270 -+ } 4.1271 -+ if (clo->head.block_size % 512 != 0) 4.1272 -+ { 4.1273 -+ printk(KERN_ERR "%s: blocksize %u not multiple of 512\n", 4.1274 -+ cloop_name, clo->head.block_size); 4.1275 -+ error=-EBADF; goto error_release; 4.1276 -+ } 4.1277 -+ total_offsets=clo->head.num_blocks; 4.1278 -+ if (!isblkdev && (sizeof(struct cloop_head)+sizeof(struct block_info)* 4.1279 -+ total_offsets > inode->i_size)) 4.1280 -+ { 4.1281 -+ printk(KERN_ERR "%s: file %s too small for %u blocks\n", 4.1282 -+ cloop_name, clo->underlying_filename, clo->head.num_blocks); 4.1283 -+ error=-EBADF; goto error_release; 4.1284 -+ } 4.1285 +- clo->block_ptrs = cloop_malloc(sizeof(cloop_block_ptr) * total_offsets); 4.1286 +- if (!clo->block_ptrs) 4.1287 + /* Allocate Memory for decompressors */ 4.1288 +#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 4.1289 + clo->zstream.workspace = cloop_malloc(zlib_inflate_workspacesize()); 4.1290 + if(!clo->zstream.workspace) 4.1291 -+ { 4.1292 + { 4.1293 +- printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name); 4.1294 + printk(KERN_ERR "%s: out of mem for zlib working area %u\n", 4.1295 + cloop_name, zlib_inflate_workspacesize()); 4.1296 error=-ENOMEM; goto error_release; 4.1297 } 4.1298 -- total_offsets = 1; /* Dummy total_offsets: will be filled in first time around */ 4.1299 -- for (i = 0, offsets_read = 0; offsets_read < total_offsets; i++) 4.1300 +- /* Read them offsets! */ 4.1301 +- if(clo->header_first) 4.1302 + zlib_inflateInit(&clo->zstream); 4.1303 +#endif 4.1304 +#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 4.1305 @@ -890,33 +713,20 @@ 4.1306 +#endif 4.1307 + if (total_offsets + 1 == 0) /* Version 3 */ 4.1308 { 4.1309 -- unsigned int offset = 0, num_readable; 4.1310 -- size_t bytes_read = cloop_read_from_file(clo, file, bbuf, 4.1311 -- i*clo->underlying_blksize, 4.1312 -- clo->underlying_blksize); 4.1313 -- if(bytes_read != clo->underlying_blksize) 4.1314 +- fs_read_position = sizeof(struct cloop_head); 4.1315 + struct cloop_tail tail; 4.1316 + if (isblkdev) 4.1317 - { 4.1318 -- printk(KERN_ERR "%s: Bad file, read() of first %lu bytes returned %d.\n", 4.1319 -- cloop_name, (unsigned long)clo->underlying_blksize, (int)bytes_read); 4.1320 -- error=-EBADF; 4.1321 -- goto error_release; 4.1322 ++ { 4.1323 + /* No end of file: can't find index */ 4.1324 + printk(KERN_ERR "%s: no V3 support for block device\n", 4.1325 + cloop_name); 4.1326 + error=-EBADF; goto error_release; 4.1327 - } 4.1328 -- /* Header will be in block zero */ 4.1329 -- if(i==0) 4.1330 ++ } 4.1331 + bytes_read = cloop_read_from_file(clo, file, (void *) &tail, 4.1332 + inode->i_size - sizeof(struct cloop_tail), 4.1333 + sizeof(struct cloop_tail)); 4.1334 + if (bytes_read == sizeof(struct cloop_tail)) 4.1335 - { 4.1336 -- memcpy(&clo->head, bbuf, sizeof(struct cloop_head)); 4.1337 -- offset = sizeof(struct cloop_head); 4.1338 -- if (ntohl(clo->head.block_size) % 512 != 0) 4.1339 ++ { 4.1340 + unsigned long len, zlen; 4.1341 + int ret; 4.1342 + void *zbuf; 4.1343 @@ -926,79 +736,47 @@ 4.1344 + zlen = ntohl(tail.table_size); 4.1345 + zbuf = cloop_malloc(zlen); 4.1346 + if (!clo->block_ptrs || !zbuf) 4.1347 - { 4.1348 -- printk(KERN_ERR "%s: blocksize %u not multiple of 512\n", 4.1349 -- cloop_name, ntohl(clo->head.block_size)); 4.1350 -- error=-EBADF; goto error_release; 4.1351 -- } 4.1352 -- if (clo->head.preamble[0x0B]!='V'||clo->head.preamble[0x0C]<'1') 4.1353 -- { 4.1354 -- printk(KERN_ERR "%s: Cannot read old 32-bit (version 0.68) images, " 4.1355 -- "please use an older version of %s for this file.\n", 4.1356 -- cloop_name, cloop_name); 4.1357 -- error=-EBADF; goto error_release; 4.1358 ++ { 4.1359 + printk(KERN_ERR "%s: out of kernel mem for index\n", cloop_name); 4.1360 + error=-ENOMEM; goto error_release; 4.1361 - } 4.1362 -- if (clo->head.preamble[0x0C]<'2') 4.1363 ++ } 4.1364 + bytes_read = cloop_read_from_file(clo, file, zbuf, 4.1365 + inode->i_size - zlen - sizeof(struct cloop_tail), 4.1366 + zlen); 4.1367 + if (bytes_read != zlen) 4.1368 - { 4.1369 -- printk(KERN_ERR "%s: Cannot read old architecture-dependent " 4.1370 -- "(format <= 1.0) images, please use an older " 4.1371 -- "version of %s for this file.\n", 4.1372 -- cloop_name, cloop_name); 4.1373 ++ { 4.1374 + printk(KERN_ERR "%s: can't read index\n", cloop_name); 4.1375 - error=-EBADF; goto error_release; 4.1376 - } 4.1377 -- total_offsets=ntohl(clo->head.num_blocks)+1; 4.1378 -- if (!isblkdev && (sizeof(struct cloop_head)+sizeof(loff_t)* 4.1379 -- total_offsets > inode->i_size)) 4.1380 ++ error=-EBADF; goto error_release; 4.1381 ++ } 4.1382 + len = CLOOP3_INDEX_SIZE(ntohl(tail.index_size)) * total_offsets; 4.1383 -+ flags = CLOOP3_BLOCKS_FLAGS(ntohl(tail.index_size)); 4.1384 -+// 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) 4.1385 -+printk(KERN_INFO "%s: uncompress(clo=%p, block_ptrs=%p, &len(%ld)=%p, zbuf=%p, zlen=%ld, flag=%d)\n", cloop_name, 4.1386 -+ clo, clo->block_ptrs, len, &len, zbuf, zlen, flags); 4.1387 -+ ret = uncompress(clo, (void *) clo->block_ptrs, &len, zbuf, zlen, flags); 4.1388 -+// May 3 19:45:20 (none) user.alert kernel: BUG: unable to handle kernel NULL pointer dereference at (null) 4.1389 -+printk(KERN_INFO "%s: uncompressed !\n", cloop_name); 4.1390 ++ ret = uncompress(clo, (void *) clo->block_ptrs, &len, zbuf, zlen, CLOOP_COMPRESSOR_ZLIB); 4.1391 + cloop_free(zbuf, zlen); 4.1392 + if (ret != 0) 4.1393 - { 4.1394 -- printk(KERN_ERR "%s: file too small for %u blocks\n", 4.1395 -- cloop_name, ntohl(clo->head.num_blocks)); 4.1396 -+ printk(KERN_ERR "%s: decompression error %i uncompressing index, flags %u\n", 4.1397 -+ cloop_name, ret, flags); 4.1398 - error=-EBADF; goto error_release; 4.1399 - } 4.1400 -- clo->offsets = cloop_malloc(sizeof(loff_t) * total_offsets); 4.1401 -- if (!clo->offsets) 4.1402 -- { 4.1403 -- printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name); 4.1404 -- error=-ENOMEM; goto error_release; 4.1405 -- } 4.1406 - } 4.1407 -- num_readable = MIN(total_offsets - offsets_read, 4.1408 -- (clo->underlying_blksize - offset) 4.1409 -- / sizeof(loff_t)); 4.1410 -- memcpy(&clo->offsets[offsets_read], bbuf+offset, num_readable * sizeof(loff_t)); 4.1411 -- offsets_read += num_readable; 4.1412 -- } 4.1413 -- { /* Search for largest block rather than estimate. KK. */ 4.1414 -- int i; 4.1415 -- for(i=0;i<total_offsets-1;i++) 4.1416 ++ { 4.1417 ++ printk(KERN_ERR "%s: decompression error %i uncompressing index\n", 4.1418 ++ cloop_name, ret); 4.1419 ++ error=-EBADF; goto error_release; 4.1420 ++ } 4.1421 ++ } 4.1422 + else 4.1423 + { 4.1424 + printk(KERN_ERR "%s: can't find index\n", cloop_name); 4.1425 + error=-ENOMEM; goto error_release; 4.1426 + } 4.1427 -+ } 4.1428 -+ else 4.1429 -+ { 4.1430 + } 4.1431 + else 4.1432 + { 4.1433 +- fs_read_position = clo->underlying_total_size - sizeof(struct cloop_head) - total_offsets * sizeof(loff_t); 4.1434 +- } 4.1435 +- for(offsets_read=0;offsets_read<total_offsets;) 4.1436 +- { 4.1437 +- size_t bytes_readable; 4.1438 +- unsigned int num_readable, offset = 0; 4.1439 +- bytes_readable = MIN(bbuf_size, clo->underlying_total_size - fs_read_position); 4.1440 +- if(bytes_readable <= 0) break; /* Done */ 4.1441 +- bytes_read = cloop_read_from_file(clo, file, bbuf, fs_read_position, bytes_readable); 4.1442 +- if(bytes_read != bytes_readable) 4.1443 + unsigned int n, total_bytes; 4.1444 -+ flags = 0; 4.1445 + clo->block_ptrs = cloop_malloc(sizeof(struct block_info) * total_offsets); 4.1446 + if (!clo->block_ptrs) 4.1447 + { 4.1448 @@ -1007,14 +785,26 @@ 4.1449 + } 4.1450 + /* Read them offsets! */ 4.1451 + if(clo->header_first) 4.1452 -+ { 4.1453 + { 4.1454 +- printk(KERN_ERR "%s: Bad file %s, read() %lu bytes @ %llu returned %d.\n", 4.1455 +- cloop_name, clo->underlying_filename, (unsigned long)clo->underlying_blksize, fs_read_position, (int)bytes_read); 4.1456 +- error=-EBADF; 4.1457 +- goto error_release; 4.1458 + total_bytes = total_offsets * sizeof(struct block_info); 4.1459 + fs_read_position = sizeof(struct cloop_head); 4.1460 -+ } 4.1461 + } 4.1462 +- /* remember where to read the next blk from file */ 4.1463 +- fs_read_position += bytes_read; 4.1464 +- /* calculate how many offsets can be taken from current bbuf */ 4.1465 +- num_readable = MIN(total_offsets - offsets_read, 4.1466 +- bytes_read / sizeof(loff_t)); 4.1467 +- DEBUGP(KERN_INFO "cloop: parsing %d offsets %d to %d\n", num_readable, offsets_read, offsets_read+num_readable-1); 4.1468 +- for (i=0,offset=0; i<num_readable; i++) 4.1469 + else 4.1470 { 4.1471 -- loff_t d=be64_to_cpu(clo->offsets[i+1]) - be64_to_cpu(clo->offsets[i]); 4.1472 -- clo->largest_block=MAX(clo->largest_block,d); 4.1473 +- loff_t tmp = be64_to_cpu( *(loff_t*) (bbuf+offset) ); 4.1474 +- if (i%50==0) DEBUGP(KERN_INFO "cloop: offset %03d: %llu\n", offsets_read, tmp); 4.1475 +- if(offsets_read > 0) 4.1476 + total_bytes = total_offsets * sizeof(loff_t); 4.1477 + fs_read_position = clo->underlying_total_size - sizeof(struct cloop_head) - total_bytes; 4.1478 + } 4.1479 @@ -1025,35 +815,28 @@ 4.1480 + if(bytes_readable <= 0) break; /* Done */ 4.1481 + bytes_read = cloop_read_from_file(clo, file, bbuf, fs_read_position, bytes_readable); 4.1482 + if(bytes_read != bytes_readable) 4.1483 -+ { 4.1484 + { 4.1485 +- loff_t d = CLOOP_BLOCK_OFFSET(tmp) - CLOOP_BLOCK_OFFSET(clo->block_ptrs[offsets_read-1]); 4.1486 +- if(d > clo->largest_block) clo->largest_block = d; 4.1487 + printk(KERN_ERR "%s: Bad file %s, read() %lu bytes @ %llu returned %d.\n", 4.1488 + cloop_name, clo->underlying_filename, (unsigned long)clo->underlying_blksize, fs_read_position, (int)bytes_read); 4.1489 + error=-EBADF; 4.1490 + goto error_release; 4.1491 -+ } 4.1492 + } 4.1493 +- clo->block_ptrs[offsets_read++] = tmp; 4.1494 +- offset += sizeof(loff_t); 4.1495 + memcpy(((char *)clo->block_ptrs) + n, bbuf, bytes_read); 4.1496 + /* remember where to read the next blk from file */ 4.1497 + fs_read_position += bytes_read; 4.1498 + n += bytes_read; 4.1499 } 4.1500 -- printk(KERN_INFO "%s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n", 4.1501 -- cloop_name, filename, ntohl(clo->head.num_blocks), 4.1502 -- ntohl(clo->head.block_size), clo->largest_block); 4.1503 } 4.1504 --/* Combo kmalloc used too large chunks (>130000). */ 4.1505 +- printk(KERN_INFO "%s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n", 4.1506 +- cloop_name, clo->underlying_filename, clo->head.num_blocks, 4.1507 +- clo->head.block_size, clo->largest_block); 4.1508 { 4.1509 int i; 4.1510 -- for(i=0;i<BUFFERED_BLOCKS;i++) 4.1511 -- { 4.1512 -- clo->buffer[i] = cloop_malloc(ntohl(clo->head.block_size)); 4.1513 -- if(!clo->buffer[i]) 4.1514 -- { 4.1515 -- printk(KERN_ERR "%s: out of memory for buffer %lu\n", 4.1516 -- cloop_name, (unsigned long) ntohl(clo->head.block_size)); 4.1517 -- error=-ENOMEM; goto error_release_free; 4.1518 -- } 4.1519 -- } 4.1520 -+ char *version = build_index(clo->block_ptrs, clo->head.num_blocks, clo->head.block_size, flags); 4.1521 ++ char *version = build_index(clo->block_ptrs, clo->head.num_blocks, clo->head.block_size); 4.1522 + clo->largest_block = 0; 4.1523 + for (i = 0; i < clo->head.num_blocks; i++) 4.1524 + if (clo->block_ptrs[i].size > clo->largest_block) 4.1525 @@ -1061,39 +844,15 @@ 4.1526 + printk(KERN_INFO "%s: %s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n", 4.1527 + cloop_name, clo->underlying_filename, version, clo->head.num_blocks, 4.1528 + clo->head.block_size, clo->largest_block); 4.1529 -+ } 4.1530 -+ { 4.1531 -+ int i; 4.1532 -+ clo->num_buffered_blocks = (buffers > 0 && clo->head.block_size >= 512) ? 4.1533 -+ (buffers / clo->head.block_size) : 1; 4.1534 -+ clo->buffered_blocknum = cloop_malloc(clo->num_buffered_blocks * sizeof (u_int32_t)); 4.1535 -+ clo->buffer = cloop_malloc(clo->num_buffered_blocks * sizeof (char*)); 4.1536 -+ if (!clo->buffered_blocknum || !clo->buffer) 4.1537 -+ { 4.1538 -+ printk(KERN_ERR "%s: out of memory for index of cache buffer (%lu bytes)\n", 4.1539 -+ cloop_name, (unsigned long)clo->num_buffered_blocks * sizeof (u_int32_t) + sizeof(char*) ); 4.1540 -+ error=-ENOMEM; goto error_release; 4.1541 -+ } 4.1542 -+ memset(clo->buffer, 0, clo->num_buffered_blocks * sizeof (char*)); 4.1543 -+ for(i=0;i<clo->num_buffered_blocks;i++) 4.1544 -+ { 4.1545 -+ clo->buffered_blocknum[i] = -1; 4.1546 -+ clo->buffer[i] = cloop_malloc(clo->head.block_size); 4.1547 -+ if(!clo->buffer[i]) 4.1548 -+ { 4.1549 -+ printk(KERN_ERR "%s: out of memory for cache buffer %lu\n", 4.1550 -+ cloop_name, (unsigned long) clo->head.block_size); 4.1551 -+ error=-ENOMEM; goto error_release_free; 4.1552 -+ } 4.1553 -+ } 4.1554 -+ clo->current_bufnum = 0; 4.1555 - } 4.1556 - clo->compressed_buffer = cloop_malloc(clo->largest_block); 4.1557 - if(!clo->compressed_buffer) 4.1558 -@@ -557,31 +803,7 @@ 4.1559 + clo->num_buffered_blocks = (buffers > 0 && clo->head.block_size >= 512) ? 4.1560 + (buffers / clo->head.block_size) : 1; 4.1561 + clo->buffered_blocknum = cloop_malloc(clo->num_buffered_blocks * sizeof (u_int32_t)); 4.1562 +@@ -705,36 +793,14 @@ 4.1563 cloop_name, clo->largest_block); 4.1564 error=-ENOMEM; goto error_release_free_buffer; 4.1565 } 4.1566 +- /* Allocate Memory for decompressors */ 4.1567 +-#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 4.1568 - clo->zstream.workspace = cloop_malloc(zlib_inflate_workspacesize()); 4.1569 - if(!clo->zstream.workspace) 4.1570 - { 4.1571 @@ -1102,443 +861,48 @@ 4.1572 - error=-ENOMEM; goto error_release_free_all; 4.1573 - } 4.1574 - zlib_inflateInit(&clo->zstream); 4.1575 -- if(!isblkdev && 4.1576 -- be64_to_cpu(clo->offsets[ntohl(clo->head.num_blocks)]) != inode->i_size) 4.1577 -- { 4.1578 -- printk(KERN_ERR "%s: final offset wrong (%Lu not %Lu)\n", 4.1579 +-#endif 4.1580 +-#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 4.1581 +-#if XZ_INTERNAL_CRC32 4.1582 +- /* This must be called before any other xz_* function to initialize the CRC32 lookup table. */ 4.1583 +- xz_crc32_init(void); 4.1584 +-#endif 4.1585 +- clo->xzdecoderstate = xz_dec_init(XZ_SINGLE, 0); 4.1586 +-#endif 4.1587 +- if(CLOOP_BLOCK_OFFSET(clo->block_ptrs[clo->head.num_blocks]) > clo->underlying_total_size) 4.1588 ++ set_capacity(clo->clo_disk, (sector_t)(clo->head.num_blocks*(clo->head.block_size>>9))); 4.1589 ++ clo->clo_thread = kthread_create(cloop_thread, clo, "cloop%d", cloop_num); 4.1590 ++ if(IS_ERR(clo->clo_thread)) 4.1591 + { 4.1592 +- printk(KERN_ERR "%s: final offset wrong (%llu > %llu)\n", 4.1593 - cloop_name, 4.1594 -- be64_to_cpu(clo->offsets[ntohl(clo->head.num_blocks)]), 4.1595 -- inode->i_size); 4.1596 +- CLOOP_BLOCK_OFFSET(clo->block_ptrs[clo->head.num_blocks]), 4.1597 +- clo->underlying_total_size); 4.1598 +-#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 4.1599 - cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); clo->zstream.workspace=NULL; 4.1600 -- goto error_release_free_all; 4.1601 -- } 4.1602 -- { 4.1603 -- int i; 4.1604 -- for(i=0; i<BUFFERED_BLOCKS; i++) clo->buffered_blocknum[i] = -1; 4.1605 -- clo->current_bufnum=0; 4.1606 -- } 4.1607 -- set_capacity(clo->clo_disk, (sector_t)(ntohl(clo->head.num_blocks)* 4.1608 -- (ntohl(clo->head.block_size)>>9))); 4.1609 -+ set_capacity(clo->clo_disk, (sector_t)(clo->head.num_blocks*(clo->head.block_size>>9))); 4.1610 - clo->clo_thread = kthread_create(cloop_thread, clo, "cloop%d", cloop_num); 4.1611 - if(IS_ERR(clo->clo_thread)) 4.1612 - { 4.1613 -@@ -591,17 +813,17 @@ 4.1614 +-#endif 4.1615 ++ error = PTR_ERR(clo->clo_thread); 4.1616 ++ clo->clo_thread=NULL; 4.1617 + goto error_release_free_all; 4.1618 } 4.1619 +- set_capacity(clo->clo_disk, (sector_t)(clo->head.num_blocks*(clo->head.block_size>>9))); 4.1620 if(preload > 0) 4.1621 { 4.1622 -- clo->preload_array_size = ((preload<=ntohl(clo->head.num_blocks))?preload:ntohl(clo->head.num_blocks)); 4.1623 -+ clo->preload_array_size = ((preload<=clo->head.num_blocks)?preload:clo->head.num_blocks); 4.1624 - clo->preload_size = 0; 4.1625 - if((clo->preload_cache = cloop_malloc(clo->preload_array_size * sizeof(char *))) != NULL) 4.1626 - { 4.1627 - int i; 4.1628 - for(i=0; i<clo->preload_array_size; i++) 4.1629 - { 4.1630 -- if((clo->preload_cache[i] = cloop_malloc(ntohl(clo->head.block_size))) == NULL) 4.1631 -+ if((clo->preload_cache[i] = cloop_malloc(clo->head.block_size)) == NULL) 4.1632 - { /* Out of memory */ 4.1633 - printk(KERN_WARNING "%s: cloop_malloc(%d) failed for preload_cache[%d] (ignored).\n", 4.1634 -- cloop_name, ntohl(clo->head.block_size), i); 4.1635 -+ cloop_name, clo->head.block_size, i); 4.1636 - break; 4.1637 - } 4.1638 - } 4.1639 -@@ -612,13 +834,13 @@ 4.1640 - if(buffered_blocknum >= 0) 4.1641 - { 4.1642 - memcpy(clo->preload_cache[i], clo->buffer[buffered_blocknum], 4.1643 -- ntohl(clo->head.block_size)); 4.1644 -+ clo->head.block_size); 4.1645 - } 4.1646 - else 4.1647 - { 4.1648 - printk(KERN_WARNING "%s: can't read block %d into preload cache, set to zero.\n", 4.1649 - cloop_name, i); 4.1650 -- memset(clo->preload_cache[i], 0, ntohl(clo->head.block_size)); 4.1651 -+ memset(clo->preload_cache[i], 0, clo->head.block_size); 4.1652 - } 4.1653 - } 4.1654 - printk(KERN_INFO "%s: preloaded %d blocks into cache.\n", cloop_name, 4.1655 -@@ -641,22 +863,19 @@ 4.1656 - cloop_free(clo->compressed_buffer, clo->largest_block); 4.1657 - clo->compressed_buffer=NULL; 4.1658 - error_release_free_buffer: 4.1659 -+ if(clo->buffer) 4.1660 - { 4.1661 - int i; 4.1662 -- for(i=0; i<BUFFERED_BLOCKS; i++) 4.1663 -- { 4.1664 -- if(clo->buffer[i]) 4.1665 -- { 4.1666 -- cloop_free(clo->buffer[i], ntohl(clo->head.block_size)); 4.1667 -- clo->buffer[i]=NULL; 4.1668 -- } 4.1669 -- } 4.1670 -+ 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; }} 4.1671 -+ cloop_free(clo->buffer, clo->num_buffered_blocks*sizeof(char*)); clo->buffer=NULL; 4.1672 + clo->preload_array_size = ((preload<=clo->head.num_blocks)?preload:clo->head.num_blocks); 4.1673 +@@ -780,6 +846,7 @@ 4.1674 + clo->preload_array_size = clo->preload_size = 0; 4.1675 + } 4.1676 + } 4.1677 ++ wake_up_process(clo->clo_thread); 4.1678 + /* Uncheck */ 4.1679 + return error; 4.1680 + error_release_free_all: 4.1681 +@@ -794,9 +861,13 @@ 4.1682 } 4.1683 -+ if (clo->buffered_blocknum) { cloop_free(clo->buffered_blocknum, sizeof(int)*clo->num_buffered_blocks); clo->buffered_blocknum=NULL; } 4.1684 + if (clo->buffered_blocknum) { cloop_free(clo->buffered_blocknum, sizeof(int)*clo->num_buffered_blocks); clo->buffered_blocknum=NULL; } 4.1685 error_release_free: 4.1686 -- cloop_free(clo->offsets, sizeof(loff_t) * total_offsets); 4.1687 -- clo->offsets=NULL; 4.1688 +- cloop_free(clo->block_ptrs, sizeof(cloop_block_ptr) * total_offsets); 4.1689 + cloop_free(clo->block_ptrs, sizeof(struct block_info) * total_offsets); 4.1690 -+ clo->block_ptrs=NULL; 4.1691 - error_release: 4.1692 - if(bbuf) cloop_free(bbuf, clo->underlying_blksize); 4.1693 -+ if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; } 4.1694 - clo->backing_file=NULL; 4.1695 - return error; 4.1696 - } 4.1697 -@@ -673,7 +892,7 @@ 4.1698 - if(clo->backing_file) return -EBUSY; 4.1699 - file = fget(arg); /* get filp struct from ioctl arg fd */ 4.1700 - if(!file) return -EBADF; 4.1701 -- error=cloop_set_file(cloop_num,file,"losetup_file"); 4.1702 -+ error=cloop_set_file(cloop_num,file); 4.1703 - set_device_ro(bdev, 1); 4.1704 - if(error) fput(file); 4.1705 - return error; 4.1706 -@@ -684,29 +903,48 @@ 4.1707 - { 4.1708 - struct cloop_device *clo = cloop_dev[cloop_num]; 4.1709 - struct file *filp = clo->backing_file; 4.1710 -- int i; 4.1711 - if(clo->refcnt > 1) /* we needed one fd for the ioctl */ 4.1712 - return -EBUSY; 4.1713 - if(filp==NULL) return -EINVAL; 4.1714 - if(clo->clo_thread) { kthread_stop(clo->clo_thread); clo->clo_thread=NULL; } 4.1715 -- if(filp!=initial_file) fput(filp); 4.1716 -- else { filp_close(initial_file,0); initial_file=NULL; } 4.1717 -+ if(filp!=initial_file) 4.1718 -+ fput(filp); 4.1719 -+ else 4.1720 -+ { 4.1721 -+ filp_close(initial_file,0); 4.1722 -+ initial_file=NULL; 4.1723 -+ } 4.1724 - clo->backing_file = NULL; 4.1725 - clo->backing_inode = NULL; 4.1726 -- if(clo->offsets) { cloop_free(clo->offsets, clo->underlying_blksize); clo->offsets = NULL; } 4.1727 -+ if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; } 4.1728 -+ if(clo->block_ptrs) { cloop_free(clo->block_ptrs, clo->head.num_blocks); clo->block_ptrs = NULL; } 4.1729 - if(clo->preload_cache) 4.1730 -- { 4.1731 -- for(i=0; i < clo->preload_size; i++) 4.1732 -- cloop_free(clo->preload_cache[i], ntohl(clo->head.block_size)); 4.1733 -- cloop_free(clo->preload_cache, clo->preload_array_size * sizeof(char *)); 4.1734 -- clo->preload_cache = NULL; 4.1735 -- clo->preload_size = clo->preload_array_size = 0; 4.1736 -- } 4.1737 -- for(i=0; i<BUFFERED_BLOCKS; i++) 4.1738 -- if(clo->buffer[i]) { cloop_free(clo->buffer[i], ntohl(clo->head.block_size)); clo->buffer[i]=NULL; } 4.1739 -+ { 4.1740 -+ int i; 4.1741 -+ for(i=0; i < clo->preload_size; i++) 4.1742 -+ cloop_free(clo->preload_cache[i], clo->head.block_size); 4.1743 -+ cloop_free(clo->preload_cache, clo->preload_array_size * sizeof(char *)); 4.1744 -+ clo->preload_cache = NULL; 4.1745 -+ clo->preload_size = clo->preload_array_size = 0; 4.1746 -+ } 4.1747 -+ if (clo->buffered_blocknum) 4.1748 -+ { 4.1749 -+ cloop_free(clo->buffered_blocknum, sizeof(int) * clo->num_buffered_blocks); clo->buffered_blocknum = NULL; 4.1750 -+ } 4.1751 -+ if (clo->buffer) 4.1752 -+ { 4.1753 -+ int i; 4.1754 -+ for(i=0; i<clo->num_buffered_blocks; i++) { if(clo->buffer[i]) cloop_free(clo->buffer[i], clo->head.block_size); } 4.1755 -+ cloop_free(clo->buffer, sizeof(char*) * clo->num_buffered_blocks); clo->buffer = NULL; 4.1756 -+ } 4.1757 - if(clo->compressed_buffer) { cloop_free(clo->compressed_buffer, clo->largest_block); clo->compressed_buffer = NULL; } 4.1758 -+#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 4.1759 - zlib_inflateEnd(&clo->zstream); 4.1760 - if(clo->zstream.workspace) { cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); clo->zstream.workspace = NULL; } 4.1761 -+#endif 4.1762 -+#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 4.1763 -+ xz_dec_end(clo->xzdecoderstate); 4.1764 -+#endif 4.1765 - if(bdev) invalidate_bdev(bdev); 4.1766 - if(clo->clo_disk) set_capacity(clo->clo_disk, 0); 4.1767 - return 0; 4.1768 -@@ -731,8 +969,8 @@ 4.1769 - const struct loop_info64 *info) 4.1770 - { 4.1771 - if (!clo->backing_file) return -ENXIO; 4.1772 -- memcpy(clo->clo_file_name, info->lo_file_name, LO_NAME_SIZE); 4.1773 -- clo->clo_file_name[LO_NAME_SIZE-1] = 0; 4.1774 -+ if(clo->underlying_filename) kfree(clo->underlying_filename); 4.1775 -+ clo->underlying_filename = kstrdup(info->lo_file_name, GFP_KERNEL); 4.1776 - return 0; 4.1777 - } 4.1778 - 4.1779 -@@ -743,7 +981,11 @@ 4.1780 - struct kstat stat; 4.1781 - int err; 4.1782 - if (!file) return -ENXIO; 4.1783 -- err = vfs_getattr(file->f_path.mnt, file->f_path.dentry, &stat); 4.1784 -+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) 4.1785 -+ err = vfs_getattr(&file->f_path, &stat); 4.1786 -+#else 4.1787 -+ err = vfs_getattr(&file->f_path, &stat, STATX_INO, AT_STATX_SYNC_AS_STAT); 4.1788 -+#endif 4.1789 - if (err) return err; 4.1790 - memset(info, 0, sizeof(*info)); 4.1791 - info->lo_number = clo->clo_number; 4.1792 -@@ -753,7 +995,8 @@ 4.1793 - info->lo_offset = 0; 4.1794 - info->lo_sizelimit = 0; 4.1795 - info->lo_flags = 0; 4.1796 -- memcpy(info->lo_file_name, clo->clo_file_name, LO_NAME_SIZE); 4.1797 -+ strncpy(info->lo_file_name, clo->underlying_filename, LO_NAME_SIZE); 4.1798 -+ info->lo_file_name[LO_NAME_SIZE-1]=0; 4.1799 - return 0; 4.1800 - } 4.1801 - 4.1802 -@@ -833,8 +1076,6 @@ 4.1803 - if (!err && copy_to_user(arg, &info64, sizeof(info64))) err = -EFAULT; 4.1804 - return err; 4.1805 - } 4.1806 --/* EOF get/set_status */ 4.1807 -- 4.1808 - 4.1809 - static int cloop_ioctl(struct block_device *bdev, fmode_t mode, 4.1810 - unsigned int cmd, unsigned long arg) 4.1811 -@@ -914,21 +1155,20 @@ 4.1812 - /* losetup uses write-open and flags=0x8002 to set a new file */ 4.1813 - if(mode & FMODE_WRITE) 4.1814 - { 4.1815 -- printk(KERN_WARNING "%s: Can't open device read-write in mode 0x%x\n", cloop_name, mode); 4.1816 -+ printk(KERN_INFO "%s: Open in read-write mode 0x%x requested, ignored.\n", cloop_name, mode); 4.1817 - return -EROFS; 4.1818 - } 4.1819 - cloop_dev[cloop_num]->refcnt+=1; 4.1820 - return 0; 4.1821 - } 4.1822 - 4.1823 --static int cloop_close(struct gendisk *disk, fmode_t mode) 4.1824 -+static void cloop_close(struct gendisk *disk, fmode_t mode) 4.1825 - { 4.1826 -- int cloop_num, err=0; 4.1827 -- if(!disk) return 0; 4.1828 -+ int cloop_num; 4.1829 -+ if(!disk) return; 4.1830 - cloop_num=((struct cloop_device *)disk->private_data)->clo_number; 4.1831 -- if(cloop_num < 0 || cloop_num > (cloop_count-1)) return 0; 4.1832 -+ if(cloop_num < 0 || cloop_num > (cloop_count-1)) return; 4.1833 - cloop_dev[cloop_num]->refcnt-=1; 4.1834 -- return err; 4.1835 - } 4.1836 - 4.1837 - static struct block_device_operations clo_fops = 4.1838 -@@ -973,6 +1213,10 @@ 4.1839 - goto error_out; 4.1840 - } 4.1841 - clo->clo_queue->queuedata = clo; 4.1842 -+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) 4.1843 -+ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, clo->clo_queue); 4.1844 -+ queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, clo->clo_queue); 4.1845 -+#endif 4.1846 - clo->clo_disk = alloc_disk(1); 4.1847 - if(!clo->clo_disk) 4.1848 - { 4.1849 -@@ -1004,6 +1248,11 @@ 4.1850 - cloop_dev[cloop_num] = NULL; 4.1851 - } 4.1852 - 4.1853 -+/* LZ4 Stuff */ 4.1854 -+#if (defined USE_LZ4_INTERNAL) 4.1855 -+#include "lz4_kmod.c" 4.1856 -+#endif 4.1857 -+ 4.1858 - static int __init cloop_init(void) 4.1859 - { 4.1860 - int error=0; 4.1861 -@@ -1044,7 +1293,7 @@ 4.1862 - initial_file=NULL; /* if IS_ERR, it's NOT open. */ 4.1863 - } 4.1864 - else 4.1865 -- error=cloop_set_file(0,initial_file,file); 4.1866 -+ error=cloop_set_file(0,initial_file); 4.1867 - if(error) 4.1868 - { 4.1869 - printk(KERN_ERR 4.1870 -@@ -1052,9 +1301,6 @@ 4.1871 - cloop_name, file, error); 4.1872 - goto init_out_dealloc; 4.1873 - } 4.1874 -- if(namelen >= LO_NAME_SIZE) namelen = LO_NAME_SIZE-1; 4.1875 -- memcpy(cloop_dev[0]->clo_file_name, file, namelen); 4.1876 -- cloop_dev[0]->clo_file_name[namelen] = 0; 4.1877 - } 4.1878 - return 0; 4.1879 - init_out_dealloc: 4.1880 ---- cloop.h 4.1881 -+++ cloop.h 4.1882 -@@ -86,11 +86,8 @@ 4.1883 - struct cloop_tail 4.1884 - { 4.1885 - u_int32_t table_size; 4.1886 -- u_int32_t index_size; /* size:4 comp:3 ctrl-c:1 lastlen:24 */ 4.1887 -+ u_int32_t index_size; /* size:4 unused:3 ctrl-c:1 lastlen:24 */ 4.1888 - #define CLOOP3_INDEX_SIZE(x) ((unsigned int)((x) & 0xF)) 4.1889 --#define CLOOP3_BLOCKS_FLAGS(x) ((unsigned int)((x) & 0x70) >> 4) 4.1890 --#define CLOOP3_TRUNCATED(x) ((unsigned int)((x) & 0x80) >> 7) 4.1891 --#define CLOOP3_LASTLEN(x) (unsigned int)((x) >> 8) 4.1892 - u_int32_t num_blocks; 4.1893 - }; 4.1894 - 4.1895 -@@ -104,8 +101,10 @@ 4.1896 - }; 4.1897 - 4.1898 - static inline char *build_index(struct block_info *offsets, unsigned long n, 4.1899 -- unsigned long block_size, unsigned global_flags) 4.1900 -+ unsigned long block_size) 4.1901 - { 4.1902 -+ static char v[11]; 4.1903 -+ u_int32_t flags = 0; 4.1904 - u_int32_t *ofs32 = (u_int32_t *) offsets; 4.1905 - loff_t *ofs64 = (loff_t *) offsets; 4.1906 - 4.1907 -@@ -130,8 +129,6 @@ 4.1908 - } 4.1909 - else { /* V2.0/V4.0 */ 4.1910 - loff_t last = CLOOP_BLOCK_OFFSET(__be64_to_cpu(ofs64[n])); 4.1911 -- u_int32_t flags; 4.1912 -- static char v4[11]; 4.1913 - unsigned long i = n; 4.1914 - 4.1915 - for (flags = 0; n-- ;) { 4.1916 -@@ -149,12 +146,7 @@ 4.1917 - offsets[i] = offsets[offsets[i].offset]; 4.1918 - } 4.1919 - } 4.1920 -- strcpy(v4, (char *) "64BE v4.0a"); 4.1921 -- v4[10] = 'a' + ((flags-1) & 0xF); // compressors used 4.1922 -- if (flags > 0x10) { // with links ? 4.1923 -- v4[10] += 'A' - 'a'; 4.1924 -- } 4.1925 -- return v4; 4.1926 -+ strcpy(v, (char *) "64BE v4.0a"); 4.1927 - } 4.1928 - } 4.1929 - else if (ofs32[1] == 0 && v3_64 == 0) { /* V1.0 */ 4.1930 -@@ -170,7 +162,6 @@ 4.1931 - else { /* V3.0 or V0.68 */ 4.1932 - unsigned long i; 4.1933 - loff_t j; 4.1934 -- static char v3[11]; 4.1935 - 4.1936 - for (i = 0; i < n && ntohl(ofs32[i]) < ntohl(ofs32[i+1]); i++); 4.1937 - if (i == n && ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */ 4.1938 -@@ -185,28 +176,33 @@ 4.1939 - } 4.1940 - 4.1941 - v3_64 = (ofs32[1] == 0); 4.1942 -- for (i = n; i-- != 0; ) 4.1943 -+ for (i = n; i-- != 0; ) { 4.1944 - offsets[i].size = ntohl(ofs32[i << v3_64]); 4.1945 -- for (i = 0, j = sizeof(struct cloop_head); i < n; i++) { 4.1946 -- offsets[i].offset = j; 4.1947 -- offsets[i].flags = global_flags; 4.1948 - if (offsets[i].size == 0xFFFFFFFF) { 4.1949 -- offsets[i].flags = CLOOP_COMPRESSOR_NONE; 4.1950 -- offsets[i].size = block_size; 4.1951 -+ offsets[i].size = 0x10000000 | block_size; 4.1952 - } 4.1953 -- if ((offsets[i].size & 0x80000000) == 0) { 4.1954 -+ offsets[i].flags = (offsets[i].size >> 28); 4.1955 -+ offsets[i].size &= 0x0FFFFFFF; 4.1956 -+ } 4.1957 -+ for (i = 0, j = sizeof(struct cloop_head); i < n; i++) { 4.1958 -+ offsets[i].offset = j; 4.1959 -+ if (offsets[i].flags < 8) { 4.1960 - j += offsets[i].size; 4.1961 - } 4.1962 - } 4.1963 - for (i = 0; i < n; i++) { 4.1964 -- if (offsets[i].size & 0x80000000) { 4.1965 -- offsets[i] = offsets[offsets[i].size & 0x7FFFFFFF]; 4.1966 -+ flags |= 1 << offsets[i].flags; 4.1967 -+ if (offsets[i].flags >= 8) { 4.1968 -+ offsets[i] = offsets[offsets[i].size]; 4.1969 - } 4.1970 - } 4.1971 -- strcpy(v3, (char *) (v3_64) ? "64BE v3.0a" : "32BE v3.0a"); 4.1972 -- v3[10] += global_flags; 4.1973 -- return v3; 4.1974 -+ strcpy(v, (char *) (v3_64) ? "64BE v3.0a" : "32BE v3.0a"); 4.1975 -+ } 4.1976 -+ v[10] = 'a' + ((flags-1) & 0xF); // compressors used 4.1977 -+ if (flags > 0x10) { // with links ? 4.1978 -+ v[10] += 'A' - 'a'; 4.1979 - } 4.1980 -+ return v; 4.1981 - } 4.1982 - 4.1983 - /* Cloop suspend IOCTL */ 4.1984 ---- cloop.c 4.1985 -+++ cloop.c 4.1986 -@@ -542,7 +542,7 @@ 4.1987 - const unsigned int header_size = sizeof(struct cloop_head); 4.1988 - unsigned int i, total_offsets=0; 4.1989 - loff_t fs_read_position = 0, header_pos[2]; 4.1990 -- int flags, isblkdev, bytes_read, error = 0; 4.1991 -+ int isblkdev, bytes_read, error = 0; 4.1992 - if (clo->suspended) return error; 4.1993 - #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) 4.1994 - inode = file->f_dentry->d_inode; 4.1995 -@@ -698,18 +698,12 @@ 4.1996 - error=-EBADF; goto error_release; 4.1997 - } 4.1998 - len = CLOOP3_INDEX_SIZE(ntohl(tail.index_size)) * total_offsets; 4.1999 -- flags = CLOOP3_BLOCKS_FLAGS(ntohl(tail.index_size)); 4.2000 --// 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) 4.2001 --printk(KERN_INFO "%s: uncompress(clo=%p, block_ptrs=%p, &len(%ld)=%p, zbuf=%p, zlen=%ld, flag=%d)\n", cloop_name, 4.2002 -- clo, clo->block_ptrs, len, &len, zbuf, zlen, flags); 4.2003 -- ret = uncompress(clo, (void *) clo->block_ptrs, &len, zbuf, zlen, flags); 4.2004 --// May 3 19:45:20 (none) user.alert kernel: BUG: unable to handle kernel NULL pointer dereference at (null) 4.2005 --printk(KERN_INFO "%s: uncompressed !\n", cloop_name); 4.2006 -+ ret = uncompress(clo, (void *) clo->block_ptrs, &len, zbuf, zlen, CLOOP_COMPRESSOR_ZLIB); 4.2007 - cloop_free(zbuf, zlen); 4.2008 - if (ret != 0) 4.2009 - { 4.2010 -- printk(KERN_ERR "%s: decompression error %i uncompressing index, flags %u\n", 4.2011 -- cloop_name, ret, flags); 4.2012 -+ printk(KERN_ERR "%s: decompression error %i uncompressing index\n", 4.2013 -+ cloop_name, ret); 4.2014 - error=-EBADF; goto error_release; 4.2015 - } 4.2016 - } 4.2017 -@@ -722,7 +716,6 @@ 4.2018 - else 4.2019 - { 4.2020 - unsigned int n, total_bytes; 4.2021 -- flags = 0; 4.2022 - clo->block_ptrs = cloop_malloc(sizeof(struct block_info) * total_offsets); 4.2023 - if (!clo->block_ptrs) 4.2024 - { 4.2025 -@@ -761,7 +754,7 @@ 4.2026 - } 4.2027 - { 4.2028 - int i; 4.2029 -- char *version = build_index(clo->block_ptrs, clo->head.num_blocks, clo->head.block_size, flags); 4.2030 -+ char *version = build_index(clo->block_ptrs, clo->head.num_blocks, clo->head.block_size); 4.2031 - clo->largest_block = 0; 4.2032 - for (i = 0; i < clo->head.num_blocks; i++) 4.2033 - if (clo->block_ptrs[i].size > clo->largest_block) 4.2034 -@@ -769,9 +762,6 @@ 4.2035 - printk(KERN_INFO "%s: %s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n", 4.2036 - cloop_name, clo->underlying_filename, version, clo->head.num_blocks, 4.2037 - clo->head.block_size, clo->largest_block); 4.2038 -- } 4.2039 -- { 4.2040 -- int i; 4.2041 - clo->num_buffered_blocks = (buffers > 0 && clo->head.block_size >= 512) ? 4.2042 - (buffers / clo->head.block_size) : 1; 4.2043 - clo->buffered_blocknum = cloop_malloc(clo->num_buffered_blocks * sizeof (u_int32_t)); 4.2044 -@@ -874,6 +864,10 @@ 4.2045 - cloop_free(clo->block_ptrs, sizeof(struct block_info) * total_offsets); 4.2046 clo->block_ptrs=NULL; 4.2047 error_release: 4.2048 +#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 4.2049 @@ -1548,3 +912,146 @@ 4.2050 if(bbuf) cloop_free(bbuf, clo->underlying_blksize); 4.2051 if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; } 4.2052 clo->backing_file=NULL; 4.2053 +@@ -829,6 +900,7 @@ 4.2054 + if(clo->refcnt > 1) /* we needed one fd for the ioctl */ 4.2055 + return -EBUSY; 4.2056 + if(filp==NULL) return -EINVAL; 4.2057 ++ if(clo->clo_thread) { kthread_stop(clo->clo_thread); clo->clo_thread=NULL; } 4.2058 + if(filp!=initial_file) 4.2059 + fput(filp); 4.2060 + else 4.2061 +@@ -839,7 +911,7 @@ 4.2062 + clo->backing_file = NULL; 4.2063 + clo->backing_inode = NULL; 4.2064 + if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; } 4.2065 +- if(clo->block_ptrs) { cloop_free(clo->block_ptrs, clo->head.num_blocks+1); clo->block_ptrs = NULL; } 4.2066 ++ if(clo->block_ptrs) { cloop_free(clo->block_ptrs, clo->head.num_blocks); clo->block_ptrs = NULL; } 4.2067 + if(clo->preload_cache) 4.2068 + { 4.2069 + int i; 4.2070 +@@ -1054,15 +1126,15 @@ 4.2071 + case LOOP_CLR_FD: /* Change arg */ 4.2072 + case LOOP_GET_STATUS64: /* Change arg */ 4.2073 + case LOOP_SET_STATUS64: /* Change arg */ 4.2074 +- return cloop_ioctl(bdev, mode, cmd, (unsigned long) compat_ptr(arg)); 4.2075 ++ arg = (unsigned long) compat_ptr(arg); 4.2076 + case LOOP_SET_STATUS: /* unchanged */ 4.2077 + case LOOP_GET_STATUS: /* unchanged */ 4.2078 + case LOOP_SET_FD: /* unchanged */ 4.2079 + case LOOP_CHANGE_FD: /* unchanged */ 4.2080 +- return cloop_ioctl(bdev, mode, cmd, arg); 4.2081 +- default: 4.2082 +- return -ENOIOCTLCMD; 4.2083 ++ return cloop_ioctl(bdev, mode, cmd, arg); 4.2084 ++ break; 4.2085 + } 4.2086 ++ return -ENOIOCTLCMD; 4.2087 + } 4.2088 + #endif 4.2089 + 4.2090 +@@ -1093,7 +1165,7 @@ 4.2091 + cloop_dev[cloop_num]->refcnt-=1; 4.2092 + } 4.2093 + 4.2094 +-static const struct block_device_operations clo_fops = 4.2095 ++static struct block_device_operations clo_fops = 4.2096 + { 4.2097 + owner: THIS_MODULE, 4.2098 + open: cloop_open, 4.2099 +@@ -1105,12 +1177,6 @@ 4.2100 + /* locked_ioctl ceased to exist in 2.6.36 */ 4.2101 + }; 4.2102 + 4.2103 +-static const struct blk_mq_ops cloop_mq_ops = { 4.2104 +- .queue_rq = cloop_queue_rq, 4.2105 +-/* .init_request = cloop_init_request, */ 4.2106 +-/* .complete = cloop_complete_rq, */ 4.2107 +-}; 4.2108 +- 4.2109 + static int cloop_register_blkdev(int major_nr) 4.2110 + { 4.2111 + return register_blkdev(major_nr, cloop_name); 4.2112 +@@ -1124,37 +1190,33 @@ 4.2113 + 4.2114 + static int cloop_alloc(int cloop_num) 4.2115 + { 4.2116 +- struct cloop_device *clo = (struct cloop_device *) cloop_malloc(sizeof(struct cloop_device)); 4.2117 ++ struct cloop_device *clo = (struct cloop_device *) cloop_malloc(sizeof(struct cloop_device));; 4.2118 + if(clo == NULL) goto error_out; 4.2119 + cloop_dev[cloop_num] = clo; 4.2120 + memset(clo, 0, sizeof(struct cloop_device)); 4.2121 + clo->clo_number = cloop_num; 4.2122 +- clo->tag_set.ops = &cloop_mq_ops; 4.2123 +- clo->tag_set.nr_hw_queues = 1; 4.2124 +- clo->tag_set.queue_depth = 128; 4.2125 +- clo->tag_set.numa_node = NUMA_NO_NODE; 4.2126 +- clo->tag_set.cmd_size = 0; /* No extra data needed */ 4.2127 +- /* BLK_MQ_F_BLOCKING is extremely important if we want to call blocking functions like vfs_read */ 4.2128 +- clo->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING; 4.2129 +- clo->tag_set.driver_data = clo; 4.2130 +- if(blk_mq_alloc_tag_set(&clo->tag_set)) goto error_out_free_clo; 4.2131 +- clo->clo_queue = blk_mq_init_queue(&clo->tag_set); 4.2132 +- if(IS_ERR(clo->clo_queue)) 4.2133 ++ clo->clo_thread = NULL; 4.2134 ++ init_waitqueue_head(&clo->clo_event); 4.2135 ++ spin_lock_init(&clo->queue_lock); 4.2136 ++ mutex_init(&clo->clo_ctl_mutex); 4.2137 ++ INIT_LIST_HEAD(&clo->clo_list); 4.2138 ++ clo->clo_queue = blk_init_queue(cloop_do_request, &clo->queue_lock); 4.2139 ++ if(!clo->clo_queue) 4.2140 + { 4.2141 + printk(KERN_ERR "%s: Unable to alloc queue[%d]\n", cloop_name, cloop_num); 4.2142 +- goto error_out_free_tags; 4.2143 ++ goto error_out; 4.2144 + } 4.2145 + clo->clo_queue->queuedata = clo; 4.2146 +- blk_queue_max_hw_sectors(clo->clo_queue, BLK_DEF_MAX_SECTORS); 4.2147 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) 4.2148 ++ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, clo->clo_queue); 4.2149 ++ queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, clo->clo_queue); 4.2150 ++#endif 4.2151 + clo->clo_disk = alloc_disk(1); 4.2152 + if(!clo->clo_disk) 4.2153 + { 4.2154 + printk(KERN_ERR "%s: Unable to alloc disk[%d]\n", cloop_name, cloop_num); 4.2155 +- goto error_out_free_queue; 4.2156 ++ goto error_disk; 4.2157 + } 4.2158 +- spin_lock_init(&clo->queue_lock); 4.2159 +- mutex_init(&clo->clo_ctl_mutex); 4.2160 +- mutex_init(&clo->clo_rq_mutex); 4.2161 + clo->clo_disk->major = cloop_major; 4.2162 + clo->clo_disk->first_minor = cloop_num; 4.2163 + clo->clo_disk->fops = &clo_fops; 4.2164 +@@ -1163,12 +1225,8 @@ 4.2165 + sprintf(clo->clo_disk->disk_name, "%s%d", cloop_name, cloop_num); 4.2166 + add_disk(clo->clo_disk); 4.2167 + return 0; 4.2168 +-error_out_free_queue: 4.2169 ++error_disk: 4.2170 + blk_cleanup_queue(clo->clo_queue); 4.2171 +-error_out_free_tags: 4.2172 +- blk_mq_free_tag_set(&clo->tag_set); 4.2173 +-error_out_free_clo: 4.2174 +- cloop_free(clo, sizeof(struct cloop_device)); 4.2175 + error_out: 4.2176 + return -ENOMEM; 4.2177 + } 4.2178 +@@ -1179,7 +1237,6 @@ 4.2179 + if(clo == NULL) return; 4.2180 + del_gendisk(clo->clo_disk); 4.2181 + blk_cleanup_queue(clo->clo_queue); 4.2182 +- blk_mq_free_tag_set(&clo->tag_set); 4.2183 + put_disk(clo->clo_disk); 4.2184 + cloop_free(clo, sizeof(struct cloop_device)); 4.2185 + cloop_dev[cloop_num] = NULL; 4.2186 +--- cloop_suspend.c 4.2187 ++++ cloop_suspend.c 4.2188 +@@ -14,6 +14,7 @@ 4.2189 + #include <fcntl.h> 4.2190 + #include <unistd.h> 4.2191 + #include <stdio.h> 4.2192 ++#include <stdint.h> 4.2193 + 4.2194 + /* We don't use the structure, so that define does not hurt */ 4.2195 + #define dev_t int
5.1 --- a/wbar/receipt Sun May 08 13:06:36 2022 +0000 5.2 +++ b/wbar/receipt Sun May 08 16:45:21 2022 +0000 5.3 @@ -8,7 +8,7 @@ 5.4 LICENSE="GPL" 5.5 TARBALL="$PACKAGE-$VERSION.tbz2" 5.6 WEB_SITE="https://github.com/rodolf0/wbar" 5.7 -WGET_URL="http://www.tecapli.com.ar/warlock/$TARBALL" 5.8 +WGET_URL="https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/$PACKAGE/$TARBALL" 5.9 CONFIG_FILES="/etc/wbar/dot.wbar" 5.10 TAGS="desktop launchbar" 5.11
6.1 --- a/xa/receipt Sun May 08 13:06:36 2022 +0000 6.2 +++ b/xa/receipt Sun May 08 16:45:21 2022 +0000 6.3 @@ -10,7 +10,7 @@ 6.4 WEB_SITE="https://www.floodgap.com/retrotech/xa/" 6.5 6.6 TARBALL="$PACKAGE-$VERSION.tar.gz" 6.7 -WGET_URL="${WEB_SITE}dists/$TARBALL" 6.8 +WGET_URL="${WEB_SITE}dists/unsupported/$TARBALL" 6.9 6.10 # What is the latest version available today? 6.11 current_version()
7.1 --- a/xautomation/receipt Sun May 08 13:06:36 2022 +0000 7.2 +++ b/xautomation/receipt Sun May 08 16:45:21 2022 +0000 7.3 @@ -7,9 +7,8 @@ 7.4 MAINTAINER="pankso@slitaz.org" 7.5 LICENSE="GPL2" 7.6 TARBALL="$PACKAGE-$VERSION.tar.gz" 7.7 -#WEB_SITE="http://hoopajoo.net/projects/xautomation.html" 7.8 -WEB_SITE="https://sourceforge.net/projects/xautomation/" 7.9 -WGET_URL="http://hoopajoo.net/static/projects/$TARBALL" 7.10 +WEB_SITE="https://www.hoopajoo.net/projects/xautomation.html" 7.11 +WGET_URL="https://www.hoopajoo.net/static/projects/$TARBALL" 7.12 #HOST_ARCH="i486 arm" 7.13 7.14 DEPENDS="xorg-libX11 libpng"
8.1 --- a/xcursor-aero/receipt Sun May 08 13:06:36 2022 +0000 8.2 +++ b/xcursor-aero/receipt Sun May 08 16:45:21 2022 +0000 8.3 @@ -8,7 +8,7 @@ 8.4 LICENSE="GPL" 8.5 WEB_SITE="https://www.gnome-look.org/p/999972/" 8.6 TARBALL="$PACKAGE-$VERSION.tar.gz" 8.7 -WGET_URL="http://www.infinality.net/files/aero.tar.gz" 8.8 +WGET_URL="https://github.com/Infinality/mouse-cursors/raw/master/aero.tar.gz" 8.9 TAGS="cursor-theme" 8.10 8.11 DEPENDS="xorg-libXcursor"
9.1 --- a/xcursor-comix/receipt Sun May 08 13:06:36 2022 +0000 9.2 +++ b/xcursor-comix/receipt Sun May 08 16:45:21 2022 +0000 9.3 @@ -1,7 +1,7 @@ 9.4 # SliTaz package receipt. 9.5 9.6 PACKAGE="xcursor-comix" 9.7 -VERSION="0.9.1" 9.8 +VERSION="0.9.2" 9.9 CATEGORY="customization" 9.10 TAGS="cursor-theme" 9.11 SHORT_DESC="Comix cursor theme." 9.12 @@ -10,6 +10,7 @@ 9.13 WEB_SITE="https://limitland.de/comixcursors" 9.14 9.15 TARBALL="ComixCursors-$VERSION.tar.bz2" 9.16 +#WGET_URL="https://gitlab.com/limitland/comixcursors/-/archive/$VERSION/comixcursors-$VERSION.tar.bz2" 9.17 WGET_URL="https://limitland.gitlab.io/comixcursors/$TARBALL" 9.18 9.19 DEPENDS="xorg-libXcursor"