wok diff linux64-cloop/stuff/cloop.u @ rev 24988
Fix perl-gd & tcptrack
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Thu May 12 11:01:25 2022 +0000 (2022-05-12) |
parents | cea6e929d21e |
children | c81179c4b106 |
line diff
1.1 --- a/linux64-cloop/stuff/cloop.u Tue May 05 11:06:44 2020 +0000 1.2 +++ b/linux64-cloop/stuff/cloop.u Thu May 12 11:01:25 2022 +0000 1.3 @@ -1,6 +1,6 @@ 1.4 --- cloop.h 1.5 +++ cloop.h 1.6 -@@ -1,15 +1,50 @@ 1.7 +@@ -1,3 +1,7 @@ 1.8 +#define CLOOP_SIGNATURE "#!/bin/sh" /* @ offset 0 */ 1.9 +#define CLOOP_SIGNATURE_SIZE 9 1.10 +#define CLOOP_SIGNATURE_OFFSET 0x0 1.11 @@ -8,99 +8,46 @@ 1.12 #ifndef _COMPRESSED_LOOP_H 1.13 #define _COMPRESSED_LOOP_H 1.14 1.15 --#define CLOOP_HEADROOM 128 1.16 -+/*************************************************************************\ 1.17 -+* Starting with Format V4.0 (cloop version 4.x), cloop can now have two * 1.18 -+* alternative structures: * 1.19 -+* * 1.20 -+* 1. Header first: "robust" format, handles missing blocks well * 1.21 -+* 2. Footer (header last): "streaming" format, easier to create * 1.22 -+* * 1.23 -+* The cloop kernel module autodetects both formats, and can (currently) * 1.24 -+* still handle the V2.0 format as well. * 1.25 -+* * 1.26 -+* 1. Header first: * 1.27 -+* +---------------------------- FIXED SIZE ---------------------------+ * 1.28 -+* |Signature (128 bytes) | * 1.29 -+* |block_size (32bit number, network order) | * 1.30 -+* |num_blocks (32bit number, network order) | * 1.31 -+* +--------------------------- VARIABLE SIZE -------------------------+ * 1.32 -+* |num_blocks * FlagsOffset (upper 4 bits flags, lower 64 bits offset)| * 1.33 -+* |compressed data blocks of variable size ... | * 1.34 -+* +-------------------------------------------------------------------+ * 1.35 -+* * 1.36 -+* 2. Footer (header last): * 1.37 -+* +--------------------------- VARIABLE SIZE -------------------------+ * 1.38 -+* |compressed data blocks of variable size ... | * 1.39 -+* |num_blocks * FlagsOffset (upper 4 bits flags, lower 64 bits offset)| * 1.40 -+* +---------------------------- FIXED SIZE ---------------------------+ * 1.41 -+* |Signature (128 bytes) | * 1.42 -+* |block_size (32bit number, network order) | * 1.43 -+* |num_blocks (32bit number, network order) | * 1.44 -+* +-------------------------------------------------------------------+ * 1.45 -+* * 1.46 -+* Offsets are always relative to beginning of file, in all formats. * 1.47 -+* The block index contains num_blocks+1 offsets, followed (1) or * 1.48 -+* preceded (2) by the compressed blocks. * 1.49 -+\*************************************************************************/ 1.50 +@@ -38,10 +42,6 @@ 1.51 1.52 --/* The cloop header usually looks like this: */ 1.53 --/* #!/bin/sh */ 1.54 --/* #V2.00 Format */ 1.55 --/* ...padding up to CLOOP_HEADROOM... */ 1.56 --/* block_size (32bit number, network order) */ 1.57 --/* num_blocks (32bit number, network order) */ 1.58 -+#include <linux/types.h> /* u_int32_t */ 1.59 -+ 1.60 -+#define CLOOP_HEADROOM 128 1.61 + #include <linux/types.h> /* u_int32_t */ 1.62 1.63 -+/* Header of fixed length, can be located at beginning or end of file */ 1.64 - struct cloop_head 1.65 - { 1.66 - char preamble[CLOOP_HEADROOM]; 1.67 -@@ -17,9 +52,163 @@ 1.68 +-#ifndef __KERNEL__ 1.69 +-#include <stdint.h> /* regular uint64_t */ 1.70 +-#endif 1.71 +- 1.72 + #define CLOOP_HEADROOM 128 1.73 + 1.74 + /* Header of fixed length, can be located at beginning or end of file */ 1.75 +@@ -52,13 +52,6 @@ 1.76 u_int32_t num_blocks; 1.77 }; 1.78 1.79 -+/************************************************************************\ 1.80 -+* CLOOP4 flags for each compressed block * 1.81 -+* Value Meaning * 1.82 -+* 0 GZIP/7ZIP compression (compatible with V2.0 Format) * 1.83 -+* 1 no compression (incompressible data) * 1.84 -+* 2 xz compression (currently best space saver) * 1.85 -+* 3 lz4 compression * 1.86 -+* 4 lzo compression (fastest) * 1.87 -+\************************************************************************/ 1.88 -+ 1.89 -+typedef uint64_t cloop_block_ptr; 1.90 -+ 1.91 -+/* Get value of first 4 bits */ 1.92 -+#define CLOOP_BLOCK_FLAGS(x) ((unsigned int)(((x) & 0xf000000000000000LLU) >> 60)) 1.93 -+/* Get value of last 60 bits */ 1.94 -+#define CLOOP_BLOCK_OFFSET(x) ((x) & 0x0fffffffffffffffLLU) 1.95 -+ 1.96 -+#define CLOOP_COMPRESSOR_ZLIB 0x0 1.97 -+#define CLOOP_COMPRESSOR_NONE 0x1 1.98 -+#define CLOOP_COMPRESSOR_XZ 0x2 1.99 -+#define CLOOP_COMPRESSOR_LZ4 0x3 1.100 -+#define CLOOP_COMPRESSOR_LZO1X 0x4 1.101 -+ 1.102 -+#define CLOOP_COMPRESSOR_VALID(x) ((x) >= CLOOP_COMPRESSOR_ZLIB && (x) <= CLOOP_COMPRESSOR_LZO1X) 1.103 -+ 1.104 +-#define CLOOP2_SIGNATURE "V2.0" /* @ offset 0x0b */ 1.105 +-#define CLOOP2_SIGNATURE_SIZE 4 1.106 +-#define CLOOP2_SIGNATURE_OFFSET 0x0b 1.107 +-#define CLOOP4_SIGNATURE "V4.0" /* @ offset 0x0b */ 1.108 +-#define CLOOP4_SIGNATURE_SIZE 4 1.109 +-#define CLOOP4_SIGNATURE_OFFSET 0x0b 1.110 +- 1.111 + /************************************************************************\ 1.112 + * CLOOP4 flags for each compressed block * 1.113 + * Value Meaning * 1.114 +@@ -84,6 +77,134 @@ 1.115 + 1.116 + #define CLOOP_COMPRESSOR_VALID(x) ((x) >= CLOOP_COMPRESSOR_ZLIB && (x) <= CLOOP_COMPRESSOR_LZO1X) 1.117 + 1.118 +#define CLOOP_COMPRESSOR_LINK 0xF 1.119 + 1.120 + 1.121 - /* data_index (num_blocks 64bit pointers, network order)... */ 1.122 - /* compressed data (gzip block compressed format)... */ 1.123 - 1.124 ++/* data_index (num_blocks 64bit pointers, network order)... */ 1.125 ++/* compressed data (gzip block compressed format)... */ 1.126 ++ 1.127 +struct cloop_tail 1.128 +{ 1.129 + u_int32_t table_size; 1.130 -+ u_int32_t index_size; /* size:4 comp:3 ctrl-c:1 lastlen:24 */ 1.131 ++ u_int32_t index_size; /* size:4 unused:3 ctrl-c:1 lastlen:24 */ 1.132 +#define CLOOP3_INDEX_SIZE(x) ((unsigned int)((x) & 0xF)) 1.133 -+#define CLOOP3_BLOCKS_FLAGS(x) ((unsigned int)((x) & 0x70) >> 4) 1.134 -+#define CLOOP3_TRUNCATED(x) ((unsigned int)((x) & 0x80) >> 7) 1.135 -+#define CLOOP3_LASTLEN(x) (unsigned int)((x) >> 8) 1.136 + u_int32_t num_blocks; 1.137 +}; 1.138 + 1.139 @@ -114,8 +61,10 @@ 1.140 +}; 1.141 + 1.142 +static inline char *build_index(struct block_info *offsets, unsigned long n, 1.143 -+ unsigned long block_size, unsigned global_flags) 1.144 ++ unsigned long block_size) 1.145 +{ 1.146 ++ static char v[11]; 1.147 ++ u_int32_t flags = 0; 1.148 + u_int32_t *ofs32 = (u_int32_t *) offsets; 1.149 + loff_t *ofs64 = (loff_t *) offsets; 1.150 + 1.151 @@ -140,8 +89,6 @@ 1.152 + } 1.153 + else { /* V2.0/V4.0 */ 1.154 + loff_t last = CLOOP_BLOCK_OFFSET(__be64_to_cpu(ofs64[n])); 1.155 -+ u_int32_t flags; 1.156 -+ static char v4[11]; 1.157 + unsigned long i = n; 1.158 + 1.159 + for (flags = 0; n-- ;) { 1.160 @@ -159,12 +106,7 @@ 1.161 + offsets[i] = offsets[offsets[i].offset]; 1.162 + } 1.163 + } 1.164 -+ strcpy(v4, (char *) "64BE v4.0a"); 1.165 -+ v4[10] = 'a' + ((flags-1) & 0xF); // compressors used 1.166 -+ if (flags > 0x10) { // with links ? 1.167 -+ v4[10] += 'A' - 'a'; 1.168 -+ } 1.169 -+ return v4; 1.170 ++ strcpy(v, (char *) "64BE v4.0a"); 1.171 + } 1.172 + } 1.173 + else if (ofs32[1] == 0 && v3_64 == 0) { /* V1.0 */ 1.174 @@ -180,7 +122,6 @@ 1.175 + else { /* V3.0 or V0.68 */ 1.176 + unsigned long i; 1.177 + loff_t j; 1.178 -+ static char v3[11]; 1.179 + 1.180 + for (i = 0; i < n && ntohl(ofs32[i]) < ntohl(ofs32[i+1]); i++); 1.181 + if (i == n && ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */ 1.182 @@ -195,28 +136,33 @@ 1.183 + } 1.184 + 1.185 + v3_64 = (ofs32[1] == 0); 1.186 -+ for (i = n; i-- != 0; ) 1.187 ++ for (i = n; i-- != 0; ) { 1.188 + offsets[i].size = ntohl(ofs32[i << v3_64]); 1.189 ++ if (offsets[i].size == 0xFFFFFFFF) { 1.190 ++ offsets[i].size = 0x10000000 | block_size; 1.191 ++ } 1.192 ++ offsets[i].flags = (offsets[i].size >> 28); 1.193 ++ offsets[i].size &= 0x0FFFFFFF; 1.194 ++ } 1.195 + for (i = 0, j = sizeof(struct cloop_head); i < n; i++) { 1.196 + offsets[i].offset = j; 1.197 -+ offsets[i].flags = global_flags; 1.198 -+ if (offsets[i].size == 0xFFFFFFFF) { 1.199 -+ offsets[i].flags = CLOOP_COMPRESSOR_NONE; 1.200 -+ offsets[i].size = block_size; 1.201 -+ } 1.202 -+ if ((offsets[i].size & 0x80000000) == 0) { 1.203 ++ if (offsets[i].flags < 8) { 1.204 + j += offsets[i].size; 1.205 + } 1.206 + } 1.207 + for (i = 0; i < n; i++) { 1.208 -+ if (offsets[i].size & 0x80000000) { 1.209 -+ offsets[i] = offsets[offsets[i].size & 0x7FFFFFFF]; 1.210 ++ flags |= 1 << offsets[i].flags; 1.211 ++ if (offsets[i].flags >= 8) { 1.212 ++ offsets[i] = offsets[offsets[i].size]; 1.213 + } 1.214 + } 1.215 -+ strcpy(v3, (char *) (v3_64) ? "64BE v3.0a" : "32BE v3.0a"); 1.216 -+ v3[10] += global_flags; 1.217 -+ return v3; 1.218 ++ strcpy(v, (char *) (v3_64) ? "64BE v3.0a" : "32BE v3.0a"); 1.219 + } 1.220 ++ v[10] = 'a' + ((flags-1) & 0xF); // compressors used 1.221 ++ if (flags > 0x10) { // with links ? 1.222 ++ v[10] += 'A' - 'a'; 1.223 ++ } 1.224 ++ return v; 1.225 +} 1.226 + 1.227 /* Cloop suspend IOCTL */ 1.228 @@ -224,661 +170,538 @@ 1.229 1.230 --- cloop.c 1.231 +++ cloop.c 1.232 -@@ -1,26 +1,23 @@ 1.233 --/* 1.234 -- * compressed_loop.c: Read-only compressed loop blockdevice 1.235 -- * hacked up by Rusty in 1999, extended and maintained by Klaus Knopper 1.236 -- * 1.237 -- * A cloop file looks like this: 1.238 -- * [32-bit uncompressed block size: network order] 1.239 -- * [32-bit number of blocks (n_blocks): network order] 1.240 -- * [64-bit file offsets of start of blocks: network order] 1.241 -- * ... 1.242 -- * (n_blocks + 1). 1.243 -- * n_blocks consisting of: 1.244 -- * [compressed block] 1.245 -- * 1.246 -- * Every version greatly inspired by code seen in loop.c 1.247 -- * by Theodore Ts'o, 3/29/93. 1.248 -- * 1.249 -- * Copyright 1999-2009 by Paul `Rusty' Russell & Klaus Knopper. 1.250 -- * Redistribution of this file is permitted under the GNU Public License. 1.251 -- * 1.252 -- */ 1.253 -+/************************************************************************\ 1.254 -+* cloop.c: Read-only compressed loop blockdevice * 1.255 -+* hacked up by Rusty in 1999, extended and maintained by Klaus Knopper * 1.256 -+* * 1.257 -+* For all supported cloop file formats, please check the file "cloop.h" * 1.258 -+* New in Version 4: * 1.259 -+* - Header can be first or last in cloop file, * 1.260 -+* - Different compression algorithms supported (compression type * 1.261 -+* encoded in first 4 bytes of block offset address) * 1.262 -+* * 1.263 -+* Every version greatly inspired by code seen in loop.c * 1.264 -+* by Theodore Ts'o, 3/29/93. * 1.265 -+* * 1.266 -+* Copyright 1999-2009 by Paul `Rusty' Russell & Klaus Knopper. * 1.267 -+* Redistribution of this file is permitted under the GNU Public License * 1.268 -+* V2. * 1.269 -+\************************************************************************/ 1.270 +@@ -17,7 +17,7 @@ 1.271 + \************************************************************************/ 1.272 1.273 #define CLOOP_NAME "cloop" 1.274 --#define CLOOP_VERSION "2.639" 1.275 +-#define CLOOP_VERSION "5.3" 1.276 +#define CLOOP_VERSION "4.12" 1.277 #define CLOOP_MAX 8 1.278 1.279 #ifndef KBUILD_MODNAME 1.280 -@@ -47,8 +44,27 @@ 1.281 - #include <asm/div64.h> /* do_div() for 64bit division */ 1.282 - #include <asm/uaccess.h> 1.283 - #include <asm/byteorder.h> 1.284 --/* Use zlib_inflate from lib/zlib_inflate */ 1.285 -+/* Check for ZLIB, LZO1X, LZ4 decompression algorithms in kernel. */ 1.286 -+#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 1.287 - #include <linux/zutil.h> 1.288 -+#endif 1.289 -+#if (defined(CONFIG_LZO_DECOMPRESS) || defined(CONFIG_LZO_DECOMPRESS_MODULE)) 1.290 -+#include <linux/lzo.h> 1.291 -+#endif 1.292 -+#if (defined(CONFIG_DECOMPRESS_LZ4) || defined(CONFIG_DECOMPRESS_LZ4_MODULE)) 1.293 -+#include <linux/lz4.h> 1.294 -+#endif 1.295 -+#if (defined(CONFIG_DECOMPRESS_LZMA) || defined(CONFIG_DECOMPRESS_LZMA_MODULE)) 1.296 -+#include <linux/decompress/unlzma.h> 1.297 -+#endif 1.298 -+#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 1.299 -+#include <linux/xz.h> 1.300 -+#endif 1.301 -+ 1.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))) 1.303 -+#error "No decompression library selected in kernel config!" 1.304 -+#endif 1.305 -+ 1.306 +@@ -68,7 +68,6 @@ 1.307 #include <linux/loop.h> 1.308 #include <linux/kthread.h> 1.309 #include <linux/compat.h> 1.310 -@@ -92,47 +108,64 @@ 1.311 - #define DEBUGP(format, x...) 1.312 - #endif 1.313 +-#include <linux/blk-mq.h> /* new multiqueue infrastructure */ 1.314 + #include "cloop.h" 1.315 1.316 -+/* Default size of buffer to keep some decompressed blocks in memory to speed up access */ 1.317 -+#define BLOCK_BUFFER_MEM (16*65536) 1.318 -+ 1.319 - /* One file can be opened at module insertion time */ 1.320 - /* insmod cloop file=/path/to/file */ 1.321 - static char *file=NULL; 1.322 - static unsigned int preload=0; 1.323 - static unsigned int cloop_max=CLOOP_MAX; 1.324 -+static unsigned int buffers=BLOCK_BUFFER_MEM; 1.325 - module_param(file, charp, 0); 1.326 - module_param(preload, uint, 0); 1.327 - module_param(cloop_max, uint, 0); 1.328 - MODULE_PARM_DESC(file, "Initial cloop image file (full path) for /dev/cloop"); 1.329 - MODULE_PARM_DESC(preload, "Preload n blocks of cloop data into memory"); 1.330 - MODULE_PARM_DESC(cloop_max, "Maximum number of cloop devices (default 8)"); 1.331 -+MODULE_PARM_DESC(buffers, "Size of buffer to keep uncompressed blocks in memory in MiB (default 1)"); 1.332 + /* New License scheme */ 1.333 +@@ -93,10 +92,7 @@ 1.334 + /* Use experimental major for now */ 1.335 + #define MAJOR_NR 240 1.336 1.337 - static struct file *initial_file=NULL; 1.338 - static int cloop_major=MAJOR_NR; 1.339 +-#ifndef DEVICE_NAME 1.340 +-#define DEVICE_NAME CLOOP_NAME 1.341 +-#endif 1.342 +- 1.343 ++/* #define DEVICE_NAME CLOOP_NAME */ 1.344 + /* #define DEVICE_NR(device) (MINOR(device)) */ 1.345 + /* #define DEVICE_ON(device) */ 1.346 + /* #define DEVICE_OFF(device) */ 1.347 +@@ -143,7 +139,7 @@ 1.348 + u_int32_t allflags; 1.349 1.350 --/* Number of buffered decompressed blocks */ 1.351 --#define BUFFERED_BLOCKS 8 1.352 - struct cloop_device 1.353 - { 1.354 -- /* Copied straight from the file */ 1.355 -+ /* Header filled from the file */ 1.356 - struct cloop_head head; 1.357 -+ int header_first; 1.358 -+ int file_format; 1.359 - 1.360 -- /* An array of offsets of compressed blocks within the file */ 1.361 -- loff_t *offsets; 1.362 -+ /* An or'd sum of all flags of each compressed block (v3) */ 1.363 -+ u_int32_t allflags; 1.364 -+ 1.365 -+ /* An array of cloop_ptr flags/offset for compressed blocks within the file */ 1.366 + /* An array of cloop_ptr flags/offset for compressed blocks within the file */ 1.367 +- cloop_block_ptr *block_ptrs; 1.368 + struct block_info *block_ptrs; 1.369 1.370 /* We buffer some uncompressed blocks for performance */ 1.371 -- int buffered_blocknum[BUFFERED_BLOCKS]; 1.372 -- int current_bufnum; 1.373 -- void *buffer[BUFFERED_BLOCKS]; 1.374 -- void *compressed_buffer; 1.375 -- size_t preload_array_size; /* Size of pointer array in blocks */ 1.376 -- size_t preload_size; /* Number of successfully allocated blocks */ 1.377 -- char **preload_cache; /* Pointers to preloaded blocks */ 1.378 -+ size_t num_buffered_blocks; /* how many uncompressed blocks buffered for performance */ 1.379 -+ int *buffered_blocknum; /* list of numbers of uncompressed blocks in buffer */ 1.380 -+ int current_bufnum; /* which block is current */ 1.381 -+ unsigned char **buffer; /* cache space for num_buffered_blocks uncompressed blocks */ 1.382 -+ void *compressed_buffer; /* space for the largest compressed block */ 1.383 -+ size_t preload_array_size; /* Size of pointer array in blocks */ 1.384 -+ size_t preload_size; /* Number of successfully allocated blocks */ 1.385 -+ char **preload_cache; /* Pointers to preloaded blocks */ 1.386 - 1.387 -+#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 1.388 - z_stream zstream; 1.389 -+#endif 1.390 -+#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 1.391 -+ struct xz_dec *xzdecoderstate; 1.392 -+ struct xz_buf xz_buffer; 1.393 -+#endif 1.394 - 1.395 - struct file *backing_file; /* associated file */ 1.396 - struct inode *backing_inode; /* for bmap */ 1.397 - 1.398 -+ unsigned char *underlying_filename; 1.399 - unsigned long largest_block; 1.400 - unsigned int underlying_blksize; 1.401 -+ loff_t underlying_total_size; 1.402 - int clo_number; 1.403 - int refcnt; 1.404 - struct block_device *bdev; 1.405 -@@ -147,7 +180,6 @@ 1.406 + size_t num_buffered_blocks; /* how many uncompressed blocks buffered for performance */ 1.407 +@@ -178,14 +174,16 @@ 1.408 + spinlock_t queue_lock; 1.409 + /* mutex for ioctl() */ 1.410 + struct mutex clo_ctl_mutex; 1.411 +- /* mutex for request */ 1.412 +- struct mutex clo_rq_mutex; 1.413 ++ struct list_head clo_list; 1.414 ++ struct task_struct *clo_thread; 1.415 ++ wait_queue_head_t clo_event; 1.416 struct request_queue *clo_queue; 1.417 struct gendisk *clo_disk; 1.418 +- struct blk_mq_tag_set tag_set; 1.419 int suspended; 1.420 -- char clo_file_name[LO_NAME_SIZE]; 1.421 }; 1.422 1.423 - /* Changed in 2.639: cloop_dev is now a an array of cloop_dev pointers, 1.424 -@@ -156,52 +188,113 @@ 1.425 ++/* Changed in 2.639: cloop_dev is now a an array of cloop_dev pointers, 1.426 ++ so we can specify how many devices we need via parameters. */ 1.427 + static struct cloop_device **cloop_dev; 1.428 static const char *cloop_name=CLOOP_NAME; 1.429 static int cloop_count = 0; 1.430 - 1.431 --#if (!(defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE))) /* Must be compiled into kernel. */ 1.432 --#error "Invalid Kernel configuration. CONFIG_ZLIB_INFLATE support is needed for cloop." 1.433 --#endif 1.434 -- 1.435 --/* Use __get_free_pages instead of vmalloc, allows up to 32 pages, 1.436 -- * 2MB in one piece */ 1.437 - static void *cloop_malloc(size_t size) 1.438 - { 1.439 -- int order = get_order(size); 1.440 -- if(order <= KMALLOC_MAX_ORDER) 1.441 -- return (void *)kmalloc(size, GFP_KERNEL); 1.442 -- else if(order < MAX_ORDER) 1.443 -- return (void *)__get_free_pages(GFP_KERNEL, order); 1.444 -+ /* kmalloc will fail after the system is running for a while, */ 1.445 -+ /* when large orders can't return contiguous memory. */ 1.446 -+ /* Let's just use vmalloc for now. :-/ */ 1.447 -+ /* int order = get_order(size); */ 1.448 -+ /* if(order <= KMALLOC_MAX_ORDER) */ 1.449 -+ /* return (void *)kmalloc(size, GFP_KERNEL); */ 1.450 -+ /* else if(order < MAX_ORDER) */ 1.451 -+ /* return (void *)__get_free_pages(GFP_KERNEL, order); */ 1.452 - return (void *)vmalloc(size); 1.453 +@@ -214,24 +212,21 @@ 1.454 + vfree(mem); 1.455 } 1.456 1.457 - static void cloop_free(void *mem, size_t size) 1.458 - { 1.459 -- int order = get_order(size); 1.460 -- if(order <= KMALLOC_MAX_ORDER) 1.461 -- kfree(mem); 1.462 -- else if(order < MAX_ORDER) 1.463 -- free_pages((unsigned long)mem, order); 1.464 -- else vfree(mem); 1.465 -+ /* int order = get_order(size); */ 1.466 -+ /* if(order <= KMALLOC_MAX_ORDER) */ 1.467 -+ /* kfree(mem); */ 1.468 -+ /* else if(order < MAX_ORDER) */ 1.469 -+ /* free_pages((unsigned long)mem, order); */ 1.470 -+ /* else */ 1.471 -+ vfree(mem); 1.472 - } 1.473 - 1.474 --static int uncompress(struct cloop_device *clo, 1.475 -- unsigned char *dest, unsigned long *destLen, 1.476 -- unsigned char *source, unsigned long sourceLen) 1.477 +-/* static int uncompress(struct cloop_device *clo, unsigned char *dest, unsigned long *destLen, unsigned char *source, unsigned long sourceLen) */ 1.478 +-static int uncompress(struct cloop_device *clo, u_int32_t block_num, u_int32_t compressed_length, unsigned long *uncompressed_length) 1.479 +static int uncompress(struct cloop_device *clo, unsigned char *dest, unsigned long *destLen, unsigned char *source, unsigned long sourceLen, int flags) 1.480 { 1.481 -- /* Most of this code can be found in fs/cramfs/uncompress.c */ 1.482 -- int err; 1.483 -- clo->zstream.next_in = source; 1.484 -- clo->zstream.avail_in = sourceLen; 1.485 -- clo->zstream.next_out = dest; 1.486 -- clo->zstream.avail_out = *destLen; 1.487 -- err = zlib_inflateReset(&clo->zstream); 1.488 -- if (err != Z_OK) 1.489 -- { 1.490 -- printk(KERN_ERR "%s: zlib_inflateReset error %d\n", cloop_name, err); 1.491 -- zlib_inflateEnd(&clo->zstream); zlib_inflateInit(&clo->zstream); 1.492 -- } 1.493 -- err = zlib_inflate(&clo->zstream, Z_FINISH); 1.494 -- *destLen = clo->zstream.total_out; 1.495 -- if (err != Z_STREAM_END) return err; 1.496 -- return Z_OK; 1.497 -+ int err = -1; 1.498 -+ switch(flags) 1.499 -+ { 1.500 -+ case CLOOP_COMPRESSOR_NONE: 1.501 + int err = -1; 1.502 +- int flags = CLOOP_BLOCK_FLAGS(clo->block_ptrs[block_num]); 1.503 + switch(flags) 1.504 + { 1.505 + case CLOOP_COMPRESSOR_NONE: 1.506 +- /* block is umcompressed, swap pointers only! */ 1.507 +- { char *tmp = clo->compressed_buffer; clo->compressed_buffer = clo->buffer[clo->current_bufnum]; clo->buffer[clo->current_bufnum] = tmp; } 1.508 +- DEBUGP("cloop: block %d is uncompressed (flags=%d), just swapping %u bytes\n", block_num, flags, compressed_length); 1.509 + memcpy(dest, source, *destLen = sourceLen); 1.510 + err = Z_OK; 1.511 -+ break; 1.512 -+#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 1.513 -+ case CLOOP_COMPRESSOR_ZLIB: 1.514 + break; 1.515 + #if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 1.516 + case CLOOP_COMPRESSOR_ZLIB: 1.517 +- clo->zstream.next_in = clo->compressed_buffer; 1.518 +- clo->zstream.avail_in = compressed_length; 1.519 +- clo->zstream.next_out = clo->buffer[clo->current_bufnum]; 1.520 +- clo->zstream.avail_out = clo->head.block_size; 1.521 + clo->zstream.next_in = source; 1.522 + clo->zstream.avail_in = sourceLen; 1.523 + clo->zstream.next_out = dest; 1.524 + clo->zstream.avail_out = *destLen; 1.525 -+ err = zlib_inflateReset(&clo->zstream); 1.526 -+ if (err != Z_OK) 1.527 -+ { 1.528 -+ printk(KERN_ERR "%s: zlib_inflateReset error %d\n", cloop_name, err); 1.529 -+ zlib_inflateEnd(&clo->zstream); zlib_inflateInit(&clo->zstream); 1.530 -+ } 1.531 -+ err = zlib_inflate(&clo->zstream, Z_FINISH); 1.532 + err = zlib_inflateReset(&clo->zstream); 1.533 + if (err != Z_OK) 1.534 + { 1.535 +@@ -239,50 +234,50 @@ 1.536 + zlib_inflateEnd(&clo->zstream); zlib_inflateInit(&clo->zstream); 1.537 + } 1.538 + err = zlib_inflate(&clo->zstream, Z_FINISH); 1.539 +- *uncompressed_length = clo->zstream.total_out; 1.540 + *destLen = clo->zstream.total_out; 1.541 -+ if (err == Z_STREAM_END) err = 0; 1.542 + if (err == Z_STREAM_END) err = 0; 1.543 +- DEBUGP("cloop: zlib decompression done, ret =%d, size =%lu\n", err, *uncompressed_length); 1.544 + DEBUGP("cloop: zlib decompression done, ret =%d, size =%lu\n", err, *destLen); 1.545 -+ break; 1.546 -+#endif 1.547 -+#if (defined(CONFIG_LZO_DECOMPRESS) || defined(CONFIG_LZO_DECOMPRESS_MODULE)) 1.548 -+ case CLOOP_COMPRESSOR_LZO1X: 1.549 -+ { 1.550 -+ size_t tmp = (size_t) clo->head.block_size; 1.551 + break; 1.552 + #endif 1.553 + #if (defined(CONFIG_LZO_DECOMPRESS) || defined(CONFIG_LZO_DECOMPRESS_MODULE)) 1.554 + case CLOOP_COMPRESSOR_LZO1X: 1.555 + { 1.556 + size_t tmp = (size_t) clo->head.block_size; 1.557 +- err = lzo1x_decompress_safe(clo->compressed_buffer, compressed_length, 1.558 +- clo->buffer[clo->current_bufnum], &tmp); 1.559 +- if (err == LZO_E_OK) *uncompressed_length = (u_int32_t) tmp; 1.560 + err = lzo1x_decompress_safe(source, sourceLen, 1.561 + dest, &tmp); 1.562 + if (err == LZO_E_OK) *destLen = (u_int32_t) tmp; 1.563 -+ } 1.564 -+ break; 1.565 -+#endif 1.566 -+#if (defined(CONFIG_DECOMPRESS_LZ4) || defined(CONFIG_DECOMPRESS_LZ4_MODULE)) 1.567 -+ case CLOOP_COMPRESSOR_LZ4: 1.568 -+ { 1.569 + } 1.570 + break; 1.571 + #endif 1.572 + #if (defined(CONFIG_DECOMPRESS_LZ4) || defined(CONFIG_DECOMPRESS_LZ4_MODULE)) 1.573 + case CLOOP_COMPRESSOR_LZ4: 1.574 + { 1.575 +- size_t outputSize = clo->head.block_size; 1.576 + size_t outputSize = *destLen; 1.577 -+ /* We should adjust outputSize here, in case the last block is smaller than block_size */ 1.578 -+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) /* field removed */ 1.579 + /* We should adjust outputSize here, in case the last block is smaller than block_size */ 1.580 + #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) /* field removed */ 1.581 +- err = lz4_decompress(clo->compressed_buffer, (size_t *) &compressed_length, 1.582 +- clo->buffer[clo->current_bufnum], outputSize); 1.583 + err = lz4_decompress(source, (size_t *) &sourceLen, 1.584 + dest, outputSize); 1.585 -+#else 1.586 + #else 1.587 +- err = LZ4_decompress_safe(clo->compressed_buffer, 1.588 +- clo->buffer[clo->current_bufnum], 1.589 +- compressed_length, outputSize); 1.590 + err = LZ4_decompress_safe(source, 1.591 + dest, 1.592 + sourceLen, outputSize); 1.593 -+#endif 1.594 -+ if (err >= 0) 1.595 -+ { 1.596 -+ err = 0; 1.597 + #endif 1.598 + if (err >= 0) 1.599 + { 1.600 + err = 0; 1.601 +- *uncompressed_length = outputSize; 1.602 + *destLen = outputSize; 1.603 -+ } 1.604 -+ } 1.605 -+ break; 1.606 -+#endif 1.607 -+#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 1.608 -+ case CLOOP_COMPRESSOR_XZ: 1.609 + } 1.610 + } 1.611 + break; 1.612 + #endif 1.613 + #if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 1.614 + case CLOOP_COMPRESSOR_XZ: 1.615 +- clo->xz_buffer.in = clo->compressed_buffer; 1.616 + clo->xz_buffer.in = source; 1.617 -+ clo->xz_buffer.in_pos = 0; 1.618 + clo->xz_buffer.in_pos = 0; 1.619 +- clo->xz_buffer.in_size = compressed_length; 1.620 +- clo->xz_buffer.out = clo->buffer[clo->current_bufnum]; 1.621 + clo->xz_buffer.in_size = sourceLen; 1.622 + clo->xz_buffer.out = dest; 1.623 -+ clo->xz_buffer.out_pos = 0; 1.624 + clo->xz_buffer.out_pos = 0; 1.625 +- clo->xz_buffer.out_size = clo->head.block_size; 1.626 + clo->xz_buffer.out_size = *destLen; 1.627 -+ xz_dec_reset(clo->xzdecoderstate); 1.628 -+ err = xz_dec_run(clo->xzdecoderstate, &clo->xz_buffer); 1.629 -+ if (err == XZ_STREAM_END || err == XZ_OK) 1.630 -+ { 1.631 -+ err = 0; 1.632 -+ } 1.633 -+ else 1.634 -+ { 1.635 -+ printk(KERN_ERR "%s: xz_dec_run error %d\n", cloop_name, err); 1.636 -+ err = 1; 1.637 -+ } 1.638 -+ break; 1.639 -+#endif 1.640 -+ default: 1.641 -+ printk(KERN_ERR "%s: compression method is not supported!\n", cloop_name); 1.642 -+ } 1.643 -+ return err; 1.644 - } 1.645 - 1.646 - static ssize_t cloop_read_from_file(struct cloop_device *clo, struct file *f, char *buf, 1.647 -@@ -220,7 +313,7 @@ 1.648 + xz_dec_reset(clo->xzdecoderstate); 1.649 + err = xz_dec_run(clo->xzdecoderstate, &clo->xz_buffer); 1.650 + if (err == XZ_STREAM_END || err == XZ_OK) 1.651 +@@ -309,16 +304,12 @@ 1.652 + while (buf_done < buf_len) 1.653 + { 1.654 + size_t size = buf_len - buf_done, size_read; 1.655 +- mm_segment_t old_fs; 1.656 + /* kernel_read() only supports 32 bit offsets, so we use vfs_read() instead. */ 1.657 + /* int size_read = kernel_read(f, pos, buf + buf_done, size); */ 1.658 +- 1.659 +- // mutex_lock(&clo->clo_rq_mutex); 1.660 +- old_fs = get_fs(); 1.661 +- set_fs(KERNEL_DS); 1.662 ++ mm_segment_t old_fs = get_fs(); 1.663 ++ set_fs(get_ds()); 1.664 + size_read = vfs_read(f, (void __user *)(buf + buf_done), size, &pos); 1.665 + set_fs(old_fs); 1.666 +- // mutex_unlock(&clo->clo_rq_mutex); 1.667 1.668 if(size_read <= 0) 1.669 { 1.670 -- printk(KERN_ERR "%s: Read error %d at pos %Lu in file %s, " 1.671 -+ printk(KERN_ERR "%s: Read error %d at pos %llu in file %s, " 1.672 - "%d bytes lost.\n", cloop_name, (int)size_read, pos, 1.673 - file, (int)size); 1.674 - memset(buf + buf_len - size, 0, size); 1.675 -@@ -232,72 +325,84 @@ 1.676 - } 1.677 +@@ -358,8 +349,8 @@ 1.678 + return i; 1.679 + } 1.680 1.681 - /* This looks more complicated than it is */ 1.682 --/* Returns number of block buffer to use for this request */ 1.683 -+/* Returns number of cache block buffer to use for this request */ 1.684 - static int cloop_load_buffer(struct cloop_device *clo, int blocknum) 1.685 - { 1.686 -- unsigned int buf_done = 0; 1.687 -- unsigned long buflen; 1.688 -- unsigned int buf_length; 1.689 -+ loff_t compressed_block_offset; 1.690 -+ long compressed_block_len; 1.691 -+ long uncompressed_block_len=0; 1.692 - int ret; 1.693 - int i; 1.694 -- if(blocknum > ntohl(clo->head.num_blocks) || blocknum < 0) 1.695 -- { 1.696 -- printk(KERN_WARNING "%s: Invalid block number %d requested.\n", 1.697 -- cloop_name, blocknum); 1.698 -- return -1; 1.699 -- } 1.700 -+ if(blocknum > clo->head.num_blocks || blocknum < 0) 1.701 -+ { 1.702 -+ printk(KERN_WARNING "%s: Invalid block number %d requested.\n", 1.703 -+ cloop_name, blocknum); 1.704 -+ return -1; 1.705 -+ } 1.706 - 1.707 - /* Quick return if the block we seek is already in one of the buffers. */ 1.708 - /* Return number of buffer */ 1.709 -- for(i=0; i<BUFFERED_BLOCKS; i++) 1.710 -+ for(i=0; i<clo->num_buffered_blocks; i++) 1.711 - if (blocknum == clo->buffered_blocknum[i]) 1.712 -- { 1.713 -- DEBUGP(KERN_INFO "cloop_load_buffer: Found buffered block %d\n", i); 1.714 -- return i; 1.715 -- } 1.716 -- 1.717 -- buf_length = be64_to_cpu(clo->offsets[blocknum+1]) - be64_to_cpu(clo->offsets[blocknum]); 1.718 -- 1.719 --/* Load one compressed block from the file. */ 1.720 -- cloop_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer, 1.721 -- be64_to_cpu(clo->offsets[blocknum]), buf_length); 1.722 -+ { 1.723 -+ DEBUGP(KERN_INFO "cloop_load_buffer: Found buffered block %d\n", i); 1.724 -+ return i; 1.725 -+ } 1.726 - 1.727 -- buflen = ntohl(clo->head.block_size); 1.728 +- compressed_block_offset = CLOOP_BLOCK_OFFSET(clo->block_ptrs[blocknum]); 1.729 +- compressed_block_len = (long) (CLOOP_BLOCK_OFFSET(clo->block_ptrs[blocknum+1]) - compressed_block_offset) ; 1.730 + compressed_block_offset = clo->block_ptrs[blocknum].offset; 1.731 + compressed_block_len = (long) (clo->block_ptrs[blocknum].size) ; 1.732 1.733 -- /* Go to next position in the block ring buffer */ 1.734 -- clo->current_bufnum++; 1.735 -- if(clo->current_bufnum >= BUFFERED_BLOCKS) clo->current_bufnum = 0; 1.736 -+ /* Load one compressed block from the file. */ 1.737 -+ if(compressed_block_offset > 0 && compressed_block_len >= 0) /* sanity check */ 1.738 -+ { 1.739 -+ size_t n = cloop_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer, 1.740 -+ compressed_block_offset, compressed_block_len); 1.741 -+ if (n!= compressed_block_len) 1.742 -+ { 1.743 -+ printk(KERN_ERR "%s: error while reading %lu bytes @ %llu from file %s\n", 1.744 + /* Load one compressed block from the file. */ 1.745 + if(compressed_block_offset > 0 && compressed_block_len >= 0) /* sanity check */ 1.746 +@@ -369,12 +360,12 @@ 1.747 + if (n!= compressed_block_len) 1.748 + { 1.749 + printk(KERN_ERR "%s: error while reading %lu bytes @ %llu from file %s\n", 1.750 +- cloop_name, compressed_block_len, clo->block_ptrs[blocknum], clo->underlying_filename); 1.751 + cloop_name, compressed_block_len, clo->block_ptrs[blocknum].offset, clo->underlying_filename); 1.752 -+ /* return -1; */ 1.753 -+ } 1.754 -+ } else { 1.755 -+ printk(KERN_ERR "%s: invalid data block len %ld bytes @ %lld from file %s\n", 1.756 + /* return -1; */ 1.757 + } 1.758 + } else { 1.759 + printk(KERN_ERR "%s: invalid data block len %ld bytes @ %lld from file %s\n", 1.760 +- cloop_name, compressed_block_len, clo->block_ptrs[blocknum], clo->underlying_filename); 1.761 + cloop_name, compressed_block_len, clo->block_ptrs[blocknum].offset, clo->underlying_filename); 1.762 -+ return -1; 1.763 -+ } 1.764 -+ 1.765 -+ /* Go to next position in the cache block buffer (which is used as a cyclic buffer) */ 1.766 -+ if(++clo->current_bufnum >= clo->num_buffered_blocks) clo->current_bufnum = 0; 1.767 + return -1; 1.768 + } 1.769 + 1.770 +@@ -382,14 +373,16 @@ 1.771 + if(++clo->current_bufnum >= clo->num_buffered_blocks) clo->current_bufnum = 0; 1.772 1.773 /* Do the uncompression */ 1.774 -- ret = uncompress(clo, clo->buffer[clo->current_bufnum], &buflen, clo->compressed_buffer, 1.775 -- buf_length); 1.776 +- ret = uncompress(clo, blocknum, compressed_block_len, &uncompressed_block_len); 1.777 + uncompressed_block_len = clo->head.block_size; 1.778 + ret = uncompress(clo, clo->buffer[clo->current_bufnum], &uncompressed_block_len, 1.779 + clo->compressed_buffer, compressed_block_len, clo->block_ptrs[blocknum].flags); 1.780 /* DEBUGP("cloop: buflen after uncompress: %ld\n",buflen); */ 1.781 if (ret != 0) 1.782 -- { 1.783 -- printk(KERN_ERR "%s: zlib decompression error %i uncompressing block %u %u/%lu/%u/%u " 1.784 -- "%Lu-%Lu\n", cloop_name, ret, blocknum, 1.785 -- ntohl(clo->head.block_size), buflen, buf_length, buf_done, 1.786 -- be64_to_cpu(clo->offsets[blocknum]), be64_to_cpu(clo->offsets[blocknum+1])); 1.787 -- clo->buffered_blocknum[clo->current_bufnum] = -1; 1.788 -- return -1; 1.789 -- } 1.790 -+ { 1.791 -+ printk(KERN_ERR "%s: decompression error %i uncompressing block %u %lu bytes @ %llu, flags %u\n", 1.792 -+ cloop_name, ret, blocknum, 1.793 + { 1.794 + printk(KERN_ERR "%s: decompression error %i uncompressing block %u %lu bytes @ %llu, flags %u\n", 1.795 + cloop_name, ret, blocknum, 1.796 +- compressed_block_len, CLOOP_BLOCK_OFFSET(clo->block_ptrs[blocknum]), 1.797 +- CLOOP_BLOCK_FLAGS(clo->block_ptrs[blocknum])); 1.798 + compressed_block_len, clo->block_ptrs[blocknum].offset, 1.799 + clo->block_ptrs[blocknum].flags); 1.800 -+ clo->buffered_blocknum[clo->current_bufnum] = -1; 1.801 -+ return -1; 1.802 -+ } 1.803 - clo->buffered_blocknum[clo->current_bufnum] = blocknum; 1.804 + clo->buffered_blocknum[clo->current_bufnum] = -1; 1.805 + return -1; 1.806 + } 1.807 +@@ -397,107 +390,146 @@ 1.808 return clo->current_bufnum; 1.809 } 1.810 1.811 - /* This function does all the real work. */ 1.812 --/* returns "uptodate" */ 1.813 +-static blk_status_t cloop_handle_request(struct cloop_device *clo, struct request *req) 1.814 ++/* This function does all the real work. */ 1.815 +/* returns "uptodate" */ 1.816 - static int cloop_handle_request(struct cloop_device *clo, struct request *req) 1.817 ++static int cloop_handle_request(struct cloop_device *clo, struct request *req) 1.818 { 1.819 int buffered_blocknum = -1; 1.820 int preloaded = 0; 1.821 - loff_t offset = (loff_t) blk_rq_pos(req)<<9; /* req->sector<<9 */ 1.822 -- struct bio_vec *bvec; 1.823 -+ struct bio_vec bvec; 1.824 +- loff_t offset = (loff_t) blk_rq_pos(req)<<9; 1.825 ++ loff_t offset = (loff_t) blk_rq_pos(req)<<9; /* req->sector<<9 */ 1.826 + struct bio_vec bvec; 1.827 struct req_iterator iter; 1.828 +- blk_status_t ret = BLK_STS_OK; 1.829 +- 1.830 +- if (unlikely(req_op(req) != REQ_OP_READ )) 1.831 +- { 1.832 +- blk_dump_rq_flags(req, DEVICE_NAME " bad request"); 1.833 +- return BLK_STS_IOERR; 1.834 +- } 1.835 +- 1.836 +- if (unlikely(!clo->backing_file && !clo->suspended)) 1.837 +- { 1.838 +- DEBUGP("cloop_handle_request: not connected to a file\n"); 1.839 +- return BLK_STS_IOERR; 1.840 +- } 1.841 +- 1.842 rq_for_each_segment(bvec, req, iter) 1.843 +- { 1.844 +- unsigned long len = bvec.bv_len; 1.845 +- loff_t to_offset = bvec.bv_offset; 1.846 +- 1.847 +- while(len > 0) 1.848 { 1.849 -- unsigned long len = bvec->bv_len; 1.850 -- char *to_ptr = kmap(bvec->bv_page) + bvec->bv_offset; 1.851 +- u_int32_t length_in_buffer; 1.852 +- loff_t block_offset = offset; 1.853 +- u_int32_t offset_in_buffer; 1.854 +- char *from_ptr, *to_ptr; 1.855 +- /* do_div (div64.h) returns the 64bit division remainder and */ 1.856 +- /* puts the result in the first argument, i.e. block_offset */ 1.857 +- /* becomes the blocknumber to load, and offset_in_buffer the */ 1.858 +- /* position in the buffer */ 1.859 +- offset_in_buffer = do_div(block_offset, clo->head.block_size); 1.860 +- /* Lookup preload cache */ 1.861 +- if(block_offset < clo->preload_size && clo->preload_cache != NULL && clo->preload_cache[block_offset] != NULL) 1.862 +- { /* Copy from cache */ 1.863 +- preloaded = 1; 1.864 +- from_ptr = clo->preload_cache[block_offset]; 1.865 +- } 1.866 +- else 1.867 +- { 1.868 +- preloaded = 0; 1.869 +- buffered_blocknum = cloop_load_buffer(clo,block_offset); 1.870 +- if(buffered_blocknum == -1) 1.871 + unsigned long len = bvec.bv_len; 1.872 + char *to_ptr = kmap(bvec.bv_page) + bvec.bv_offset; 1.873 - while(len > 0) 1.874 ++ while(len > 0) 1.875 { 1.876 - u_int32_t length_in_buffer; 1.877 -@@ -308,7 +413,7 @@ 1.878 - /* puts the result in the first argument, i.e. block_offset */ 1.879 - /* becomes the blocknumber to load, and offset_in_buffer the */ 1.880 - /* position in the buffer */ 1.881 -- offset_in_buffer = do_div(block_offset, ntohl(clo->head.block_size)); 1.882 +- ret = BLK_STS_IOERR; 1.883 +- break; /* invalid data, leave inner loop */ 1.884 ++ u_int32_t length_in_buffer; 1.885 ++ loff_t block_offset = offset; 1.886 ++ u_int32_t offset_in_buffer; 1.887 ++ char *from_ptr; 1.888 ++ /* do_div (div64.h) returns the 64bit division remainder and */ 1.889 ++ /* puts the result in the first argument, i.e. block_offset */ 1.890 ++ /* becomes the blocknumber to load, and offset_in_buffer the */ 1.891 ++ /* position in the buffer */ 1.892 + offset_in_buffer = do_div(block_offset, clo->head.block_size); 1.893 - /* Lookup preload cache */ 1.894 - if(block_offset < clo->preload_size && clo->preload_cache != NULL && 1.895 - clo->preload_cache[block_offset] != NULL) 1.896 -@@ -325,7 +430,7 @@ 1.897 - from_ptr = clo->buffer[buffered_blocknum]; 1.898 - } 1.899 - /* Now, at least part of what we want will be in the buffer. */ 1.900 -- length_in_buffer = ntohl(clo->head.block_size) - offset_in_buffer; 1.901 ++ /* Lookup preload cache */ 1.902 ++ if(block_offset < clo->preload_size && clo->preload_cache != NULL && 1.903 ++ clo->preload_cache[block_offset] != NULL) 1.904 ++ { /* Copy from cache */ 1.905 ++ preloaded = 1; 1.906 ++ from_ptr = clo->preload_cache[block_offset]; 1.907 ++ } 1.908 ++ else 1.909 ++ { 1.910 ++ preloaded = 0; 1.911 ++ buffered_blocknum = cloop_load_buffer(clo,block_offset); 1.912 ++ if(buffered_blocknum == -1) break; /* invalid data, leave inner loop */ 1.913 ++ /* Copy from buffer */ 1.914 ++ from_ptr = clo->buffer[buffered_blocknum]; 1.915 ++ } 1.916 ++ /* Now, at least part of what we want will be in the buffer. */ 1.917 + length_in_buffer = clo->head.block_size - offset_in_buffer; 1.918 - if(length_in_buffer > len) 1.919 - { 1.920 - /* DEBUGP("Warning: length_in_buffer=%u > len=%u\n", 1.921 -@@ -337,18 +442,19 @@ 1.922 - len -= length_in_buffer; 1.923 - offset += length_in_buffer; 1.924 - } /* while inner loop */ 1.925 -- kunmap(bvec->bv_page); 1.926 ++ if(length_in_buffer > len) 1.927 ++ { 1.928 ++/* DEBUGP("Warning: length_in_buffer=%u > len=%u\n", 1.929 ++ length_in_buffer,len); */ 1.930 ++ length_in_buffer = len; 1.931 ++ } 1.932 ++ memcpy(to_ptr, from_ptr + offset_in_buffer, length_in_buffer); 1.933 ++ to_ptr += length_in_buffer; 1.934 ++ len -= length_in_buffer; 1.935 ++ offset += length_in_buffer; 1.936 ++ } /* while inner loop */ 1.937 + kunmap(bvec.bv_page); 1.938 + cond_resched(); 1.939 - } /* end rq_for_each_segment*/ 1.940 - return ((buffered_blocknum!=-1) || preloaded); 1.941 - } 1.942 - 1.943 - /* Adopted from loop.c, a kernel thread to handle physical reads and 1.944 -- * decompression. */ 1.945 ++ } /* end rq_for_each_segment*/ 1.946 ++ return ((buffered_blocknum!=-1) || preloaded); 1.947 ++} 1.948 ++ 1.949 ++/* Adopted from loop.c, a kernel thread to handle physical reads and 1.950 + decompression. */ 1.951 - static int cloop_thread(void *data) 1.952 - { 1.953 - struct cloop_device *clo = data; 1.954 - current->flags |= PF_NOFREEZE; 1.955 -- set_user_nice(current, -15); 1.956 ++static int cloop_thread(void *data) 1.957 ++{ 1.958 ++ struct cloop_device *clo = data; 1.959 ++ current->flags |= PF_NOFREEZE; 1.960 + set_user_nice(current, 10); 1.961 - while (!kthread_should_stop()||!list_empty(&clo->clo_list)) 1.962 - { 1.963 - int err; 1.964 -@@ -390,10 +496,18 @@ 1.965 - int rw; 1.966 - /* quick sanity checks */ 1.967 - /* blk_fs_request() was removed in 2.6.36 */ 1.968 -- if (unlikely(req == NULL || (req->cmd_type != REQ_TYPE_FS))) 1.969 ++ while (!kthread_should_stop()||!list_empty(&clo->clo_list)) 1.970 ++ { 1.971 ++ int err; 1.972 ++ err = wait_event_interruptible(clo->clo_event, !list_empty(&clo->clo_list) || 1.973 ++ kthread_should_stop()); 1.974 ++ if(unlikely(err)) 1.975 ++ { 1.976 ++ DEBUGP(KERN_ERR "cloop thread activated on error!? Continuing.\n"); 1.977 ++ continue; 1.978 + } 1.979 +- /* Copy from buffer */ 1.980 +- from_ptr = clo->buffer[buffered_blocknum]; 1.981 +- } 1.982 +- /* Now, at least part of what we want will be in the buffer. */ 1.983 +- length_in_buffer = clo->head.block_size - offset_in_buffer; 1.984 +- if(length_in_buffer > len) 1.985 +- { 1.986 +- /* DEBUGP("Warning: length_in_buffer=%u > len=%u\n", length_in_buffer,len); */ 1.987 +- length_in_buffer = len; 1.988 +- } 1.989 +- to_ptr = kmap_atomic(bvec.bv_page); 1.990 +- memcpy(to_ptr + to_offset, from_ptr + offset_in_buffer, length_in_buffer); 1.991 +- kunmap_atomic(to_ptr); 1.992 +- to_offset += length_in_buffer; 1.993 +- len -= length_in_buffer; 1.994 +- offset += length_in_buffer; 1.995 +- } /* while inner loop */ 1.996 +- } /* rq_for_each_segment */ 1.997 +- return ret; 1.998 +-} 1.999 +- 1.1000 +-static blk_status_t cloop_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) 1.1001 +-{ 1.1002 +-// struct request_queue *q = hctx->queue; 1.1003 +-// struct cloop_device *clo = q->queuedata; 1.1004 +- struct request *req = bd->rq; 1.1005 +- struct cloop_device *clo = req->rq_disk->private_data; 1.1006 +- blk_status_t ret = BLK_STS_OK; 1.1007 +- 1.1008 +-#if 1 /* Does it work when loading libraries? */ 1.1009 +- /* Since we have a buffered block list as well as data to read */ 1.1010 +- /* from disk (slow), and are (probably) never called from an */ 1.1011 +- /* interrupt, we use a simple mutex lock right here to ensure */ 1.1012 +- /* consistency. */ 1.1013 +- mutex_lock(&clo->clo_rq_mutex); 1.1014 +- #else 1.1015 +- spin_lock_irq(&clo->queue_lock); 1.1016 +- #endif 1.1017 +- blk_mq_start_request(req); 1.1018 +- do { 1.1019 +- ret = cloop_handle_request(clo, req); 1.1020 +- } while(blk_update_request(req, ret, blk_rq_cur_bytes(req))); 1.1021 +- blk_mq_end_request(req, ret); 1.1022 +- #if 1 /* See above */ 1.1023 +- mutex_unlock(&clo->clo_rq_mutex); 1.1024 +- #else 1.1025 +- spin_unlock_irq(&clo->queue_lock); 1.1026 +- #endif 1.1027 +- return ret; 1.1028 ++ if(!list_empty(&clo->clo_list)) 1.1029 ++ { 1.1030 ++ struct request *req; 1.1031 ++ unsigned long flags; 1.1032 ++ int uptodate; 1.1033 ++ spin_lock_irq(&clo->queue_lock); 1.1034 ++ req = list_entry(clo->clo_list.next, struct request, queuelist); 1.1035 ++ list_del_init(&req->queuelist); 1.1036 ++ spin_unlock_irq(&clo->queue_lock); 1.1037 ++ uptodate = cloop_handle_request(clo, req); 1.1038 ++ spin_lock_irqsave(&clo->queue_lock, flags); 1.1039 ++ __blk_end_request_all(req, uptodate ? 0 : -EIO); 1.1040 ++ spin_unlock_irqrestore(&clo->queue_lock, flags); 1.1041 ++ } 1.1042 ++ } 1.1043 ++ DEBUGP(KERN_ERR "cloop_thread exited.\n"); 1.1044 ++ return 0; 1.1045 ++} 1.1046 ++ 1.1047 ++/* This is called by the kernel block queue management every now and then, 1.1048 ++ * with successive read requests qeued and sorted in a (hopefully) 1.1049 ++ * "most efficient way". spin_lock_irq() is being held by the kernel. */ 1.1050 ++static void cloop_do_request(struct request_queue *q) 1.1051 ++{ 1.1052 ++ struct request *req; 1.1053 ++ while((req = blk_fetch_request(q)) != NULL) 1.1054 ++ { 1.1055 ++ struct cloop_device *clo; 1.1056 ++ int rw; 1.1057 ++ /* quick sanity checks */ 1.1058 ++ /* blk_fs_request() was removed in 2.6.36 */ 1.1059 + if (unlikely(req == NULL 1.1060 +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) /* field removed */ 1.1061 + || (req->cmd_type != REQ_TYPE_FS) 1.1062 +#endif 1.1063 + )) 1.1064 - goto error_continue; 1.1065 - rw = rq_data_dir(req); 1.1066 -- if (unlikely(rw != READ && rw != READA)) 1.1067 ++ goto error_continue; 1.1068 ++ rw = rq_data_dir(req); 1.1069 + if (unlikely(rw != READ 1.1070 +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0) 1.1071 + && rw != READA 1.1072 +#endif 1.1073 + )) 1.1074 - { 1.1075 - DEBUGP("cloop_do_request: bad command\n"); 1.1076 - goto error_continue; 1.1077 -@@ -409,40 +523,51 @@ 1.1078 - continue; /* next request */ 1.1079 - error_continue: 1.1080 - DEBUGP(KERN_ERR "cloop_do_request: Discarding request %p.\n", req); 1.1081 ++ { 1.1082 ++ DEBUGP("cloop_do_request: bad command\n"); 1.1083 ++ goto error_continue; 1.1084 ++ } 1.1085 ++ clo = req->rq_disk->private_data; 1.1086 ++ if (unlikely(!clo->backing_file && !clo->suspended)) 1.1087 ++ { 1.1088 ++ DEBUGP("cloop_do_request: not connected to a file\n"); 1.1089 ++ goto error_continue; 1.1090 ++ } 1.1091 ++ list_add_tail(&req->queuelist, &clo->clo_list); /* Add to working list for thread */ 1.1092 ++ wake_up(&clo->clo_event); /* Wake up cloop_thread */ 1.1093 ++ continue; /* next request */ 1.1094 ++ error_continue: 1.1095 ++ DEBUGP(KERN_ERR "cloop_do_request: Discarding request %p.\n", req); 1.1096 +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) 1.1097 - req->errors++; 1.1098 ++ req->errors++; 1.1099 +#else 1.1100 + req->error_count++; 1.1101 +#endif 1.1102 - __blk_end_request_all(req, -EIO); 1.1103 - } 1.1104 ++ __blk_end_request_all(req, -EIO); 1.1105 ++ } 1.1106 } 1.1107 1.1108 --/* Read header and offsets from already opened file */ 1.1109 --static int cloop_set_file(int cloop_num, struct file *file, char *filename) 1.1110 -+/* Read header, flags and offsets from already opened file */ 1.1111 -+static int cloop_set_file(int cloop_num, struct file *file) 1.1112 - { 1.1113 - struct cloop_device *clo = cloop_dev[cloop_num]; 1.1114 - struct inode *inode; 1.1115 + /* Read header, flags and offsets from already opened file */ 1.1116 +@@ -508,7 +540,7 @@ 1.1117 char *bbuf=NULL; 1.1118 -- unsigned int i, offsets_read, total_offsets; 1.1119 -- int isblkdev; 1.1120 -- int error = 0; 1.1121 -+ unsigned int bbuf_size = 0; 1.1122 -+ const unsigned int header_size = sizeof(struct cloop_head); 1.1123 + unsigned int bbuf_size = 0; 1.1124 + const unsigned int header_size = sizeof(struct cloop_head); 1.1125 +- unsigned int i, offsets_read=0, total_offsets=0; 1.1126 + unsigned int i, total_offsets=0; 1.1127 -+ loff_t fs_read_position = 0, header_pos[2]; 1.1128 -+ int flags, isblkdev, bytes_read, error = 0; 1.1129 -+ if (clo->suspended) return error; 1.1130 -+ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) 1.1131 - inode = file->f_dentry->d_inode; 1.1132 -+ clo->underlying_filename = kstrdup(file->f_dentry->d_name.name ? file->f_dentry->d_name.name : (const unsigned char *)"anonymous filename", GFP_KERNEL); 1.1133 -+ #else 1.1134 -+ inode = file->f_path.dentry->d_inode; 1.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); 1.1136 -+ #endif 1.1137 - isblkdev=S_ISBLK(inode->i_mode)?1:0; 1.1138 - if(!isblkdev&&!S_ISREG(inode->i_mode)) 1.1139 + loff_t fs_read_position = 0, header_pos[2]; 1.1140 + int isblkdev, bytes_read, error = 0; 1.1141 + if (clo->suspended) return error; 1.1142 +@@ -581,29 +613,19 @@ 1.1143 + goto error_release; 1.1144 + } 1.1145 + memcpy(&clo->head, bbuf, header_size); 1.1146 +- if (strncmp(bbuf+CLOOP4_SIGNATURE_OFFSET, CLOOP4_SIGNATURE, CLOOP4_SIGNATURE_SIZE)==0) 1.1147 ++ if (strncmp(bbuf+CLOOP_SIGNATURE_OFFSET, CLOOP_SIGNATURE, CLOOP_SIGNATURE_SIZE)==0) 1.1148 + { 1.1149 +- clo->file_format=4; 1.1150 ++ clo->file_format++; 1.1151 + clo->head.block_size=ntohl(clo->head.block_size); 1.1152 + clo->head.num_blocks=ntohl(clo->head.num_blocks); 1.1153 + clo->header_first = (i==0) ? 1 : 0; 1.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"); 1.1155 +- break; 1.1156 +- } 1.1157 +- else if (strncmp(bbuf+CLOOP2_SIGNATURE_OFFSET, CLOOP2_SIGNATURE, CLOOP2_SIGNATURE_SIZE)==0) 1.1158 +- { 1.1159 +- clo->file_format=2; 1.1160 +- clo->head.block_size=ntohl(clo->head.block_size); 1.1161 +- clo->head.num_blocks=ntohl(clo->head.num_blocks); 1.1162 +- clo->header_first = (i==0) ? 1 : 0; 1.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"); 1.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"); 1.1165 + break; 1.1166 + } 1.1167 + } 1.1168 + if (clo->file_format == 0) 1.1169 { 1.1170 - printk(KERN_ERR "%s: %s not a regular file or block device\n", 1.1171 -- cloop_name, filename); 1.1172 -+ cloop_name, clo->underlying_filename); 1.1173 +- printk(KERN_ERR "%s: Cannot read old 32-bit (version 0.68) images, " 1.1174 +- "please use an older version of %s for this file.\n", 1.1175 ++ printk(KERN_ERR "%s: Cannot detect %s format.\n", 1.1176 + cloop_name, cloop_name); 1.1177 + error=-EBADF; goto error_release; 1.1178 + } 1.1179 +@@ -613,67 +635,133 @@ 1.1180 + cloop_name, clo->head.block_size); 1.1181 error=-EBADF; goto error_release; 1.1182 } 1.1183 - clo->backing_file = file; 1.1184 - clo->backing_inode= inode ; 1.1185 -- if(!isblkdev&&inode->i_size<sizeof(struct cloop_head)) 1.1186 -+ clo->underlying_total_size = (isblkdev) ? inode->i_bdev->bd_inode->i_size : inode->i_size; 1.1187 -+ if(clo->underlying_total_size < header_size) 1.1188 +- total_offsets=clo->head.num_blocks+1; 1.1189 +- if (!isblkdev && (sizeof(struct cloop_head)+sizeof(loff_t)* 1.1190 ++ total_offsets=clo->head.num_blocks; 1.1191 ++ if (!isblkdev && (sizeof(struct cloop_head)+sizeof(struct block_info)* 1.1192 + total_offsets > inode->i_size)) 1.1193 { 1.1194 -- printk(KERN_ERR "%s: %lu bytes (must be >= %u bytes)\n", 1.1195 -- cloop_name, (unsigned long)inode->i_size, 1.1196 -- (unsigned)sizeof(struct cloop_head)); 1.1197 -+ printk(KERN_ERR "%s: %llu bytes (must be >= %u bytes)\n", 1.1198 -+ cloop_name, clo->underlying_total_size, 1.1199 -+ (unsigned int)header_size); 1.1200 + printk(KERN_ERR "%s: file %s too small for %u blocks\n", 1.1201 + cloop_name, clo->underlying_filename, clo->head.num_blocks); 1.1202 error=-EBADF; goto error_release; 1.1203 } 1.1204 -- /* In suspended mode, we have done all checks necessary - FF */ 1.1205 -- if (clo->suspended) 1.1206 -- return error; 1.1207 - if(isblkdev) 1.1208 - { 1.1209 - struct request_queue *q = bdev_get_queue(inode->i_bdev); 1.1210 -@@ -451,104 +576,225 @@ 1.1211 - /* blk_queue_max_hw_segments(clo->clo_queue, queue_max_hw_segments(q)); */ /* Removed in 2.6.34 */ 1.1212 - blk_queue_max_segment_size(clo->clo_queue, queue_max_segment_size(q)); 1.1213 - blk_queue_segment_boundary(clo->clo_queue, queue_segment_boundary(q)); 1.1214 -+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) 1.1215 - blk_queue_merge_bvec(clo->clo_queue, q->merge_bvec_fn); 1.1216 -+#endif 1.1217 - clo->underlying_blksize = block_size(inode->i_bdev); 1.1218 - } 1.1219 - else 1.1220 - clo->underlying_blksize = PAGE_SIZE; 1.1221 -- DEBUGP("Underlying blocksize is %u\n", clo->underlying_blksize); 1.1222 -- bbuf = cloop_malloc(clo->underlying_blksize); 1.1223 -+ 1.1224 -+ DEBUGP(KERN_INFO "Underlying blocksize of %s is %u\n", clo->underlying_filename, clo->underlying_blksize); 1.1225 -+ DEBUGP(KERN_INFO "Underlying total size of %s is %llu\n", clo->underlying_filename, clo->underlying_total_size); 1.1226 -+ 1.1227 -+ /* clo->underlying_blksize should be larger than header_size, even if it's only PAGE_SIZE */ 1.1228 -+ bbuf_size = clo->underlying_blksize; 1.1229 -+ bbuf = cloop_malloc(bbuf_size); 1.1230 - if(!bbuf) 1.1231 - { 1.1232 -- printk(KERN_ERR "%s: out of kernel mem for block buffer (%lu bytes)\n", 1.1233 -- cloop_name, (unsigned long)clo->underlying_blksize); 1.1234 -+ printk(KERN_ERR "%s: out of kernel mem for buffer (%u bytes)\n", 1.1235 -+ cloop_name, (unsigned int) bbuf_size); 1.1236 -+ error=-ENOMEM; goto error_release; 1.1237 -+ } 1.1238 -+ 1.1239 -+ header_pos[0] = 0; /* header first */ 1.1240 -+ header_pos[1] = clo->underlying_total_size - sizeof(struct cloop_head); /* header last */ 1.1241 -+ for(i=0; i<2; i++) 1.1242 -+ { 1.1243 -+ /* Check for header */ 1.1244 -+ size_t bytes_readable = MIN(clo->underlying_blksize, clo->underlying_total_size - header_pos[i]); 1.1245 -+ size_t bytes_read = cloop_read_from_file(clo, file, bbuf, header_pos[i], bytes_readable); 1.1246 -+ if(bytes_read != bytes_readable) 1.1247 -+ { 1.1248 -+ printk(KERN_ERR "%s: Bad file %s, read() of %s %u bytes returned %d.\n", 1.1249 -+ cloop_name, clo->underlying_filename, (i==0)?"first":"last", 1.1250 -+ (unsigned int)header_size, (int)bytes_read); 1.1251 -+ error=-EBADF; 1.1252 -+ goto error_release; 1.1253 -+ } 1.1254 -+ memcpy(&clo->head, bbuf, header_size); 1.1255 -+ if (strncmp(bbuf+CLOOP_SIGNATURE_OFFSET, CLOOP_SIGNATURE, CLOOP_SIGNATURE_SIZE)==0) 1.1256 -+ { 1.1257 -+ clo->file_format++; 1.1258 -+ clo->head.block_size=ntohl(clo->head.block_size); 1.1259 -+ clo->head.num_blocks=ntohl(clo->head.num_blocks); 1.1260 -+ clo->header_first = (i==0) ? 1 : 0; 1.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"); 1.1262 -+ break; 1.1263 -+ } 1.1264 -+ } 1.1265 -+ if (clo->file_format == 0) 1.1266 -+ { 1.1267 -+ printk(KERN_ERR "%s: Cannot detect %s format.\n", 1.1268 -+ cloop_name, cloop_name); 1.1269 -+ error=-EBADF; goto error_release; 1.1270 -+ } 1.1271 -+ if (clo->head.block_size % 512 != 0) 1.1272 -+ { 1.1273 -+ printk(KERN_ERR "%s: blocksize %u not multiple of 512\n", 1.1274 -+ cloop_name, clo->head.block_size); 1.1275 -+ error=-EBADF; goto error_release; 1.1276 -+ } 1.1277 -+ total_offsets=clo->head.num_blocks; 1.1278 -+ if (!isblkdev && (sizeof(struct cloop_head)+sizeof(struct block_info)* 1.1279 -+ total_offsets > inode->i_size)) 1.1280 -+ { 1.1281 -+ printk(KERN_ERR "%s: file %s too small for %u blocks\n", 1.1282 -+ cloop_name, clo->underlying_filename, clo->head.num_blocks); 1.1283 -+ error=-EBADF; goto error_release; 1.1284 -+ } 1.1285 +- clo->block_ptrs = cloop_malloc(sizeof(cloop_block_ptr) * total_offsets); 1.1286 +- if (!clo->block_ptrs) 1.1287 + /* Allocate Memory for decompressors */ 1.1288 +#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 1.1289 + clo->zstream.workspace = cloop_malloc(zlib_inflate_workspacesize()); 1.1290 + if(!clo->zstream.workspace) 1.1291 -+ { 1.1292 + { 1.1293 +- printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name); 1.1294 + printk(KERN_ERR "%s: out of mem for zlib working area %u\n", 1.1295 + cloop_name, zlib_inflate_workspacesize()); 1.1296 error=-ENOMEM; goto error_release; 1.1297 } 1.1298 -- total_offsets = 1; /* Dummy total_offsets: will be filled in first time around */ 1.1299 -- for (i = 0, offsets_read = 0; offsets_read < total_offsets; i++) 1.1300 +- /* Read them offsets! */ 1.1301 +- if(clo->header_first) 1.1302 + zlib_inflateInit(&clo->zstream); 1.1303 +#endif 1.1304 +#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 1.1305 @@ -890,33 +713,20 @@ 1.1306 +#endif 1.1307 + if (total_offsets + 1 == 0) /* Version 3 */ 1.1308 { 1.1309 -- unsigned int offset = 0, num_readable; 1.1310 -- size_t bytes_read = cloop_read_from_file(clo, file, bbuf, 1.1311 -- i*clo->underlying_blksize, 1.1312 -- clo->underlying_blksize); 1.1313 -- if(bytes_read != clo->underlying_blksize) 1.1314 +- fs_read_position = sizeof(struct cloop_head); 1.1315 + struct cloop_tail tail; 1.1316 + if (isblkdev) 1.1317 - { 1.1318 -- printk(KERN_ERR "%s: Bad file, read() of first %lu bytes returned %d.\n", 1.1319 -- cloop_name, (unsigned long)clo->underlying_blksize, (int)bytes_read); 1.1320 -- error=-EBADF; 1.1321 -- goto error_release; 1.1322 ++ { 1.1323 + /* No end of file: can't find index */ 1.1324 + printk(KERN_ERR "%s: no V3 support for block device\n", 1.1325 + cloop_name); 1.1326 + error=-EBADF; goto error_release; 1.1327 - } 1.1328 -- /* Header will be in block zero */ 1.1329 -- if(i==0) 1.1330 ++ } 1.1331 + bytes_read = cloop_read_from_file(clo, file, (void *) &tail, 1.1332 + inode->i_size - sizeof(struct cloop_tail), 1.1333 + sizeof(struct cloop_tail)); 1.1334 + if (bytes_read == sizeof(struct cloop_tail)) 1.1335 - { 1.1336 -- memcpy(&clo->head, bbuf, sizeof(struct cloop_head)); 1.1337 -- offset = sizeof(struct cloop_head); 1.1338 -- if (ntohl(clo->head.block_size) % 512 != 0) 1.1339 ++ { 1.1340 + unsigned long len, zlen; 1.1341 + int ret; 1.1342 + void *zbuf; 1.1343 @@ -926,79 +736,47 @@ 1.1344 + zlen = ntohl(tail.table_size); 1.1345 + zbuf = cloop_malloc(zlen); 1.1346 + if (!clo->block_ptrs || !zbuf) 1.1347 - { 1.1348 -- printk(KERN_ERR "%s: blocksize %u not multiple of 512\n", 1.1349 -- cloop_name, ntohl(clo->head.block_size)); 1.1350 -- error=-EBADF; goto error_release; 1.1351 -- } 1.1352 -- if (clo->head.preamble[0x0B]!='V'||clo->head.preamble[0x0C]<'1') 1.1353 -- { 1.1354 -- printk(KERN_ERR "%s: Cannot read old 32-bit (version 0.68) images, " 1.1355 -- "please use an older version of %s for this file.\n", 1.1356 -- cloop_name, cloop_name); 1.1357 -- error=-EBADF; goto error_release; 1.1358 ++ { 1.1359 + printk(KERN_ERR "%s: out of kernel mem for index\n", cloop_name); 1.1360 + error=-ENOMEM; goto error_release; 1.1361 - } 1.1362 -- if (clo->head.preamble[0x0C]<'2') 1.1363 ++ } 1.1364 + bytes_read = cloop_read_from_file(clo, file, zbuf, 1.1365 + inode->i_size - zlen - sizeof(struct cloop_tail), 1.1366 + zlen); 1.1367 + if (bytes_read != zlen) 1.1368 - { 1.1369 -- printk(KERN_ERR "%s: Cannot read old architecture-dependent " 1.1370 -- "(format <= 1.0) images, please use an older " 1.1371 -- "version of %s for this file.\n", 1.1372 -- cloop_name, cloop_name); 1.1373 ++ { 1.1374 + printk(KERN_ERR "%s: can't read index\n", cloop_name); 1.1375 - error=-EBADF; goto error_release; 1.1376 - } 1.1377 -- total_offsets=ntohl(clo->head.num_blocks)+1; 1.1378 -- if (!isblkdev && (sizeof(struct cloop_head)+sizeof(loff_t)* 1.1379 -- total_offsets > inode->i_size)) 1.1380 ++ error=-EBADF; goto error_release; 1.1381 ++ } 1.1382 + len = CLOOP3_INDEX_SIZE(ntohl(tail.index_size)) * total_offsets; 1.1383 -+ flags = CLOOP3_BLOCKS_FLAGS(ntohl(tail.index_size)); 1.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) 1.1385 -+printk(KERN_INFO "%s: uncompress(clo=%p, block_ptrs=%p, &len(%ld)=%p, zbuf=%p, zlen=%ld, flag=%d)\n", cloop_name, 1.1386 -+ clo, clo->block_ptrs, len, &len, zbuf, zlen, flags); 1.1387 -+ ret = uncompress(clo, (void *) clo->block_ptrs, &len, zbuf, zlen, flags); 1.1388 -+// May 3 19:45:20 (none) user.alert kernel: BUG: unable to handle kernel NULL pointer dereference at (null) 1.1389 -+printk(KERN_INFO "%s: uncompressed !\n", cloop_name); 1.1390 ++ ret = uncompress(clo, (void *) clo->block_ptrs, &len, zbuf, zlen, CLOOP_COMPRESSOR_ZLIB); 1.1391 + cloop_free(zbuf, zlen); 1.1392 + if (ret != 0) 1.1393 - { 1.1394 -- printk(KERN_ERR "%s: file too small for %u blocks\n", 1.1395 -- cloop_name, ntohl(clo->head.num_blocks)); 1.1396 -+ printk(KERN_ERR "%s: decompression error %i uncompressing index, flags %u\n", 1.1397 -+ cloop_name, ret, flags); 1.1398 - error=-EBADF; goto error_release; 1.1399 - } 1.1400 -- clo->offsets = cloop_malloc(sizeof(loff_t) * total_offsets); 1.1401 -- if (!clo->offsets) 1.1402 -- { 1.1403 -- printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name); 1.1404 -- error=-ENOMEM; goto error_release; 1.1405 -- } 1.1406 - } 1.1407 -- num_readable = MIN(total_offsets - offsets_read, 1.1408 -- (clo->underlying_blksize - offset) 1.1409 -- / sizeof(loff_t)); 1.1410 -- memcpy(&clo->offsets[offsets_read], bbuf+offset, num_readable * sizeof(loff_t)); 1.1411 -- offsets_read += num_readable; 1.1412 -- } 1.1413 -- { /* Search for largest block rather than estimate. KK. */ 1.1414 -- int i; 1.1415 -- for(i=0;i<total_offsets-1;i++) 1.1416 ++ { 1.1417 ++ printk(KERN_ERR "%s: decompression error %i uncompressing index\n", 1.1418 ++ cloop_name, ret); 1.1419 ++ error=-EBADF; goto error_release; 1.1420 ++ } 1.1421 ++ } 1.1422 + else 1.1423 + { 1.1424 + printk(KERN_ERR "%s: can't find index\n", cloop_name); 1.1425 + error=-ENOMEM; goto error_release; 1.1426 + } 1.1427 -+ } 1.1428 -+ else 1.1429 -+ { 1.1430 + } 1.1431 + else 1.1432 + { 1.1433 +- fs_read_position = clo->underlying_total_size - sizeof(struct cloop_head) - total_offsets * sizeof(loff_t); 1.1434 +- } 1.1435 +- for(offsets_read=0;offsets_read<total_offsets;) 1.1436 +- { 1.1437 +- size_t bytes_readable; 1.1438 +- unsigned int num_readable, offset = 0; 1.1439 +- bytes_readable = MIN(bbuf_size, clo->underlying_total_size - fs_read_position); 1.1440 +- if(bytes_readable <= 0) break; /* Done */ 1.1441 +- bytes_read = cloop_read_from_file(clo, file, bbuf, fs_read_position, bytes_readable); 1.1442 +- if(bytes_read != bytes_readable) 1.1443 + unsigned int n, total_bytes; 1.1444 -+ flags = 0; 1.1445 + clo->block_ptrs = cloop_malloc(sizeof(struct block_info) * total_offsets); 1.1446 + if (!clo->block_ptrs) 1.1447 + { 1.1448 @@ -1007,14 +785,26 @@ 1.1449 + } 1.1450 + /* Read them offsets! */ 1.1451 + if(clo->header_first) 1.1452 -+ { 1.1453 + { 1.1454 +- printk(KERN_ERR "%s: Bad file %s, read() %lu bytes @ %llu returned %d.\n", 1.1455 +- cloop_name, clo->underlying_filename, (unsigned long)clo->underlying_blksize, fs_read_position, (int)bytes_read); 1.1456 +- error=-EBADF; 1.1457 +- goto error_release; 1.1458 + total_bytes = total_offsets * sizeof(struct block_info); 1.1459 + fs_read_position = sizeof(struct cloop_head); 1.1460 -+ } 1.1461 + } 1.1462 +- /* remember where to read the next blk from file */ 1.1463 +- fs_read_position += bytes_read; 1.1464 +- /* calculate how many offsets can be taken from current bbuf */ 1.1465 +- num_readable = MIN(total_offsets - offsets_read, 1.1466 +- bytes_read / sizeof(loff_t)); 1.1467 +- DEBUGP(KERN_INFO "cloop: parsing %d offsets %d to %d\n", num_readable, offsets_read, offsets_read+num_readable-1); 1.1468 +- for (i=0,offset=0; i<num_readable; i++) 1.1469 + else 1.1470 { 1.1471 -- loff_t d=be64_to_cpu(clo->offsets[i+1]) - be64_to_cpu(clo->offsets[i]); 1.1472 -- clo->largest_block=MAX(clo->largest_block,d); 1.1473 +- loff_t tmp = be64_to_cpu( *(loff_t*) (bbuf+offset) ); 1.1474 +- if (i%50==0) DEBUGP(KERN_INFO "cloop: offset %03d: %llu\n", offsets_read, tmp); 1.1475 +- if(offsets_read > 0) 1.1476 + total_bytes = total_offsets * sizeof(loff_t); 1.1477 + fs_read_position = clo->underlying_total_size - sizeof(struct cloop_head) - total_bytes; 1.1478 + } 1.1479 @@ -1025,35 +815,28 @@ 1.1480 + if(bytes_readable <= 0) break; /* Done */ 1.1481 + bytes_read = cloop_read_from_file(clo, file, bbuf, fs_read_position, bytes_readable); 1.1482 + if(bytes_read != bytes_readable) 1.1483 -+ { 1.1484 + { 1.1485 +- loff_t d = CLOOP_BLOCK_OFFSET(tmp) - CLOOP_BLOCK_OFFSET(clo->block_ptrs[offsets_read-1]); 1.1486 +- if(d > clo->largest_block) clo->largest_block = d; 1.1487 + printk(KERN_ERR "%s: Bad file %s, read() %lu bytes @ %llu returned %d.\n", 1.1488 + cloop_name, clo->underlying_filename, (unsigned long)clo->underlying_blksize, fs_read_position, (int)bytes_read); 1.1489 + error=-EBADF; 1.1490 + goto error_release; 1.1491 -+ } 1.1492 + } 1.1493 +- clo->block_ptrs[offsets_read++] = tmp; 1.1494 +- offset += sizeof(loff_t); 1.1495 + memcpy(((char *)clo->block_ptrs) + n, bbuf, bytes_read); 1.1496 + /* remember where to read the next blk from file */ 1.1497 + fs_read_position += bytes_read; 1.1498 + n += bytes_read; 1.1499 } 1.1500 -- printk(KERN_INFO "%s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n", 1.1501 -- cloop_name, filename, ntohl(clo->head.num_blocks), 1.1502 -- ntohl(clo->head.block_size), clo->largest_block); 1.1503 } 1.1504 --/* Combo kmalloc used too large chunks (>130000). */ 1.1505 +- printk(KERN_INFO "%s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n", 1.1506 +- cloop_name, clo->underlying_filename, clo->head.num_blocks, 1.1507 +- clo->head.block_size, clo->largest_block); 1.1508 { 1.1509 int i; 1.1510 -- for(i=0;i<BUFFERED_BLOCKS;i++) 1.1511 -- { 1.1512 -- clo->buffer[i] = cloop_malloc(ntohl(clo->head.block_size)); 1.1513 -- if(!clo->buffer[i]) 1.1514 -- { 1.1515 -- printk(KERN_ERR "%s: out of memory for buffer %lu\n", 1.1516 -- cloop_name, (unsigned long) ntohl(clo->head.block_size)); 1.1517 -- error=-ENOMEM; goto error_release_free; 1.1518 -- } 1.1519 -- } 1.1520 -+ char *version = build_index(clo->block_ptrs, clo->head.num_blocks, clo->head.block_size, flags); 1.1521 ++ char *version = build_index(clo->block_ptrs, clo->head.num_blocks, clo->head.block_size); 1.1522 + clo->largest_block = 0; 1.1523 + for (i = 0; i < clo->head.num_blocks; i++) 1.1524 + if (clo->block_ptrs[i].size > clo->largest_block) 1.1525 @@ -1061,39 +844,15 @@ 1.1526 + printk(KERN_INFO "%s: %s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n", 1.1527 + cloop_name, clo->underlying_filename, version, clo->head.num_blocks, 1.1528 + clo->head.block_size, clo->largest_block); 1.1529 -+ } 1.1530 -+ { 1.1531 -+ int i; 1.1532 -+ clo->num_buffered_blocks = (buffers > 0 && clo->head.block_size >= 512) ? 1.1533 -+ (buffers / clo->head.block_size) : 1; 1.1534 -+ clo->buffered_blocknum = cloop_malloc(clo->num_buffered_blocks * sizeof (u_int32_t)); 1.1535 -+ clo->buffer = cloop_malloc(clo->num_buffered_blocks * sizeof (char*)); 1.1536 -+ if (!clo->buffered_blocknum || !clo->buffer) 1.1537 -+ { 1.1538 -+ printk(KERN_ERR "%s: out of memory for index of cache buffer (%lu bytes)\n", 1.1539 -+ cloop_name, (unsigned long)clo->num_buffered_blocks * sizeof (u_int32_t) + sizeof(char*) ); 1.1540 -+ error=-ENOMEM; goto error_release; 1.1541 -+ } 1.1542 -+ memset(clo->buffer, 0, clo->num_buffered_blocks * sizeof (char*)); 1.1543 -+ for(i=0;i<clo->num_buffered_blocks;i++) 1.1544 -+ { 1.1545 -+ clo->buffered_blocknum[i] = -1; 1.1546 -+ clo->buffer[i] = cloop_malloc(clo->head.block_size); 1.1547 -+ if(!clo->buffer[i]) 1.1548 -+ { 1.1549 -+ printk(KERN_ERR "%s: out of memory for cache buffer %lu\n", 1.1550 -+ cloop_name, (unsigned long) clo->head.block_size); 1.1551 -+ error=-ENOMEM; goto error_release_free; 1.1552 -+ } 1.1553 -+ } 1.1554 -+ clo->current_bufnum = 0; 1.1555 - } 1.1556 - clo->compressed_buffer = cloop_malloc(clo->largest_block); 1.1557 - if(!clo->compressed_buffer) 1.1558 -@@ -557,31 +803,7 @@ 1.1559 + clo->num_buffered_blocks = (buffers > 0 && clo->head.block_size >= 512) ? 1.1560 + (buffers / clo->head.block_size) : 1; 1.1561 + clo->buffered_blocknum = cloop_malloc(clo->num_buffered_blocks * sizeof (u_int32_t)); 1.1562 +@@ -705,36 +793,14 @@ 1.1563 cloop_name, clo->largest_block); 1.1564 error=-ENOMEM; goto error_release_free_buffer; 1.1565 } 1.1566 +- /* Allocate Memory for decompressors */ 1.1567 +-#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 1.1568 - clo->zstream.workspace = cloop_malloc(zlib_inflate_workspacesize()); 1.1569 - if(!clo->zstream.workspace) 1.1570 - { 1.1571 @@ -1102,443 +861,48 @@ 1.1572 - error=-ENOMEM; goto error_release_free_all; 1.1573 - } 1.1574 - zlib_inflateInit(&clo->zstream); 1.1575 -- if(!isblkdev && 1.1576 -- be64_to_cpu(clo->offsets[ntohl(clo->head.num_blocks)]) != inode->i_size) 1.1577 -- { 1.1578 -- printk(KERN_ERR "%s: final offset wrong (%Lu not %Lu)\n", 1.1579 +-#endif 1.1580 +-#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 1.1581 +-#if XZ_INTERNAL_CRC32 1.1582 +- /* This must be called before any other xz_* function to initialize the CRC32 lookup table. */ 1.1583 +- xz_crc32_init(void); 1.1584 +-#endif 1.1585 +- clo->xzdecoderstate = xz_dec_init(XZ_SINGLE, 0); 1.1586 +-#endif 1.1587 +- if(CLOOP_BLOCK_OFFSET(clo->block_ptrs[clo->head.num_blocks]) > clo->underlying_total_size) 1.1588 ++ set_capacity(clo->clo_disk, (sector_t)(clo->head.num_blocks*(clo->head.block_size>>9))); 1.1589 ++ clo->clo_thread = kthread_create(cloop_thread, clo, "cloop%d", cloop_num); 1.1590 ++ if(IS_ERR(clo->clo_thread)) 1.1591 + { 1.1592 +- printk(KERN_ERR "%s: final offset wrong (%llu > %llu)\n", 1.1593 - cloop_name, 1.1594 -- be64_to_cpu(clo->offsets[ntohl(clo->head.num_blocks)]), 1.1595 -- inode->i_size); 1.1596 +- CLOOP_BLOCK_OFFSET(clo->block_ptrs[clo->head.num_blocks]), 1.1597 +- clo->underlying_total_size); 1.1598 +-#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 1.1599 - cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); clo->zstream.workspace=NULL; 1.1600 -- goto error_release_free_all; 1.1601 -- } 1.1602 -- { 1.1603 -- int i; 1.1604 -- for(i=0; i<BUFFERED_BLOCKS; i++) clo->buffered_blocknum[i] = -1; 1.1605 -- clo->current_bufnum=0; 1.1606 -- } 1.1607 -- set_capacity(clo->clo_disk, (sector_t)(ntohl(clo->head.num_blocks)* 1.1608 -- (ntohl(clo->head.block_size)>>9))); 1.1609 -+ set_capacity(clo->clo_disk, (sector_t)(clo->head.num_blocks*(clo->head.block_size>>9))); 1.1610 - clo->clo_thread = kthread_create(cloop_thread, clo, "cloop%d", cloop_num); 1.1611 - if(IS_ERR(clo->clo_thread)) 1.1612 - { 1.1613 -@@ -591,17 +813,17 @@ 1.1614 +-#endif 1.1615 ++ error = PTR_ERR(clo->clo_thread); 1.1616 ++ clo->clo_thread=NULL; 1.1617 + goto error_release_free_all; 1.1618 } 1.1619 +- set_capacity(clo->clo_disk, (sector_t)(clo->head.num_blocks*(clo->head.block_size>>9))); 1.1620 if(preload > 0) 1.1621 { 1.1622 -- clo->preload_array_size = ((preload<=ntohl(clo->head.num_blocks))?preload:ntohl(clo->head.num_blocks)); 1.1623 -+ clo->preload_array_size = ((preload<=clo->head.num_blocks)?preload:clo->head.num_blocks); 1.1624 - clo->preload_size = 0; 1.1625 - if((clo->preload_cache = cloop_malloc(clo->preload_array_size * sizeof(char *))) != NULL) 1.1626 - { 1.1627 - int i; 1.1628 - for(i=0; i<clo->preload_array_size; i++) 1.1629 - { 1.1630 -- if((clo->preload_cache[i] = cloop_malloc(ntohl(clo->head.block_size))) == NULL) 1.1631 -+ if((clo->preload_cache[i] = cloop_malloc(clo->head.block_size)) == NULL) 1.1632 - { /* Out of memory */ 1.1633 - printk(KERN_WARNING "%s: cloop_malloc(%d) failed for preload_cache[%d] (ignored).\n", 1.1634 -- cloop_name, ntohl(clo->head.block_size), i); 1.1635 -+ cloop_name, clo->head.block_size, i); 1.1636 - break; 1.1637 - } 1.1638 - } 1.1639 -@@ -612,13 +834,13 @@ 1.1640 - if(buffered_blocknum >= 0) 1.1641 - { 1.1642 - memcpy(clo->preload_cache[i], clo->buffer[buffered_blocknum], 1.1643 -- ntohl(clo->head.block_size)); 1.1644 -+ clo->head.block_size); 1.1645 - } 1.1646 - else 1.1647 - { 1.1648 - printk(KERN_WARNING "%s: can't read block %d into preload cache, set to zero.\n", 1.1649 - cloop_name, i); 1.1650 -- memset(clo->preload_cache[i], 0, ntohl(clo->head.block_size)); 1.1651 -+ memset(clo->preload_cache[i], 0, clo->head.block_size); 1.1652 - } 1.1653 - } 1.1654 - printk(KERN_INFO "%s: preloaded %d blocks into cache.\n", cloop_name, 1.1655 -@@ -641,22 +863,19 @@ 1.1656 - cloop_free(clo->compressed_buffer, clo->largest_block); 1.1657 - clo->compressed_buffer=NULL; 1.1658 - error_release_free_buffer: 1.1659 -+ if(clo->buffer) 1.1660 - { 1.1661 - int i; 1.1662 -- for(i=0; i<BUFFERED_BLOCKS; i++) 1.1663 -- { 1.1664 -- if(clo->buffer[i]) 1.1665 -- { 1.1666 -- cloop_free(clo->buffer[i], ntohl(clo->head.block_size)); 1.1667 -- clo->buffer[i]=NULL; 1.1668 -- } 1.1669 -- } 1.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; }} 1.1671 -+ cloop_free(clo->buffer, clo->num_buffered_blocks*sizeof(char*)); clo->buffer=NULL; 1.1672 + clo->preload_array_size = ((preload<=clo->head.num_blocks)?preload:clo->head.num_blocks); 1.1673 +@@ -780,6 +846,7 @@ 1.1674 + clo->preload_array_size = clo->preload_size = 0; 1.1675 + } 1.1676 + } 1.1677 ++ wake_up_process(clo->clo_thread); 1.1678 + /* Uncheck */ 1.1679 + return error; 1.1680 + error_release_free_all: 1.1681 +@@ -794,9 +861,13 @@ 1.1682 } 1.1683 -+ if (clo->buffered_blocknum) { cloop_free(clo->buffered_blocknum, sizeof(int)*clo->num_buffered_blocks); clo->buffered_blocknum=NULL; } 1.1684 + if (clo->buffered_blocknum) { cloop_free(clo->buffered_blocknum, sizeof(int)*clo->num_buffered_blocks); clo->buffered_blocknum=NULL; } 1.1685 error_release_free: 1.1686 -- cloop_free(clo->offsets, sizeof(loff_t) * total_offsets); 1.1687 -- clo->offsets=NULL; 1.1688 +- cloop_free(clo->block_ptrs, sizeof(cloop_block_ptr) * total_offsets); 1.1689 + cloop_free(clo->block_ptrs, sizeof(struct block_info) * total_offsets); 1.1690 -+ clo->block_ptrs=NULL; 1.1691 - error_release: 1.1692 - if(bbuf) cloop_free(bbuf, clo->underlying_blksize); 1.1693 -+ if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; } 1.1694 - clo->backing_file=NULL; 1.1695 - return error; 1.1696 - } 1.1697 -@@ -673,7 +892,7 @@ 1.1698 - if(clo->backing_file) return -EBUSY; 1.1699 - file = fget(arg); /* get filp struct from ioctl arg fd */ 1.1700 - if(!file) return -EBADF; 1.1701 -- error=cloop_set_file(cloop_num,file,"losetup_file"); 1.1702 -+ error=cloop_set_file(cloop_num,file); 1.1703 - set_device_ro(bdev, 1); 1.1704 - if(error) fput(file); 1.1705 - return error; 1.1706 -@@ -684,29 +903,48 @@ 1.1707 - { 1.1708 - struct cloop_device *clo = cloop_dev[cloop_num]; 1.1709 - struct file *filp = clo->backing_file; 1.1710 -- int i; 1.1711 - if(clo->refcnt > 1) /* we needed one fd for the ioctl */ 1.1712 - return -EBUSY; 1.1713 - if(filp==NULL) return -EINVAL; 1.1714 - if(clo->clo_thread) { kthread_stop(clo->clo_thread); clo->clo_thread=NULL; } 1.1715 -- if(filp!=initial_file) fput(filp); 1.1716 -- else { filp_close(initial_file,0); initial_file=NULL; } 1.1717 -+ if(filp!=initial_file) 1.1718 -+ fput(filp); 1.1719 -+ else 1.1720 -+ { 1.1721 -+ filp_close(initial_file,0); 1.1722 -+ initial_file=NULL; 1.1723 -+ } 1.1724 - clo->backing_file = NULL; 1.1725 - clo->backing_inode = NULL; 1.1726 -- if(clo->offsets) { cloop_free(clo->offsets, clo->underlying_blksize); clo->offsets = NULL; } 1.1727 -+ if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; } 1.1728 -+ if(clo->block_ptrs) { cloop_free(clo->block_ptrs, clo->head.num_blocks); clo->block_ptrs = NULL; } 1.1729 - if(clo->preload_cache) 1.1730 -- { 1.1731 -- for(i=0; i < clo->preload_size; i++) 1.1732 -- cloop_free(clo->preload_cache[i], ntohl(clo->head.block_size)); 1.1733 -- cloop_free(clo->preload_cache, clo->preload_array_size * sizeof(char *)); 1.1734 -- clo->preload_cache = NULL; 1.1735 -- clo->preload_size = clo->preload_array_size = 0; 1.1736 -- } 1.1737 -- for(i=0; i<BUFFERED_BLOCKS; i++) 1.1738 -- if(clo->buffer[i]) { cloop_free(clo->buffer[i], ntohl(clo->head.block_size)); clo->buffer[i]=NULL; } 1.1739 -+ { 1.1740 -+ int i; 1.1741 -+ for(i=0; i < clo->preload_size; i++) 1.1742 -+ cloop_free(clo->preload_cache[i], clo->head.block_size); 1.1743 -+ cloop_free(clo->preload_cache, clo->preload_array_size * sizeof(char *)); 1.1744 -+ clo->preload_cache = NULL; 1.1745 -+ clo->preload_size = clo->preload_array_size = 0; 1.1746 -+ } 1.1747 -+ if (clo->buffered_blocknum) 1.1748 -+ { 1.1749 -+ cloop_free(clo->buffered_blocknum, sizeof(int) * clo->num_buffered_blocks); clo->buffered_blocknum = NULL; 1.1750 -+ } 1.1751 -+ if (clo->buffer) 1.1752 -+ { 1.1753 -+ int i; 1.1754 -+ for(i=0; i<clo->num_buffered_blocks; i++) { if(clo->buffer[i]) cloop_free(clo->buffer[i], clo->head.block_size); } 1.1755 -+ cloop_free(clo->buffer, sizeof(char*) * clo->num_buffered_blocks); clo->buffer = NULL; 1.1756 -+ } 1.1757 - if(clo->compressed_buffer) { cloop_free(clo->compressed_buffer, clo->largest_block); clo->compressed_buffer = NULL; } 1.1758 -+#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 1.1759 - zlib_inflateEnd(&clo->zstream); 1.1760 - if(clo->zstream.workspace) { cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); clo->zstream.workspace = NULL; } 1.1761 -+#endif 1.1762 -+#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE)) 1.1763 -+ xz_dec_end(clo->xzdecoderstate); 1.1764 -+#endif 1.1765 - if(bdev) invalidate_bdev(bdev); 1.1766 - if(clo->clo_disk) set_capacity(clo->clo_disk, 0); 1.1767 - return 0; 1.1768 -@@ -731,8 +969,8 @@ 1.1769 - const struct loop_info64 *info) 1.1770 - { 1.1771 - if (!clo->backing_file) return -ENXIO; 1.1772 -- memcpy(clo->clo_file_name, info->lo_file_name, LO_NAME_SIZE); 1.1773 -- clo->clo_file_name[LO_NAME_SIZE-1] = 0; 1.1774 -+ if(clo->underlying_filename) kfree(clo->underlying_filename); 1.1775 -+ clo->underlying_filename = kstrdup(info->lo_file_name, GFP_KERNEL); 1.1776 - return 0; 1.1777 - } 1.1778 - 1.1779 -@@ -743,7 +981,11 @@ 1.1780 - struct kstat stat; 1.1781 - int err; 1.1782 - if (!file) return -ENXIO; 1.1783 -- err = vfs_getattr(file->f_path.mnt, file->f_path.dentry, &stat); 1.1784 -+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) 1.1785 -+ err = vfs_getattr(&file->f_path, &stat); 1.1786 -+#else 1.1787 -+ err = vfs_getattr(&file->f_path, &stat, STATX_INO, AT_STATX_SYNC_AS_STAT); 1.1788 -+#endif 1.1789 - if (err) return err; 1.1790 - memset(info, 0, sizeof(*info)); 1.1791 - info->lo_number = clo->clo_number; 1.1792 -@@ -753,7 +995,8 @@ 1.1793 - info->lo_offset = 0; 1.1794 - info->lo_sizelimit = 0; 1.1795 - info->lo_flags = 0; 1.1796 -- memcpy(info->lo_file_name, clo->clo_file_name, LO_NAME_SIZE); 1.1797 -+ strncpy(info->lo_file_name, clo->underlying_filename, LO_NAME_SIZE); 1.1798 -+ info->lo_file_name[LO_NAME_SIZE-1]=0; 1.1799 - return 0; 1.1800 - } 1.1801 - 1.1802 -@@ -833,8 +1076,6 @@ 1.1803 - if (!err && copy_to_user(arg, &info64, sizeof(info64))) err = -EFAULT; 1.1804 - return err; 1.1805 - } 1.1806 --/* EOF get/set_status */ 1.1807 -- 1.1808 - 1.1809 - static int cloop_ioctl(struct block_device *bdev, fmode_t mode, 1.1810 - unsigned int cmd, unsigned long arg) 1.1811 -@@ -914,21 +1155,20 @@ 1.1812 - /* losetup uses write-open and flags=0x8002 to set a new file */ 1.1813 - if(mode & FMODE_WRITE) 1.1814 - { 1.1815 -- printk(KERN_WARNING "%s: Can't open device read-write in mode 0x%x\n", cloop_name, mode); 1.1816 -+ printk(KERN_INFO "%s: Open in read-write mode 0x%x requested, ignored.\n", cloop_name, mode); 1.1817 - return -EROFS; 1.1818 - } 1.1819 - cloop_dev[cloop_num]->refcnt+=1; 1.1820 - return 0; 1.1821 - } 1.1822 - 1.1823 --static int cloop_close(struct gendisk *disk, fmode_t mode) 1.1824 -+static void cloop_close(struct gendisk *disk, fmode_t mode) 1.1825 - { 1.1826 -- int cloop_num, err=0; 1.1827 -- if(!disk) return 0; 1.1828 -+ int cloop_num; 1.1829 -+ if(!disk) return; 1.1830 - cloop_num=((struct cloop_device *)disk->private_data)->clo_number; 1.1831 -- if(cloop_num < 0 || cloop_num > (cloop_count-1)) return 0; 1.1832 -+ if(cloop_num < 0 || cloop_num > (cloop_count-1)) return; 1.1833 - cloop_dev[cloop_num]->refcnt-=1; 1.1834 -- return err; 1.1835 - } 1.1836 - 1.1837 - static struct block_device_operations clo_fops = 1.1838 -@@ -973,6 +1213,10 @@ 1.1839 - goto error_out; 1.1840 - } 1.1841 - clo->clo_queue->queuedata = clo; 1.1842 -+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) 1.1843 -+ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, clo->clo_queue); 1.1844 -+ queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, clo->clo_queue); 1.1845 -+#endif 1.1846 - clo->clo_disk = alloc_disk(1); 1.1847 - if(!clo->clo_disk) 1.1848 - { 1.1849 -@@ -1004,6 +1248,11 @@ 1.1850 - cloop_dev[cloop_num] = NULL; 1.1851 - } 1.1852 - 1.1853 -+/* LZ4 Stuff */ 1.1854 -+#if (defined USE_LZ4_INTERNAL) 1.1855 -+#include "lz4_kmod.c" 1.1856 -+#endif 1.1857 -+ 1.1858 - static int __init cloop_init(void) 1.1859 - { 1.1860 - int error=0; 1.1861 -@@ -1044,7 +1293,7 @@ 1.1862 - initial_file=NULL; /* if IS_ERR, it's NOT open. */ 1.1863 - } 1.1864 - else 1.1865 -- error=cloop_set_file(0,initial_file,file); 1.1866 -+ error=cloop_set_file(0,initial_file); 1.1867 - if(error) 1.1868 - { 1.1869 - printk(KERN_ERR 1.1870 -@@ -1052,9 +1301,6 @@ 1.1871 - cloop_name, file, error); 1.1872 - goto init_out_dealloc; 1.1873 - } 1.1874 -- if(namelen >= LO_NAME_SIZE) namelen = LO_NAME_SIZE-1; 1.1875 -- memcpy(cloop_dev[0]->clo_file_name, file, namelen); 1.1876 -- cloop_dev[0]->clo_file_name[namelen] = 0; 1.1877 - } 1.1878 - return 0; 1.1879 - init_out_dealloc: 1.1880 ---- cloop.h 1.1881 -+++ cloop.h 1.1882 -@@ -86,11 +86,8 @@ 1.1883 - struct cloop_tail 1.1884 - { 1.1885 - u_int32_t table_size; 1.1886 -- u_int32_t index_size; /* size:4 comp:3 ctrl-c:1 lastlen:24 */ 1.1887 -+ u_int32_t index_size; /* size:4 unused:3 ctrl-c:1 lastlen:24 */ 1.1888 - #define CLOOP3_INDEX_SIZE(x) ((unsigned int)((x) & 0xF)) 1.1889 --#define CLOOP3_BLOCKS_FLAGS(x) ((unsigned int)((x) & 0x70) >> 4) 1.1890 --#define CLOOP3_TRUNCATED(x) ((unsigned int)((x) & 0x80) >> 7) 1.1891 --#define CLOOP3_LASTLEN(x) (unsigned int)((x) >> 8) 1.1892 - u_int32_t num_blocks; 1.1893 - }; 1.1894 - 1.1895 -@@ -104,8 +101,10 @@ 1.1896 - }; 1.1897 - 1.1898 - static inline char *build_index(struct block_info *offsets, unsigned long n, 1.1899 -- unsigned long block_size, unsigned global_flags) 1.1900 -+ unsigned long block_size) 1.1901 - { 1.1902 -+ static char v[11]; 1.1903 -+ u_int32_t flags = 0; 1.1904 - u_int32_t *ofs32 = (u_int32_t *) offsets; 1.1905 - loff_t *ofs64 = (loff_t *) offsets; 1.1906 - 1.1907 -@@ -130,8 +129,6 @@ 1.1908 - } 1.1909 - else { /* V2.0/V4.0 */ 1.1910 - loff_t last = CLOOP_BLOCK_OFFSET(__be64_to_cpu(ofs64[n])); 1.1911 -- u_int32_t flags; 1.1912 -- static char v4[11]; 1.1913 - unsigned long i = n; 1.1914 - 1.1915 - for (flags = 0; n-- ;) { 1.1916 -@@ -149,12 +146,7 @@ 1.1917 - offsets[i] = offsets[offsets[i].offset]; 1.1918 - } 1.1919 - } 1.1920 -- strcpy(v4, (char *) "64BE v4.0a"); 1.1921 -- v4[10] = 'a' + ((flags-1) & 0xF); // compressors used 1.1922 -- if (flags > 0x10) { // with links ? 1.1923 -- v4[10] += 'A' - 'a'; 1.1924 -- } 1.1925 -- return v4; 1.1926 -+ strcpy(v, (char *) "64BE v4.0a"); 1.1927 - } 1.1928 - } 1.1929 - else if (ofs32[1] == 0 && v3_64 == 0) { /* V1.0 */ 1.1930 -@@ -170,7 +162,6 @@ 1.1931 - else { /* V3.0 or V0.68 */ 1.1932 - unsigned long i; 1.1933 - loff_t j; 1.1934 -- static char v3[11]; 1.1935 - 1.1936 - for (i = 0; i < n && ntohl(ofs32[i]) < ntohl(ofs32[i+1]); i++); 1.1937 - if (i == n && ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */ 1.1938 -@@ -185,28 +176,33 @@ 1.1939 - } 1.1940 - 1.1941 - v3_64 = (ofs32[1] == 0); 1.1942 -- for (i = n; i-- != 0; ) 1.1943 -+ for (i = n; i-- != 0; ) { 1.1944 - offsets[i].size = ntohl(ofs32[i << v3_64]); 1.1945 -- for (i = 0, j = sizeof(struct cloop_head); i < n; i++) { 1.1946 -- offsets[i].offset = j; 1.1947 -- offsets[i].flags = global_flags; 1.1948 - if (offsets[i].size == 0xFFFFFFFF) { 1.1949 -- offsets[i].flags = CLOOP_COMPRESSOR_NONE; 1.1950 -- offsets[i].size = block_size; 1.1951 -+ offsets[i].size = 0x10000000 | block_size; 1.1952 - } 1.1953 -- if ((offsets[i].size & 0x80000000) == 0) { 1.1954 -+ offsets[i].flags = (offsets[i].size >> 28); 1.1955 -+ offsets[i].size &= 0x0FFFFFFF; 1.1956 -+ } 1.1957 -+ for (i = 0, j = sizeof(struct cloop_head); i < n; i++) { 1.1958 -+ offsets[i].offset = j; 1.1959 -+ if (offsets[i].flags < 8) { 1.1960 - j += offsets[i].size; 1.1961 - } 1.1962 - } 1.1963 - for (i = 0; i < n; i++) { 1.1964 -- if (offsets[i].size & 0x80000000) { 1.1965 -- offsets[i] = offsets[offsets[i].size & 0x7FFFFFFF]; 1.1966 -+ flags |= 1 << offsets[i].flags; 1.1967 -+ if (offsets[i].flags >= 8) { 1.1968 -+ offsets[i] = offsets[offsets[i].size]; 1.1969 - } 1.1970 - } 1.1971 -- strcpy(v3, (char *) (v3_64) ? "64BE v3.0a" : "32BE v3.0a"); 1.1972 -- v3[10] += global_flags; 1.1973 -- return v3; 1.1974 -+ strcpy(v, (char *) (v3_64) ? "64BE v3.0a" : "32BE v3.0a"); 1.1975 -+ } 1.1976 -+ v[10] = 'a' + ((flags-1) & 0xF); // compressors used 1.1977 -+ if (flags > 0x10) { // with links ? 1.1978 -+ v[10] += 'A' - 'a'; 1.1979 - } 1.1980 -+ return v; 1.1981 - } 1.1982 - 1.1983 - /* Cloop suspend IOCTL */ 1.1984 ---- cloop.c 1.1985 -+++ cloop.c 1.1986 -@@ -542,7 +542,7 @@ 1.1987 - const unsigned int header_size = sizeof(struct cloop_head); 1.1988 - unsigned int i, total_offsets=0; 1.1989 - loff_t fs_read_position = 0, header_pos[2]; 1.1990 -- int flags, isblkdev, bytes_read, error = 0; 1.1991 -+ int isblkdev, bytes_read, error = 0; 1.1992 - if (clo->suspended) return error; 1.1993 - #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) 1.1994 - inode = file->f_dentry->d_inode; 1.1995 -@@ -698,18 +698,12 @@ 1.1996 - error=-EBADF; goto error_release; 1.1997 - } 1.1998 - len = CLOOP3_INDEX_SIZE(ntohl(tail.index_size)) * total_offsets; 1.1999 -- flags = CLOOP3_BLOCKS_FLAGS(ntohl(tail.index_size)); 1.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) 1.2001 --printk(KERN_INFO "%s: uncompress(clo=%p, block_ptrs=%p, &len(%ld)=%p, zbuf=%p, zlen=%ld, flag=%d)\n", cloop_name, 1.2002 -- clo, clo->block_ptrs, len, &len, zbuf, zlen, flags); 1.2003 -- ret = uncompress(clo, (void *) clo->block_ptrs, &len, zbuf, zlen, flags); 1.2004 --// May 3 19:45:20 (none) user.alert kernel: BUG: unable to handle kernel NULL pointer dereference at (null) 1.2005 --printk(KERN_INFO "%s: uncompressed !\n", cloop_name); 1.2006 -+ ret = uncompress(clo, (void *) clo->block_ptrs, &len, zbuf, zlen, CLOOP_COMPRESSOR_ZLIB); 1.2007 - cloop_free(zbuf, zlen); 1.2008 - if (ret != 0) 1.2009 - { 1.2010 -- printk(KERN_ERR "%s: decompression error %i uncompressing index, flags %u\n", 1.2011 -- cloop_name, ret, flags); 1.2012 -+ printk(KERN_ERR "%s: decompression error %i uncompressing index\n", 1.2013 -+ cloop_name, ret); 1.2014 - error=-EBADF; goto error_release; 1.2015 - } 1.2016 - } 1.2017 -@@ -722,7 +716,6 @@ 1.2018 - else 1.2019 - { 1.2020 - unsigned int n, total_bytes; 1.2021 -- flags = 0; 1.2022 - clo->block_ptrs = cloop_malloc(sizeof(struct block_info) * total_offsets); 1.2023 - if (!clo->block_ptrs) 1.2024 - { 1.2025 -@@ -761,7 +754,7 @@ 1.2026 - } 1.2027 - { 1.2028 - int i; 1.2029 -- char *version = build_index(clo->block_ptrs, clo->head.num_blocks, clo->head.block_size, flags); 1.2030 -+ char *version = build_index(clo->block_ptrs, clo->head.num_blocks, clo->head.block_size); 1.2031 - clo->largest_block = 0; 1.2032 - for (i = 0; i < clo->head.num_blocks; i++) 1.2033 - if (clo->block_ptrs[i].size > clo->largest_block) 1.2034 -@@ -769,9 +762,6 @@ 1.2035 - printk(KERN_INFO "%s: %s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n", 1.2036 - cloop_name, clo->underlying_filename, version, clo->head.num_blocks, 1.2037 - clo->head.block_size, clo->largest_block); 1.2038 -- } 1.2039 -- { 1.2040 -- int i; 1.2041 - clo->num_buffered_blocks = (buffers > 0 && clo->head.block_size >= 512) ? 1.2042 - (buffers / clo->head.block_size) : 1; 1.2043 - clo->buffered_blocknum = cloop_malloc(clo->num_buffered_blocks * sizeof (u_int32_t)); 1.2044 -@@ -874,6 +864,10 @@ 1.2045 - cloop_free(clo->block_ptrs, sizeof(struct block_info) * total_offsets); 1.2046 clo->block_ptrs=NULL; 1.2047 error_release: 1.2048 +#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE)) 1.2049 @@ -1548,3 +912,146 @@ 1.2050 if(bbuf) cloop_free(bbuf, clo->underlying_blksize); 1.2051 if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; } 1.2052 clo->backing_file=NULL; 1.2053 +@@ -829,6 +900,7 @@ 1.2054 + if(clo->refcnt > 1) /* we needed one fd for the ioctl */ 1.2055 + return -EBUSY; 1.2056 + if(filp==NULL) return -EINVAL; 1.2057 ++ if(clo->clo_thread) { kthread_stop(clo->clo_thread); clo->clo_thread=NULL; } 1.2058 + if(filp!=initial_file) 1.2059 + fput(filp); 1.2060 + else 1.2061 +@@ -839,7 +911,7 @@ 1.2062 + clo->backing_file = NULL; 1.2063 + clo->backing_inode = NULL; 1.2064 + if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; } 1.2065 +- if(clo->block_ptrs) { cloop_free(clo->block_ptrs, clo->head.num_blocks+1); clo->block_ptrs = NULL; } 1.2066 ++ if(clo->block_ptrs) { cloop_free(clo->block_ptrs, clo->head.num_blocks); clo->block_ptrs = NULL; } 1.2067 + if(clo->preload_cache) 1.2068 + { 1.2069 + int i; 1.2070 +@@ -1054,15 +1126,15 @@ 1.2071 + case LOOP_CLR_FD: /* Change arg */ 1.2072 + case LOOP_GET_STATUS64: /* Change arg */ 1.2073 + case LOOP_SET_STATUS64: /* Change arg */ 1.2074 +- return cloop_ioctl(bdev, mode, cmd, (unsigned long) compat_ptr(arg)); 1.2075 ++ arg = (unsigned long) compat_ptr(arg); 1.2076 + case LOOP_SET_STATUS: /* unchanged */ 1.2077 + case LOOP_GET_STATUS: /* unchanged */ 1.2078 + case LOOP_SET_FD: /* unchanged */ 1.2079 + case LOOP_CHANGE_FD: /* unchanged */ 1.2080 +- return cloop_ioctl(bdev, mode, cmd, arg); 1.2081 +- default: 1.2082 +- return -ENOIOCTLCMD; 1.2083 ++ return cloop_ioctl(bdev, mode, cmd, arg); 1.2084 ++ break; 1.2085 + } 1.2086 ++ return -ENOIOCTLCMD; 1.2087 + } 1.2088 + #endif 1.2089 + 1.2090 +@@ -1093,7 +1165,7 @@ 1.2091 + cloop_dev[cloop_num]->refcnt-=1; 1.2092 + } 1.2093 + 1.2094 +-static const struct block_device_operations clo_fops = 1.2095 ++static struct block_device_operations clo_fops = 1.2096 + { 1.2097 + owner: THIS_MODULE, 1.2098 + open: cloop_open, 1.2099 +@@ -1105,12 +1177,6 @@ 1.2100 + /* locked_ioctl ceased to exist in 2.6.36 */ 1.2101 + }; 1.2102 + 1.2103 +-static const struct blk_mq_ops cloop_mq_ops = { 1.2104 +- .queue_rq = cloop_queue_rq, 1.2105 +-/* .init_request = cloop_init_request, */ 1.2106 +-/* .complete = cloop_complete_rq, */ 1.2107 +-}; 1.2108 +- 1.2109 + static int cloop_register_blkdev(int major_nr) 1.2110 + { 1.2111 + return register_blkdev(major_nr, cloop_name); 1.2112 +@@ -1124,37 +1190,33 @@ 1.2113 + 1.2114 + static int cloop_alloc(int cloop_num) 1.2115 + { 1.2116 +- struct cloop_device *clo = (struct cloop_device *) cloop_malloc(sizeof(struct cloop_device)); 1.2117 ++ struct cloop_device *clo = (struct cloop_device *) cloop_malloc(sizeof(struct cloop_device));; 1.2118 + if(clo == NULL) goto error_out; 1.2119 + cloop_dev[cloop_num] = clo; 1.2120 + memset(clo, 0, sizeof(struct cloop_device)); 1.2121 + clo->clo_number = cloop_num; 1.2122 +- clo->tag_set.ops = &cloop_mq_ops; 1.2123 +- clo->tag_set.nr_hw_queues = 1; 1.2124 +- clo->tag_set.queue_depth = 128; 1.2125 +- clo->tag_set.numa_node = NUMA_NO_NODE; 1.2126 +- clo->tag_set.cmd_size = 0; /* No extra data needed */ 1.2127 +- /* BLK_MQ_F_BLOCKING is extremely important if we want to call blocking functions like vfs_read */ 1.2128 +- clo->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING; 1.2129 +- clo->tag_set.driver_data = clo; 1.2130 +- if(blk_mq_alloc_tag_set(&clo->tag_set)) goto error_out_free_clo; 1.2131 +- clo->clo_queue = blk_mq_init_queue(&clo->tag_set); 1.2132 +- if(IS_ERR(clo->clo_queue)) 1.2133 ++ clo->clo_thread = NULL; 1.2134 ++ init_waitqueue_head(&clo->clo_event); 1.2135 ++ spin_lock_init(&clo->queue_lock); 1.2136 ++ mutex_init(&clo->clo_ctl_mutex); 1.2137 ++ INIT_LIST_HEAD(&clo->clo_list); 1.2138 ++ clo->clo_queue = blk_init_queue(cloop_do_request, &clo->queue_lock); 1.2139 ++ if(!clo->clo_queue) 1.2140 + { 1.2141 + printk(KERN_ERR "%s: Unable to alloc queue[%d]\n", cloop_name, cloop_num); 1.2142 +- goto error_out_free_tags; 1.2143 ++ goto error_out; 1.2144 + } 1.2145 + clo->clo_queue->queuedata = clo; 1.2146 +- blk_queue_max_hw_sectors(clo->clo_queue, BLK_DEF_MAX_SECTORS); 1.2147 ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) 1.2148 ++ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, clo->clo_queue); 1.2149 ++ queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, clo->clo_queue); 1.2150 ++#endif 1.2151 + clo->clo_disk = alloc_disk(1); 1.2152 + if(!clo->clo_disk) 1.2153 + { 1.2154 + printk(KERN_ERR "%s: Unable to alloc disk[%d]\n", cloop_name, cloop_num); 1.2155 +- goto error_out_free_queue; 1.2156 ++ goto error_disk; 1.2157 + } 1.2158 +- spin_lock_init(&clo->queue_lock); 1.2159 +- mutex_init(&clo->clo_ctl_mutex); 1.2160 +- mutex_init(&clo->clo_rq_mutex); 1.2161 + clo->clo_disk->major = cloop_major; 1.2162 + clo->clo_disk->first_minor = cloop_num; 1.2163 + clo->clo_disk->fops = &clo_fops; 1.2164 +@@ -1163,12 +1225,8 @@ 1.2165 + sprintf(clo->clo_disk->disk_name, "%s%d", cloop_name, cloop_num); 1.2166 + add_disk(clo->clo_disk); 1.2167 + return 0; 1.2168 +-error_out_free_queue: 1.2169 ++error_disk: 1.2170 + blk_cleanup_queue(clo->clo_queue); 1.2171 +-error_out_free_tags: 1.2172 +- blk_mq_free_tag_set(&clo->tag_set); 1.2173 +-error_out_free_clo: 1.2174 +- cloop_free(clo, sizeof(struct cloop_device)); 1.2175 + error_out: 1.2176 + return -ENOMEM; 1.2177 + } 1.2178 +@@ -1179,7 +1237,6 @@ 1.2179 + if(clo == NULL) return; 1.2180 + del_gendisk(clo->clo_disk); 1.2181 + blk_cleanup_queue(clo->clo_queue); 1.2182 +- blk_mq_free_tag_set(&clo->tag_set); 1.2183 + put_disk(clo->clo_disk); 1.2184 + cloop_free(clo, sizeof(struct cloop_device)); 1.2185 + cloop_dev[cloop_num] = NULL; 1.2186 +--- cloop_suspend.c 1.2187 ++++ cloop_suspend.c 1.2188 +@@ -14,6 +14,7 @@ 1.2189 + #include <fcntl.h> 1.2190 + #include <unistd.h> 1.2191 + #include <stdio.h> 1.2192 ++#include <stdint.h> 1.2193 + 1.2194 + /* We don't use the structure, so that define does not hurt */ 1.2195 + #define dev_t int