wok annotate linux64-cloop/stuff/cloop.u @ rev 24910

Update some web_site (again)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sat Apr 09 14:32:04 2022 +0000 (2022-04-09)
parents 36e9a3dcd5de
children 5a92a26adcc1
rev   line source
pascal@17214 1 --- cloop.h
pascal@17214 2 +++ cloop.h
pascal@23761 3 @@ -1,15 +1,50 @@
pascal@23761 4 +#define CLOOP_SIGNATURE "#!/bin/sh" /* @ offset 0 */
pascal@23761 5 +#define CLOOP_SIGNATURE_SIZE 9
pascal@23761 6 +#define CLOOP_SIGNATURE_OFFSET 0x0
pascal@23761 7 +
pascal@23761 8 #ifndef _COMPRESSED_LOOP_H
pascal@23761 9 #define _COMPRESSED_LOOP_H
pascal@23761 10
pascal@23761 11 -#define CLOOP_HEADROOM 128
pascal@23761 12 +/*************************************************************************\
pascal@23761 13 +* Starting with Format V4.0 (cloop version 4.x), cloop can now have two *
pascal@23761 14 +* alternative structures: *
pascal@23761 15 +* *
pascal@23761 16 +* 1. Header first: "robust" format, handles missing blocks well *
pascal@23761 17 +* 2. Footer (header last): "streaming" format, easier to create *
pascal@23761 18 +* *
pascal@23761 19 +* The cloop kernel module autodetects both formats, and can (currently) *
pascal@23761 20 +* still handle the V2.0 format as well. *
pascal@23761 21 +* *
pascal@23761 22 +* 1. Header first: *
pascal@23761 23 +* +---------------------------- FIXED SIZE ---------------------------+ *
pascal@23761 24 +* |Signature (128 bytes) | *
pascal@23761 25 +* |block_size (32bit number, network order) | *
pascal@23761 26 +* |num_blocks (32bit number, network order) | *
pascal@23761 27 +* +--------------------------- VARIABLE SIZE -------------------------+ *
pascal@23761 28 +* |num_blocks * FlagsOffset (upper 4 bits flags, lower 64 bits offset)| *
pascal@23761 29 +* |compressed data blocks of variable size ... | *
pascal@23761 30 +* +-------------------------------------------------------------------+ *
pascal@23761 31 +* *
pascal@23761 32 +* 2. Footer (header last): *
pascal@23761 33 +* +--------------------------- VARIABLE SIZE -------------------------+ *
pascal@23761 34 +* |compressed data blocks of variable size ... | *
pascal@23761 35 +* |num_blocks * FlagsOffset (upper 4 bits flags, lower 64 bits offset)| *
pascal@23761 36 +* +---------------------------- FIXED SIZE ---------------------------+ *
pascal@23761 37 +* |Signature (128 bytes) | *
pascal@23761 38 +* |block_size (32bit number, network order) | *
pascal@23761 39 +* |num_blocks (32bit number, network order) | *
pascal@23761 40 +* +-------------------------------------------------------------------+ *
pascal@23761 41 +* *
pascal@23761 42 +* Offsets are always relative to beginning of file, in all formats. *
pascal@23761 43 +* The block index contains num_blocks+1 offsets, followed (1) or *
pascal@23761 44 +* preceded (2) by the compressed blocks. *
pascal@23761 45 +\*************************************************************************/
pascal@23761 46
pascal@23761 47 -/* The cloop header usually looks like this: */
pascal@23761 48 -/* #!/bin/sh */
pascal@23761 49 -/* #V2.00 Format */
pascal@23761 50 -/* ...padding up to CLOOP_HEADROOM... */
pascal@23761 51 -/* block_size (32bit number, network order) */
pascal@23761 52 -/* num_blocks (32bit number, network order) */
pascal@23761 53 +#include <linux/types.h> /* u_int32_t */
pascal@23761 54 +
pascal@23761 55 +#define CLOOP_HEADROOM 128
pascal@23761 56
pascal@23761 57 +/* Header of fixed length, can be located at beginning or end of file */
pascal@23761 58 struct cloop_head
pascal@23761 59 {
pascal@23761 60 char preamble[CLOOP_HEADROOM];
pascal@23761 61 @@ -17,9 +52,163 @@
pascal@23761 62 u_int32_t num_blocks;
pascal@23761 63 };
pascal@23761 64
pascal@23761 65 +/************************************************************************\
pascal@23761 66 +* CLOOP4 flags for each compressed block *
pascal@23761 67 +* Value Meaning *
pascal@23761 68 +* 0 GZIP/7ZIP compression (compatible with V2.0 Format) *
pascal@23761 69 +* 1 no compression (incompressible data) *
pascal@23761 70 +* 2 xz compression (currently best space saver) *
pascal@23761 71 +* 3 lz4 compression *
pascal@23761 72 +* 4 lzo compression (fastest) *
pascal@23761 73 +\************************************************************************/
pascal@23761 74 +
pascal@23761 75 +typedef uint64_t cloop_block_ptr;
pascal@23761 76 +
pascal@23761 77 +/* Get value of first 4 bits */
pascal@23761 78 +#define CLOOP_BLOCK_FLAGS(x) ((unsigned int)(((x) & 0xf000000000000000LLU) >> 60))
pascal@23761 79 +/* Get value of last 60 bits */
pascal@23761 80 +#define CLOOP_BLOCK_OFFSET(x) ((x) & 0x0fffffffffffffffLLU)
pascal@23761 81 +
pascal@23761 82 +#define CLOOP_COMPRESSOR_ZLIB 0x0
pascal@23761 83 +#define CLOOP_COMPRESSOR_NONE 0x1
pascal@23761 84 +#define CLOOP_COMPRESSOR_XZ 0x2
pascal@23761 85 +#define CLOOP_COMPRESSOR_LZ4 0x3
pascal@23761 86 +#define CLOOP_COMPRESSOR_LZO1X 0x4
pascal@23761 87 +
pascal@23761 88 +#define CLOOP_COMPRESSOR_VALID(x) ((x) >= CLOOP_COMPRESSOR_ZLIB && (x) <= CLOOP_COMPRESSOR_LZO1X)
pascal@23761 89 +
pascal@23761 90 +#define CLOOP_COMPRESSOR_LINK 0xF
pascal@23761 91 +
pascal@23761 92 +
pascal@17214 93 /* data_index (num_blocks 64bit pointers, network order)... */
pascal@17214 94 /* compressed data (gzip block compressed format)... */
pascal@17214 95
pascal@17214 96 +struct cloop_tail
pascal@17214 97 +{
pascal@23761 98 + u_int32_t table_size;
pascal@23761 99 + u_int32_t index_size; /* size:4 comp:3 ctrl-c:1 lastlen:24 */
pascal@23761 100 +#define CLOOP3_INDEX_SIZE(x) ((unsigned int)((x) & 0xF))
pascal@23761 101 +#define CLOOP3_BLOCKS_FLAGS(x) ((unsigned int)((x) & 0x70) >> 4)
pascal@23761 102 +#define CLOOP3_TRUNCATED(x) ((unsigned int)((x) & 0x80) >> 7)
pascal@23761 103 +#define CLOOP3_LASTLEN(x) (unsigned int)((x) >> 8)
pascal@17214 104 + u_int32_t num_blocks;
pascal@17214 105 +};
pascal@17214 106 +
pascal@23761 107 +#define GZIP_MAX_BUFFER(n) ((n) + (n)/1000 + 12)
pascal@23761 108 +
pascal@17214 109 +struct block_info
pascal@17214 110 +{
pascal@17214 111 + loff_t offset; /* 64-bit offsets of compressed block */
pascal@17214 112 + u_int32_t size; /* 32-bit compressed block size */
pascal@23761 113 + u_int32_t flags; /* 32-bit compression flags */
pascal@17214 114 +};
pascal@17214 115 +
pascal@23761 116 +static inline char *build_index(struct block_info *offsets, unsigned long n,
pascal@23761 117 + unsigned long block_size, unsigned global_flags)
pascal@17214 118 +{
pascal@17214 119 + u_int32_t *ofs32 = (u_int32_t *) offsets;
pascal@17214 120 + loff_t *ofs64 = (loff_t *) offsets;
pascal@23761 121 +
pascal@23761 122 + /* v3 64bits bug: v1 assumed */
pascal@23761 123 + unsigned long v3_64 = (n+1)/2;
pascal@23761 124 + loff_t prev;
pascal@23761 125 +
pascal@23761 126 + if (ofs32[0] != 0 && ofs32[1] == 0) {
pascal@23761 127 + for (prev=__le64_to_cpu(ofs64[v3_64]);
pascal@23761 128 + v3_64 > 0 && __le64_to_cpu(ofs64[--v3_64]) < prev;
pascal@23761 129 + prev=__le64_to_cpu(ofs64[v3_64]));
pascal@23761 130 + }
pascal@23761 131 +
pascal@17214 132 + if (ofs32[0] == 0) {
pascal@17214 133 + if (ofs32[2]) { /* ACCELERATED KNOPPIX V1.0 */
pascal@17214 134 + while (n--) {
pascal@17214 135 + offsets[n].offset = __be64_to_cpu(offsets[n].offset);
pascal@17214 136 + offsets[n].size = ntohl(offsets[n].size);
pascal@23761 137 + offsets[n].flags = 0;
pascal@17214 138 + }
pascal@17214 139 + return (char *) "128BE accelerated knoppix 1.0";
pascal@17214 140 + }
pascal@23761 141 + else { /* V2.0/V4.0 */
pascal@23761 142 + loff_t last = CLOOP_BLOCK_OFFSET(__be64_to_cpu(ofs64[n]));
pascal@23761 143 + u_int32_t flags;
pascal@23761 144 + static char v4[11];
pascal@23761 145 + unsigned long i = n;
pascal@23761 146 +
pascal@23761 147 + for (flags = 0; n-- ;) {
pascal@23761 148 + loff_t data = __be64_to_cpu(ofs64[n]);
pascal@23761 149 +
pascal@17214 150 + offsets[n].size = last -
pascal@23761 151 + (offsets[n].offset = CLOOP_BLOCK_OFFSET(data));
pascal@17214 152 + last = offsets[n].offset;
pascal@23761 153 + offsets[n].flags = CLOOP_BLOCK_FLAGS(data);
pascal@23761 154 + flags |= 1 << offsets[n].flags;
pascal@17214 155 + }
pascal@23761 156 + if (flags < 2) return (char *) "64BE v2.0";
pascal@23761 157 + while (i--) {
pascal@23761 158 + if (offsets[i].flags == CLOOP_COMPRESSOR_LINK) {
pascal@23761 159 + offsets[i] = offsets[offsets[i].offset];
pascal@23761 160 + }
pascal@23761 161 + }
pascal@23761 162 + strcpy(v4, (char *) "64BE v4.0a");
pascal@23761 163 + v4[10] = 'a' + ((flags-1) & 0xF); // compressors used
pascal@23761 164 + if (flags > 0x10) { // with links ?
pascal@23761 165 + v4[10] += 'A' - 'a';
pascal@23761 166 + }
pascal@23761 167 + return v4;
pascal@17214 168 + }
pascal@17214 169 + }
pascal@23761 170 + else if (ofs32[1] == 0 && v3_64 == 0) { /* V1.0 */
pascal@23761 171 + loff_t last = __le64_to_cpu(ofs64[n]);
pascal@17214 172 + while (n--) {
pascal@17214 173 + offsets[n].size = last -
pascal@17214 174 + (offsets[n].offset = __le64_to_cpu(ofs64[n]));
pascal@17214 175 + last = offsets[n].offset;
pascal@23761 176 + offsets[n].flags = 0;
pascal@17214 177 + }
pascal@17214 178 + return (char *) "64LE v1.0";
pascal@17214 179 + }
pascal@23761 180 + else { /* V3.0 or V0.68 */
pascal@17214 181 + unsigned long i;
pascal@17214 182 + loff_t j;
pascal@23761 183 + static char v3[11];
pascal@17214 184 +
pascal@23761 185 + for (i = 0; i < n && ntohl(ofs32[i]) < ntohl(ofs32[i+1]); i++);
pascal@23761 186 + if (i == n && ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */
pascal@23761 187 + loff_t last = ntohl(ofs32[n]);
pascal@23761 188 + while (n--) {
pascal@23761 189 + offsets[n].size = last -
pascal@23761 190 + (offsets[n].offset = ntohl(ofs32[n]));
pascal@23761 191 + last = offsets[n].offset;
pascal@23761 192 + offsets[n].flags = 0;
pascal@23761 193 + }
pascal@23761 194 + return (char *) "32BE v0.68";
pascal@23761 195 + }
pascal@23761 196 +
pascal@23761 197 + v3_64 = (ofs32[1] == 0);
pascal@17214 198 + for (i = n; i-- != 0; )
pascal@23761 199 + offsets[i].size = ntohl(ofs32[i << v3_64]);
pascal@17214 200 + for (i = 0, j = sizeof(struct cloop_head); i < n; i++) {
pascal@17214 201 + offsets[i].offset = j;
pascal@23761 202 + offsets[i].flags = global_flags;
pascal@23761 203 + if (offsets[i].size == 0xFFFFFFFF) {
pascal@23761 204 + offsets[i].flags = CLOOP_COMPRESSOR_NONE;
pascal@23761 205 + offsets[i].size = block_size;
pascal@23761 206 + }
pascal@23761 207 + if ((offsets[i].size & 0x80000000) == 0) {
pascal@23761 208 + j += offsets[i].size;
pascal@23761 209 + }
pascal@23761 210 + }
pascal@23761 211 + for (i = 0; i < n; i++) {
pascal@18828 212 + if (offsets[i].size & 0x80000000) {
pascal@23761 213 + offsets[i] = offsets[offsets[i].size & 0x7FFFFFFF];
pascal@18828 214 + }
pascal@17214 215 + }
pascal@23761 216 + strcpy(v3, (char *) (v3_64) ? "64BE v3.0a" : "32BE v3.0a");
pascal@23761 217 + v3[10] += global_flags;
pascal@23761 218 + return v3;
pascal@17214 219 + }
pascal@17214 220 +}
pascal@17214 221 +
pascal@17214 222 /* Cloop suspend IOCTL */
pascal@17214 223 #define CLOOP_SUSPEND 0x4C07
pascal@17214 224
pascal@17214 225 --- cloop.c
pascal@17214 226 +++ cloop.c
pascal@23761 227 @@ -1,26 +1,23 @@
pascal@23761 228 -/*
pascal@23761 229 - * compressed_loop.c: Read-only compressed loop blockdevice
pascal@23761 230 - * hacked up by Rusty in 1999, extended and maintained by Klaus Knopper
pascal@23761 231 - *
pascal@23761 232 - * A cloop file looks like this:
pascal@23761 233 - * [32-bit uncompressed block size: network order]
pascal@23761 234 - * [32-bit number of blocks (n_blocks): network order]
pascal@17214 235 - * [64-bit file offsets of start of blocks: network order]
pascal@23761 236 - * ...
pascal@23761 237 - * (n_blocks + 1).
pascal@23761 238 - * n_blocks consisting of:
pascal@23761 239 - * [compressed block]
pascal@23761 240 - *
pascal@23761 241 - * Every version greatly inspired by code seen in loop.c
pascal@23761 242 - * by Theodore Ts'o, 3/29/93.
pascal@23761 243 - *
pascal@23761 244 - * Copyright 1999-2009 by Paul `Rusty' Russell & Klaus Knopper.
pascal@23761 245 - * Redistribution of this file is permitted under the GNU Public License.
pascal@23761 246 - *
pascal@23761 247 - */
pascal@23761 248 +/************************************************************************\
pascal@23761 249 +* cloop.c: Read-only compressed loop blockdevice *
pascal@23761 250 +* hacked up by Rusty in 1999, extended and maintained by Klaus Knopper *
pascal@23761 251 +* *
pascal@23761 252 +* For all supported cloop file formats, please check the file "cloop.h" *
pascal@23761 253 +* New in Version 4: *
pascal@23761 254 +* - Header can be first or last in cloop file, *
pascal@23761 255 +* - Different compression algorithms supported (compression type *
pascal@23761 256 +* encoded in first 4 bytes of block offset address) *
pascal@23761 257 +* *
pascal@23761 258 +* Every version greatly inspired by code seen in loop.c *
pascal@23761 259 +* by Theodore Ts'o, 3/29/93. *
pascal@23761 260 +* *
pascal@23761 261 +* Copyright 1999-2009 by Paul `Rusty' Russell & Klaus Knopper. *
pascal@23761 262 +* Redistribution of this file is permitted under the GNU Public License *
pascal@23761 263 +* V2. *
pascal@23761 264 +\************************************************************************/
pascal@23761 265
pascal@23761 266 #define CLOOP_NAME "cloop"
pascal@23761 267 -#define CLOOP_VERSION "2.639"
pascal@23761 268 +#define CLOOP_VERSION "4.12"
pascal@23761 269 #define CLOOP_MAX 8
pascal@23761 270
pascal@23761 271 #ifndef KBUILD_MODNAME
pascal@23761 272 @@ -47,8 +44,27 @@
pascal@23761 273 #include <asm/div64.h> /* do_div() for 64bit division */
pascal@23761 274 #include <asm/uaccess.h>
pascal@23761 275 #include <asm/byteorder.h>
pascal@23761 276 -/* Use zlib_inflate from lib/zlib_inflate */
pascal@23761 277 +/* Check for ZLIB, LZO1X, LZ4 decompression algorithms in kernel. */
pascal@23761 278 +#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE))
pascal@23761 279 #include <linux/zutil.h>
pascal@23761 280 +#endif
pascal@23761 281 +#if (defined(CONFIG_LZO_DECOMPRESS) || defined(CONFIG_LZO_DECOMPRESS_MODULE))
pascal@23761 282 +#include <linux/lzo.h>
pascal@23761 283 +#endif
pascal@23761 284 +#if (defined(CONFIG_DECOMPRESS_LZ4) || defined(CONFIG_DECOMPRESS_LZ4_MODULE))
pascal@23761 285 +#include <linux/lz4.h>
pascal@23761 286 +#endif
pascal@23761 287 +#if (defined(CONFIG_DECOMPRESS_LZMA) || defined(CONFIG_DECOMPRESS_LZMA_MODULE))
pascal@23761 288 +#include <linux/decompress/unlzma.h>
pascal@23761 289 +#endif
pascal@23761 290 +#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE))
pascal@23761 291 +#include <linux/xz.h>
pascal@23761 292 +#endif
pascal@23761 293 +
pascal@23761 294 +#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)))
pascal@23761 295 +#error "No decompression library selected in kernel config!"
pascal@23761 296 +#endif
pascal@23761 297 +
pascal@23761 298 #include <linux/loop.h>
pascal@23761 299 #include <linux/kthread.h>
pascal@23761 300 #include <linux/compat.h>
pascal@23761 301 @@ -92,47 +108,64 @@
pascal@23761 302 #define DEBUGP(format, x...)
pascal@23761 303 #endif
pascal@23761 304
pascal@23761 305 +/* Default size of buffer to keep some decompressed blocks in memory to speed up access */
pascal@23761 306 +#define BLOCK_BUFFER_MEM (16*65536)
pascal@23761 307 +
pascal@23761 308 /* One file can be opened at module insertion time */
pascal@23761 309 /* insmod cloop file=/path/to/file */
pascal@23761 310 static char *file=NULL;
pascal@23761 311 static unsigned int preload=0;
pascal@23761 312 static unsigned int cloop_max=CLOOP_MAX;
pascal@23761 313 +static unsigned int buffers=BLOCK_BUFFER_MEM;
pascal@23761 314 module_param(file, charp, 0);
pascal@23761 315 module_param(preload, uint, 0);
pascal@23761 316 module_param(cloop_max, uint, 0);
pascal@23761 317 MODULE_PARM_DESC(file, "Initial cloop image file (full path) for /dev/cloop");
pascal@23761 318 MODULE_PARM_DESC(preload, "Preload n blocks of cloop data into memory");
pascal@23761 319 MODULE_PARM_DESC(cloop_max, "Maximum number of cloop devices (default 8)");
pascal@23761 320 +MODULE_PARM_DESC(buffers, "Size of buffer to keep uncompressed blocks in memory in MiB (default 1)");
pascal@23761 321
pascal@23761 322 static struct file *initial_file=NULL;
pascal@23761 323 static int cloop_major=MAJOR_NR;
pascal@23761 324
pascal@23761 325 -/* Number of buffered decompressed blocks */
pascal@23761 326 -#define BUFFERED_BLOCKS 8
pascal@23761 327 struct cloop_device
pascal@23761 328 {
pascal@23761 329 - /* Copied straight from the file */
pascal@23761 330 + /* Header filled from the file */
pascal@17214 331 struct cloop_head head;
pascal@23761 332 + int header_first;
pascal@23761 333 + int file_format;
pascal@17214 334
pascal@23761 335 - /* An array of offsets of compressed blocks within the file */
pascal@17214 336 - loff_t *offsets;
pascal@23761 337 + /* An or'd sum of all flags of each compressed block (v3) */
pascal@23761 338 + u_int32_t allflags;
pascal@23761 339 +
pascal@23761 340 + /* An array of cloop_ptr flags/offset for compressed blocks within the file */
pascal@23761 341 + struct block_info *block_ptrs;
pascal@17214 342
pascal@17214 343 /* We buffer some uncompressed blocks for performance */
pascal@23761 344 - int buffered_blocknum[BUFFERED_BLOCKS];
pascal@23761 345 - int current_bufnum;
pascal@23761 346 - void *buffer[BUFFERED_BLOCKS];
pascal@23761 347 - void *compressed_buffer;
pascal@23761 348 - size_t preload_array_size; /* Size of pointer array in blocks */
pascal@23761 349 - size_t preload_size; /* Number of successfully allocated blocks */
pascal@23761 350 - char **preload_cache; /* Pointers to preloaded blocks */
pascal@23761 351 + size_t num_buffered_blocks; /* how many uncompressed blocks buffered for performance */
pascal@23761 352 + int *buffered_blocknum; /* list of numbers of uncompressed blocks in buffer */
pascal@23761 353 + int current_bufnum; /* which block is current */
pascal@23761 354 + unsigned char **buffer; /* cache space for num_buffered_blocks uncompressed blocks */
pascal@23761 355 + void *compressed_buffer; /* space for the largest compressed block */
pascal@23761 356 + size_t preload_array_size; /* Size of pointer array in blocks */
pascal@23761 357 + size_t preload_size; /* Number of successfully allocated blocks */
pascal@23761 358 + char **preload_cache; /* Pointers to preloaded blocks */
pascal@17214 359
pascal@23761 360 +#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE))
pascal@23761 361 z_stream zstream;
pascal@23761 362 +#endif
pascal@23761 363 +#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE))
pascal@23761 364 + struct xz_dec *xzdecoderstate;
pascal@23761 365 + struct xz_buf xz_buffer;
pascal@23761 366 +#endif
pascal@23761 367
pascal@23761 368 struct file *backing_file; /* associated file */
pascal@23761 369 struct inode *backing_inode; /* for bmap */
pascal@23761 370
pascal@23761 371 + unsigned char *underlying_filename;
pascal@23761 372 unsigned long largest_block;
pascal@23761 373 unsigned int underlying_blksize;
pascal@23761 374 + loff_t underlying_total_size;
pascal@23761 375 int clo_number;
pascal@23761 376 int refcnt;
pascal@23761 377 struct block_device *bdev;
pascal@23761 378 @@ -147,7 +180,6 @@
pascal@23761 379 struct request_queue *clo_queue;
pascal@23761 380 struct gendisk *clo_disk;
pascal@23761 381 int suspended;
pascal@23761 382 - char clo_file_name[LO_NAME_SIZE];
pascal@23761 383 };
pascal@23761 384
pascal@23761 385 /* Changed in 2.639: cloop_dev is now a an array of cloop_dev pointers,
pascal@23761 386 @@ -156,52 +188,113 @@
pascal@23761 387 static const char *cloop_name=CLOOP_NAME;
pascal@23761 388 static int cloop_count = 0;
pascal@23761 389
pascal@23761 390 -#if (!(defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE))) /* Must be compiled into kernel. */
pascal@23761 391 -#error "Invalid Kernel configuration. CONFIG_ZLIB_INFLATE support is needed for cloop."
pascal@23761 392 -#endif
pascal@23761 393 -
pascal@23761 394 -/* Use __get_free_pages instead of vmalloc, allows up to 32 pages,
pascal@23761 395 - * 2MB in one piece */
pascal@23761 396 static void *cloop_malloc(size_t size)
pascal@23761 397 {
pascal@23761 398 - int order = get_order(size);
pascal@23761 399 - if(order <= KMALLOC_MAX_ORDER)
pascal@23761 400 - return (void *)kmalloc(size, GFP_KERNEL);
pascal@23761 401 - else if(order < MAX_ORDER)
pascal@23761 402 - return (void *)__get_free_pages(GFP_KERNEL, order);
pascal@23761 403 + /* kmalloc will fail after the system is running for a while, */
pascal@23761 404 + /* when large orders can't return contiguous memory. */
pascal@23761 405 + /* Let's just use vmalloc for now. :-/ */
pascal@23761 406 + /* int order = get_order(size); */
pascal@23761 407 + /* if(order <= KMALLOC_MAX_ORDER) */
pascal@23761 408 + /* return (void *)kmalloc(size, GFP_KERNEL); */
pascal@23761 409 + /* else if(order < MAX_ORDER) */
pascal@23761 410 + /* return (void *)__get_free_pages(GFP_KERNEL, order); */
pascal@23761 411 return (void *)vmalloc(size);
pascal@23761 412 }
pascal@23761 413
pascal@23761 414 static void cloop_free(void *mem, size_t size)
pascal@23761 415 {
pascal@23761 416 - int order = get_order(size);
pascal@23761 417 - if(order <= KMALLOC_MAX_ORDER)
pascal@23761 418 - kfree(mem);
pascal@23761 419 - else if(order < MAX_ORDER)
pascal@23761 420 - free_pages((unsigned long)mem, order);
pascal@23761 421 - else vfree(mem);
pascal@23761 422 + /* int order = get_order(size); */
pascal@23761 423 + /* if(order <= KMALLOC_MAX_ORDER) */
pascal@23761 424 + /* kfree(mem); */
pascal@23761 425 + /* else if(order < MAX_ORDER) */
pascal@23761 426 + /* free_pages((unsigned long)mem, order); */
pascal@23761 427 + /* else */
pascal@23761 428 + vfree(mem);
pascal@23761 429 }
pascal@23761 430
pascal@23761 431 -static int uncompress(struct cloop_device *clo,
pascal@23761 432 - unsigned char *dest, unsigned long *destLen,
pascal@23761 433 - unsigned char *source, unsigned long sourceLen)
pascal@23761 434 +static int uncompress(struct cloop_device *clo, unsigned char *dest, unsigned long *destLen, unsigned char *source, unsigned long sourceLen, int flags)
pascal@23761 435 {
pascal@23761 436 - /* Most of this code can be found in fs/cramfs/uncompress.c */
pascal@23761 437 - int err;
pascal@23761 438 - clo->zstream.next_in = source;
pascal@23761 439 - clo->zstream.avail_in = sourceLen;
pascal@23761 440 - clo->zstream.next_out = dest;
pascal@23761 441 - clo->zstream.avail_out = *destLen;
pascal@23761 442 - err = zlib_inflateReset(&clo->zstream);
pascal@23761 443 - if (err != Z_OK)
pascal@23761 444 - {
pascal@23761 445 - printk(KERN_ERR "%s: zlib_inflateReset error %d\n", cloop_name, err);
pascal@23761 446 - zlib_inflateEnd(&clo->zstream); zlib_inflateInit(&clo->zstream);
pascal@23761 447 - }
pascal@23761 448 - err = zlib_inflate(&clo->zstream, Z_FINISH);
pascal@23761 449 - *destLen = clo->zstream.total_out;
pascal@23761 450 - if (err != Z_STREAM_END) return err;
pascal@23761 451 - return Z_OK;
pascal@23761 452 + int err = -1;
pascal@23761 453 + switch(flags)
pascal@23761 454 + {
pascal@23761 455 + case CLOOP_COMPRESSOR_NONE:
pascal@23761 456 + memcpy(dest, source, *destLen = sourceLen);
pascal@23761 457 + err = Z_OK;
pascal@23761 458 + break;
pascal@23761 459 +#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE))
pascal@23761 460 + case CLOOP_COMPRESSOR_ZLIB:
pascal@23761 461 + clo->zstream.next_in = source;
pascal@23761 462 + clo->zstream.avail_in = sourceLen;
pascal@23761 463 + clo->zstream.next_out = dest;
pascal@23761 464 + clo->zstream.avail_out = *destLen;
pascal@23761 465 + err = zlib_inflateReset(&clo->zstream);
pascal@23761 466 + if (err != Z_OK)
pascal@23761 467 + {
pascal@23761 468 + printk(KERN_ERR "%s: zlib_inflateReset error %d\n", cloop_name, err);
pascal@23761 469 + zlib_inflateEnd(&clo->zstream); zlib_inflateInit(&clo->zstream);
pascal@23761 470 + }
pascal@23761 471 + err = zlib_inflate(&clo->zstream, Z_FINISH);
pascal@23761 472 + *destLen = clo->zstream.total_out;
pascal@23761 473 + if (err == Z_STREAM_END) err = 0;
pascal@23761 474 + DEBUGP("cloop: zlib decompression done, ret =%d, size =%lu\n", err, *destLen);
pascal@23761 475 + break;
pascal@23761 476 +#endif
pascal@23761 477 +#if (defined(CONFIG_LZO_DECOMPRESS) || defined(CONFIG_LZO_DECOMPRESS_MODULE))
pascal@23761 478 + case CLOOP_COMPRESSOR_LZO1X:
pascal@23761 479 + {
pascal@23761 480 + size_t tmp = (size_t) clo->head.block_size;
pascal@23761 481 + err = lzo1x_decompress_safe(source, sourceLen,
pascal@23761 482 + dest, &tmp);
pascal@23761 483 + if (err == LZO_E_OK) *destLen = (u_int32_t) tmp;
pascal@23761 484 + }
pascal@23761 485 + break;
pascal@23761 486 +#endif
pascal@23761 487 +#if (defined(CONFIG_DECOMPRESS_LZ4) || defined(CONFIG_DECOMPRESS_LZ4_MODULE))
pascal@23761 488 + case CLOOP_COMPRESSOR_LZ4:
pascal@23761 489 + {
pascal@23761 490 + size_t outputSize = *destLen;
pascal@23761 491 + /* We should adjust outputSize here, in case the last block is smaller than block_size */
pascal@23761 492 +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) /* field removed */
pascal@23761 493 + err = lz4_decompress(source, (size_t *) &sourceLen,
pascal@23761 494 + dest, outputSize);
pascal@23761 495 +#else
pascal@23761 496 + err = LZ4_decompress_safe(source,
pascal@23761 497 + dest,
pascal@23761 498 + sourceLen, outputSize);
pascal@23761 499 +#endif
pascal@23761 500 + if (err >= 0)
pascal@23761 501 + {
pascal@23761 502 + err = 0;
pascal@23761 503 + *destLen = outputSize;
pascal@23761 504 + }
pascal@23761 505 + }
pascal@23761 506 + break;
pascal@23761 507 +#endif
pascal@23761 508 +#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE))
pascal@23761 509 + case CLOOP_COMPRESSOR_XZ:
pascal@23761 510 + clo->xz_buffer.in = source;
pascal@23761 511 + clo->xz_buffer.in_pos = 0;
pascal@23761 512 + clo->xz_buffer.in_size = sourceLen;
pascal@23761 513 + clo->xz_buffer.out = dest;
pascal@23761 514 + clo->xz_buffer.out_pos = 0;
pascal@23761 515 + clo->xz_buffer.out_size = *destLen;
pascal@23761 516 + xz_dec_reset(clo->xzdecoderstate);
pascal@23761 517 + err = xz_dec_run(clo->xzdecoderstate, &clo->xz_buffer);
pascal@23761 518 + if (err == XZ_STREAM_END || err == XZ_OK)
pascal@23761 519 + {
pascal@23761 520 + err = 0;
pascal@23761 521 + }
pascal@23761 522 + else
pascal@23761 523 + {
pascal@23761 524 + printk(KERN_ERR "%s: xz_dec_run error %d\n", cloop_name, err);
pascal@23761 525 + err = 1;
pascal@23761 526 + }
pascal@23761 527 + break;
pascal@23761 528 +#endif
pascal@23761 529 + default:
pascal@23761 530 + printk(KERN_ERR "%s: compression method is not supported!\n", cloop_name);
pascal@23761 531 + }
pascal@23761 532 + return err;
pascal@23761 533 }
pascal@23761 534
pascal@23761 535 static ssize_t cloop_read_from_file(struct cloop_device *clo, struct file *f, char *buf,
pascal@23761 536 @@ -220,7 +313,7 @@
pascal@23761 537
pascal@23761 538 if(size_read <= 0)
pascal@23761 539 {
pascal@23761 540 - printk(KERN_ERR "%s: Read error %d at pos %Lu in file %s, "
pascal@23761 541 + printk(KERN_ERR "%s: Read error %d at pos %llu in file %s, "
pascal@23761 542 "%d bytes lost.\n", cloop_name, (int)size_read, pos,
pascal@23761 543 file, (int)size);
pascal@23761 544 memset(buf + buf_len - size, 0, size);
pascal@23761 545 @@ -232,72 +325,84 @@
pascal@23761 546 }
pascal@23761 547
pascal@23761 548 /* This looks more complicated than it is */
pascal@23761 549 -/* Returns number of block buffer to use for this request */
pascal@23761 550 +/* Returns number of cache block buffer to use for this request */
pascal@23761 551 static int cloop_load_buffer(struct cloop_device *clo, int blocknum)
pascal@23761 552 {
pascal@23761 553 - unsigned int buf_done = 0;
pascal@23761 554 - unsigned long buflen;
pascal@23761 555 - unsigned int buf_length;
pascal@23761 556 + loff_t compressed_block_offset;
pascal@23761 557 + long compressed_block_len;
pascal@23761 558 + long uncompressed_block_len=0;
pascal@23761 559 int ret;
pascal@23761 560 int i;
pascal@23761 561 - if(blocknum > ntohl(clo->head.num_blocks) || blocknum < 0)
pascal@23761 562 - {
pascal@23761 563 - printk(KERN_WARNING "%s: Invalid block number %d requested.\n",
pascal@23761 564 - cloop_name, blocknum);
pascal@23761 565 - return -1;
pascal@23761 566 - }
pascal@23761 567 + if(blocknum > clo->head.num_blocks || blocknum < 0)
pascal@23761 568 + {
pascal@23761 569 + printk(KERN_WARNING "%s: Invalid block number %d requested.\n",
pascal@23761 570 + cloop_name, blocknum);
pascal@23761 571 + return -1;
pascal@23761 572 + }
pascal@23761 573
pascal@23761 574 /* Quick return if the block we seek is already in one of the buffers. */
pascal@23761 575 /* Return number of buffer */
pascal@23761 576 - for(i=0; i<BUFFERED_BLOCKS; i++)
pascal@23761 577 + for(i=0; i<clo->num_buffered_blocks; i++)
pascal@23761 578 if (blocknum == clo->buffered_blocknum[i])
pascal@23761 579 - {
pascal@23761 580 - DEBUGP(KERN_INFO "cloop_load_buffer: Found buffered block %d\n", i);
pascal@23761 581 - return i;
pascal@23761 582 - }
pascal@23761 583 -
pascal@17214 584 - buf_length = be64_to_cpu(clo->offsets[blocknum+1]) - be64_to_cpu(clo->offsets[blocknum]);
pascal@23761 585 -
pascal@23761 586 -/* Load one compressed block from the file. */
pascal@23761 587 - cloop_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer,
pascal@23761 588 - be64_to_cpu(clo->offsets[blocknum]), buf_length);
pascal@23761 589 + {
pascal@23761 590 + DEBUGP(KERN_INFO "cloop_load_buffer: Found buffered block %d\n", i);
pascal@23761 591 + return i;
pascal@23761 592 + }
pascal@17214 593
pascal@23761 594 - buflen = ntohl(clo->head.block_size);
pascal@23761 595 + compressed_block_offset = clo->block_ptrs[blocknum].offset;
pascal@23761 596 + compressed_block_len = (long) (clo->block_ptrs[blocknum].size) ;
pascal@17214 597
pascal@23761 598 - /* Go to next position in the block ring buffer */
pascal@23761 599 - clo->current_bufnum++;
pascal@23761 600 - if(clo->current_bufnum >= BUFFERED_BLOCKS) clo->current_bufnum = 0;
pascal@23761 601 + /* Load one compressed block from the file. */
pascal@23761 602 + if(compressed_block_offset > 0 && compressed_block_len >= 0) /* sanity check */
pascal@23761 603 + {
pascal@23761 604 + size_t n = cloop_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer,
pascal@23761 605 + compressed_block_offset, compressed_block_len);
pascal@23761 606 + if (n!= compressed_block_len)
pascal@23761 607 + {
pascal@23761 608 + printk(KERN_ERR "%s: error while reading %lu bytes @ %llu from file %s\n",
pascal@23761 609 + cloop_name, compressed_block_len, clo->block_ptrs[blocknum].offset, clo->underlying_filename);
pascal@23761 610 + /* return -1; */
pascal@23761 611 + }
pascal@23761 612 + } else {
pascal@23761 613 + printk(KERN_ERR "%s: invalid data block len %ld bytes @ %lld from file %s\n",
pascal@23761 614 + cloop_name, compressed_block_len, clo->block_ptrs[blocknum].offset, clo->underlying_filename);
pascal@23761 615 + return -1;
pascal@23761 616 + }
pascal@23761 617 +
pascal@23761 618 + /* Go to next position in the cache block buffer (which is used as a cyclic buffer) */
pascal@23761 619 + if(++clo->current_bufnum >= clo->num_buffered_blocks) clo->current_bufnum = 0;
pascal@17214 620
pascal@23761 621 /* Do the uncompression */
pascal@23761 622 - ret = uncompress(clo, clo->buffer[clo->current_bufnum], &buflen, clo->compressed_buffer,
pascal@23761 623 - buf_length);
pascal@23761 624 + uncompressed_block_len = clo->head.block_size;
pascal@23761 625 + ret = uncompress(clo, clo->buffer[clo->current_bufnum], &uncompressed_block_len,
pascal@23761 626 + clo->compressed_buffer, compressed_block_len, clo->block_ptrs[blocknum].flags);
pascal@23761 627 /* DEBUGP("cloop: buflen after uncompress: %ld\n",buflen); */
pascal@17214 628 if (ret != 0)
pascal@23761 629 - {
pascal@23761 630 - printk(KERN_ERR "%s: zlib decompression error %i uncompressing block %u %u/%lu/%u/%u "
pascal@23761 631 - "%Lu-%Lu\n", cloop_name, ret, blocknum,
pascal@23761 632 - ntohl(clo->head.block_size), buflen, buf_length, buf_done,
pascal@23761 633 - be64_to_cpu(clo->offsets[blocknum]), be64_to_cpu(clo->offsets[blocknum+1]));
pascal@23761 634 - clo->buffered_blocknum[clo->current_bufnum] = -1;
pascal@23761 635 - return -1;
pascal@23761 636 - }
pascal@23761 637 + {
pascal@23761 638 + printk(KERN_ERR "%s: decompression error %i uncompressing block %u %lu bytes @ %llu, flags %u\n",
pascal@23761 639 + cloop_name, ret, blocknum,
pascal@23761 640 + compressed_block_len, clo->block_ptrs[blocknum].offset,
pascal@23761 641 + clo->block_ptrs[blocknum].flags);
pascal@23761 642 + clo->buffered_blocknum[clo->current_bufnum] = -1;
pascal@23761 643 + return -1;
pascal@23761 644 + }
pascal@23761 645 clo->buffered_blocknum[clo->current_bufnum] = blocknum;
pascal@23761 646 return clo->current_bufnum;
pascal@23761 647 }
pascal@23761 648
pascal@23761 649 /* This function does all the real work. */
pascal@23761 650 -/* returns "uptodate" */
pascal@23761 651 +/* returns "uptodate" */
pascal@23761 652 static int cloop_handle_request(struct cloop_device *clo, struct request *req)
pascal@23761 653 {
pascal@23761 654 int buffered_blocknum = -1;
pascal@23761 655 int preloaded = 0;
pascal@23761 656 loff_t offset = (loff_t) blk_rq_pos(req)<<9; /* req->sector<<9 */
pascal@23761 657 - struct bio_vec *bvec;
pascal@23761 658 + struct bio_vec bvec;
pascal@23761 659 struct req_iterator iter;
pascal@23761 660 rq_for_each_segment(bvec, req, iter)
pascal@17214 661 {
pascal@23761 662 - unsigned long len = bvec->bv_len;
pascal@23761 663 - char *to_ptr = kmap(bvec->bv_page) + bvec->bv_offset;
pascal@23761 664 + unsigned long len = bvec.bv_len;
pascal@23761 665 + char *to_ptr = kmap(bvec.bv_page) + bvec.bv_offset;
pascal@23761 666 while(len > 0)
pascal@23761 667 {
pascal@23761 668 u_int32_t length_in_buffer;
pascal@23761 669 @@ -308,7 +413,7 @@
pascal@23761 670 /* puts the result in the first argument, i.e. block_offset */
pascal@23761 671 /* becomes the blocknumber to load, and offset_in_buffer the */
pascal@23761 672 /* position in the buffer */
pascal@23761 673 - offset_in_buffer = do_div(block_offset, ntohl(clo->head.block_size));
pascal@23761 674 + offset_in_buffer = do_div(block_offset, clo->head.block_size);
pascal@23761 675 /* Lookup preload cache */
pascal@23761 676 if(block_offset < clo->preload_size && clo->preload_cache != NULL &&
pascal@23761 677 clo->preload_cache[block_offset] != NULL)
pascal@23761 678 @@ -325,7 +430,7 @@
pascal@23761 679 from_ptr = clo->buffer[buffered_blocknum];
pascal@23761 680 }
pascal@23761 681 /* Now, at least part of what we want will be in the buffer. */
pascal@23761 682 - length_in_buffer = ntohl(clo->head.block_size) - offset_in_buffer;
pascal@23761 683 + length_in_buffer = clo->head.block_size - offset_in_buffer;
pascal@23761 684 if(length_in_buffer > len)
pascal@23761 685 {
pascal@23761 686 /* DEBUGP("Warning: length_in_buffer=%u > len=%u\n",
pascal@23761 687 @@ -337,18 +442,19 @@
pascal@23761 688 len -= length_in_buffer;
pascal@23761 689 offset += length_in_buffer;
pascal@23761 690 } /* while inner loop */
pascal@23761 691 - kunmap(bvec->bv_page);
pascal@23761 692 + kunmap(bvec.bv_page);
pascal@23761 693 + cond_resched();
pascal@23761 694 } /* end rq_for_each_segment*/
pascal@23761 695 return ((buffered_blocknum!=-1) || preloaded);
pascal@23761 696 }
pascal@23761 697
pascal@23761 698 /* Adopted from loop.c, a kernel thread to handle physical reads and
pascal@23761 699 - * decompression. */
pascal@23761 700 + decompression. */
pascal@23761 701 static int cloop_thread(void *data)
pascal@23761 702 {
pascal@23761 703 struct cloop_device *clo = data;
pascal@23761 704 current->flags |= PF_NOFREEZE;
pascal@23761 705 - set_user_nice(current, -15);
pascal@23761 706 + set_user_nice(current, 10);
pascal@23761 707 while (!kthread_should_stop()||!list_empty(&clo->clo_list))
pascal@23761 708 {
pascal@23761 709 int err;
pascal@23761 710 @@ -390,10 +496,18 @@
pascal@23761 711 int rw;
pascal@23761 712 /* quick sanity checks */
pascal@23761 713 /* blk_fs_request() was removed in 2.6.36 */
pascal@23761 714 - if (unlikely(req == NULL || (req->cmd_type != REQ_TYPE_FS)))
pascal@23761 715 + if (unlikely(req == NULL
pascal@23761 716 +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) /* field removed */
pascal@23761 717 + || (req->cmd_type != REQ_TYPE_FS)
pascal@23761 718 +#endif
pascal@23761 719 + ))
pascal@23761 720 goto error_continue;
pascal@23761 721 rw = rq_data_dir(req);
pascal@23761 722 - if (unlikely(rw != READ && rw != READA))
pascal@23761 723 + if (unlikely(rw != READ
pascal@23761 724 +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 8, 0)
pascal@23761 725 + && rw != READA
pascal@23761 726 +#endif
pascal@23761 727 + ))
pascal@23761 728 {
pascal@23761 729 DEBUGP("cloop_do_request: bad command\n");
pascal@23761 730 goto error_continue;
pascal@23761 731 @@ -409,40 +523,51 @@
pascal@23761 732 continue; /* next request */
pascal@23761 733 error_continue:
pascal@23761 734 DEBUGP(KERN_ERR "cloop_do_request: Discarding request %p.\n", req);
pascal@23761 735 +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
pascal@23761 736 req->errors++;
pascal@23761 737 +#else
pascal@23761 738 + req->error_count++;
pascal@23761 739 +#endif
pascal@23761 740 __blk_end_request_all(req, -EIO);
pascal@17214 741 }
pascal@23761 742 }
pascal@23761 743
pascal@23761 744 -/* Read header and offsets from already opened file */
pascal@23761 745 -static int cloop_set_file(int cloop_num, struct file *file, char *filename)
pascal@23761 746 +/* Read header, flags and offsets from already opened file */
pascal@23761 747 +static int cloop_set_file(int cloop_num, struct file *file)
pascal@23761 748 {
pascal@23761 749 struct cloop_device *clo = cloop_dev[cloop_num];
pascal@23761 750 struct inode *inode;
pascal@23761 751 char *bbuf=NULL;
pascal@23761 752 - unsigned int i, offsets_read, total_offsets;
pascal@23761 753 - int isblkdev;
pascal@23761 754 - int error = 0;
pascal@23761 755 + unsigned int bbuf_size = 0;
pascal@23761 756 + const unsigned int header_size = sizeof(struct cloop_head);
pascal@23761 757 + unsigned int i, total_offsets=0;
pascal@23761 758 + loff_t fs_read_position = 0, header_pos[2];
pascal@23761 759 + int flags, isblkdev, bytes_read, error = 0;
pascal@23761 760 + if (clo->suspended) return error;
pascal@23761 761 + #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
pascal@23761 762 inode = file->f_dentry->d_inode;
pascal@23761 763 + clo->underlying_filename = kstrdup(file->f_dentry->d_name.name ? file->f_dentry->d_name.name : (const unsigned char *)"anonymous filename", GFP_KERNEL);
pascal@23761 764 + #else
pascal@23761 765 + inode = file->f_path.dentry->d_inode;
pascal@23761 766 + 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);
pascal@23761 767 + #endif
pascal@23761 768 isblkdev=S_ISBLK(inode->i_mode)?1:0;
pascal@23761 769 if(!isblkdev&&!S_ISREG(inode->i_mode))
pascal@23761 770 {
pascal@23761 771 printk(KERN_ERR "%s: %s not a regular file or block device\n",
pascal@23761 772 - cloop_name, filename);
pascal@23761 773 + cloop_name, clo->underlying_filename);
pascal@23761 774 error=-EBADF; goto error_release;
pascal@23761 775 }
pascal@23761 776 clo->backing_file = file;
pascal@23761 777 clo->backing_inode= inode ;
pascal@23761 778 - if(!isblkdev&&inode->i_size<sizeof(struct cloop_head))
pascal@23761 779 + clo->underlying_total_size = (isblkdev) ? inode->i_bdev->bd_inode->i_size : inode->i_size;
pascal@23761 780 + if(clo->underlying_total_size < header_size)
pascal@23761 781 {
pascal@23761 782 - printk(KERN_ERR "%s: %lu bytes (must be >= %u bytes)\n",
pascal@23761 783 - cloop_name, (unsigned long)inode->i_size,
pascal@23761 784 - (unsigned)sizeof(struct cloop_head));
pascal@23761 785 + printk(KERN_ERR "%s: %llu bytes (must be >= %u bytes)\n",
pascal@23761 786 + cloop_name, clo->underlying_total_size,
pascal@23761 787 + (unsigned int)header_size);
pascal@23761 788 error=-EBADF; goto error_release;
pascal@23761 789 }
pascal@23761 790 - /* In suspended mode, we have done all checks necessary - FF */
pascal@23761 791 - if (clo->suspended)
pascal@23761 792 - return error;
pascal@23761 793 if(isblkdev)
pascal@23761 794 {
pascal@23761 795 struct request_queue *q = bdev_get_queue(inode->i_bdev);
pascal@23761 796 @@ -451,104 +576,225 @@
pascal@23761 797 /* blk_queue_max_hw_segments(clo->clo_queue, queue_max_hw_segments(q)); */ /* Removed in 2.6.34 */
pascal@23761 798 blk_queue_max_segment_size(clo->clo_queue, queue_max_segment_size(q));
pascal@23761 799 blk_queue_segment_boundary(clo->clo_queue, queue_segment_boundary(q));
pascal@23761 800 +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0)
pascal@23761 801 blk_queue_merge_bvec(clo->clo_queue, q->merge_bvec_fn);
pascal@23761 802 +#endif
pascal@23761 803 clo->underlying_blksize = block_size(inode->i_bdev);
pascal@23761 804 }
pascal@23761 805 else
pascal@23761 806 clo->underlying_blksize = PAGE_SIZE;
pascal@23761 807 - DEBUGP("Underlying blocksize is %u\n", clo->underlying_blksize);
pascal@23761 808 - bbuf = cloop_malloc(clo->underlying_blksize);
pascal@23761 809 +
pascal@23761 810 + DEBUGP(KERN_INFO "Underlying blocksize of %s is %u\n", clo->underlying_filename, clo->underlying_blksize);
pascal@23761 811 + DEBUGP(KERN_INFO "Underlying total size of %s is %llu\n", clo->underlying_filename, clo->underlying_total_size);
pascal@23761 812 +
pascal@23761 813 + /* clo->underlying_blksize should be larger than header_size, even if it's only PAGE_SIZE */
pascal@23761 814 + bbuf_size = clo->underlying_blksize;
pascal@23761 815 + bbuf = cloop_malloc(bbuf_size);
pascal@23761 816 if(!bbuf)
pascal@23761 817 {
pascal@23761 818 - printk(KERN_ERR "%s: out of kernel mem for block buffer (%lu bytes)\n",
pascal@23761 819 - cloop_name, (unsigned long)clo->underlying_blksize);
pascal@23761 820 + printk(KERN_ERR "%s: out of kernel mem for buffer (%u bytes)\n",
pascal@23761 821 + cloop_name, (unsigned int) bbuf_size);
pascal@23761 822 + error=-ENOMEM; goto error_release;
pascal@23761 823 + }
pascal@23761 824 +
pascal@23761 825 + header_pos[0] = 0; /* header first */
pascal@23761 826 + header_pos[1] = clo->underlying_total_size - sizeof(struct cloop_head); /* header last */
pascal@23761 827 + for(i=0; i<2; i++)
pascal@23761 828 + {
pascal@23761 829 + /* Check for header */
pascal@23761 830 + size_t bytes_readable = MIN(clo->underlying_blksize, clo->underlying_total_size - header_pos[i]);
pascal@23761 831 + size_t bytes_read = cloop_read_from_file(clo, file, bbuf, header_pos[i], bytes_readable);
pascal@23761 832 + if(bytes_read != bytes_readable)
pascal@23761 833 + {
pascal@23761 834 + printk(KERN_ERR "%s: Bad file %s, read() of %s %u bytes returned %d.\n",
pascal@23761 835 + cloop_name, clo->underlying_filename, (i==0)?"first":"last",
pascal@23761 836 + (unsigned int)header_size, (int)bytes_read);
pascal@23761 837 + error=-EBADF;
pascal@23761 838 + goto error_release;
pascal@23761 839 + }
pascal@23761 840 + memcpy(&clo->head, bbuf, header_size);
pascal@23761 841 + if (strncmp(bbuf+CLOOP_SIGNATURE_OFFSET, CLOOP_SIGNATURE, CLOOP_SIGNATURE_SIZE)==0)
pascal@23761 842 + {
pascal@23761 843 + clo->file_format++;
pascal@23761 844 + clo->head.block_size=ntohl(clo->head.block_size);
pascal@23761 845 + clo->head.num_blocks=ntohl(clo->head.num_blocks);
pascal@23761 846 + clo->header_first = (i==0) ? 1 : 0;
pascal@23761 847 + 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");
pascal@23761 848 + break;
pascal@23761 849 + }
pascal@23761 850 + }
pascal@23761 851 + if (clo->file_format == 0)
pascal@23761 852 + {
pascal@23761 853 + printk(KERN_ERR "%s: Cannot detect %s format.\n",
pascal@23761 854 + cloop_name, cloop_name);
pascal@23761 855 + error=-EBADF; goto error_release;
pascal@23761 856 + }
pascal@23761 857 + if (clo->head.block_size % 512 != 0)
pascal@23761 858 + {
pascal@23761 859 + printk(KERN_ERR "%s: blocksize %u not multiple of 512\n",
pascal@23761 860 + cloop_name, clo->head.block_size);
pascal@23761 861 + error=-EBADF; goto error_release;
pascal@23761 862 + }
pascal@23761 863 + total_offsets=clo->head.num_blocks;
pascal@23761 864 + if (!isblkdev && (sizeof(struct cloop_head)+sizeof(struct block_info)*
pascal@23761 865 + total_offsets > inode->i_size))
pascal@23761 866 + {
pascal@23761 867 + printk(KERN_ERR "%s: file %s too small for %u blocks\n",
pascal@23761 868 + cloop_name, clo->underlying_filename, clo->head.num_blocks);
pascal@23761 869 + error=-EBADF; goto error_release;
pascal@23761 870 + }
pascal@23761 871 + /* Allocate Memory for decompressors */
pascal@23761 872 +#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE))
pascal@23761 873 + clo->zstream.workspace = cloop_malloc(zlib_inflate_workspacesize());
pascal@23761 874 + if(!clo->zstream.workspace)
pascal@23761 875 + {
pascal@23761 876 + printk(KERN_ERR "%s: out of mem for zlib working area %u\n",
pascal@23761 877 + cloop_name, zlib_inflate_workspacesize());
pascal@23761 878 error=-ENOMEM; goto error_release;
pascal@23761 879 }
pascal@23761 880 - total_offsets = 1; /* Dummy total_offsets: will be filled in first time around */
pascal@23761 881 - for (i = 0, offsets_read = 0; offsets_read < total_offsets; i++)
pascal@23761 882 + zlib_inflateInit(&clo->zstream);
pascal@23761 883 +#endif
pascal@23761 884 +#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE))
pascal@23761 885 +#if XZ_INTERNAL_CRC32
pascal@23761 886 + /* This must be called before any other xz_* function to initialize the CRC32 lookup table. */
pascal@23761 887 + xz_crc32_init(void);
pascal@23761 888 +#endif
pascal@23761 889 + clo->xzdecoderstate = xz_dec_init(XZ_SINGLE, 0);
pascal@23761 890 +#endif
pascal@23761 891 + if (total_offsets + 1 == 0) /* Version 3 */
pascal@23761 892 {
pascal@23761 893 - unsigned int offset = 0, num_readable;
pascal@23761 894 - size_t bytes_read = cloop_read_from_file(clo, file, bbuf,
pascal@23761 895 - i*clo->underlying_blksize,
pascal@23761 896 - clo->underlying_blksize);
pascal@23761 897 - if(bytes_read != clo->underlying_blksize)
pascal@23761 898 + struct cloop_tail tail;
pascal@23761 899 + if (isblkdev)
pascal@23761 900 {
pascal@23761 901 - printk(KERN_ERR "%s: Bad file, read() of first %lu bytes returned %d.\n",
pascal@23761 902 - cloop_name, (unsigned long)clo->underlying_blksize, (int)bytes_read);
pascal@23761 903 - error=-EBADF;
pascal@23761 904 - goto error_release;
pascal@23761 905 + /* No end of file: can't find index */
pascal@23761 906 + printk(KERN_ERR "%s: no V3 support for block device\n",
pascal@23761 907 + cloop_name);
pascal@23761 908 + error=-EBADF; goto error_release;
pascal@23761 909 }
pascal@23761 910 - /* Header will be in block zero */
pascal@23761 911 - if(i==0)
pascal@23761 912 + bytes_read = cloop_read_from_file(clo, file, (void *) &tail,
pascal@23761 913 + inode->i_size - sizeof(struct cloop_tail),
pascal@23761 914 + sizeof(struct cloop_tail));
pascal@23761 915 + if (bytes_read == sizeof(struct cloop_tail))
pascal@23761 916 {
pascal@23761 917 - memcpy(&clo->head, bbuf, sizeof(struct cloop_head));
pascal@23761 918 - offset = sizeof(struct cloop_head);
pascal@23761 919 - if (ntohl(clo->head.block_size) % 512 != 0)
pascal@23761 920 + unsigned long len, zlen;
pascal@23761 921 + int ret;
pascal@23761 922 + void *zbuf;
pascal@23761 923 + clo->head.num_blocks = ntohl(tail.num_blocks);
pascal@23761 924 + total_offsets = clo->head.num_blocks;
pascal@23761 925 + clo->block_ptrs = cloop_malloc(sizeof(struct block_info) * total_offsets);
pascal@23761 926 + zlen = ntohl(tail.table_size);
pascal@23761 927 + zbuf = cloop_malloc(zlen);
pascal@23761 928 + if (!clo->block_ptrs || !zbuf)
pascal@23761 929 {
pascal@23761 930 - printk(KERN_ERR "%s: blocksize %u not multiple of 512\n",
pascal@23761 931 - cloop_name, ntohl(clo->head.block_size));
pascal@23761 932 - error=-EBADF; goto error_release;
pascal@23761 933 - }
pascal@17214 934 - if (clo->head.preamble[0x0B]!='V'||clo->head.preamble[0x0C]<'1')
pascal@17214 935 - {
pascal@17214 936 - printk(KERN_ERR "%s: Cannot read old 32-bit (version 0.68) images, "
pascal@17214 937 - "please use an older version of %s for this file.\n",
pascal@17214 938 - cloop_name, cloop_name);
pascal@17214 939 - error=-EBADF; goto error_release;
pascal@23761 940 + printk(KERN_ERR "%s: out of kernel mem for index\n", cloop_name);
pascal@23761 941 + error=-ENOMEM; goto error_release;
pascal@23761 942 }
pascal@17214 943 - if (clo->head.preamble[0x0C]<'2')
pascal@23761 944 + bytes_read = cloop_read_from_file(clo, file, zbuf,
pascal@23761 945 + inode->i_size - zlen - sizeof(struct cloop_tail),
pascal@23761 946 + zlen);
pascal@23761 947 + if (bytes_read != zlen)
pascal@23761 948 {
pascal@17214 949 - printk(KERN_ERR "%s: Cannot read old architecture-dependent "
pascal@17214 950 - "(format <= 1.0) images, please use an older "
pascal@17214 951 - "version of %s for this file.\n",
pascal@17214 952 - cloop_name, cloop_name);
pascal@23761 953 + printk(KERN_ERR "%s: can't read index\n", cloop_name);
pascal@23761 954 error=-EBADF; goto error_release;
pascal@23761 955 }
pascal@17214 956 - total_offsets=ntohl(clo->head.num_blocks)+1;
pascal@17214 957 - if (!isblkdev && (sizeof(struct cloop_head)+sizeof(loff_t)*
pascal@23761 958 - total_offsets > inode->i_size))
pascal@23761 959 + len = CLOOP3_INDEX_SIZE(ntohl(tail.index_size)) * total_offsets;
pascal@23761 960 + flags = CLOOP3_BLOCKS_FLAGS(ntohl(tail.index_size));
pascal@23761 961 +// 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)
pascal@23761 962 +printk(KERN_INFO "%s: uncompress(clo=%p, block_ptrs=%p, &len(%ld)=%p, zbuf=%p, zlen=%ld, flag=%d)\n", cloop_name,
pascal@23761 963 + clo, clo->block_ptrs, len, &len, zbuf, zlen, flags);
pascal@23761 964 + ret = uncompress(clo, (void *) clo->block_ptrs, &len, zbuf, zlen, flags);
pascal@23761 965 +// May 3 19:45:20 (none) user.alert kernel: BUG: unable to handle kernel NULL pointer dereference at (null)
pascal@23761 966 +printk(KERN_INFO "%s: uncompressed !\n", cloop_name);
pascal@23761 967 + cloop_free(zbuf, zlen);
pascal@23761 968 + if (ret != 0)
pascal@17214 969 {
pascal@23761 970 - printk(KERN_ERR "%s: file too small for %u blocks\n",
pascal@23761 971 - cloop_name, ntohl(clo->head.num_blocks));
pascal@23761 972 + printk(KERN_ERR "%s: decompression error %i uncompressing index, flags %u\n",
pascal@23761 973 + cloop_name, ret, flags);
pascal@17214 974 error=-EBADF; goto error_release;
pascal@17214 975 }
pascal@17214 976 - clo->offsets = cloop_malloc(sizeof(loff_t) * total_offsets);
pascal@23761 977 - if (!clo->offsets)
pascal@23761 978 - {
pascal@23761 979 - printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name);
pascal@23761 980 - error=-ENOMEM; goto error_release;
pascal@23761 981 - }
pascal@17214 982 }
pascal@23761 983 - num_readable = MIN(total_offsets - offsets_read,
pascal@23761 984 - (clo->underlying_blksize - offset)
pascal@17214 985 - / sizeof(loff_t));
pascal@17214 986 - memcpy(&clo->offsets[offsets_read], bbuf+offset, num_readable * sizeof(loff_t));
pascal@23761 987 - offsets_read += num_readable;
pascal@23761 988 - }
pascal@23761 989 - { /* Search for largest block rather than estimate. KK. */
pascal@23761 990 - int i;
pascal@17214 991 - for(i=0;i<total_offsets-1;i++)
pascal@23761 992 + else
pascal@23761 993 + {
pascal@23761 994 + printk(KERN_ERR "%s: can't find index\n", cloop_name);
pascal@23761 995 + error=-ENOMEM; goto error_release;
pascal@23761 996 + }
pascal@23761 997 + }
pascal@23761 998 + else
pascal@23761 999 + {
pascal@23761 1000 + unsigned int n, total_bytes;
pascal@23761 1001 + flags = 0;
pascal@23761 1002 + clo->block_ptrs = cloop_malloc(sizeof(struct block_info) * total_offsets);
pascal@23761 1003 + if (!clo->block_ptrs)
pascal@23761 1004 + {
pascal@23761 1005 + printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name);
pascal@23761 1006 + error=-ENOMEM; goto error_release;
pascal@23761 1007 + }
pascal@23761 1008 + /* Read them offsets! */
pascal@23761 1009 + if(clo->header_first)
pascal@23761 1010 + {
pascal@23761 1011 + total_bytes = total_offsets * sizeof(struct block_info);
pascal@23761 1012 + fs_read_position = sizeof(struct cloop_head);
pascal@23761 1013 + }
pascal@23761 1014 + else
pascal@17214 1015 {
pascal@17214 1016 - loff_t d=be64_to_cpu(clo->offsets[i+1]) - be64_to_cpu(clo->offsets[i]);
pascal@17214 1017 - clo->largest_block=MAX(clo->largest_block,d);
pascal@23761 1018 + total_bytes = total_offsets * sizeof(loff_t);
pascal@23761 1019 + fs_read_position = clo->underlying_total_size - sizeof(struct cloop_head) - total_bytes;
pascal@23761 1020 + }
pascal@23761 1021 + for(n=0;n<total_bytes;)
pascal@23761 1022 + {
pascal@23761 1023 + size_t bytes_readable;
pascal@23761 1024 + bytes_readable = MIN(bbuf_size, clo->underlying_total_size - fs_read_position);
pascal@23761 1025 + if(bytes_readable <= 0) break; /* Done */
pascal@23761 1026 + bytes_read = cloop_read_from_file(clo, file, bbuf, fs_read_position, bytes_readable);
pascal@23761 1027 + if(bytes_read != bytes_readable)
pascal@23761 1028 + {
pascal@23761 1029 + printk(KERN_ERR "%s: Bad file %s, read() %lu bytes @ %llu returned %d.\n",
pascal@23761 1030 + cloop_name, clo->underlying_filename, (unsigned long)clo->underlying_blksize, fs_read_position, (int)bytes_read);
pascal@23761 1031 + error=-EBADF;
pascal@23761 1032 + goto error_release;
pascal@23761 1033 + }
pascal@23761 1034 + memcpy(((char *)clo->block_ptrs) + n, bbuf, bytes_read);
pascal@23761 1035 + /* remember where to read the next blk from file */
pascal@23761 1036 + fs_read_position += bytes_read;
pascal@23761 1037 + n += bytes_read;
pascal@17214 1038 }
pascal@17214 1039 - printk(KERN_INFO "%s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n",
pascal@17214 1040 - cloop_name, filename, ntohl(clo->head.num_blocks),
pascal@23761 1041 - ntohl(clo->head.block_size), clo->largest_block);
pascal@17214 1042 }
pascal@23761 1043 -/* Combo kmalloc used too large chunks (>130000). */
pascal@23761 1044 {
pascal@23761 1045 int i;
pascal@23761 1046 - for(i=0;i<BUFFERED_BLOCKS;i++)
pascal@23761 1047 - {
pascal@23761 1048 - clo->buffer[i] = cloop_malloc(ntohl(clo->head.block_size));
pascal@23761 1049 - if(!clo->buffer[i])
pascal@23761 1050 - {
pascal@23761 1051 - printk(KERN_ERR "%s: out of memory for buffer %lu\n",
pascal@23761 1052 - cloop_name, (unsigned long) ntohl(clo->head.block_size));
pascal@23761 1053 - error=-ENOMEM; goto error_release_free;
pascal@23761 1054 - }
pascal@23761 1055 - }
pascal@23761 1056 + char *version = build_index(clo->block_ptrs, clo->head.num_blocks, clo->head.block_size, flags);
pascal@23761 1057 + clo->largest_block = 0;
pascal@23761 1058 + for (i = 0; i < clo->head.num_blocks; i++)
pascal@23761 1059 + if (clo->block_ptrs[i].size > clo->largest_block)
pascal@23761 1060 + clo->largest_block = clo->block_ptrs[i].size;
pascal@23761 1061 + printk(KERN_INFO "%s: %s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n",
pascal@23761 1062 + cloop_name, clo->underlying_filename, version, clo->head.num_blocks,
pascal@23761 1063 + clo->head.block_size, clo->largest_block);
pascal@23761 1064 + }
pascal@23761 1065 + {
pascal@23761 1066 + int i;
pascal@23761 1067 + clo->num_buffered_blocks = (buffers > 0 && clo->head.block_size >= 512) ?
pascal@23761 1068 + (buffers / clo->head.block_size) : 1;
pascal@23761 1069 + clo->buffered_blocknum = cloop_malloc(clo->num_buffered_blocks * sizeof (u_int32_t));
pascal@23761 1070 + clo->buffer = cloop_malloc(clo->num_buffered_blocks * sizeof (char*));
pascal@23761 1071 + if (!clo->buffered_blocknum || !clo->buffer)
pascal@23761 1072 + {
pascal@23761 1073 + printk(KERN_ERR "%s: out of memory for index of cache buffer (%lu bytes)\n",
pascal@23761 1074 + cloop_name, (unsigned long)clo->num_buffered_blocks * sizeof (u_int32_t) + sizeof(char*) );
pascal@23761 1075 + error=-ENOMEM; goto error_release;
pascal@23761 1076 + }
pascal@23761 1077 + memset(clo->buffer, 0, clo->num_buffered_blocks * sizeof (char*));
pascal@23761 1078 + for(i=0;i<clo->num_buffered_blocks;i++)
pascal@23761 1079 + {
pascal@23761 1080 + clo->buffered_blocknum[i] = -1;
pascal@23761 1081 + clo->buffer[i] = cloop_malloc(clo->head.block_size);
pascal@23761 1082 + if(!clo->buffer[i])
pascal@23761 1083 + {
pascal@23761 1084 + printk(KERN_ERR "%s: out of memory for cache buffer %lu\n",
pascal@23761 1085 + cloop_name, (unsigned long) clo->head.block_size);
pascal@23761 1086 + error=-ENOMEM; goto error_release_free;
pascal@23761 1087 + }
pascal@23761 1088 + }
pascal@23761 1089 + clo->current_bufnum = 0;
pascal@23761 1090 }
pascal@23761 1091 clo->compressed_buffer = cloop_malloc(clo->largest_block);
pascal@23761 1092 if(!clo->compressed_buffer)
pascal@23761 1093 @@ -557,31 +803,7 @@
pascal@23761 1094 cloop_name, clo->largest_block);
pascal@23761 1095 error=-ENOMEM; goto error_release_free_buffer;
pascal@17214 1096 }
pascal@23761 1097 - clo->zstream.workspace = cloop_malloc(zlib_inflate_workspacesize());
pascal@23761 1098 - if(!clo->zstream.workspace)
pascal@23761 1099 - {
pascal@23761 1100 - printk(KERN_ERR "%s: out of mem for zlib working area %u\n",
pascal@23761 1101 - cloop_name, zlib_inflate_workspacesize());
pascal@23761 1102 - error=-ENOMEM; goto error_release_free_all;
pascal@23761 1103 - }
pascal@23761 1104 - zlib_inflateInit(&clo->zstream);
pascal@17214 1105 - if(!isblkdev &&
pascal@17214 1106 - be64_to_cpu(clo->offsets[ntohl(clo->head.num_blocks)]) != inode->i_size)
pascal@17214 1107 - {
pascal@17214 1108 - printk(KERN_ERR "%s: final offset wrong (%Lu not %Lu)\n",
pascal@17214 1109 - cloop_name,
pascal@17214 1110 - be64_to_cpu(clo->offsets[ntohl(clo->head.num_blocks)]),
pascal@17214 1111 - inode->i_size);
pascal@17214 1112 - cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); clo->zstream.workspace=NULL;
pascal@17214 1113 - goto error_release_free_all;
pascal@17214 1114 - }
pascal@23761 1115 - {
pascal@23761 1116 - int i;
pascal@23761 1117 - for(i=0; i<BUFFERED_BLOCKS; i++) clo->buffered_blocknum[i] = -1;
pascal@23761 1118 - clo->current_bufnum=0;
pascal@23761 1119 - }
pascal@23761 1120 - set_capacity(clo->clo_disk, (sector_t)(ntohl(clo->head.num_blocks)*
pascal@23761 1121 - (ntohl(clo->head.block_size)>>9)));
pascal@23761 1122 + set_capacity(clo->clo_disk, (sector_t)(clo->head.num_blocks*(clo->head.block_size>>9)));
pascal@23761 1123 clo->clo_thread = kthread_create(cloop_thread, clo, "cloop%d", cloop_num);
pascal@23761 1124 if(IS_ERR(clo->clo_thread))
pascal@23761 1125 {
pascal@23761 1126 @@ -591,17 +813,17 @@
pascal@23761 1127 }
pascal@23761 1128 if(preload > 0)
pascal@23761 1129 {
pascal@23761 1130 - clo->preload_array_size = ((preload<=ntohl(clo->head.num_blocks))?preload:ntohl(clo->head.num_blocks));
pascal@23761 1131 + clo->preload_array_size = ((preload<=clo->head.num_blocks)?preload:clo->head.num_blocks);
pascal@23761 1132 clo->preload_size = 0;
pascal@23761 1133 if((clo->preload_cache = cloop_malloc(clo->preload_array_size * sizeof(char *))) != NULL)
pascal@23761 1134 {
pascal@23761 1135 int i;
pascal@23761 1136 for(i=0; i<clo->preload_array_size; i++)
pascal@23761 1137 {
pascal@23761 1138 - if((clo->preload_cache[i] = cloop_malloc(ntohl(clo->head.block_size))) == NULL)
pascal@23761 1139 + if((clo->preload_cache[i] = cloop_malloc(clo->head.block_size)) == NULL)
pascal@23761 1140 { /* Out of memory */
pascal@23761 1141 printk(KERN_WARNING "%s: cloop_malloc(%d) failed for preload_cache[%d] (ignored).\n",
pascal@23761 1142 - cloop_name, ntohl(clo->head.block_size), i);
pascal@23761 1143 + cloop_name, clo->head.block_size, i);
pascal@23761 1144 break;
pascal@23761 1145 }
pascal@23761 1146 }
pascal@23761 1147 @@ -612,13 +834,13 @@
pascal@23761 1148 if(buffered_blocknum >= 0)
pascal@23761 1149 {
pascal@23761 1150 memcpy(clo->preload_cache[i], clo->buffer[buffered_blocknum],
pascal@23761 1151 - ntohl(clo->head.block_size));
pascal@23761 1152 + clo->head.block_size);
pascal@23761 1153 }
pascal@23761 1154 else
pascal@23761 1155 {
pascal@23761 1156 printk(KERN_WARNING "%s: can't read block %d into preload cache, set to zero.\n",
pascal@23761 1157 cloop_name, i);
pascal@23761 1158 - memset(clo->preload_cache[i], 0, ntohl(clo->head.block_size));
pascal@23761 1159 + memset(clo->preload_cache[i], 0, clo->head.block_size);
pascal@23761 1160 }
pascal@23761 1161 }
pascal@23761 1162 printk(KERN_INFO "%s: preloaded %d blocks into cache.\n", cloop_name,
pascal@23761 1163 @@ -641,22 +863,19 @@
pascal@23761 1164 cloop_free(clo->compressed_buffer, clo->largest_block);
pascal@23761 1165 clo->compressed_buffer=NULL;
pascal@23761 1166 error_release_free_buffer:
pascal@23761 1167 + if(clo->buffer)
pascal@17214 1168 {
pascal@17214 1169 int i;
pascal@23761 1170 - for(i=0; i<BUFFERED_BLOCKS; i++)
pascal@23761 1171 - {
pascal@23761 1172 - if(clo->buffer[i])
pascal@23761 1173 - {
pascal@23761 1174 - cloop_free(clo->buffer[i], ntohl(clo->head.block_size));
pascal@23761 1175 - clo->buffer[i]=NULL;
pascal@23761 1176 - }
pascal@23761 1177 - }
pascal@23761 1178 + 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; }}
pascal@23761 1179 + cloop_free(clo->buffer, clo->num_buffered_blocks*sizeof(char*)); clo->buffer=NULL;
pascal@17214 1180 }
pascal@23761 1181 + if (clo->buffered_blocknum) { cloop_free(clo->buffered_blocknum, sizeof(int)*clo->num_buffered_blocks); clo->buffered_blocknum=NULL; }
pascal@17214 1182 error_release_free:
pascal@17214 1183 - cloop_free(clo->offsets, sizeof(loff_t) * total_offsets);
pascal@23761 1184 - clo->offsets=NULL;
pascal@23761 1185 + cloop_free(clo->block_ptrs, sizeof(struct block_info) * total_offsets);
pascal@23761 1186 + clo->block_ptrs=NULL;
pascal@17214 1187 error_release:
pascal@17214 1188 if(bbuf) cloop_free(bbuf, clo->underlying_blksize);
pascal@23761 1189 + if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; }
pascal@23761 1190 clo->backing_file=NULL;
pascal@23761 1191 return error;
pascal@23761 1192 }
pascal@23761 1193 @@ -673,7 +892,7 @@
pascal@23761 1194 if(clo->backing_file) return -EBUSY;
pascal@23761 1195 file = fget(arg); /* get filp struct from ioctl arg fd */
pascal@23761 1196 if(!file) return -EBADF;
pascal@23761 1197 - error=cloop_set_file(cloop_num,file,"losetup_file");
pascal@23761 1198 + error=cloop_set_file(cloop_num,file);
pascal@23761 1199 set_device_ro(bdev, 1);
pascal@23761 1200 if(error) fput(file);
pascal@23761 1201 return error;
pascal@23761 1202 @@ -684,29 +903,48 @@
pascal@23761 1203 {
pascal@23761 1204 struct cloop_device *clo = cloop_dev[cloop_num];
pascal@23761 1205 struct file *filp = clo->backing_file;
pascal@23761 1206 - int i;
pascal@23761 1207 if(clo->refcnt > 1) /* we needed one fd for the ioctl */
pascal@23761 1208 return -EBUSY;
pascal@23761 1209 if(filp==NULL) return -EINVAL;
pascal@23761 1210 if(clo->clo_thread) { kthread_stop(clo->clo_thread); clo->clo_thread=NULL; }
pascal@23761 1211 - if(filp!=initial_file) fput(filp);
pascal@23761 1212 - else { filp_close(initial_file,0); initial_file=NULL; }
pascal@23761 1213 + if(filp!=initial_file)
pascal@23761 1214 + fput(filp);
pascal@23761 1215 + else
pascal@23761 1216 + {
pascal@23761 1217 + filp_close(initial_file,0);
pascal@23761 1218 + initial_file=NULL;
pascal@23761 1219 + }
pascal@23761 1220 clo->backing_file = NULL;
pascal@23761 1221 clo->backing_inode = NULL;
pascal@23761 1222 - if(clo->offsets) { cloop_free(clo->offsets, clo->underlying_blksize); clo->offsets = NULL; }
pascal@23761 1223 + if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; }
pascal@23761 1224 + if(clo->block_ptrs) { cloop_free(clo->block_ptrs, clo->head.num_blocks); clo->block_ptrs = NULL; }
pascal@23761 1225 if(clo->preload_cache)
pascal@23761 1226 - {
pascal@23761 1227 - for(i=0; i < clo->preload_size; i++)
pascal@23761 1228 - cloop_free(clo->preload_cache[i], ntohl(clo->head.block_size));
pascal@23761 1229 - cloop_free(clo->preload_cache, clo->preload_array_size * sizeof(char *));
pascal@23761 1230 - clo->preload_cache = NULL;
pascal@23761 1231 - clo->preload_size = clo->preload_array_size = 0;
pascal@23761 1232 - }
pascal@23761 1233 - for(i=0; i<BUFFERED_BLOCKS; i++)
pascal@23761 1234 - if(clo->buffer[i]) { cloop_free(clo->buffer[i], ntohl(clo->head.block_size)); clo->buffer[i]=NULL; }
pascal@23761 1235 + {
pascal@23761 1236 + int i;
pascal@23761 1237 + for(i=0; i < clo->preload_size; i++)
pascal@23761 1238 + cloop_free(clo->preload_cache[i], clo->head.block_size);
pascal@23761 1239 + cloop_free(clo->preload_cache, clo->preload_array_size * sizeof(char *));
pascal@23761 1240 + clo->preload_cache = NULL;
pascal@23761 1241 + clo->preload_size = clo->preload_array_size = 0;
pascal@23761 1242 + }
pascal@23761 1243 + if (clo->buffered_blocknum)
pascal@23761 1244 + {
pascal@23761 1245 + cloop_free(clo->buffered_blocknum, sizeof(int) * clo->num_buffered_blocks); clo->buffered_blocknum = NULL;
pascal@23761 1246 + }
pascal@23761 1247 + if (clo->buffer)
pascal@23761 1248 + {
pascal@23761 1249 + int i;
pascal@23761 1250 + for(i=0; i<clo->num_buffered_blocks; i++) { if(clo->buffer[i]) cloop_free(clo->buffer[i], clo->head.block_size); }
pascal@23761 1251 + cloop_free(clo->buffer, sizeof(char*) * clo->num_buffered_blocks); clo->buffer = NULL;
pascal@23761 1252 + }
pascal@23761 1253 if(clo->compressed_buffer) { cloop_free(clo->compressed_buffer, clo->largest_block); clo->compressed_buffer = NULL; }
pascal@23761 1254 +#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE))
pascal@23761 1255 zlib_inflateEnd(&clo->zstream);
pascal@23761 1256 if(clo->zstream.workspace) { cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); clo->zstream.workspace = NULL; }
pascal@23761 1257 +#endif
pascal@23761 1258 +#if (defined(CONFIG_DECOMPRESS_XZ) || defined(CONFIG_DECOMPRESS_XZ_MODULE))
pascal@23761 1259 + xz_dec_end(clo->xzdecoderstate);
pascal@23761 1260 +#endif
pascal@23761 1261 if(bdev) invalidate_bdev(bdev);
pascal@23761 1262 if(clo->clo_disk) set_capacity(clo->clo_disk, 0);
pascal@23761 1263 return 0;
pascal@23761 1264 @@ -731,8 +969,8 @@
pascal@23761 1265 const struct loop_info64 *info)
pascal@23761 1266 {
pascal@23761 1267 if (!clo->backing_file) return -ENXIO;
pascal@23761 1268 - memcpy(clo->clo_file_name, info->lo_file_name, LO_NAME_SIZE);
pascal@23761 1269 - clo->clo_file_name[LO_NAME_SIZE-1] = 0;
pascal@23761 1270 + if(clo->underlying_filename) kfree(clo->underlying_filename);
pascal@23761 1271 + clo->underlying_filename = kstrdup(info->lo_file_name, GFP_KERNEL);
pascal@23761 1272 return 0;
pascal@23761 1273 }
pascal@23761 1274
pascal@23761 1275 @@ -743,7 +981,11 @@
pascal@23761 1276 struct kstat stat;
pascal@23761 1277 int err;
pascal@23761 1278 if (!file) return -ENXIO;
pascal@23761 1279 - err = vfs_getattr(file->f_path.mnt, file->f_path.dentry, &stat);
pascal@23761 1280 +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
pascal@23761 1281 + err = vfs_getattr(&file->f_path, &stat);
pascal@23761 1282 +#else
pascal@23761 1283 + err = vfs_getattr(&file->f_path, &stat, STATX_INO, AT_STATX_SYNC_AS_STAT);
pascal@23761 1284 +#endif
pascal@23761 1285 if (err) return err;
pascal@23761 1286 memset(info, 0, sizeof(*info));
pascal@23761 1287 info->lo_number = clo->clo_number;
pascal@23761 1288 @@ -753,7 +995,8 @@
pascal@23761 1289 info->lo_offset = 0;
pascal@23761 1290 info->lo_sizelimit = 0;
pascal@23761 1291 info->lo_flags = 0;
pascal@23761 1292 - memcpy(info->lo_file_name, clo->clo_file_name, LO_NAME_SIZE);
pascal@23761 1293 + strncpy(info->lo_file_name, clo->underlying_filename, LO_NAME_SIZE);
pascal@23761 1294 + info->lo_file_name[LO_NAME_SIZE-1]=0;
pascal@23761 1295 return 0;
pascal@23761 1296 }
pascal@23761 1297
pascal@23761 1298 @@ -833,8 +1076,6 @@
pascal@23761 1299 if (!err && copy_to_user(arg, &info64, sizeof(info64))) err = -EFAULT;
pascal@23761 1300 return err;
pascal@23761 1301 }
pascal@23761 1302 -/* EOF get/set_status */
pascal@23761 1303 -
pascal@23761 1304
pascal@23761 1305 static int cloop_ioctl(struct block_device *bdev, fmode_t mode,
pascal@23761 1306 unsigned int cmd, unsigned long arg)
pascal@23761 1307 @@ -914,21 +1155,20 @@
pascal@23761 1308 /* losetup uses write-open and flags=0x8002 to set a new file */
pascal@23761 1309 if(mode & FMODE_WRITE)
pascal@23761 1310 {
pascal@23761 1311 - printk(KERN_WARNING "%s: Can't open device read-write in mode 0x%x\n", cloop_name, mode);
pascal@23761 1312 + printk(KERN_INFO "%s: Open in read-write mode 0x%x requested, ignored.\n", cloop_name, mode);
pascal@23761 1313 return -EROFS;
pascal@23761 1314 }
pascal@23761 1315 cloop_dev[cloop_num]->refcnt+=1;
pascal@23761 1316 return 0;
pascal@23761 1317 }
pascal@23761 1318
pascal@23761 1319 -static int cloop_close(struct gendisk *disk, fmode_t mode)
pascal@23761 1320 +static void cloop_close(struct gendisk *disk, fmode_t mode)
pascal@23761 1321 {
pascal@23761 1322 - int cloop_num, err=0;
pascal@23761 1323 - if(!disk) return 0;
pascal@23761 1324 + int cloop_num;
pascal@23761 1325 + if(!disk) return;
pascal@23761 1326 cloop_num=((struct cloop_device *)disk->private_data)->clo_number;
pascal@23761 1327 - if(cloop_num < 0 || cloop_num > (cloop_count-1)) return 0;
pascal@23761 1328 + if(cloop_num < 0 || cloop_num > (cloop_count-1)) return;
pascal@23761 1329 cloop_dev[cloop_num]->refcnt-=1;
pascal@23761 1330 - return err;
pascal@23761 1331 }
pascal@23761 1332
pascal@23761 1333 static struct block_device_operations clo_fops =
pascal@23761 1334 @@ -973,6 +1213,10 @@
pascal@23761 1335 goto error_out;
pascal@23761 1336 }
pascal@23761 1337 clo->clo_queue->queuedata = clo;
pascal@23761 1338 +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
pascal@23761 1339 + queue_flag_set_unlocked(QUEUE_FLAG_NONROT, clo->clo_queue);
pascal@23761 1340 + queue_flag_set_unlocked(QUEUE_FLAG_NOMERGES, clo->clo_queue);
pascal@23761 1341 +#endif
pascal@23761 1342 clo->clo_disk = alloc_disk(1);
pascal@23761 1343 if(!clo->clo_disk)
pascal@23761 1344 {
pascal@23761 1345 @@ -1004,6 +1248,11 @@
pascal@23761 1346 cloop_dev[cloop_num] = NULL;
pascal@23761 1347 }
pascal@23761 1348
pascal@23761 1349 +/* LZ4 Stuff */
pascal@23761 1350 +#if (defined USE_LZ4_INTERNAL)
pascal@23761 1351 +#include "lz4_kmod.c"
pascal@23761 1352 +#endif
pascal@23761 1353 +
pascal@23761 1354 static int __init cloop_init(void)
pascal@23761 1355 {
pascal@23761 1356 int error=0;
pascal@23761 1357 @@ -1044,7 +1293,7 @@
pascal@23761 1358 initial_file=NULL; /* if IS_ERR, it's NOT open. */
pascal@23761 1359 }
pascal@23761 1360 else
pascal@23761 1361 - error=cloop_set_file(0,initial_file,file);
pascal@23761 1362 + error=cloop_set_file(0,initial_file);
pascal@23761 1363 if(error)
pascal@23761 1364 {
pascal@23761 1365 printk(KERN_ERR
pascal@23761 1366 @@ -1052,9 +1301,6 @@
pascal@23761 1367 cloop_name, file, error);
pascal@23761 1368 goto init_out_dealloc;
pascal@23761 1369 }
pascal@23761 1370 - if(namelen >= LO_NAME_SIZE) namelen = LO_NAME_SIZE-1;
pascal@23761 1371 - memcpy(cloop_dev[0]->clo_file_name, file, namelen);
pascal@23761 1372 - cloop_dev[0]->clo_file_name[namelen] = 0;
pascal@23761 1373 }
pascal@23761 1374 return 0;
pascal@23761 1375 init_out_dealloc:
pascal@23762 1376 --- cloop.h
pascal@23762 1377 +++ cloop.h
pascal@23762 1378 @@ -86,11 +86,8 @@
pascal@23762 1379 struct cloop_tail
pascal@23762 1380 {
pascal@23762 1381 u_int32_t table_size;
pascal@23762 1382 - u_int32_t index_size; /* size:4 comp:3 ctrl-c:1 lastlen:24 */
pascal@23762 1383 + u_int32_t index_size; /* size:4 unused:3 ctrl-c:1 lastlen:24 */
pascal@23762 1384 #define CLOOP3_INDEX_SIZE(x) ((unsigned int)((x) & 0xF))
pascal@23762 1385 -#define CLOOP3_BLOCKS_FLAGS(x) ((unsigned int)((x) & 0x70) >> 4)
pascal@23762 1386 -#define CLOOP3_TRUNCATED(x) ((unsigned int)((x) & 0x80) >> 7)
pascal@23762 1387 -#define CLOOP3_LASTLEN(x) (unsigned int)((x) >> 8)
pascal@23762 1388 u_int32_t num_blocks;
pascal@23762 1389 };
pascal@23762 1390
pascal@23762 1391 @@ -104,8 +101,10 @@
pascal@23762 1392 };
pascal@23762 1393
pascal@23762 1394 static inline char *build_index(struct block_info *offsets, unsigned long n,
pascal@23762 1395 - unsigned long block_size, unsigned global_flags)
pascal@23762 1396 + unsigned long block_size)
pascal@23762 1397 {
pascal@23762 1398 + static char v[11];
pascal@23762 1399 + u_int32_t flags = 0;
pascal@23762 1400 u_int32_t *ofs32 = (u_int32_t *) offsets;
pascal@23762 1401 loff_t *ofs64 = (loff_t *) offsets;
pascal@23762 1402
pascal@23762 1403 @@ -130,8 +129,6 @@
pascal@23762 1404 }
pascal@23762 1405 else { /* V2.0/V4.0 */
pascal@23762 1406 loff_t last = CLOOP_BLOCK_OFFSET(__be64_to_cpu(ofs64[n]));
pascal@23762 1407 - u_int32_t flags;
pascal@23762 1408 - static char v4[11];
pascal@23762 1409 unsigned long i = n;
pascal@23762 1410
pascal@23762 1411 for (flags = 0; n-- ;) {
pascal@23762 1412 @@ -149,12 +146,7 @@
pascal@23762 1413 offsets[i] = offsets[offsets[i].offset];
pascal@23762 1414 }
pascal@23762 1415 }
pascal@23762 1416 - strcpy(v4, (char *) "64BE v4.0a");
pascal@23762 1417 - v4[10] = 'a' + ((flags-1) & 0xF); // compressors used
pascal@23762 1418 - if (flags > 0x10) { // with links ?
pascal@23762 1419 - v4[10] += 'A' - 'a';
pascal@23762 1420 - }
pascal@23762 1421 - return v4;
pascal@23762 1422 + strcpy(v, (char *) "64BE v4.0a");
pascal@23762 1423 }
pascal@23762 1424 }
pascal@23762 1425 else if (ofs32[1] == 0 && v3_64 == 0) { /* V1.0 */
pascal@23762 1426 @@ -170,7 +162,6 @@
pascal@23762 1427 else { /* V3.0 or V0.68 */
pascal@23762 1428 unsigned long i;
pascal@23762 1429 loff_t j;
pascal@23762 1430 - static char v3[11];
pascal@23762 1431
pascal@23762 1432 for (i = 0; i < n && ntohl(ofs32[i]) < ntohl(ofs32[i+1]); i++);
pascal@23762 1433 if (i == n && ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */
pascal@23762 1434 @@ -185,28 +176,33 @@
pascal@23762 1435 }
pascal@23762 1436
pascal@23762 1437 v3_64 = (ofs32[1] == 0);
pascal@23762 1438 - for (i = n; i-- != 0; )
pascal@23762 1439 + for (i = n; i-- != 0; ) {
pascal@23762 1440 offsets[i].size = ntohl(ofs32[i << v3_64]);
pascal@23762 1441 - for (i = 0, j = sizeof(struct cloop_head); i < n; i++) {
pascal@23762 1442 - offsets[i].offset = j;
pascal@23762 1443 - offsets[i].flags = global_flags;
pascal@23762 1444 if (offsets[i].size == 0xFFFFFFFF) {
pascal@23762 1445 - offsets[i].flags = CLOOP_COMPRESSOR_NONE;
pascal@23762 1446 - offsets[i].size = block_size;
pascal@23762 1447 + offsets[i].size = 0x10000000 | block_size;
pascal@23762 1448 }
pascal@23762 1449 - if ((offsets[i].size & 0x80000000) == 0) {
pascal@23762 1450 + offsets[i].flags = (offsets[i].size >> 28);
pascal@23762 1451 + offsets[i].size &= 0x0FFFFFFF;
pascal@23762 1452 + }
pascal@23762 1453 + for (i = 0, j = sizeof(struct cloop_head); i < n; i++) {
pascal@23762 1454 + offsets[i].offset = j;
pascal@23762 1455 + if (offsets[i].flags < 8) {
pascal@23762 1456 j += offsets[i].size;
pascal@23762 1457 }
pascal@23762 1458 }
pascal@23762 1459 for (i = 0; i < n; i++) {
pascal@23762 1460 - if (offsets[i].size & 0x80000000) {
pascal@23762 1461 - offsets[i] = offsets[offsets[i].size & 0x7FFFFFFF];
pascal@23762 1462 + flags |= 1 << offsets[i].flags;
pascal@23762 1463 + if (offsets[i].flags >= 8) {
pascal@23762 1464 + offsets[i] = offsets[offsets[i].size];
pascal@23762 1465 }
pascal@23762 1466 }
pascal@23762 1467 - strcpy(v3, (char *) (v3_64) ? "64BE v3.0a" : "32BE v3.0a");
pascal@23762 1468 - v3[10] += global_flags;
pascal@23762 1469 - return v3;
pascal@23762 1470 + strcpy(v, (char *) (v3_64) ? "64BE v3.0a" : "32BE v3.0a");
pascal@23762 1471 + }
pascal@23762 1472 + v[10] = 'a' + ((flags-1) & 0xF); // compressors used
pascal@23762 1473 + if (flags > 0x10) { // with links ?
pascal@23762 1474 + v[10] += 'A' - 'a';
pascal@23762 1475 }
pascal@23762 1476 + return v;
pascal@23762 1477 }
pascal@23762 1478
pascal@23762 1479 /* Cloop suspend IOCTL */
pascal@23762 1480 --- cloop.c
pascal@23762 1481 +++ cloop.c
pascal@23762 1482 @@ -542,7 +542,7 @@
pascal@23762 1483 const unsigned int header_size = sizeof(struct cloop_head);
pascal@23762 1484 unsigned int i, total_offsets=0;
pascal@23762 1485 loff_t fs_read_position = 0, header_pos[2];
pascal@23762 1486 - int flags, isblkdev, bytes_read, error = 0;
pascal@23762 1487 + int isblkdev, bytes_read, error = 0;
pascal@23762 1488 if (clo->suspended) return error;
pascal@23762 1489 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
pascal@23762 1490 inode = file->f_dentry->d_inode;
pascal@23762 1491 @@ -698,18 +698,12 @@
pascal@23762 1492 error=-EBADF; goto error_release;
pascal@23762 1493 }
pascal@23762 1494 len = CLOOP3_INDEX_SIZE(ntohl(tail.index_size)) * total_offsets;
pascal@23762 1495 - flags = CLOOP3_BLOCKS_FLAGS(ntohl(tail.index_size));
pascal@23762 1496 -// 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)
pascal@23762 1497 -printk(KERN_INFO "%s: uncompress(clo=%p, block_ptrs=%p, &len(%ld)=%p, zbuf=%p, zlen=%ld, flag=%d)\n", cloop_name,
pascal@23762 1498 - clo, clo->block_ptrs, len, &len, zbuf, zlen, flags);
pascal@23762 1499 - ret = uncompress(clo, (void *) clo->block_ptrs, &len, zbuf, zlen, flags);
pascal@23762 1500 -// May 3 19:45:20 (none) user.alert kernel: BUG: unable to handle kernel NULL pointer dereference at (null)
pascal@23762 1501 -printk(KERN_INFO "%s: uncompressed !\n", cloop_name);
pascal@23762 1502 + ret = uncompress(clo, (void *) clo->block_ptrs, &len, zbuf, zlen, CLOOP_COMPRESSOR_ZLIB);
pascal@23762 1503 cloop_free(zbuf, zlen);
pascal@23762 1504 if (ret != 0)
pascal@23762 1505 {
pascal@23762 1506 - printk(KERN_ERR "%s: decompression error %i uncompressing index, flags %u\n",
pascal@23762 1507 - cloop_name, ret, flags);
pascal@23762 1508 + printk(KERN_ERR "%s: decompression error %i uncompressing index\n",
pascal@23762 1509 + cloop_name, ret);
pascal@23762 1510 error=-EBADF; goto error_release;
pascal@23762 1511 }
pascal@23762 1512 }
pascal@23762 1513 @@ -722,7 +716,6 @@
pascal@23762 1514 else
pascal@23762 1515 {
pascal@23762 1516 unsigned int n, total_bytes;
pascal@23762 1517 - flags = 0;
pascal@23762 1518 clo->block_ptrs = cloop_malloc(sizeof(struct block_info) * total_offsets);
pascal@23762 1519 if (!clo->block_ptrs)
pascal@23762 1520 {
pascal@23762 1521 @@ -761,7 +754,7 @@
pascal@23762 1522 }
pascal@23762 1523 {
pascal@23762 1524 int i;
pascal@23762 1525 - char *version = build_index(clo->block_ptrs, clo->head.num_blocks, clo->head.block_size, flags);
pascal@23762 1526 + char *version = build_index(clo->block_ptrs, clo->head.num_blocks, clo->head.block_size);
pascal@23762 1527 clo->largest_block = 0;
pascal@23762 1528 for (i = 0; i < clo->head.num_blocks; i++)
pascal@23762 1529 if (clo->block_ptrs[i].size > clo->largest_block)
pascal@23762 1530 @@ -769,9 +762,6 @@
pascal@23762 1531 printk(KERN_INFO "%s: %s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n",
pascal@23762 1532 cloop_name, clo->underlying_filename, version, clo->head.num_blocks,
pascal@23762 1533 clo->head.block_size, clo->largest_block);
pascal@23762 1534 - }
pascal@23762 1535 - {
pascal@23762 1536 - int i;
pascal@23762 1537 clo->num_buffered_blocks = (buffers > 0 && clo->head.block_size >= 512) ?
pascal@23762 1538 (buffers / clo->head.block_size) : 1;
pascal@23762 1539 clo->buffered_blocknum = cloop_malloc(clo->num_buffered_blocks * sizeof (u_int32_t));
pascal@23762 1540 @@ -874,6 +864,10 @@
pascal@23762 1541 cloop_free(clo->block_ptrs, sizeof(struct block_info) * total_offsets);
pascal@23762 1542 clo->block_ptrs=NULL;
pascal@23762 1543 error_release:
pascal@23762 1544 +#if (defined(CONFIG_ZLIB_INFLATE) || defined(CONFIG_ZLIB_INFLATE_MODULE))
pascal@23762 1545 + zlib_inflateEnd(&clo->zstream);
pascal@23762 1546 + if(clo->zstream.workspace) { cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); clo->zstream.workspace = NULL; }
pascal@23762 1547 +#endif
pascal@23762 1548 if(bbuf) cloop_free(bbuf, clo->underlying_blksize);
pascal@23762 1549 if(clo->underlying_filename) { kfree(clo->underlying_filename); clo->underlying_filename=NULL; }
pascal@23762 1550 clo->backing_file=NULL;