[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[debian-knoppix] [patch] cloop-0.65



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

- --- English message below ---
Guten Tag Herr Knopper und wer immer sonst dies liest

Da ich fuer meine eigene bootbare CD so einiges programmiert habe,
moechte ich hiermit meinen Patch fuer das cloop modul veroeffentlichen.

pros: kaum Bedarf an Hauptspeicher
      drum schnellere Kompression
cons: geringfuegig groessere Ausgabe-Datei (max +250KB)
      Ausgabe kann keine Pipe sein

- ---

Dear Mr. Knopper or whoever is reading...

I made my own bootable CD (SuSE 7.3 based) using your cloop module.

Even on my system with 512MB RAM swapping took several minutes and
considerable CPU time.

README says thus:
blocksize must be a multiple of 512  bytes. Make sure you have enough
swap to hold the entire compressed image in virtual memory!

I had a look on create_compressed_fs.c and figured out that
the only reason to keep 600MB in memory was to prepend number of blocks
and individual block offsets.
With a fixed-size offset-area (I use 254KB, 128KB would suffice)
it is possible to have faster compression with only 1MB RAM used.
The tradeoffs are:
- - Image gets larger by less than 250KB
- - You need to seek in output, thus you need an output FILE, no pipe.

Additionally you may want to have a look at my kernel-module
allowing to virtually change files on CD while changes really go
to RAM-disk, floppy or NFS
http://translucency.sourceforge.net/
use it, if you like
ignore it, if you don't

regards
Bernhard M. Wiedemann
_____________
patch follows
_____________
diff -ur cloop-0.65/compressed_loop.c cloop-0.65-bmw1/compressed_loop.c
- --- cloop-0.65/compressed_loop.c        Wed Apr 24 22:15:35 2002
+++ cloop-0.65-bmw1/compressed_loop.c   Sun Aug 25 16:36:52 2002
@@ -686,7 +686,7 @@
  if(file->f_mode & FMODE_WRITE)
   {
    printk(KERN_WARNING "clo_open: can't open read-write\n");
- -   return -EPERM;
+   return -EROFS;
   }

  MOD_INC_USE_COUNT;
diff -ur cloop-0.65/compressed_loop.h cloop-0.65-bmw1/compressed_loop.h
- --- cloop-0.65/compressed_loop.h	Mon Dec 17 23:19:07 2001
+++ cloop-0.65-bmw1/compressed_loop.h	Sat Jul 20 11:03:22 2002
@@ -8,6 +8,7 @@
 	char preamble[CLOOP_HEADROOM];
 	u_int32_t block_size;
 	u_int32_t num_blocks;
+	u_int32_t offset[0];
 };

 #endif /*_COMPRESSED_LOOP_H*/
diff -ur cloop-0.65/create_compressed_fs.c cloop-0.65-bmw1/create_compressed_fs.c
- --- cloop-0.65/create_compressed_fs.c	Thu Mar 21 00:13:01 2002
+++ cloop-0.65-bmw1/create_compressed_fs.c	Sun Aug 25 15:44:02 2002
@@ -17,11 +17,13 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <sys/mman.h>
 #include <fcntl.h>
 #include "compressed_loop.h"
 #include "zlib-1.1.4/zlib.h"

- -#define MAX_KMALLOC_SIZE 2L<<17
+#define MAX_KMALLOC_SIZE (2L<<17)
+#define OFFSET_SPACE (MAX_KMALLOC_SIZE-2048)

 #define CLOOP_PREAMBLE "#!/bin/sh\n" "insmod cloop.o file=$0 && mount -r -t iso9660 /dev/cloop $1\n" "exit $?\n"

@@ -32,97 +34,66 @@
 	char data[0];
 };

- -void free_cb_list(struct cb_list *cbl)
- -{
- - if(cbl->next) free_cb_list(cbl->next);
- - free(cbl);
- -}
+char *compressed, *uncompressed;
+unsigned long long total_uncompressed=0, total_compressed=0;
+unsigned long maxlen;
+unsigned long numblocks=0;
+unsigned int last;

 /* Now using the goto style because it is quicker to read */
- -static struct cb_list *create_compressed_blocks(int handle, unsigned long
- -                          blocksize, unsigned long *numblocks)
+static int create_compressed_block(int handle, unsigned long blocksize)
 {
- - struct cb_list *cbl,**cbp=&cbl;
- - unsigned long i=0;
- - unsigned int last;
- - unsigned long long total_uncompressed=0,total_compressed=0;
- - unsigned long maxlen = blocksize + blocksize/1000 + 12;
- - char *compressed, *uncompressed;
- - if((uncompressed=malloc(blocksize))==NULL)
- -  {
- -   fprintf(stderr, "*** Can't malloc(%ld).\n",blocksize);
- -   return NULL;
- -  }
- - if((compressed=malloc(maxlen))==NULL)
- -  {
- -   fprintf(stderr, "*** Can't malloc(%ld).\n",blocksize);
- -   goto free_uncompressed;
- -  }
- - for(i=0,last=0; !last; i++)
- -  {
+   int ratio;
    int z_error;
    unsigned long total=0, len = maxlen;
- -   memset(compressed,0,len); memset(uncompressed,0,blocksize);
+   memset(compressed,0,len);
+   memset(uncompressed,0,blocksize);
    while(total<blocksize) /* Read a complete block */
     {
      ssize_t r=read(handle, uncompressed+total, blocksize-total);
- -     if(r<=0) { last=1; break; }
+     if(r<0) goto error;
+     if(r==0) { last=1; break; }
      total+=r;
     }
    total_uncompressed += total;
- -   if (total != blocksize)
- -    {
- -     last=1;
+   if (total != blocksize) last=1;
+   if (last)
      fprintf(stderr, "Partial read (%lu bytes of %lu), padding with zeros.\n",
 					total, blocksize);
- -    }
 /* BEST_COMPRESSION does not seem to improve compression at a blocksize */
 /* of 64k or less, but is significantly slower. KK.                     */
    if((z_error=compress2(compressed, &len, uncompressed, blocksize, Z_DEFAULT_COMPRESSION)) != Z_OK)
     {
- -     fprintf(stderr, "*** Error %d compressing block %lu! (compressed=%p, len=%lu, uncompressed=%p, blocksize=%lu)\n", z_error, i, compressed,len,uncompressed,blocksize);
- -     goto error_free_cb_list;
- -    }
- -   if((*cbp = malloc(sizeof(struct cb_list)+len))==NULL) /* get another block */
- -    {
- -     fprintf(stderr, "*** Out of memory allocating block ptrs (virtual memory exhausted).\n");
- -     goto error_free_cb_list;
+     fprintf(stderr, "*** Error %d compressing block %lu! (compressed=%p, len=%lu, uncompressed=%p, blocksize=%lu)\n", z_error, numblocks, compressed,len,uncompressed,blocksize);
+     goto error;
     }
    total_compressed+=len;
    /* Print status */
- -   fprintf(stderr, "Block# %5lu size %6lu -> %6lu [compression ratio %3lu%%, overall: %3Lu%%]\n", i, total, len, total>0?((len*100)/total):100,total_uncompressed>0?((total_compressed*100)/total_uncompressed):100);
- -   (*cbp)->size = len;
- -   memcpy((*cbp)->data, compressed, len);
- -   (*cbp)->next=NULL;
- -   cbp=&((*cbp)->next);
- -  } /* for */
- - goto free_compressed;
- -
- - error_free_cb_list:
- -    if(cbl) { free_cb_list(cbl); cbl=NULL; i=0; }
- -
- - free_compressed:
- -    free(compressed);
- - free_uncompressed:
- -    free(uncompressed);
- -
- - *numblocks=i;
- - return cbl;
+//   fprintf(stderr, "Block# %5lu size %6lu -> %6lu [compression ratio %3lu%%, overall: %3Lu%%]\n", numblocks, total, len, total>0?((len*100)/total):100,total_uncompressed>0?((total_compressed*100)/total_uncompressed):100);
+   if(total>0) {
+     ratio=(len*100)/total;
+     fprintf(stderr, "%c", ratio<25?'+':(ratio>50?'-':'.'));
+     fflush(stderr);
+   }
+
+ ++numblocks;
+ return len;
+error:
+ return -1;
 }

 int main(int argc, char **argv)
 {
- - int in;
+ int in, out;
  unsigned long blocksize;
- - struct cloop_head head;
- - unsigned long numblocks;
+ struct cloop_head head, *filehead;
+ long compressed_size;
  unsigned long bytes_so_far;
  unsigned long i;
- - struct cb_list *compressed_blocks,*cbp;

- - if (argc != 3)
+ if (argc != 4)
   {
- -   fprintf(stderr, "Usage: %s filename blocksize(bytes).\n",argv[0]);
+   fprintf(stderr, "Usage: %s filename blocksize(bytes) outfile.\n",argv[0]);
    fprintf(stderr, "Use '-' as filename for stdin.\n");
    return 1;
   }
@@ -146,7 +117,14 @@
 			sizeof(CLOOP_PREAMBLE), CLOOP_HEADROOM);
    return 1;
   }
- -
+
+ out=open(argv[3], O_RDWR|O_TRUNC|O_CREAT, 0777);
+ if (out < 0)
+  {
+   perror("Opening output");
+   return 1;
+  }
+
  in=strcmp(argv[1],"-")==0?dup(fileno(stdin)):open(argv[1], O_RDONLY);

  if (in < 0)
@@ -155,50 +133,56 @@
    return 1;
   }

- - compressed_blocks = create_compressed_blocks(in, blocksize, &numblocks);
- -
- - close(in);
- -
+ memset(&head, 0, sizeof(head));
  memcpy(head.preamble, CLOOP_PREAMBLE, sizeof(CLOOP_PREAMBLE));
  head.block_size = htonl(blocksize);
- - head.num_blocks = htonl(numblocks);
+// head.num_blocks = is filled up later
+
+ /* Write out head... */
+ write(out, &head, sizeof(head));
+ i=lseek(out, OFFSET_SPACE, SEEK_CUR);
+ bytes_so_far = sizeof(head) + OFFSET_SPACE;
+ filehead = (struct cloop_head *) mmap(NULL, i, PROT_WRITE, MAP_SHARED, out, 0);
+ if(filehead<0) { perror("mmap"); return 1; }

- - fprintf(stderr, "Block size %lu, number of blocks %lu.\n",
- -         blocksize, numblocks);
+// fprintf(stderr, "Block size %lu, number of blocks %lu.\n", blocksize, numblocks);

- - bytes_so_far = sizeof(head) + sizeof(u_int32_t) * (numblocks + 1);
  if(bytes_so_far > MAX_KMALLOC_SIZE)
   {
    fprintf(stderr, "\nWARNING: cloop block index may not fit into a kmalloc()\n*** (%lu bytes max, current %lu)\n\n", MAX_KMALLOC_SIZE, bytes_so_far);
    sleep(2);
   }

- - /* Write out head... */
- - write(STDOUT_FILENO, &head, sizeof(head));
- -
- - if (!compressed_blocks) return 1;
- -
- - /* Write offsets */
- - for (i=0,cbp=compressed_blocks; i < numblocks+1; i++)
+ maxlen = blocksize + blocksize/1000 + 12;
+ if((uncompressed=malloc(blocksize))==NULL)
   {
- -   u_int32_t tmp;
- -   tmp = htonl(bytes_so_far);
- -   write(STDOUT_FILENO, &tmp, sizeof(tmp));
- -   if(cbp) { bytes_so_far += cbp->size; cbp=cbp->next; }
+   fprintf(stderr, "*** Can't malloc(%ld).\n",blocksize);
+   return 1;
   }
- -
- - /* Now write blocks and free them. */
- - for (i = 0, cbp=compressed_blocks; cbp && i < numblocks; i++)
+ if((compressed=malloc(maxlen))==NULL)
   {
- -   if (write(STDOUT_FILENO, cbp->data, cbp->size) != cbp->size)
- -    {
- -     perror("writing block");
- -     free_cb_list(compressed_blocks);
- -     return 1;
- -    }
- -   cbp=cbp->next;
- -   free(compressed_blocks); compressed_blocks=cbp;
+   fprintf(stderr, "*** Can't malloc(%ld).\n",maxlen);
+   return 1;
+  }
+ while (!last)
+  {
+   compressed_size=create_compressed_block(in, blocksize);
+   if (compressed_size < 0) return 1;
+
+   /* Write offset */
+   filehead->offset[numblocks-1] = htonl(bytes_so_far);
+   bytes_so_far += compressed_size;
+
+   /* Write data */
+   write(out, compressed, compressed_size);
   }
+ filehead->offset[numblocks] = htonl(bytes_so_far);
+ filehead->num_blocks = htonl(numblocks);
+
+ close(in);
+ free(compressed);
+ free(uncompressed);
+
  fprintf(stderr,"Done.\n");
  return 0;
 }


-----BEGIN PGP SIGNATURE-----
Comment: Weitere Infos: siehe http://www.gnupg.org

iEYEARECAAYFAj1pHfIACgkQSTYLOx37oWS3nQCbB4MUcwz4JSqmY1fYeVtiLKr9
qfEAoO+IAdPetAI+Hg403G4eb2UrKIHF
=cWpc
-----END PGP SIGNATURE-----


_______________________________________________
debian-knoppix mailing list
debian-knoppix@linuxtag.org
http://mailman.linuxtag.org/mailman/listinfo/debian-knoppix


Reply to: