PDA

View Full Version : cloop 2.01-1 update (support for older formats in 2.6.x)



bc
03-05-2004, 04:21 PM
I needed support for 1.0 and .68 formats in cloop. With the driver and devfs changes in 2.6, it was easier to migrate the changes to 2.01-1 than to port. So I made a patch. cloop should read all formats correctly.
2.6.4 should also work now (minior changes to module init/exit routines).
Aplolgies if this was done already...




--- cloop-2.01.orig/compressed_loop.c 2004-02-05 20:14:19.000000000 -0500
+++ cloop-2.01/compressed_loop.c 2004-03-04 01:19:07.000000000 -0500
@@ -16,6 +16,9 @@
* Redistribution of this file is permitted under the GNU Public License.
*
* CHANGES: (see CHANGELOG file)
+ * ([email protected]) 2003.03.03
+ * Support for reading 1.0 and .68 formats
+ * Changed module init/exit routines so 2.6.4 works
*/

#define CLOOP_NAME "cloop"
@@ -25,6 +28,8 @@
/* Define this if you are using Greenshoe Linux */
/* #define REDHAT_KERNEL */

+#include <linux/types.h>
+#include <linux/init.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/sched.h>
@@ -89,6 +94,10 @@
#define DEBUGP(format, x...)
#endif

+#define ntohl(x) __be32_to_cpu(x)
+static int read_ver=210;
+static size_t offsets_size = sizeof(loff_t);
+
/* One file can be opened at module insertion time */
/* insmod cloop file=/path/to/file */
static char *file=NULL;
@@ -103,6 +112,7 @@

/* An array of offsets of compressed blocks within the file */
loff_t *offsets;
+ u_int32_t *offsets32;

/* We buffer one uncompressed `block' */
int buffered_blocknum;
@@ -208,7 +218,7 @@
}

static size_t clo_read_from_file(struct cloop_device *clo, struct file *f, char *buf,
- loff_t pos, size_t buf_len)
+ loff_t pos, size_t buf_len)
{
size_t buf_done=0;
while (buf_done < buf_len)
@@ -258,14 +268,36 @@
return 0;
}

+
if (blocknum == clo->buffered_blocknum) return 1;

/* Is there a ntohl for 64-bit values? */
+if (read_ver>=200)
buf_length = be64_to_cpu(clo->offsets[blocknum+1]) - be64_to_cpu(clo->offsets[blocknum]);
+else
+if (read_ver>=100 && read_ver<200)
+ buf_length = clo->offsets[blocknum+1] - clo->offsets[blocknum];
+else
+if (read_ver<100)
+ buf_length = ntohl(clo->offsets32[blocknum+1]) - ntohl(clo->offsets32[blocknum]);
+

/* Load one compressed block from the file. */
+if (read_ver>=200)
clo_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer,
be64_to_cpu(clo->offsets[blocknum]), buf_length);
+else
+if (read_ver>=100 && read_ver<200)
+ clo_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer,
+ clo->offsets[blocknum], buf_length);
+else
+if (read_ver<100)
+{
+ loff_t offval = 0;
+ offval=ntohl(clo->offsets32[blocknum]);
+ clo_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer,
+ offval, buf_length);
+}

/* Do decompression into real buffer. */
buflen = ntohl(clo->head.block_size);
@@ -273,13 +305,29 @@
/* Do the uncompression */
ret = uncompress(clo, clo->buffer, &buflen, clo->compressed_buffer,
buf_length);
+
+
/* DEBUGP("cloop: buflen after uncompress: %ld\n",buflen); */
if (ret != 0)
{
+ if (read_ver>=200)
printk(KERN_ERR "%s: error %i uncompressing block %u %u/%lu/%u/%u "
"%Lu-%Lu\n", cloop_name, ret, blocknum,
ntohl(clo->head.block_size), buflen, buf_length, buf_done,
be64_to_cpu(clo->offsets[blocknum]), be64_to_cpu(clo->offsets[blocknum+1]));
+ else
+ if (read_ver>=100 && read_ver<200)
+ printk(KERN_ERR "%s: error %i uncompressing block %u %u/%lu/%u/%u "
+ "%Lu-%Lu\n", cloop_name, ret, blocknum,
+ ntohl(clo->head.block_size), buflen, buf_length, buf_done,
+ clo->offsets[blocknum], clo->offsets[blocknum+1]);
+ else
+ if (read_ver<100)
+ printk(KERN_ERR "%s: error %i uncompressing block %u %u/%lu/%u/%u "
+ "%u-%u\n", cloop_name, ret, blocknum,
+ ntohl(clo->head.block_size), buflen, buf_length, buf_done,
+ ntohl(clo->offsets32[blocknum]), ntohl(clo->offsets32[blocknum+1]));
+
clo->buffered_blocknum = -1;
return 0;
}
@@ -300,6 +348,7 @@
#endif
unsigned int len;
loff_t offset;
+ u_int32_t offset32;
char *dest;

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
@@ -345,11 +394,17 @@

down(&cloop->clo_lock);
len = bh->b_size;
+ if (read_ver >= 100)
offset = (loff_t)bh->b_rsector << 9;
+ else
+ offset32 = (u_int32_t)bh->b_rsector << 9;
dest = bh->b_data;
#else
down(&cloop->clo_lock);
+ if (read_ver >= 100)
offset = (loff_t)bio->bi_sector << 9;
+ else
+ offset32 = (u_int32_t)bio->bi_sector << 9;
for(vecnr=0; vecnr < bio->bi_vcnt; vecnr++)
{
struct bio_vec *bvec=&bio->bi_io_vec[vecnr];
@@ -368,11 +423,21 @@
/* becomes the blocknumber to load, and offset_in_buffer the */
/* position in the buffer */
u_int32_t offset_in_buffer;
- offset_in_buffer = do_div(block_offset, ntohl(cloop->head.block_size));
-
- status=load_buffer(cloop,block_offset);
+
+ if (read_ver >= 100)
+ {
+ offset_in_buffer = do_div(block_offset, ntohl(cloop->head.block_size));
+ status=load_buffer(cloop,block_offset);
+ }
+ else
+ {
+ status=load_buffer(cloop,offset32/ntohl(cloop->head.block_size));
+ if (!status) break;
+ offset_in_buffer = offset32 % ntohl(cloop->head.block_size);
+ }
+
if(!status) break; /* invalid data, leave inner loop, goto next request */
-
+
/* Now, at least part of what we want will be in the buffer. */
length_in_buffer = ntohl(cloop->head.block_size) - offset_in_buffer;

@@ -387,7 +452,10 @@

dest += length_in_buffer;
len -= length_in_buffer;
+ if (read_ver >= 100)
offset += length_in_buffer;
+ else
+ offset32 += length_in_buffer;
} /* while inner loop */

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
@@ -498,24 +566,25 @@

if (clo->head.preamble[0x0B]!='V'||clo->head.preamble[0x0C]<'1')
{
- printk(KERN_ERR "%s: Cannot read old 32-bit (version 0.68) images, "
- "please use an older version of %s for this file.\n",
- cloop_name, cloop_name);
- error=-EBADF; goto error_release;
+ printk(KERN_WARNING "%s: Reading old 32-bit (version 0.68) image.\n",
+ cloop_name);
+ read_ver = 68;
+ offsets_size = sizeof(u_int32_t);
}

if (clo->head.preamble[0x0C]<'2')
{
- printk(KERN_ERR "%s: Cannot read old architecture-dependent "
- "(format <= 1.0) images, please use an older "
- "version of %s for this file.\n",
- cloop_name, cloop_name);
- error=-EBADF; goto error_release;
+ printk(KERN_WARNING "%s: Reading old architecture-dependent "
+ "(format <= 1.0) image. \n",
+ cloop_name);
+
+ read_ver = 100;
+ offsets_size = sizeof(loff_t);
}

total_offsets=ntohl(clo->head.num_blocks)+1;

- if (!isblkdev && (sizeof(struct cloop_head)+sizeof(loff_t)*
+ if (!isblkdev && (sizeof(struct cloop_head)+offsets_size*
total_offsets > inode->i_size))
{
printk(KERN_ERR "%s: file too small for %u blocks\n",
@@ -523,26 +592,56 @@
error=-EBADF; goto error_release;
}

- clo->offsets = vmalloc(sizeof(loff_t) * total_offsets);
- if (!clo->offsets)
- {
- printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name);
- error=-ENOMEM; goto error_release;
- }
+ if (read_ver >= 100)
+ {
+ clo->offsets = vmalloc(offsets_size * total_offsets);
+ if (!clo->offsets)
+ {
+ printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name);
+ error=-ENOMEM; goto error_release;
+ }
+ }
+ else
+ {
+ clo->offsets32 = vmalloc(offsets_size * total_offsets);
+ if (!clo->offsets32)
+ {
+ printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name);
+ error=-ENOMEM; goto error_release;
+ }
+ }
+
+
}

num_readable = MIN(total_offsets - offsets_read,
(clo->underlying_blksize - offset)
- / sizeof(loff_t));
- memcpy(&clo->offsets[offsets_read], bbuf+offset, num_readable * sizeof(loff_t));
+ / offsets_size);
+
+
+ if (read_ver >= 100)
+ memcpy(&clo->offsets[offsets_read], bbuf+offset, num_readable * offsets_size);
+ else
+ memcpy(&clo->offsets32[offsets_read], bbuf+offset, num_readable * offsets_size);
+
offsets_read += num_readable;
}

+
{ /* Search for largest block rather than estimate. KK. */
int i;
for(i=0;i<total_offsets-1;i++)
{
- loff_t d=be64_to_cpu(clo->offsets[i+1]) - be64_to_cpu(clo->offsets[i]);
+ loff_t d;
+ if (read_ver>=200)
+ d=be64_to_cpu(clo->offsets[i+1]) - be64_to_cpu(clo->offsets[i]);
+ else
+ if (read_ver>=100 && read_ver<200)
+ d=clo->offsets[i+1] - clo->offsets[i];
+ else
+ if (read_ver<100)
+ d=ntohl(clo->offsets32[i+1]) - ntohl(clo->offsets32[i]);
+
largest_block=MAX(largest_block,d);
}
printk("%s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n",
@@ -576,7 +675,7 @@
}
zlib_inflateInit(&clo->zstream);

- if(!isblkdev &&
+ if(read_ver>=200 && !isblkdev &&
be64_to_cpu(clo->offsets[ntohl(clo->head.num_blocks)]) != inode->i_size)
{
printk(KERN_ERR "%s: final offset wrong (%Lu not %Lu)\n",
@@ -586,6 +685,29 @@
vfree(clo->zstream.workspace); clo->zstream.workspace=NULL;
goto error_release_free_all;
}
+ else
+ if((read_ver>=100 && read_ver<200) && !isblkdev &&
+ clo->offsets[ntohl(clo->head.num_blocks)] != inode->i_size)
+ {
+ printk(KERN_ERR "%s: final offset wrong (%Lu not %Lu)\n",
+ cloop_name,
+ clo->offsets[ntohl(clo->head.num_blocks)],
+ inode->i_size);
+ vfree(clo->zstream.workspace); clo->zstream.workspace=NULL;
+ goto error_release_free_all;
+ }
+ else
+ if(read_ver<100 && !isblkdev &&
+ ntohl(clo->offsets32[ntohl(clo->head.num_blocks)]) != inode->i_size)
+ {
+ printk(KERN_ERR "%s: final offset wrong (%u not %Lu)\n",
+ cloop_name,
+ ntohl(clo->offsets32[ntohl(clo->head.num_blocks)]),
+ inode->i_size);
+ vfree(clo->zstream.workspace); clo->zstream.workspace=NULL;
+ goto error_release_free_all;
+ }
+

clo->buffered_blocknum = -1;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
@@ -605,8 +727,12 @@
vfree(clo->buffer);
clo->buffer=NULL;
error_release_free:
+ if (read_ver >= 100)
vfree(clo->offsets);
+ else
+ vfree(clo->offsets32);
clo->offsets=NULL;
+ clo->offsets32=NULL;
error_release:
if(bbuf) vfree(bbuf);
clo->backing_file=NULL;
@@ -756,7 +882,7 @@
ioctl: clo_ioctl
};

-static int cloop_init(void)
+static int __init cloop_init(void)
{
int i, error=0;
printk("%s: Initializing %s v"CLOOP_VERSION"\n", cloop_name, cloop_name);
@@ -845,7 +971,7 @@
return error;
}

-static void cloop_exit(void)
+static void __exit cloop_exit(void)
{
int i;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
@@ -863,6 +989,7 @@
put_disk(cloop_dev[i].disk);
#endif
if(cloop_dev[i].offsets) vfree(cloop_dev[i].offsets);
+ if(cloop_dev[i].offsets32) vfree(cloop_dev[i].offsets32);
if(cloop_dev[i].buffer) vfree(cloop_dev[i].buffer);
if(cloop_dev[i].compressed_buffer) vfree(cloop_dev[i].compressed_buffer);
zlib_inflateEnd(&cloop_dev[i].zstream);

ghstridr
03-08-2004, 08:59 AM
BC, since you seem to know what is going on with cloop.o, could you take a look at my post http://www.knoppix.net/forum/viewtopic.php?p=39328#39328
and see if you can tell me what is wrong? Thanks.