Commit bc67baa3 authored by Mike Hibler's avatar Mike Hibler

Add option to vary the minimum free range size.

This replaces a couple of ad-hoc checks in the FreeBSD and Linux filesystem
code.  The idea is that we record a free range only if it is over a certain
length.  This has the effect of combining multiple short allocated ranges
into a single range, making for more efficient disk writes in the unzipper.
parent d380d13a
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm .Nm
.Op Fl dhiorv .Op Fl dhiorv
.Op Fl F Ar sectors
.Op Fl I Ar slice .Op Fl I Ar slice
.Op Fl s Ar slice .Op Fl s Ar slice
.Op Fl z Ar level .Op Fl z Ar level
...@@ -191,6 +192,16 @@ how many sectors to compress in full disk mode. Can be used to compress ...@@ -191,6 +192,16 @@ how many sectors to compress in full disk mode. Can be used to compress
a subset of a disk. a subset of a disk.
Incompatible with Incompatible with
.Fl s . .Fl s .
.It Fl F Ar sectors
The minimum length in sectors that a free range needs to be before it
is recorded as a free range. Ranges shorter than this length are
.Dq forgotten
and wind up being compressed as allocated data. This option has the
effect of combining multiple, short allocated ranges into a single,
longer range resulting in more efficient disk writes in
.Xr imageunzip .
A value of zero will cause all free blocks to be recorded accurately
in the resulting image. The default value is 64 (32KB).
.It Fl l .It Fl l
Tells Tells
.Nm .Nm
......
...@@ -73,6 +73,7 @@ int level = 4; ...@@ -73,6 +73,7 @@ int level = 4;
long dev_bsize = 1; long dev_bsize = 1;
int ignore[NDOSPART]; int ignore[NDOSPART];
int oldstyle = 0; int oldstyle = 0;
int frangesize= 64; /* 32k */
#define sectobytes(s) ((off_t)(s) * secsize) #define sectobytes(s) ((off_t)(s) * secsize)
#define bytestosec(b) (uint32_t)((b) / secsize) #define bytestosec(b) (uint32_t)((b) / secsize)
...@@ -228,7 +229,7 @@ main(argc, argv) ...@@ -228,7 +229,7 @@ main(argc, argv)
int rawmode = 0; int rawmode = 0;
extern char build_info[]; extern char build_info[];
while ((ch = getopt(argc, argv, "vlbdihrs:c:z:oI:1")) != -1) while ((ch = getopt(argc, argv, "vlbdihrs:c:z:oI:1F:")) != -1)
switch(ch) { switch(ch) {
case 'v': case 'v':
version++; version++;
...@@ -273,6 +274,11 @@ main(argc, argv) ...@@ -273,6 +274,11 @@ main(argc, argv)
case '1': case '1':
oldstyle = 1; oldstyle = 1;
break; break;
case 'F':
frangesize = atoi(optarg);
if (frangesize < 0)
usage();
break;
case 'h': case 'h':
case '?': case '?':
default: default:
...@@ -768,31 +774,24 @@ read_bsdcg(struct fs *fsp, struct cg *cgp, unsigned int dbstart) ...@@ -768,31 +774,24 @@ read_bsdcg(struct fs *fsp, struct cg *cgp, unsigned int dbstart)
fprintf(stderr, " "); fprintf(stderr, " ");
for (count = i = 0; i < max; i++) for (count = i = 0; i < max; i++)
if (isset(p, i)) { if (isset(p, i)) {
unsigned long dboff, dbcount;
j = i; j = i;
while ((i+1)<max && isset(p, i+1)) while ((i+1)<max && isset(p, i+1))
i++; i++;
#if 1
if (i != j && i-j >= 31) {
#else
if (i-j >= 0) {
#endif
unsigned long dboff =
dbstart + fsbtodb(fsp, j);
unsigned long dbcount = dboff = dbstart + fsbtodb(fsp, j);
fsbtodb(fsp, (i-j) + 1); dbcount = fsbtodb(fsp, (i-j) + 1);
if (debug > 2) { if (debug > 2) {
if (count) if (count)
fprintf(stderr, ",%s", fprintf(stderr, ",%s",
count % 4 ? " " : count % 4 ?
"\n "); " " : "\n ");
fprintf(stderr, fprintf(stderr, "%lu:%ld", dboff, dbcount);
"%lu:%ld", dboff, dbcount);
}
addskip(dboff, dbcount);
count++;
} }
addskip(dboff, dbcount);
count++;
} }
if (debug > 2) if (debug > 2)
fprintf(stderr, "\n"); fprintf(stderr, "\n");
...@@ -969,37 +968,36 @@ read_linuxgroup(struct ext2_super_block *super, ...@@ -969,37 +968,36 @@ read_linuxgroup(struct ext2_super_block *super,
fprintf(stderr, " "); fprintf(stderr, " ");
for (count = i = 0; i < max; i++) for (count = i = 0; i < max; i++)
if (!isset(p, i)) { if (!isset(p, i)) {
unsigned long dboff;
int dbcount;
j = i; j = i;
while ((i+1)<max && !isset(p, i+1)) while ((i+1)<max && !isset(p, i+1))
i++; i++;
if (i != j && i-j >= 7) {
unsigned long dboff;
int dbcount;
/* /*
* The offset of this free range, relative * The offset of this free range, relative
* to the start of the disk, is the slice * to the start of the disk, is the slice
* offset, plus the offset of the group itself, * offset, plus the offset of the group itself,
* plus the index of the first free block in * plus the index of the first free block in
* the current range. * the current range.
*/ */
dboff = sliceoffset + dboff = sliceoffset +
LINUX_FSBTODB(index * max) + LINUX_FSBTODB(index * max) +
LINUX_FSBTODB(j); LINUX_FSBTODB(j);
dbcount = LINUX_FSBTODB((i-j) + 1); dbcount = LINUX_FSBTODB((i-j) + 1);
if (debug > 2) { if (debug > 2) {
if (count) if (count)
fprintf(stderr, ",%s", fprintf(stderr, ",%s",
count % 4 ? " " : count % 4 ?
"\n "); " " : "\n ");
fprintf(stderr, "%lu:%d %d:%d", fprintf(stderr, "%lu:%d %d:%d",
dboff, dbcount, j, i); dboff, dbcount, j, i);
}
addskip(dboff, dbcount);
count++;
} }
addskip(dboff, dbcount);
count++;
} }
if (debug > 2) if (debug > 2)
fprintf(stderr, "\n"); fprintf(stderr, "\n");
...@@ -1323,8 +1321,14 @@ addskip(uint32_t start, uint32_t size) ...@@ -1323,8 +1321,14 @@ addskip(uint32_t start, uint32_t size)
{ {
struct range *skip; struct range *skip;
if (size < frangesize)
return;
if ((skip = (struct range *) malloc(sizeof(*skip))) == NULL) { if ((skip = (struct range *) malloc(sizeof(*skip))) == NULL) {
fprintf(stderr, "Out of memory!\n"); fprintf(stderr, "No memory for skip range, "
"try again with '-F <numsect>'\n"
"where <numsect> is greater than the current %d\n",
frangesize);
exit(1); exit(1);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment