genext2fs: support large files and filesystems without using large amounts of memory

update_to_1.95.patch was generated by making a diff bewteen the 1.4.1 release
and the latest 1.9.5 version in the cvs repo:
http://genext2fs.cvs.sourceforge.net/viewvc/genext2fs/genext2fs/genext2fs.c?revision=1.95

The patches 0001-0019 come from mailing list of genext2fs-devel
http://sourceforge.net/mailarchive/forum.php?forum_name=genext2fs-devel&max_rows=100&style=flat&viewmonth=201106

(From OE-Core rev: 8f17e499cf91191727c8767e839738cb39c21655)

Signed-off-by: Dexuan Cui <dexuan.cui@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Dexuan Cui 2012-03-29 00:35:09 +08:00 committed by Richard Purdie
parent 84b7541abc
commit 79c806cb40
22 changed files with 4776 additions and 10 deletions

View File

@ -0,0 +1,72 @@
Upstream-Status: inappropriate
From 1399df7672ec309523bcd067da24d72aa624f783 Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Wed, 1 Jun 2011 07:51:24 -0500
Subject: [PATCH 01/19] Fix warnings, remove some unused macros.
These are some annoying warnings with newer toolchains. And NAMLEN is
never used, so just get rid of it.
---
genext2fs.c | 15 +++++++++------
1 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/genext2fs.c b/genext2fs.c
index f0d797d..284862d 100644
--- a/genext2fs.c
+++ b/genext2fs.c
@@ -107,10 +107,8 @@
#if HAVE_DIRENT_H
# include <dirent.h>
-# define NAMLEN(dirent) strlen((dirent)->d_name)
#else
# define dirent direct
-# define NAMLEN(dirent) (dirent)->d_namlen
# if HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
@@ -1441,7 +1439,8 @@ mkfile_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode, size
if(!(b = (uint8*)calloc(rndup(size, BLOCKSIZE), 1)))
error_msg_and_die("not enough mem to read file '%s'", name);
if(f)
- fread(b, size, 1, f); // FIXME: ugly. use mmap() ...
+ if (fread(b, size, 1, f) != 1) // FIXME: ugly. use mmap() ...
+ error_msg_and_die("fread failed");
extend_blk(fs, nod, b, rndup(size, BLOCKSIZE) / BLOCKSIZE);
free(b);
}
@@ -1673,7 +1672,9 @@ add2fs_from_dir(filesystem *fs, uint32 this_nod, int squash_uids, int squash_per
if(chdir(dent->d_name) < 0)
perror_msg_and_die(dent->d_name);
add2fs_from_dir(fs, this_nod, squash_uids, squash_perms, fs_timestamp, stats);
- chdir("..");
+ if (chdir("..") == -1)
+ perror_msg_and_die("..");
+
break;
default:
break;
@@ -1687,7 +1688,8 @@ add2fs_from_dir(filesystem *fs, uint32 this_nod, int squash_uids, int squash_per
if(chdir(dent->d_name) < 0)
perror_msg_and_die(name);
add2fs_from_dir(fs, nod, squash_uids, squash_perms, fs_timestamp, stats);
- chdir("..");
+ if (chdir("..") == -1)
+ perror_msg_and_die("..");
}
continue;
}
@@ -1733,7 +1735,8 @@ add2fs_from_dir(filesystem *fs, uint32 this_nod, int squash_uids, int squash_per
if(chdir(dent->d_name) < 0)
perror_msg_and_die(name);
add2fs_from_dir(fs, nod, squash_uids, squash_perms, fs_timestamp, stats);
- chdir("..");
+ if (chdir("..") == -1)
+ perror_msg_and_die("..");
break;
default:
error_msg("ignoring entry %s", name);
--
1.7.4.1

View File

@ -0,0 +1,222 @@
Upstream-Status: inappropriate
From c196bdeae7932c5d54bbdb7e7574d3cdae46ad02 Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Sat, 4 Jun 2011 22:04:24 -0500
Subject: [PATCH 03/19] Add get_blkmap and put_blkmap.
Add routines for getting an putting a block map. This does not do
anything functional, but is getting ready for when blockmaps are
byteswapped when being read and written.
---
genext2fs.c | 84 ++++++++++++++++++++++++++++++++++++++++-------------------
1 files changed, 57 insertions(+), 27 deletions(-)
diff --git a/genext2fs.c b/genext2fs.c
index bd06369..0b5ba6f 100644
--- a/genext2fs.c
+++ b/genext2fs.c
@@ -837,6 +837,36 @@ put_blk(blk_info *bi)
{
}
+// Used by get_blkmap/put_blkmap to hold information about an block map
+// owned by the user.
+typedef struct
+{
+ blk_info *bi;
+} blkmap_info;
+
+// Return a given block map from a filesystem. Make sure to call
+// put_blkmap when you are done with it.
+static inline uint32 *
+get_blkmap(filesystem *fs, uint32 blk, blkmap_info **rbmi)
+{
+ blkmap_info *bmi;
+ uint8 *b;
+
+ bmi = malloc(sizeof(*bmi));
+ if (!bmi)
+ error_msg_and_die("get_blkmap: out of memory");
+ b = get_blk(fs, blk, &bmi->bi);
+ *rbmi = bmi;
+ return (uint32 *) b;
+}
+
+static inline void
+put_blkmap(blkmap_info *bmi)
+{
+ put_blk(bmi->bi);
+ free(bmi);
+}
+
// Used by get_nod/put_nod to hold information about an inode owned
// by the user.
typedef struct
@@ -1020,12 +1050,12 @@ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
{
uint32 *bkref = 0;
uint32 bk = 0;
+ blkmap_info *bmi1 = NULL, *bmi2 = NULL, *bmi3 = NULL;
uint32 *b;
int extend = 0, reduce = 0;
inode *inod;
nod_info *ni;
uint32 *iblk;
- blk_info *bi1 = NULL, *bi2 = NULL, *bi3 = NULL;
if(create && (*create) < 0)
reduce = 1;
@@ -1072,7 +1102,7 @@ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
iblk[bw->bpdir] = alloc_blk(fs,nod);
if(reduce) // free indirect block
free_blk(fs, iblk[bw->bpdir]);
- b = (uint32*)get_blk(fs, iblk[bw->bpdir], &bi1);
+ b = get_blkmap(fs, iblk[bw->bpdir], &bmi1);
bkref = &b[bw->bpind];
if(extend) // allocate first block
*bkref = hole ? 0 : alloc_blk(fs,nod);
@@ -1083,7 +1113,7 @@ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
else if((bw->bpdir == EXT2_IND_BLOCK) && (bw->bpind < BLOCKSIZE/4 - 1))
{
bw->bpind++;
- b = (uint32*)get_blk(fs, iblk[bw->bpdir], &bi1);
+ b = get_blkmap(fs, iblk[bw->bpdir], &bmi1);
bkref = &b[bw->bpind];
if(extend) // allocate block
*bkref = hole ? 0 : alloc_blk(fs,nod);
@@ -1101,12 +1131,12 @@ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
iblk[bw->bpdir] = alloc_blk(fs,nod);
if(reduce) // free double indirect block
free_blk(fs, iblk[bw->bpdir]);
- b = (uint32*)get_blk(fs, iblk[bw->bpdir], &bi1);
+ b = get_blkmap(fs, iblk[bw->bpdir], &bmi1);
if(extend) // allocate first indirect block
b[bw->bpind] = alloc_blk(fs,nod);
if(reduce) // free firstindirect block
free_blk(fs, b[bw->bpind]);
- b = (uint32*)get_blk(fs, b[bw->bpind], &bi1);
+ b = get_blkmap(fs, b[bw->bpind], &bmi2);
bkref = &b[bw->bpdind];
if(extend) // allocate first block
*bkref = hole ? 0 : alloc_blk(fs,nod);
@@ -1117,8 +1147,8 @@ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
else if((bw->bpdir == EXT2_DIND_BLOCK) && (bw->bpdind < BLOCKSIZE/4 - 1))
{
bw->bpdind++;
- b = (uint32*)get_blk(fs, iblk[bw->bpdir], &bi1);
- b = (uint32*)get_blk(fs, b[bw->bpind], &bi2);
+ b = get_blkmap(fs, iblk[bw->bpdir], &bmi1);
+ b = get_blkmap(fs, b[bw->bpind], &bmi2);
bkref = &b[bw->bpdind];
if(extend) // allocate block
*bkref = hole ? 0 : alloc_blk(fs,nod);
@@ -1131,12 +1161,12 @@ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
bw->bnum++;
bw->bpdind = 0;
bw->bpind++;
- b = (uint32*)get_blk(fs, iblk[bw->bpdir], &bi1);
+ b = get_blkmap(fs, iblk[bw->bpdir], &bmi1);
if(extend) // allocate indirect block
b[bw->bpind] = alloc_blk(fs,nod);
if(reduce) // free indirect block
free_blk(fs, b[bw->bpind]);
- b = (uint32*)get_blk(fs, b[bw->bpind], &bi2);
+ b = get_blkmap(fs, b[bw->bpind], &bmi2);
bkref = &b[bw->bpdind];
if(extend) // allocate first block
*bkref = hole ? 0 : alloc_blk(fs,nod);
@@ -1159,17 +1189,17 @@ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
iblk[bw->bpdir] = alloc_blk(fs,nod);
if(reduce) // free triple indirect block
free_blk(fs, iblk[bw->bpdir]);
- b = (uint32*)get_blk(fs, iblk[bw->bpdir], &bi1);
+ b = get_blkmap(fs, iblk[bw->bpdir], &bmi1);
if(extend) // allocate first double indirect block
b[bw->bpind] = alloc_blk(fs,nod);
if(reduce) // free first double indirect block
free_blk(fs, b[bw->bpind]);
- b = (uint32*)get_blk(fs, b[bw->bpind], &bi2);
+ b = get_blkmap(fs, b[bw->bpind], &bmi2);
if(extend) // allocate first indirect block
b[bw->bpdind] = alloc_blk(fs,nod);
if(reduce) // free first indirect block
free_blk(fs, b[bw->bpind]);
- b = (uint32*)get_blk(fs, b[bw->bpdind], &bi3);
+ b = get_blkmap(fs, b[bw->bpdind], &bmi3);
bkref = &b[bw->bptind];
if(extend) // allocate first data block
*bkref = hole ? 0 : alloc_blk(fs,nod);
@@ -1183,9 +1213,9 @@ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
(bw->bptind < BLOCKSIZE/4 -1) )
{
bw->bptind++;
- b = (uint32*)get_blk(fs, iblk[bw->bpdir], &bi1);
- b = (uint32*)get_blk(fs, b[bw->bpind], &bi2);
- b = (uint32*)get_blk(fs, b[bw->bpdind], &bi3);
+ b = get_blkmap(fs, iblk[bw->bpdir], &bmi1);
+ b = get_blkmap(fs, b[bw->bpind], &bmi2);
+ b = get_blkmap(fs, b[bw->bpdind], &bmi3);
bkref = &b[bw->bptind];
if(extend) // allocate data block
*bkref = hole ? 0 : alloc_blk(fs,nod);
@@ -1202,13 +1232,13 @@ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
bw->bnum++;
bw->bptind = 0;
bw->bpdind++;
- b = (uint32*)get_blk(fs, iblk[bw->bpdir], &bi1);
- b = (uint32*)get_blk(fs, b[bw->bpind], &bi2);
+ b = get_blkmap(fs, iblk[bw->bpdir], &bmi1);
+ b = get_blkmap(fs, b[bw->bpind], &bmi2);
if(extend) // allocate single indirect block
b[bw->bpdind] = alloc_blk(fs,nod);
if(reduce) // free indirect block
free_blk(fs, b[bw->bpind]);
- b = (uint32*)get_blk(fs, b[bw->bpdind], &bi3);
+ b = get_blkmap(fs, b[bw->bpdind], &bmi3);
bkref = &b[bw->bptind];
if(extend) // allocate first data block
*bkref = hole ? 0 : alloc_blk(fs,nod);
@@ -1225,17 +1255,17 @@ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
bw->bpdind = 0;
bw->bptind = 0;
bw->bpind++;
- b = (uint32*)get_blk(fs, iblk[bw->bpdir], &bi1);
+ b = get_blkmap(fs, iblk[bw->bpdir], &bmi1);
if(extend) // allocate double indirect block
b[bw->bpind] = alloc_blk(fs,nod);
if(reduce) // free double indirect block
free_blk(fs, b[bw->bpind]);
- b = (uint32*)get_blk(fs, b[bw->bpind], &bi2);
+ b = get_blkmap(fs, b[bw->bpind], &bmi2);
if(extend) // allocate single indirect block
b[bw->bpdind] = alloc_blk(fs,nod);
if(reduce) // free indirect block
free_blk(fs, b[bw->bpind]);
- b = (uint32*)get_blk(fs, b[bw->bpdind], &bi3);
+ b = get_blkmap(fs, b[bw->bpdind], &bmi3);
bkref = &b[bw->bptind];
if(extend) // allocate first block
*bkref = hole ? 0 : alloc_blk(fs,nod);
@@ -1247,12 +1277,12 @@ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
/* End change for walking triple indirection */
bk = *bkref;
- if (bi3)
- put_blk(bi3);
- if (bi2)
- put_blk(bi2);
- if (bi1)
- put_blk(bi1);
+ if (bmi3)
+ put_blkmap(bmi3);
+ if (bmi2)
+ put_blkmap(bmi2);
+ if (bmi1)
+ put_blkmap(bmi1);
if(bk)
{
--
1.7.4.1

View File

@ -0,0 +1,357 @@
Upstream-Status: inappropriate
From 3d47e37e21f6a2ced489d49e8bf5a5c24bb9baaf Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Sun, 5 Jun 2011 09:36:11 -0500
Subject: [PATCH 04/19] Add a dirwalker for walking through directory entries
The code to walk directory items was messy, to say the least. Write a
clean structure to do this.
Also, remove d_name[0]. This is bad style, and newer compilers will
think it is really a zero-length array and will abort if trying to write
any data to it, since the compiler thinks it has no contents.
---
genext2fs.c | 210 +++++++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 154 insertions(+), 56 deletions(-)
diff --git a/genext2fs.c b/genext2fs.c
index 0b5ba6f..03d1b27 100644
--- a/genext2fs.c
+++ b/genext2fs.c
@@ -533,7 +533,6 @@ typedef struct
typedef struct
{
directory_decl
- char d_name[0];
} directory;
typedef uint8 block[BLOCKSIZE];
@@ -795,6 +794,8 @@ static inline uint8 *
get_workblk(void)
{
unsigned char* b=calloc(1,BLOCKSIZE);
+ if (!b)
+ error_msg_and_die("get_workblk() failed, out of memory");
return b;
}
static inline void
@@ -902,6 +903,126 @@ put_nod(nod_info *ni)
free(ni);
}
+// Used to hold state information while walking a directory inode.
+typedef struct
+{
+ directory d;
+ filesystem *fs;
+ uint32 nod;
+ directory *last_d;
+ uint8 *b;
+ blk_info *bi;
+} dirwalker;
+
+// Start a directory walk on the given inode. You must pass in a
+// dirwalker structure, then use that dirwalker for future operations.
+// Call put_dir when you are done walking the directory.
+static inline directory *
+get_dir(filesystem *fs, uint32 nod, dirwalker *dw)
+{
+ dw->fs = fs;
+ dw->b = get_blk(fs, nod, &dw->bi);
+ dw->nod = nod;
+ dw->last_d = (directory *) dw->b;
+
+ memcpy(&dw->d, dw->last_d, sizeof(directory));
+ return &dw->d;
+}
+
+// Move to the next directory.
+static inline directory *
+next_dir(dirwalker *dw)
+{
+ directory *next_d = (directory *)((int8*)dw->last_d + dw->d.d_rec_len);
+
+ memcpy(dw->last_d, &dw->d, sizeof(directory));
+
+ if (((int8 *) next_d) >= ((int8 *) dw->b + BLOCKSIZE))
+ return NULL;
+
+ dw->last_d = next_d;
+ memcpy(&dw->d, next_d, sizeof(directory));
+ return &dw->d;
+}
+
+// Call then when you are done with the directory walk.
+static inline void
+put_dir(dirwalker *dw)
+{
+ memcpy(dw->last_d, &dw->d, sizeof(directory));
+
+ if (dw->nod == 0)
+ free_workblk(dw->b);
+ else
+ put_blk(dw->bi);
+}
+
+// Create a new directory block with the given inode as it's destination
+// and append it to the current dirwalker.
+static directory *
+new_dir(filesystem *fs, uint32 dnod, const char *name, int nlen, dirwalker *dw)
+{
+ directory *d;
+
+ dw->fs = fs;
+ dw->b = get_workblk();
+ dw->nod = 0;
+ dw->last_d = (directory *) dw->b;
+ d = &dw->d;
+ d->d_inode = dnod;
+ d->d_rec_len = BLOCKSIZE;
+ d->d_name_len = nlen;
+ strncpy(((char *) dw->last_d) + sizeof(directory), name, nlen);
+ return d;
+}
+
+// Shrink the current directory entry, make a new one with the free
+// space, and return the new directory entry (making it current).
+static inline directory *
+shrink_dir(dirwalker *dw, uint32 nod, const char *name, int nlen)
+{
+ int reclen, preclen;
+ directory *d = &dw->d;
+
+ reclen = d->d_rec_len;
+ d->d_rec_len = sizeof(directory) + rndup(d->d_name_len, 4);
+ preclen = d->d_rec_len;
+ reclen -= preclen;
+ memcpy(dw->last_d, &dw->d, sizeof(directory));
+
+ dw->last_d = (directory *) (((int8 *) dw->last_d) + preclen);
+ d->d_rec_len = reclen;
+ d->d_inode = nod;
+ d->d_name_len = nlen;
+ strncpy(((char *) dw->last_d) + sizeof(directory), name, nlen);
+
+ return d;
+}
+
+// Return the current block the directory is walking
+static inline uint8 *
+dir_data(dirwalker *dw)
+{
+ return dw->b;
+}
+
+// Return the pointer to the name for the current directory
+static inline char *
+dir_name(dirwalker *dw)
+{
+ return ((char *) dw->last_d) + sizeof(directory);
+}
+
+// Set the name for the current directory. Note that this doesn't
+// verify that there is space for the directory name, you must do
+// that yourself.
+static void
+dir_set_name(dirwalker *dw, const char *name, int nlen)
+{
+ dw->d.d_name_len = nlen;
+ strncpy(((char *) dw->last_d) + sizeof(directory), name, nlen);
+}
+
// allocate a given block/inode in the bitmap
// allocate first free if item == 0
static uint32
@@ -1354,11 +1475,10 @@ extend_blk(filesystem *fs, uint32 nod, block b, int amount)
static void
add2dir(filesystem *fs, uint32 dnod, uint32 nod, const char* name)
{
- blockwalker bw;
+ blockwalker bw, lbw;
uint32 bk;
- uint8 *b;
- blk_info *bi;
directory *d;
+ dirwalker dw;
int reclen, nlen;
inode *node;
inode *pnode;
@@ -1376,55 +1496,46 @@ add2dir(filesystem *fs, uint32 dnod, uint32 nod, const char* name)
if(reclen > BLOCKSIZE)
error_msg_and_die("bad name '%s' (too long)", name);
init_bw(&bw);
+ lbw = bw;
while((bk = walk_bw(fs, dnod, &bw, 0, 0)) != WALK_END) // for all blocks in dir
{
- b = get_blk(fs, bk, &bi);
// for all dir entries in block
- for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + d->d_rec_len))
+ for(d = get_dir(fs, bk, &dw); d; d = next_dir(&dw))
{
// if empty dir entry, large enough, use it
if((!d->d_inode) && (d->d_rec_len >= reclen))
{
d->d_inode = nod;
node = get_nod(fs, nod, &ni);
+ dir_set_name(&dw, name, nlen);
+ put_dir(&dw);
node->i_links_count++;
- d->d_name_len = nlen;
- strncpy(d->d_name, name, nlen);
put_nod(ni);
goto out;
}
// if entry with enough room (last one?), shrink it & use it
if(d->d_rec_len >= (sizeof(directory) + rndup(d->d_name_len, 4) + reclen))
{
- reclen = d->d_rec_len;
- d->d_rec_len = sizeof(directory) + rndup(d->d_name_len, 4);
- reclen -= d->d_rec_len;
- d = (directory*) (((int8*)d) + d->d_rec_len);
- d->d_rec_len = reclen;
- d->d_inode = nod;
node = get_nod(fs, nod, &ni);
+ d = shrink_dir(&dw, nod, name, nlen);
+ put_dir(&dw);
node->i_links_count++;
- d->d_name_len = nlen;
- strncpy(d->d_name, name, nlen);
put_nod(ni);
goto out;
}
}
+ put_dir(&dw);
+ lbw = bw;
}
// we found no free entry in the directory, so we add a block
- if(!(b = get_workblk()))
- error_msg_and_die("get_workblk() failed.");
- d = (directory*)b;
- d->d_inode = nod;
node = get_nod(fs, nod, &ni);
+ d = new_dir(fs, nod, name, nlen, &dw);
node->i_links_count++;
put_nod(ni);
- d->d_rec_len = BLOCKSIZE;
- d->d_name_len = nlen;
- strncpy(d->d_name, name, nlen);
- extend_blk(fs, dnod, b, 1);
+ next_dir(&dw); // Force the data into the buffer
+ extend_blk(fs, dnod, dir_data(&dw), 1);
+ put_dir(&dw);
pnode->i_size += BLOCKSIZE;
- free_workblk(b);
out:
put_nod(dni);
}
@@ -1435,20 +1546,18 @@ find_dir(filesystem *fs, uint32 nod, const char * name)
{
blockwalker bw;
uint32 bk;
- blk_info *bi;
int nlen = strlen(name);
init_bw(&bw);
while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END)
{
directory *d;
- uint8 *b;
- b = get_blk(fs, bk, &bi);
- for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + d->d_rec_len))
- if(d->d_inode && (nlen == d->d_name_len) && !strncmp(d->d_name, name, nlen)) {
- put_blk(bi);
+ dirwalker dw;
+ for (d = get_dir(fs, bk, &dw); d; d=next_dir(&dw))
+ if(d->d_inode && (nlen == d->d_name_len) && !strncmp(dir_name(&dw), name, nlen)) {
+ put_dir(&dw);
return d->d_inode;
}
- put_blk(bi);
+ put_dir(&dw);
}
return 0;
}
@@ -2090,8 +2199,7 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
{
uint32 i;
filesystem *fs;
- directory *d;
- uint8 * b;
+ dirwalker dw;
uint32 nod, first_block;
uint32 nbgroups,nbinodes_per_group,overhead_per_group,free_blocks,
free_blocks_per_group,nbblocks_per_group,min_nbgroups;
@@ -2217,26 +2325,20 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
itab0->i_links_count = 2;
put_nod(ni);
- if(!(b = get_workblk()))
- error_msg_and_die("get_workblk() failed.");
- d = (directory*)b;
- d->d_inode = EXT2_ROOT_INO;
- d->d_rec_len = sizeof(directory)+4;
- d->d_name_len = 1;
- strcpy(d->d_name, ".");
- d = (directory*)(b + d->d_rec_len);
- d->d_inode = EXT2_ROOT_INO;
- d->d_rec_len = BLOCKSIZE - (sizeof(directory)+4);
- d->d_name_len = 2;
- strcpy(d->d_name, "..");
- extend_blk(fs, EXT2_ROOT_INO, b, 1);
+ new_dir(fs, EXT2_ROOT_INO, ".", 1, &dw);
+ shrink_dir(&dw, EXT2_ROOT_INO, "..", 2);
+ next_dir(&dw); // Force the data into the buffer
+ extend_blk(fs, EXT2_ROOT_INO, dir_data(&dw), 1);
+ put_dir(&dw);
// make lost+found directory and reserve blocks
if(fs->sb.s_r_blocks_count)
{
inode *node;
+ uint8 *b;
nod = mkdir_fs(fs, EXT2_ROOT_INO, "lost+found", FM_IRWXU, 0, 0, fs_timestamp, fs_timestamp);
+ b = get_workblk();
memset(b, 0, BLOCKSIZE);
((directory*)b)->d_rec_len = BLOCKSIZE;
/* We run into problems with e2fsck if directory lost+found grows
@@ -2246,11 +2348,11 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
fs->sb.s_r_blocks_count = fs->sb.s_blocks_count * MAX_RESERVED_BLOCKS;
for(i = 1; i < fs->sb.s_r_blocks_count; i++)
extend_blk(fs, nod, b, 1);
+ free_workblk(b);
node = get_nod(fs, nod, &ni);
node->i_size = fs->sb.s_r_blocks_count * BLOCKSIZE;
put_nod(ni);
}
- free_workblk(b);
// administrative info
fs->sb.s_state = 1;
@@ -2368,19 +2470,15 @@ print_dir(filesystem *fs, uint32 nod)
while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END)
{
directory *d;
- uint8 *b;
- blk_info *bi;
- b = get_blk(fs, bk, &bi);
- for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + d->d_rec_len))
+ dirwalker dw;
+ for (d = get_dir(fs, bk, &dw); d; d = next_dir(&dw))
if(d->d_inode)
{
- int i;
printf("entry '");
- for(i = 0; i < d->d_name_len; i++)
- putchar(d->d_name[i]);
+ fwrite(dir_name(&dw), 1, d->d_name_len, stdout);
printf("' (inode %d): rec_len: %d (name_len: %d)\n", d->d_inode, d->d_rec_len, d->d_name_len);
}
- put_blk(bi);
+ put_dir(&dw);
}
}
--
1.7.4.1

View File

@ -0,0 +1,374 @@
Upstream-Status: inappropriate
From f2090608aef32f3012b1c5943b73314176bce832 Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Sun, 5 Jun 2011 10:09:51 -0500
Subject: [PATCH 05/19] Make filesystem struct not an overloay
Having the filesystem structure just be a big overlay for the raw data
means you can't easily carry along any useful metadata in it. So
modify the filesystem structure to not be an overlay, but allocate the
data and various pieces to be components inside the structure.
---
genext2fs.c | 150 +++++++++++++++++++++++++++++++++--------------------------
1 files changed, 84 insertions(+), 66 deletions(-)
diff --git a/genext2fs.c b/genext2fs.c
index 03d1b27..46c9605 100644
--- a/genext2fs.c
+++ b/genext2fs.c
@@ -233,8 +233,8 @@ struct stats {
// Number of groups in the filesystem
#define GRP_NBGROUPS(fs) \
- (((fs)->sb.s_blocks_count - fs->sb.s_first_data_block + \
- (fs)->sb.s_blocks_per_group - 1) / (fs)->sb.s_blocks_per_group)
+ (((fs)->sb->s_blocks_count - fs->sb->s_first_data_block + \
+ (fs)->sb->s_blocks_per_group - 1) / (fs)->sb->s_blocks_per_group)
// Get/put group block bitmap (bbm) given the group number
#define GRP_GET_GROUP_BBM(fs,grp,bi) ( get_blk((fs),(fs)->gd[(grp)].bg_block_bitmap,(bi)) )
@@ -245,7 +245,7 @@ struct stats {
#define GRP_PUT_GROUP_IBM(bi) ( put_blk((bi)) )
// Given an inode number find the group it belongs to
-#define GRP_GROUP_OF_INODE(fs,nod) ( ((nod)-1) / (fs)->sb.s_inodes_per_group)
+#define GRP_GROUP_OF_INODE(fs,nod) ( ((nod)-1) / (fs)->sb->s_inodes_per_group)
//Given an inode number get/put the inode bitmap that covers it
#define GRP_GET_INODE_BITMAP(fs,nod,bi) \
@@ -255,10 +255,10 @@ struct stats {
//Given an inode number find its offset within the inode bitmap that covers it
#define GRP_IBM_OFFSET(fs,nod) \
- ( (nod) - GRP_GROUP_OF_INODE((fs),(nod))*(fs)->sb.s_inodes_per_group )
+ ( (nod) - GRP_GROUP_OF_INODE((fs),(nod))*(fs)->sb->s_inodes_per_group )
// Given a block number find the group it belongs to
-#define GRP_GROUP_OF_BLOCK(fs,blk) ( ((blk)-1) / (fs)->sb.s_blocks_per_group)
+#define GRP_GROUP_OF_BLOCK(fs,blk) ( ((blk)-1) / (fs)->sb->s_blocks_per_group)
//Given a block number get/put the block bitmap that covers it
#define GRP_GET_BLOCK_BITMAP(fs,blk,bi) \
@@ -268,7 +268,7 @@ struct stats {
//Given a block number find its offset within the block bitmap that covers it
#define GRP_BBM_OFFSET(fs,blk) \
- ( (blk) - GRP_GROUP_OF_BLOCK((fs),(blk))*(fs)->sb.s_blocks_per_group )
+ ( (blk) - GRP_GROUP_OF_BLOCK((fs),(blk))*(fs)->sb->s_blocks_per_group )
// used types
@@ -577,9 +577,10 @@ typedef struct
#if BLOCKSIZE == 1024
typedef struct
{
- block zero; // The famous block 0
- superblock sb; // The superblock
- groupdescriptor gd[0]; // The group descriptors
+ uint8 *data;
+ superblock *sb;
+ groupdescriptor *gd;
+ uint32 nheadblocks;
} filesystem;
#else
#error UNHANDLED BLOCKSIZE
@@ -830,7 +831,7 @@ typedef struct
static inline uint8 *
get_blk(filesystem *fs, uint32 blk, blk_info **rbi)
{
- return (uint8*)fs + blk*BLOCKSIZE;
+ return fs->data + blk*BLOCKSIZE;
}
static inline void
@@ -1079,9 +1080,9 @@ alloc_blk(filesystem *fs, uint32 nod)
error_msg_and_die("couldn't allocate a block (no free space)");
if(!(fs->gd[grp].bg_free_blocks_count--))
error_msg_and_die("group descr %d. free blocks count == 0 (corrupted fs?)",grp);
- if(!(fs->sb.s_free_blocks_count--))
+ if(!(fs->sb->s_free_blocks_count--))
error_msg_and_die("superblock free blocks count == 0 (corrupted fs?)");
- return fs->sb.s_blocks_per_group*grp + bk;
+ return fs->sb->s_blocks_per_group*grp + bk;
}
// free a block
@@ -1091,12 +1092,12 @@ free_blk(filesystem *fs, uint32 bk)
uint32 grp;
blk_info *bi;
- grp = bk / fs->sb.s_blocks_per_group;
- bk %= fs->sb.s_blocks_per_group;
+ grp = bk / fs->sb->s_blocks_per_group;
+ bk %= fs->sb->s_blocks_per_group;
deallocate(get_blk(fs, fs->gd[grp].bg_block_bitmap, &bi), bk);
put_blk(bi);
fs->gd[grp].bg_free_blocks_count++;
- fs->sb.s_free_blocks_count++;
+ fs->sb->s_free_blocks_count++;
}
// allocate an inode
@@ -1114,7 +1115,7 @@ alloc_nod(filesystem *fs)
/* find the one with the most free blocks and allocate node there */
/* Idea from find_group_dir in fs/ext2/ialloc.c in 2.4.19 kernel */
/* We do it for all inodes. */
- avefreei = fs->sb.s_free_inodes_count / nbgroups;
+ avefreei = fs->sb->s_free_inodes_count / nbgroups;
for(grp=0; grp<nbgroups; grp++) {
if (fs->gd[grp].bg_free_inodes_count < avefreei ||
fs->gd[grp].bg_free_inodes_count == 0)
@@ -1129,9 +1130,9 @@ alloc_nod(filesystem *fs)
put_blk(bi);
if(!(fs->gd[best_group].bg_free_inodes_count--))
error_msg_and_die("group descr. free blocks count == 0 (corrupted fs?)");
- if(!(fs->sb.s_free_inodes_count--))
+ if(!(fs->sb->s_free_inodes_count--))
error_msg_and_die("superblock free blocks count == 0 (corrupted fs?)");
- return fs->sb.s_inodes_per_group*best_group+nod;
+ return fs->sb->s_inodes_per_group*best_group+nod;
}
// print a bitmap allocation
@@ -1451,7 +1452,7 @@ extend_blk(filesystem *fs, uint32 nod, block b, int amount)
while(create)
{
int i, copyb = 0;
- if(!(fs->sb.s_reserved[200] & OP_HOLES))
+ if(!(fs->sb->s_reserved[200] & OP_HOLES))
copyb = 1;
else
for(i = 0; i < BLOCKSIZE / 4; i++)
@@ -2133,7 +2134,7 @@ swap_goodfs(filesystem *fs)
uint32 i;
nod_info *ni;
- for(i = 1; i < fs->sb.s_inodes_count; i++)
+ for(i = 1; i < fs->sb->s_inodes_count; i++)
{
inode *nod = get_nod(fs, i, &ni);
if(nod->i_mode & FM_IFDIR)
@@ -2158,17 +2159,17 @@ swap_goodfs(filesystem *fs)
}
for(i=0;i<GRP_NBGROUPS(fs);i++)
swap_gd(&(fs->gd[i]));
- swap_sb(&fs->sb);
+ swap_sb(fs->sb);
}
static void
swap_badfs(filesystem *fs)
{
uint32 i;
- swap_sb(&fs->sb);
+ swap_sb(fs->sb);
for(i=0;i<GRP_NBGROUPS(fs);i++)
swap_gd(&(fs->gd[i]));
- for(i = 1; i < fs->sb.s_inodes_count; i++)
+ for(i = 1; i < fs->sb->s_inodes_count; i++)
{
nod_info *ni;
inode *nod = get_nod(fs, i, &ni);
@@ -2242,24 +2243,32 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
free_blocks = nbblocks - overhead_per_group*nbgroups - 1 /*boot block*/;
free_blocks_per_group = nbblocks_per_group - overhead_per_group;
- if(!(fs = (filesystem*)calloc(nbblocks, BLOCKSIZE)))
+ fs = malloc(sizeof(*fs));
+ if (!fs)
error_msg_and_die("not enough memory for filesystem");
+ fs->nheadblocks = (((nbgroups * sizeof(groupdescriptor))
+ + sizeof(superblock) + (BLOCKSIZE - 1))
+ / BLOCKSIZE);
+ if(!(fs->data = calloc(nbblocks, BLOCKSIZE)))
+ error_msg_and_die("not enough memory for filesystem");
+ fs->sb = (superblock *) (fs->data + BLOCKSIZE);
+ fs->gd = (groupdescriptor *) (fs->sb + 1);
// create the superblock for an empty filesystem
- fs->sb.s_inodes_count = nbinodes_per_group * nbgroups;
- fs->sb.s_blocks_count = nbblocks;
- fs->sb.s_r_blocks_count = nbresrvd;
- fs->sb.s_free_blocks_count = free_blocks;
- fs->sb.s_free_inodes_count = fs->sb.s_inodes_count - EXT2_FIRST_INO + 1;
- fs->sb.s_first_data_block = first_block;
- fs->sb.s_log_block_size = BLOCKSIZE >> 11;
- fs->sb.s_log_frag_size = BLOCKSIZE >> 11;
- fs->sb.s_blocks_per_group = nbblocks_per_group;
- fs->sb.s_frags_per_group = nbblocks_per_group;
- fs->sb.s_inodes_per_group = nbinodes_per_group;
- fs->sb.s_wtime = fs_timestamp;
- fs->sb.s_magic = EXT2_MAGIC_NUMBER;
- fs->sb.s_lastcheck = fs_timestamp;
+ fs->sb->s_inodes_count = nbinodes_per_group * nbgroups;
+ fs->sb->s_blocks_count = nbblocks;
+ fs->sb->s_r_blocks_count = nbresrvd;
+ fs->sb->s_free_blocks_count = free_blocks;
+ fs->sb->s_free_inodes_count = fs->sb->s_inodes_count - EXT2_FIRST_INO + 1;
+ fs->sb->s_first_data_block = first_block;
+ fs->sb->s_log_block_size = BLOCKSIZE >> 11;
+ fs->sb->s_log_frag_size = BLOCKSIZE >> 11;
+ fs->sb->s_blocks_per_group = nbblocks_per_group;
+ fs->sb->s_frags_per_group = nbblocks_per_group;
+ fs->sb->s_inodes_per_group = nbinodes_per_group;
+ fs->sb->s_wtime = fs_timestamp;
+ fs->sb->s_magic = EXT2_MAGIC_NUMBER;
+ fs->sb->s_lastcheck = fs_timestamp;
// set up groupdescriptors
for(i=0, bbmpos=gdsz+2, ibmpos=bbmpos+1, itblpos=ibmpos+1;
@@ -2301,7 +2310,7 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
/* Inode bitmap */
ibm = get_blk(fs,fs->gd[i].bg_inode_bitmap, &bi);
//non-filesystem inodes
- for(j = fs->sb.s_inodes_per_group+1; j <= BLOCKSIZE * 8; j++)
+ for(j = fs->sb->s_inodes_per_group+1; j <= BLOCKSIZE * 8; j++)
allocate(ibm, j);
//system inodes
@@ -2332,7 +2341,7 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
put_dir(&dw);
// make lost+found directory and reserve blocks
- if(fs->sb.s_r_blocks_count)
+ if(fs->sb->s_r_blocks_count)
{
inode *node;
uint8 *b;
@@ -2344,23 +2353,23 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
/* We run into problems with e2fsck if directory lost+found grows
* bigger than this. Need to find out why this happens - sundar
*/
- if (fs->sb.s_r_blocks_count > fs->sb.s_blocks_count * MAX_RESERVED_BLOCKS )
- fs->sb.s_r_blocks_count = fs->sb.s_blocks_count * MAX_RESERVED_BLOCKS;
- for(i = 1; i < fs->sb.s_r_blocks_count; i++)
+ if (fs->sb->s_r_blocks_count > fs->sb->s_blocks_count * MAX_RESERVED_BLOCKS )
+ fs->sb->s_r_blocks_count = fs->sb->s_blocks_count * MAX_RESERVED_BLOCKS;
+ for(i = 1; i < fs->sb->s_r_blocks_count; i++)
extend_blk(fs, nod, b, 1);
free_workblk(b);
node = get_nod(fs, nod, &ni);
- node->i_size = fs->sb.s_r_blocks_count * BLOCKSIZE;
+ node->i_size = fs->sb->s_r_blocks_count * BLOCKSIZE;
put_nod(ni);
}
// administrative info
- fs->sb.s_state = 1;
- fs->sb.s_max_mnt_count = 20;
+ fs->sb->s_state = 1;
+ fs->sb->s_max_mnt_count = 20;
// options for me
if(holes)
- fs->sb.s_reserved[200] |= OP_HOLES;
+ fs->sb->s_reserved[200] |= OP_HOLES;
return fs;
}
@@ -2377,20 +2386,29 @@ load_fs(FILE * fh, int swapit)
fssize = (fssize + BLOCKSIZE - 1) / BLOCKSIZE;
if(fssize < 16) // totally arbitrary
error_msg_and_die("too small filesystem");
- if(!(fs = (filesystem*)calloc(fssize, BLOCKSIZE)))
+ fs = malloc(sizeof(*fs));
+ if (!fs)
+ error_msg_and_die("not enough memory for filesystem");
+ if(!(fs->data = calloc(fssize, BLOCKSIZE)))
error_msg_and_die("not enough memory for filesystem");
- if(fread(fs, BLOCKSIZE, fssize, fh) != fssize)
+ if(fread(fs->data, BLOCKSIZE, fssize, fh) != fssize)
perror_msg_and_die("input filesystem image");
+ fs->sb = (superblock *) (fs->data + BLOCKSIZE);
+ fs->gd = (groupdescriptor *) (fs->sb + 1);
if(swapit)
swap_badfs(fs);
- if(fs->sb.s_rev_level || (fs->sb.s_magic != EXT2_MAGIC_NUMBER))
+ if(fs->sb->s_rev_level || (fs->sb->s_magic != EXT2_MAGIC_NUMBER))
error_msg_and_die("not a suitable ext2 filesystem");
+ fs->nheadblocks = (((GRP_NBGROUPS(fs) * sizeof(groupdescriptor))
+ + sizeof(superblock) + (BLOCKSIZE - 1))
+ / BLOCKSIZE);
return fs;
}
static void
free_fs(filesystem *fs)
{
+ free(fs->data);
free(fs);
}
@@ -2645,19 +2663,19 @@ print_fs(filesystem *fs)
uint8 *ibm;
printf("%d blocks (%d free, %d reserved), first data block: %d\n",
- fs->sb.s_blocks_count, fs->sb.s_free_blocks_count,
- fs->sb.s_r_blocks_count, fs->sb.s_first_data_block);
- printf("%d inodes (%d free)\n", fs->sb.s_inodes_count,
- fs->sb.s_free_inodes_count);
+ fs->sb->s_blocks_count, fs->sb->s_free_blocks_count,
+ fs->sb->s_r_blocks_count, fs->sb->s_first_data_block);
+ printf("%d inodes (%d free)\n", fs->sb->s_inodes_count,
+ fs->sb->s_free_inodes_count);
printf("block size = %d, frag size = %d\n",
- fs->sb.s_log_block_size ? (fs->sb.s_log_block_size << 11) : 1024,
- fs->sb.s_log_frag_size ? (fs->sb.s_log_frag_size << 11) : 1024);
+ fs->sb->s_log_block_size ? (fs->sb->s_log_block_size << 11) : 1024,
+ fs->sb->s_log_frag_size ? (fs->sb->s_log_frag_size << 11) : 1024);
printf("number of groups: %d\n",GRP_NBGROUPS(fs));
printf("%d blocks per group,%d frags per group,%d inodes per group\n",
- fs->sb.s_blocks_per_group, fs->sb.s_frags_per_group,
- fs->sb.s_inodes_per_group);
+ fs->sb->s_blocks_per_group, fs->sb->s_frags_per_group,
+ fs->sb->s_inodes_per_group);
printf("Size of inode table: %d blocks\n",
- (int)(fs->sb.s_inodes_per_group * sizeof(inode) / BLOCKSIZE));
+ (int)(fs->sb->s_inodes_per_group * sizeof(inode) / BLOCKSIZE));
for (i = 0; i < GRP_NBGROUPS(fs); i++) {
printf("Group No: %d\n", i+1);
printf("block bitmap: block %d,inode bitmap: block %d, inode table: block %d\n",
@@ -2665,12 +2683,12 @@ print_fs(filesystem *fs)
fs->gd[i].bg_inode_table);
printf("block bitmap allocation:\n");
print_bm(GRP_GET_GROUP_BBM(fs, i, &bi),
- fs->sb.s_blocks_per_group);
+ fs->sb->s_blocks_per_group);
GRP_PUT_GROUP_BBM(bi);
printf("inode bitmap allocation:\n");
ibm = GRP_GET_GROUP_IBM(fs, i, &bi);
- print_bm(ibm, fs->sb.s_inodes_per_group);
- for (i = 1; i <= fs->sb.s_inodes_per_group; i++)
+ print_bm(ibm, fs->sb->s_inodes_per_group);
+ for (i = 1; i <= fs->sb->s_inodes_per_group; i++)
if (allocated(ibm, i))
print_inode(fs, i);
GRP_PUT_GROUP_IBM(bi);
@@ -2680,11 +2698,11 @@ print_fs(filesystem *fs)
static void
dump_fs(filesystem *fs, FILE * fh, int swapit)
{
- uint32 nbblocks = fs->sb.s_blocks_count;
- fs->sb.s_reserved[200] = 0;
+ uint32 nbblocks = fs->sb->s_blocks_count;
+ fs->sb->s_reserved[200] = 0;
if(swapit)
swap_goodfs(fs);
- if(fwrite(fs, BLOCKSIZE, nbblocks, fh) < nbblocks)
+ if(fwrite(fs->data, BLOCKSIZE, nbblocks, fh) < nbblocks)
perror_msg_and_die("output filesystem image");
if(swapit)
swap_badfs(fs);
@@ -2944,7 +2962,7 @@ main(int argc, char **argv)
if(emptyval) {
uint32 b;
- for(b = 1; b < fs->sb.s_blocks_count; b++) {
+ for(b = 1; b < fs->sb->s_blocks_count; b++) {
blk_info *bi;
if(!allocated(GRP_GET_BLOCK_BITMAP(fs,b,&bi),
GRP_BBM_OFFSET(fs,b))) {
--
1.7.4.1

View File

@ -0,0 +1,272 @@
Upstream-Status: inappropriate
From ea6cbe2880e02026667b9007db9a742be7dcd52b Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Sun, 5 Jun 2011 10:26:11 -0500
Subject: [PATCH 06/19] Improve the efficiency of extend_blk
When doing multiple extensions operations on the same inode, extend_blk()
would search to the end every time. In the current structure, that means
when creating the reserved blocks, it could parse over the block list
many thousands of time on a large filesystem. For an 800MB filesystem,
that took 2/3rds of the time.
So create a structure for holding the inode position and use it to
know where the end is. This neatens things up a bit, too, more
clearly showing when a truncate or extend is occuring. In future
changes, this will also make it efficient for supporting very large
files that cannot be fully allocated in memory.
---
genext2fs.c | 147 ++++++++++++++++++++++++++++++++++++++++-------------------
1 files changed, 100 insertions(+), 47 deletions(-)
diff --git a/genext2fs.c b/genext2fs.c
index 46c9605..e45e520 100644
--- a/genext2fs.c
+++ b/genext2fs.c
@@ -436,6 +436,17 @@ swab32(uint32 val)
((val<<8)&0xFF0000) | (val<<24));
}
+static inline int
+is_blk_empty(uint8 *b)
+{
+ uint32 i;
+ uint32 *v = (uint32 *) b;
+
+ for(i = 0; i < BLOCKSIZE / 4; i++)
+ if (*v++)
+ return 0;
+ return 1;
+}
// on-disk structures
// this trick makes me declare things only once
@@ -1165,7 +1176,6 @@ init_bw(blockwalker *bw)
// used after being freed, so once you start
// freeing blocks don't stop until the end of
// the file. moreover, i_blocks isn't updated.
-// in fact, don't do that, just use extend_blk
// if hole!=0, create a hole in the file
static uint32
walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
@@ -1422,52 +1432,80 @@ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
return bk;
}
-// add blocks to an inode (file/dir/etc...)
-static void
-extend_blk(filesystem *fs, uint32 nod, block b, int amount)
+typedef struct
{
- int create = amount;
- blockwalker bw, lbw;
- uint32 bk;
+ blockwalker bw;
+ uint32 nod;
nod_info *ni;
inode *inod;
+} inode_pos;
+#define INODE_POS_TRUNCATE 0
+#define INODE_POS_EXTEND 1
+
+// Call this to set up an ipos structure for future use with
+// extend_inode_blk to append blocks to the given inode. If
+// op is INODE_POS_TRUNCATE, the inode is truncated to zero size.
+// If op is INODE_POS_EXTEND, the position is moved to the end
+// of the inode's data blocks.
+// Call inode_pos_finish when done with the inode_pos structure.
+static void
+inode_pos_init(filesystem *fs, inode_pos *ipos, uint32 nod, int op,
+ blockwalker *endbw)
+{
+ blockwalker lbw;
- inod = get_nod(fs, nod, &ni);
- init_bw(&bw);
- if(amount < 0)
- {
- uint32 i;
- for(i = 0; i < inod->i_blocks / INOBLK + amount; i++)
- walk_bw(fs, nod, &bw, 0, 0);
- while(walk_bw(fs, nod, &bw, &create, 0) != WALK_END)
+ init_bw(&ipos->bw);
+ ipos->nod = nod;
+ ipos->inod = get_nod(fs, nod, &ipos->ni);
+ if (op == INODE_POS_TRUNCATE) {
+ int32 create = -1;
+ while(walk_bw(fs, nod, &ipos->bw, &create, 0) != WALK_END)
/*nop*/;
- inod->i_blocks += amount * INOBLK;
+ ipos->inod->i_blocks = 0;
}
- else
+
+ if (endbw)
+ ipos->bw = *endbw;
+ else {
+ /* Seek to the end */
+ init_bw(&ipos->bw);
+ lbw = ipos->bw;
+ while(walk_bw(fs, nod, &ipos->bw, 0, 0) != WALK_END)
+ lbw = ipos->bw;
+ ipos->bw = lbw;
+ }
+}
+
+// Clean up the inode_pos structure.
+static void
+inode_pos_finish(filesystem *fs, inode_pos *ipos)
+{
+ put_nod(ipos->ni);
+}
+
+// add blocks to an inode (file/dir/etc...) at the given position.
+// This will only work when appending to the end of an inode.
+static void
+extend_inode_blk(filesystem *fs, inode_pos *ipos, block b, int amount)
+{
+ uint32 bk;
+ uint32 pos;
+
+ if (amount < 0)
+ error_msg_and_die("extend_inode_blk: Got negative amount");
+
+ for (pos = 0; amount; pos += BLOCKSIZE)
{
- lbw = bw;
- while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END)
- lbw = bw;
- bw = lbw;
- while(create)
- {
- int i, copyb = 0;
- if(!(fs->sb->s_reserved[200] & OP_HOLES))
- copyb = 1;
- else
- for(i = 0; i < BLOCKSIZE / 4; i++)
- if(((int32*)(b + BLOCKSIZE * (amount - create)))[i])
- {
- copyb = 1;
- break;
- }
- if((bk = walk_bw(fs, nod, &bw, &create, !copyb)) == WALK_END)
- break;
- if(copyb) {
- blk_info *bi;
- memcpy(get_blk(fs, bk, &bi), b + BLOCKSIZE * (amount - create - 1), BLOCKSIZE);
- put_blk(bi);
- }
+ int hole = ((fs->sb->s_reserved[200] & OP_HOLES) && is_blk_empty(b + pos));
+
+ bk = walk_bw(fs, ipos->nod, &ipos->bw, &amount, hole);
+ if (bk == WALK_END)
+ error_msg_and_die("extend_inode_blk: extend failed");
+ if (!hole) {
+ blk_info *bi;
+ uint8 *block = get_blk(fs, bk, &bi);
+ memcpy(block, b + pos, BLOCKSIZE);
+ put_blk(bi);
}
}
}
@@ -1484,6 +1522,7 @@ add2dir(filesystem *fs, uint32 dnod, uint32 nod, const char* name)
inode *node;
inode *pnode;
nod_info *dni, *ni;
+ inode_pos ipos;
pnode = get_nod(fs, dnod, &dni);
if((pnode->i_mode & FM_IFMT) != FM_IFDIR)
@@ -1534,7 +1573,11 @@ add2dir(filesystem *fs, uint32 dnod, uint32 nod, const char* name)
node->i_links_count++;
put_nod(ni);
next_dir(&dw); // Force the data into the buffer
- extend_blk(fs, dnod, dir_data(&dw), 1);
+
+ inode_pos_init(fs, &ipos, dnod, INODE_POS_EXTEND, &lbw);
+ extend_inode_blk(fs, &ipos, dir_data(&dw), 1);
+ inode_pos_finish(fs, &ipos);
+
put_dir(&dw);
pnode->i_size += BLOCKSIZE;
out:
@@ -1654,8 +1697,9 @@ mklink_fs(filesystem *fs, uint32 parent_nod, const char *name, size_t size, uint
uint32 nod = mknod_fs(fs, parent_nod, name, FM_IFLNK | FM_IRWXU | FM_IRWXG | FM_IRWXO, uid, gid, 0, 0, ctime, mtime);
nod_info *ni;
inode *node = get_nod(fs, nod, &ni);
+ inode_pos ipos;
- extend_blk(fs, nod, 0, - (int)node->i_blocks / INOBLK);
+ inode_pos_init(fs, &ipos, nod, INODE_POS_TRUNCATE, NULL);
node->i_size = size;
if(size <= 4 * (EXT2_TIND_BLOCK+1))
{
@@ -1663,7 +1707,8 @@ mklink_fs(filesystem *fs, uint32 parent_nod, const char *name, size_t size, uint
put_nod(ni);
return nod;
}
- extend_blk(fs, nod, b, rndup(size, BLOCKSIZE) / BLOCKSIZE);
+ extend_inode_blk(fs, &ipos, b, rndup(size, BLOCKSIZE) / BLOCKSIZE);
+ inode_pos_finish(fs, &ipos);
put_nod(ni);
return nod;
}
@@ -1676,8 +1721,9 @@ mkfile_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode, size
uint32 nod = mknod_fs(fs, parent_nod, name, mode|FM_IFREG, uid, gid, 0, 0, ctime, mtime);
nod_info *ni;
inode *node = get_nod(fs, nod, &ni);
+ inode_pos ipos;
- extend_blk(fs, nod, 0, - (int)node->i_blocks / INOBLK);
+ inode_pos_init(fs, &ipos, nod, INODE_POS_TRUNCATE, NULL);
node->i_size = size;
if (size) {
if(!(b = (uint8*)calloc(rndup(size, BLOCKSIZE), 1)))
@@ -1685,9 +1731,11 @@ mkfile_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode, size
if(f)
if (fread(b, size, 1, f) != 1) // FIXME: ugly. use mmap() ...
error_msg_and_die("fread failed");
- extend_blk(fs, nod, b, rndup(size, BLOCKSIZE) / BLOCKSIZE);
+ extend_inode_blk(fs, &ipos, b,
+ rndup(size, BLOCKSIZE) / BLOCKSIZE);
free(b);
}
+ inode_pos_finish(fs, &ipos);
put_nod(ni);
return nod;
}
@@ -2210,6 +2258,7 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
inode *itab0;
blk_info *bi;
nod_info *ni;
+ inode_pos ipos;
if(nbresrvd < 0)
error_msg_and_die("reserved blocks value is invalid. Note: options have changed, see --help or the man page.");
@@ -2337,7 +2386,9 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
new_dir(fs, EXT2_ROOT_INO, ".", 1, &dw);
shrink_dir(&dw, EXT2_ROOT_INO, "..", 2);
next_dir(&dw); // Force the data into the buffer
- extend_blk(fs, EXT2_ROOT_INO, dir_data(&dw), 1);
+ inode_pos_init(fs, &ipos, EXT2_ROOT_INO, INODE_POS_EXTEND, NULL);
+ extend_inode_blk(fs, &ipos, dir_data(&dw), 1);
+ inode_pos_finish(fs, &ipos);
put_dir(&dw);
// make lost+found directory and reserve blocks
@@ -2355,8 +2406,10 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
*/
if (fs->sb->s_r_blocks_count > fs->sb->s_blocks_count * MAX_RESERVED_BLOCKS )
fs->sb->s_r_blocks_count = fs->sb->s_blocks_count * MAX_RESERVED_BLOCKS;
+ inode_pos_init(fs, &ipos, nod, INODE_POS_EXTEND, NULL);
for(i = 1; i < fs->sb->s_r_blocks_count; i++)
- extend_blk(fs, nod, b, 1);
+ extend_inode_blk(fs, &ipos, b, 1);
+ inode_pos_finish(fs, &ipos);
free_workblk(b);
node = get_nod(fs, nod, &ni);
node->i_size = fs->sb->s_r_blocks_count * BLOCKSIZE;
--
1.7.4.1

View File

@ -0,0 +1,175 @@
Upstream-Status: inappropriate
From 1ea2332c6cec1fb979a7cb4502360005bed50da4 Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Sun, 5 Jun 2011 14:08:02 -0500
Subject: [PATCH 07/19] Move hdlinks into the filesystem structure.
Since the hard links structures are associated with a filesystem, put
them in the filesystem structure since it can hold other stuff now.
---
genext2fs.c | 71 +++++++++++++++++++++++++++++++---------------------------
1 files changed, 38 insertions(+), 33 deletions(-)
diff --git a/genext2fs.c b/genext2fs.c
index e45e520..d130362 100644
--- a/genext2fs.c
+++ b/genext2fs.c
@@ -583,6 +583,18 @@ typedef struct
uint32 bptind;
} blockwalker;
+#define HDLINK_CNT 16
+struct hdlink_s
+{
+ uint32 src_inode;
+ uint32 dst_nod;
+};
+
+struct hdlinks_s
+{
+ int32 count;
+ struct hdlink_s *hdl;
+};
/* Filesystem structure that support groups */
#if BLOCKSIZE == 1024
@@ -592,6 +604,8 @@ typedef struct
superblock *sb;
groupdescriptor *gd;
uint32 nheadblocks;
+ int32 hdlink_cnt;
+ struct hdlinks_s hdlinks;
} filesystem;
#else
#error UNHANDLED BLOCKSIZE
@@ -615,22 +629,6 @@ typedef struct
#define udecl32(x) this->x = swab32(this->x);
#define utdecl32(x,n) { int i; for(i=0; i<n; i++) this->x[i] = swab32(this->x[i]); }
-#define HDLINK_CNT 16
-static int32 hdlink_cnt = HDLINK_CNT;
-struct hdlink_s
-{
- uint32 src_inode;
- uint32 dst_nod;
-};
-
-struct hdlinks_s
-{
- int32 count;
- struct hdlink_s *hdl;
-};
-
-static struct hdlinks_s hdlinks;
-
static void
swap_sb(superblock *sb)
{
@@ -787,12 +785,12 @@ xreadlink(const char *path)
}
int
-is_hardlink(ino_t inode)
+is_hardlink(filesystem *fs, ino_t inode)
{
int i;
- for(i = 0; i < hdlinks.count; i++) {
- if(hdlinks.hdl[i].src_inode == inode)
+ for(i = 0; i < fs->hdlinks.count; i++) {
+ if(fs->hdlinks.hdl[i].src_inode == inode)
return i;
}
return -1;
@@ -1989,9 +1987,9 @@ add2fs_from_dir(filesystem *fs, uint32 this_nod, int squash_uids, int squash_per
save_nod = 0;
/* Check for hardlinks */
if (!S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode) && st.st_nlink > 1) {
- int32 hdlink = is_hardlink(st.st_ino);
+ int32 hdlink = is_hardlink(fs, st.st_ino);
if (hdlink >= 0) {
- add2dir(fs, this_nod, hdlinks.hdl[hdlink].dst_nod, name);
+ add2dir(fs, this_nod, fs->hdlinks.hdl[hdlink].dst_nod, name);
continue;
} else {
save_nod = 1;
@@ -2035,17 +2033,17 @@ add2fs_from_dir(filesystem *fs, uint32 this_nod, int squash_uids, int squash_per
error_msg("ignoring entry %s", name);
}
if (save_nod) {
- if (hdlinks.count == hdlink_cnt) {
- if ((hdlinks.hdl =
- realloc (hdlinks.hdl, (hdlink_cnt + HDLINK_CNT) *
+ if (fs->hdlinks.count == fs->hdlink_cnt) {
+ if ((fs->hdlinks.hdl =
+ realloc (fs->hdlinks.hdl, (fs->hdlink_cnt + HDLINK_CNT) *
sizeof (struct hdlink_s))) == NULL) {
error_msg_and_die("Not enough memory");
}
- hdlink_cnt += HDLINK_CNT;
+ fs->hdlink_cnt += HDLINK_CNT;
}
- hdlinks.hdl[hdlinks.count].src_inode = st.st_ino;
- hdlinks.hdl[hdlinks.count].dst_nod = nod;
- hdlinks.count++;
+ fs->hdlinks.hdl[fs->hdlinks.count].src_inode = st.st_ino;
+ fs->hdlinks.hdl[fs->hdlinks.count].dst_nod = nod;
+ fs->hdlinks.count++;
}
}
}
@@ -2300,6 +2298,11 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
/ BLOCKSIZE);
if(!(fs->data = calloc(nbblocks, BLOCKSIZE)))
error_msg_and_die("not enough memory for filesystem");
+ fs->hdlink_cnt = HDLINK_CNT;
+ fs->hdlinks.hdl = calloc(sizeof(struct hdlink_s), fs->hdlink_cnt);
+ if (!fs->hdlinks.hdl)
+ error_msg_and_die("Not enough memory");
+ fs->hdlinks.count = 0 ;
fs->sb = (superblock *) (fs->data + BLOCKSIZE);
fs->gd = (groupdescriptor *) (fs->sb + 1);
@@ -2442,12 +2445,18 @@ load_fs(FILE * fh, int swapit)
fs = malloc(sizeof(*fs));
if (!fs)
error_msg_and_die("not enough memory for filesystem");
+ fs->hdlink_cnt = HDLINK_CNT;
+ fs->hdlinks.hdl = calloc(sizeof(struct hdlink_s), fs->hdlink_cnt);
+ if (!fs->hdlinks.hdl)
+ error_msg_and_die("Not enough memory");
+ fs->hdlinks.count = 0 ;
if(!(fs->data = calloc(fssize, BLOCKSIZE)))
error_msg_and_die("not enough memory for filesystem");
if(fread(fs->data, BLOCKSIZE, fssize, fh) != fssize)
perror_msg_and_die("input filesystem image");
fs->sb = (superblock *) (fs->data + BLOCKSIZE);
fs->gd = (groupdescriptor *) (fs->sb + 1);
+
if(swapit)
swap_badfs(fs);
if(fs->sb->s_rev_level || (fs->sb->s_magic != EXT2_MAGIC_NUMBER))
@@ -2461,6 +2470,7 @@ load_fs(FILE * fh, int swapit)
static void
free_fs(filesystem *fs)
{
+ free(fs->hdlinks.hdl);
free(fs->data);
free(fs);
}
@@ -2964,11 +2974,6 @@ main(int argc, char **argv)
error_msg_and_die("Not enough arguments. Try --help or else see the man page.");
fsout = argv[optind];
- hdlinks.hdl = (struct hdlink_s *)malloc(hdlink_cnt * sizeof(struct hdlink_s));
- if (!hdlinks.hdl)
- error_msg_and_die("Not enough memory");
- hdlinks.count = 0 ;
-
if(fsin)
{
if(strcmp(fsin, "-"))
--
1.7.4.1

View File

@ -0,0 +1,95 @@
Upstream-Status: inappropriate
From 797e8548e5857b7a0586b27a9bdcadbea1561d8d Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Sun, 5 Jun 2011 14:53:57 -0500
Subject: [PATCH 08/19] Separate out the creation of the filesystem structure.
Consolidate some processing that occurs when allocating a filesystem
structure.
---
genext2fs.c | 49 +++++++++++++++++++++++++------------------------
1 files changed, 25 insertions(+), 24 deletions(-)
diff --git a/genext2fs.c b/genext2fs.c
index d130362..497c9af 100644
--- a/genext2fs.c
+++ b/genext2fs.c
@@ -2240,6 +2240,29 @@ swap_badfs(filesystem *fs)
}
}
+// Allocate a new filesystem structure, allocate internal memory,
+// and initialize the contents.
+static filesystem *
+alloc_fs(uint32 nbblocks)
+{
+ filesystem *fs;
+
+ fs = malloc(sizeof(*fs));
+ if (!fs)
+ error_msg_and_die("not enough memory for filesystem");
+ memset(fs, 0, sizeof(*fs));
+ if(!(fs->data = calloc(nbblocks, BLOCKSIZE)))
+ error_msg_and_die("not enough memory for filesystem");
+ fs->hdlink_cnt = HDLINK_CNT;
+ fs->hdlinks.hdl = calloc(sizeof(struct hdlink_s), fs->hdlink_cnt);
+ if (!fs->hdlinks.hdl)
+ error_msg_and_die("Not enough memory");
+ fs->hdlinks.count = 0 ;
+ fs->sb = (superblock *) (fs->data + BLOCKSIZE);
+ fs->gd = (groupdescriptor *) (fs->sb + 1);
+ return fs;
+}
+
// initialize an empty filesystem
static filesystem *
init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp)
@@ -2290,21 +2313,10 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
free_blocks = nbblocks - overhead_per_group*nbgroups - 1 /*boot block*/;
free_blocks_per_group = nbblocks_per_group - overhead_per_group;
- fs = malloc(sizeof(*fs));
- if (!fs)
- error_msg_and_die("not enough memory for filesystem");
+ fs = alloc_fs(nbblocks);
fs->nheadblocks = (((nbgroups * sizeof(groupdescriptor))
+ sizeof(superblock) + (BLOCKSIZE - 1))
/ BLOCKSIZE);
- if(!(fs->data = calloc(nbblocks, BLOCKSIZE)))
- error_msg_and_die("not enough memory for filesystem");
- fs->hdlink_cnt = HDLINK_CNT;
- fs->hdlinks.hdl = calloc(sizeof(struct hdlink_s), fs->hdlink_cnt);
- if (!fs->hdlinks.hdl)
- error_msg_and_die("Not enough memory");
- fs->hdlinks.count = 0 ;
- fs->sb = (superblock *) (fs->data + BLOCKSIZE);
- fs->gd = (groupdescriptor *) (fs->sb + 1);
// create the superblock for an empty filesystem
fs->sb->s_inodes_count = nbinodes_per_group * nbgroups;
@@ -2442,20 +2454,9 @@ load_fs(FILE * fh, int swapit)
fssize = (fssize + BLOCKSIZE - 1) / BLOCKSIZE;
if(fssize < 16) // totally arbitrary
error_msg_and_die("too small filesystem");
- fs = malloc(sizeof(*fs));
- if (!fs)
- error_msg_and_die("not enough memory for filesystem");
- fs->hdlink_cnt = HDLINK_CNT;
- fs->hdlinks.hdl = calloc(sizeof(struct hdlink_s), fs->hdlink_cnt);
- if (!fs->hdlinks.hdl)
- error_msg_and_die("Not enough memory");
- fs->hdlinks.count = 0 ;
- if(!(fs->data = calloc(fssize, BLOCKSIZE)))
- error_msg_and_die("not enough memory for filesystem");
+ fs = alloc_fs(fssize);
if(fread(fs->data, BLOCKSIZE, fssize, fh) != fssize)
perror_msg_and_die("input filesystem image");
- fs->sb = (superblock *) (fs->data + BLOCKSIZE);
- fs->gd = (groupdescriptor *) (fs->sb + 1);
if(swapit)
swap_badfs(fs);
--
1.7.4.1

View File

@ -0,0 +1,421 @@
Upstream-Status: inappropriate
From 46d57a42a2185970807971f4d6d8f62b4facbaf5 Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Sun, 5 Jun 2011 15:00:15 -0500
Subject: [PATCH 09/19] Move byte swapping into the get/put routines.
Remove the full byte-swapping of the filesystem at start/end time, and
instead byteswap each inode/block map/directory as it is read and written.
This is getting ready for the change of not holding the entire filesystem
in memory.
---
genext2fs.c | 234 +++++++++++++---------------------------------------------
1 files changed, 53 insertions(+), 181 deletions(-)
diff --git a/genext2fs.c b/genext2fs.c
index 497c9af..51403a2 100644
--- a/genext2fs.c
+++ b/genext2fs.c
@@ -604,6 +604,7 @@ typedef struct
superblock *sb;
groupdescriptor *gd;
uint32 nheadblocks;
+ int swapit;
int32 hdlink_cnt;
struct hdlinks_s hdlinks;
} filesystem;
@@ -648,9 +649,24 @@ swap_gd(groupdescriptor *gd)
static void
swap_nod(inode *nod)
{
+ uint32 nblk;
+
#define this nod
inode_decl
#undef this
+
+ // block and character inodes store the major and minor in the
+ // i_block, so we need to unswap to get those. Also, if it's
+ // zero iblocks, put the data back like it belongs.
+ nblk = nod->i_blocks / INOBLK;
+ if ((nod->i_size && !nblk)
+ || ((nod->i_mode & FM_IFBLK) == FM_IFBLK)
+ || ((nod->i_mode & FM_IFCHR) == FM_IFCHR))
+ {
+ int i;
+ for(i = 0; i <= EXT2_TIND_BLOCK; i++)
+ nod->i_block[i] = swab32(nod->i_block[i]);
+ }
}
static void
@@ -852,6 +868,8 @@ put_blk(blk_info *bi)
// owned by the user.
typedef struct
{
+ filesystem *fs;
+ uint8 *b;
blk_info *bi;
} blkmap_info;
@@ -861,19 +879,23 @@ static inline uint32 *
get_blkmap(filesystem *fs, uint32 blk, blkmap_info **rbmi)
{
blkmap_info *bmi;
- uint8 *b;
bmi = malloc(sizeof(*bmi));
if (!bmi)
error_msg_and_die("get_blkmap: out of memory");
- b = get_blk(fs, blk, &bmi->bi);
+ bmi->fs = fs;
+ bmi->b = get_blk(fs, blk, &bmi->bi);
+ if (bmi->fs->swapit)
+ swap_block(bmi->b);
*rbmi = bmi;
- return (uint32 *) b;
+ return (uint32 *) bmi->b;
}
static inline void
put_blkmap(blkmap_info *bmi)
{
+ if (bmi->fs->swapit)
+ swap_block(bmi->b);
put_blk(bmi->bi);
free(bmi);
}
@@ -882,7 +904,9 @@ put_blkmap(blkmap_info *bmi)
// by the user.
typedef struct
{
+ filesystem *fs;
blk_info *bi;
+ inode *itab;
} nod_info;
// Return a given inode from a filesystem. Make sure to call put_nod()
@@ -891,8 +915,8 @@ static inline inode *
get_nod(filesystem *fs, uint32 nod, nod_info **rni)
{
int grp, offset, boffset;
- inode *itab;
nod_info *ni;
+ uint8 *b;
offset = GRP_IBM_OFFSET(fs,nod) - 1;
boffset = offset / (BLOCKSIZE / sizeof(inode));
@@ -901,14 +925,20 @@ get_nod(filesystem *fs, uint32 nod, nod_info **rni)
ni = malloc(sizeof(*ni));
if (!ni)
error_msg_and_die("get_nod: out of memory");
- itab = (inode *)get_blk(fs, fs->gd[grp].bg_inode_table + boffset, &ni->bi);
+ ni->fs = fs;
+ b = get_blk(fs, fs->gd[grp].bg_inode_table + boffset, &ni->bi);
+ ni->itab = ((inode *) b) + offset;
+ if (fs->swapit)
+ swap_nod(ni->itab);
*rni = ni;
- return itab+offset;
+ return ni->itab;
}
static inline void
put_nod(nod_info *ni)
{
+ if (ni->fs->swapit)
+ swap_nod(ni->itab);
put_blk(ni->bi);
free(ni);
}
@@ -936,6 +966,8 @@ get_dir(filesystem *fs, uint32 nod, dirwalker *dw)
dw->last_d = (directory *) dw->b;
memcpy(&dw->d, dw->last_d, sizeof(directory));
+ if (fs->swapit)
+ swap_dir(&dw->d);
return &dw->d;
}
@@ -945,6 +977,8 @@ next_dir(dirwalker *dw)
{
directory *next_d = (directory *)((int8*)dw->last_d + dw->d.d_rec_len);
+ if (dw->fs->swapit)
+ swap_dir(&dw->d);
memcpy(dw->last_d, &dw->d, sizeof(directory));
if (((int8 *) next_d) >= ((int8 *) dw->b + BLOCKSIZE))
@@ -952,6 +986,8 @@ next_dir(dirwalker *dw)
dw->last_d = next_d;
memcpy(&dw->d, next_d, sizeof(directory));
+ if (dw->fs->swapit)
+ swap_dir(&dw->d);
return &dw->d;
}
@@ -959,6 +995,8 @@ next_dir(dirwalker *dw)
static inline void
put_dir(dirwalker *dw)
{
+ if (dw->fs->swapit)
+ swap_dir(&dw->d);
memcpy(dw->last_d, &dw->d, sizeof(directory));
if (dw->nod == 0)
@@ -998,6 +1036,8 @@ shrink_dir(dirwalker *dw, uint32 nod, const char *name, int nlen)
d->d_rec_len = sizeof(directory) + rndup(d->d_name_len, 4);
preclen = d->d_rec_len;
reclen -= preclen;
+ if (dw->fs->swapit)
+ swap_dir(&dw->d);
memcpy(dw->last_d, &dw->d, sizeof(directory));
dw->last_d = (directory *) (((int8 *) dw->last_d) + preclen);
@@ -2050,159 +2090,12 @@ add2fs_from_dir(filesystem *fs, uint32 this_nod, int squash_uids, int squash_per
closedir(dh);
}
-// endianness swap of x-indirect blocks
-static void
-swap_goodblocks(filesystem *fs, inode *nod)
-{
- uint32 i,j;
- int done=0;
- uint32 *b,*b2;
- blk_info *bi, *bi2, *bi3;
-
- uint32 nblk = nod->i_blocks / INOBLK;
- if((nod->i_size && !nblk) || ((nod->i_mode & FM_IFBLK) == FM_IFBLK) || ((nod->i_mode & FM_IFCHR) == FM_IFCHR))
- for(i = 0; i <= EXT2_TIND_BLOCK; i++)
- nod->i_block[i] = swab32(nod->i_block[i]);
- if(nblk <= EXT2_IND_BLOCK)
- return;
- swap_block(get_blk(fs, nod->i_block[EXT2_IND_BLOCK], &bi));
- put_blk(bi);
- if(nblk <= EXT2_DIND_BLOCK + BLOCKSIZE/4)
- return;
- /* Currently this will fail b'cos the number of blocks as stored
- in i_blocks also includes the indirection blocks (see
- walk_bw). But this function assumes that i_blocks only
- stores the count of data blocks ( Actually according to
- "Understanding the Linux Kernel" (Table 17-3 p502 1st Ed)
- i_blocks IS supposed to store the count of data blocks). so
- with a file of size 268K nblk would be 269.The above check
- will be false even though double indirection hasn't been
- started.This is benign as 0 means block 0 which has been
- zeroed out and therefore points back to itself from any offset
- */
- // FIXME: I have fixed that, but I have the feeling the rest of
- // ths function needs to be fixed for the same reasons - Xav
- assert(nod->i_block[EXT2_DIND_BLOCK] != 0);
- for(i = 0; i < BLOCKSIZE/4; i++)
- if(nblk > EXT2_IND_BLOCK + BLOCKSIZE/4 + (BLOCKSIZE/4)*i ) {
- swap_block(get_blk(fs, ((uint32*)get_blk(fs, nod->i_block[EXT2_DIND_BLOCK], &bi))[i], &bi2));
- put_blk(bi);
- put_blk(bi2);
- }
- swap_block(get_blk(fs, nod->i_block[EXT2_DIND_BLOCK], &bi));
- put_blk(bi);
- if(nblk <= EXT2_IND_BLOCK + BLOCKSIZE/4 + BLOCKSIZE/4 * BLOCKSIZE/4)
- return;
- /* Adding support for triple indirection */
- b = (uint32*)get_blk(fs,nod->i_block[EXT2_TIND_BLOCK], &bi);
- for(i=0;i < BLOCKSIZE/4 && !done ; i++) {
- b2 = (uint32*)get_blk(fs,b[i], &bi2);
- for(j=0; j<BLOCKSIZE/4;j++) {
- if (nblk > ( EXT2_IND_BLOCK + BLOCKSIZE/4 +
- (BLOCKSIZE/4)*(BLOCKSIZE/4) +
- i*(BLOCKSIZE/4)*(BLOCKSIZE/4) +
- j*(BLOCKSIZE/4)) ) {
- swap_block(get_blk(fs,b2[j],&bi3));
- put_blk(bi3);
- }
- else {
- done = 1;
- break;
- }
- }
- swap_block((uint8 *)b2);
- put_blk(bi2);
- }
- swap_block((uint8 *)b);
- put_blk(bi);
- return;
-}
-
-static void
-swap_badblocks(filesystem *fs, inode *nod)
-{
- uint32 i,j;
- int done=0;
- uint32 *b,*b2;
- blk_info *bi, *bi2, *bi3;
-
- uint32 nblk = nod->i_blocks / INOBLK;
- if((nod->i_size && !nblk) || ((nod->i_mode & FM_IFBLK) == FM_IFBLK) || ((nod->i_mode & FM_IFCHR) == FM_IFCHR))
- for(i = 0; i <= EXT2_TIND_BLOCK; i++)
- nod->i_block[i] = swab32(nod->i_block[i]);
- if(nblk <= EXT2_IND_BLOCK)
- return;
- swap_block(get_blk(fs, nod->i_block[EXT2_IND_BLOCK], &bi));
- put_blk(bi);
- if(nblk <= EXT2_DIND_BLOCK + BLOCKSIZE/4)
- return;
- /* See comment in swap_goodblocks */
- assert(nod->i_block[EXT2_DIND_BLOCK] != 0);
- swap_block(get_blk(fs, nod->i_block[EXT2_DIND_BLOCK], &bi));
- put_blk(bi);
- for(i = 0; i < BLOCKSIZE/4; i++)
- if(nblk > EXT2_IND_BLOCK + BLOCKSIZE/4 + (BLOCKSIZE/4)*i ) {
- swap_block(get_blk(fs, ((uint32*)get_blk(fs, nod->i_block[EXT2_DIND_BLOCK],&bi))[i], &bi2));
- put_blk(bi);
- put_blk(bi2);
- }
- if(nblk <= EXT2_IND_BLOCK + BLOCKSIZE/4 + BLOCKSIZE/4 * BLOCKSIZE/4)
- return;
- /* Adding support for triple indirection */
- b = (uint32*)get_blk(fs,nod->i_block[EXT2_TIND_BLOCK],&bi);
- swap_block((uint8 *)b);
- for(i=0;i < BLOCKSIZE/4 && !done ; i++) {
- b2 = (uint32*)get_blk(fs,b[i],&bi2);
- swap_block((uint8 *)b2);
- for(j=0; j<BLOCKSIZE/4;j++) {
- if (nblk > ( EXT2_IND_BLOCK + BLOCKSIZE/4 +
- (BLOCKSIZE/4)*(BLOCKSIZE/4) +
- i*(BLOCKSIZE/4)*(BLOCKSIZE/4) +
- j*(BLOCKSIZE/4)) ) {
- swap_block(get_blk(fs,b2[j],&bi3));
- put_blk(bi3);
- }
- else {
- done = 1;
- break;
- }
- }
- put_blk(bi2);
- }
- put_blk(bi);
- return;
-}
-
// endianness swap of the whole filesystem
static void
swap_goodfs(filesystem *fs)
{
uint32 i;
- nod_info *ni;
- for(i = 1; i < fs->sb->s_inodes_count; i++)
- {
- inode *nod = get_nod(fs, i, &ni);
- if(nod->i_mode & FM_IFDIR)
- {
- blockwalker bw;
- uint32 bk;
- init_bw(&bw);
- while((bk = walk_bw(fs, i, &bw, 0, 0)) != WALK_END)
- {
- directory *d;
- uint8 *b;
- blk_info *bi;
- b = get_blk(fs, bk, &bi);
- for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + swab16(d->d_rec_len)))
- swap_dir(d);
- put_blk(bi);
- }
- }
- swap_goodblocks(fs, nod);
- swap_nod(nod);
- put_nod(ni);
- }
for(i=0;i<GRP_NBGROUPS(fs);i++)
swap_gd(&(fs->gd[i]));
swap_sb(fs->sb);
@@ -2215,35 +2108,12 @@ swap_badfs(filesystem *fs)
swap_sb(fs->sb);
for(i=0;i<GRP_NBGROUPS(fs);i++)
swap_gd(&(fs->gd[i]));
- for(i = 1; i < fs->sb->s_inodes_count; i++)
- {
- nod_info *ni;
- inode *nod = get_nod(fs, i, &ni);
- swap_nod(nod);
- swap_badblocks(fs, nod);
- if(nod->i_mode & FM_IFDIR)
- {
- blockwalker bw;
- uint32 bk;
- init_bw(&bw);
- while((bk = walk_bw(fs, i, &bw, 0, 0)) != WALK_END)
- {
- directory *d;
- uint8 *b;
- blk_info *bi;
- b = get_blk(fs, bk, &bi);
- for(d = (directory*)b; (int8*)d + sizeof(*d) < (int8*)b + BLOCKSIZE; d = (directory*)((int8*)d + d->d_rec_len))
- swap_dir(d);
- put_blk(bi);
- }
- }
- }
}
// Allocate a new filesystem structure, allocate internal memory,
// and initialize the contents.
static filesystem *
-alloc_fs(uint32 nbblocks)
+alloc_fs(uint32 nbblocks, int swapit)
{
filesystem *fs;
@@ -2251,6 +2121,7 @@ alloc_fs(uint32 nbblocks)
if (!fs)
error_msg_and_die("not enough memory for filesystem");
memset(fs, 0, sizeof(*fs));
+ fs->swapit = swapit;
if(!(fs->data = calloc(nbblocks, BLOCKSIZE)))
error_msg_and_die("not enough memory for filesystem");
fs->hdlink_cnt = HDLINK_CNT;
@@ -2265,7 +2136,7 @@ alloc_fs(uint32 nbblocks)
// initialize an empty filesystem
static filesystem *
-init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp)
+init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp, int swapit)
{
uint32 i;
filesystem *fs;
@@ -2313,7 +2184,7 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
free_blocks = nbblocks - overhead_per_group*nbgroups - 1 /*boot block*/;
free_blocks_per_group = nbblocks_per_group - overhead_per_group;
- fs = alloc_fs(nbblocks);
+ fs = alloc_fs(nbblocks, swapit);
fs->nheadblocks = (((nbgroups * sizeof(groupdescriptor))
+ sizeof(superblock) + (BLOCKSIZE - 1))
/ BLOCKSIZE);
@@ -2454,7 +2325,7 @@ load_fs(FILE * fh, int swapit)
fssize = (fssize + BLOCKSIZE - 1) / BLOCKSIZE;
if(fssize < 16) // totally arbitrary
error_msg_and_die("too small filesystem");
- fs = alloc_fs(fssize);
+ fs = alloc_fs(fssize, swapit);
if(fread(fs->data, BLOCKSIZE, fssize, fh) != fssize)
perror_msg_and_die("input filesystem image");
@@ -3014,7 +2885,8 @@ main(int argc, char **argv)
}
if(fs_timestamp == -1)
fs_timestamp = time(NULL);
- fs = init_fs(nbblocks, nbinodes, nbresrvd, holes, fs_timestamp);
+ fs = init_fs(nbblocks, nbinodes, nbresrvd, holes, fs_timestamp,
+ bigendian);
}
populate_fs(fs, dopt, didx, squash_uids, squash_perms, fs_timestamp, NULL);
--
1.7.4.1

View File

@ -0,0 +1,839 @@
Upstream-Status: inappropriate
From 29a36b0b91ee009ee4219934c7a70278b1361834 Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Sun, 5 Jun 2011 15:24:57 -0500
Subject: [PATCH 10/19] Convert over to keeping the filesystem on disk
This makes the actual filesystem be on disk and not in memory. It
adds caching of the filesystem data to help keep oft-accessed blocks
in memory and byteswapped.
---
cache.h | 128 ++++++++++++++++++++
genext2fs.c | 377 +++++++++++++++++++++++++++++++++++++++++++++++++----------
list.h | 78 ++++++++++++
3 files changed, 521 insertions(+), 62 deletions(-)
create mode 100644 cache.h
create mode 100644 list.h
diff --git a/cache.h b/cache.h
new file mode 100644
index 0000000..5275be6
--- /dev/null
+++ b/cache.h
@@ -0,0 +1,128 @@
+#ifndef __CACHE_H__
+#define __CACHE_H__
+
+#include "list.h"
+
+#define CACHE_LISTS 256
+
+typedef struct
+{
+ list_elem link;
+ list_elem lru_link;
+} cache_link;
+
+typedef struct
+{
+ /* LRU list holds unused items */
+ unsigned int lru_entries;
+ list_elem lru_list;
+ unsigned int max_free_entries;
+
+ unsigned int entries;
+ list_elem lists[CACHE_LISTS];
+ unsigned int (*elem_val)(cache_link *elem);
+ void (*freed)(cache_link *elem);
+} listcache;
+
+static inline void
+cache_add(listcache *c, cache_link *elem)
+{
+ unsigned int hash = c->elem_val(elem) % CACHE_LISTS;
+ int delcount = c->lru_entries - c->max_free_entries;
+
+ if (delcount > 0) {
+ /* Delete some unused items. */
+ list_elem *lru, *next;
+ cache_link *l;
+ list_for_each_elem_safe(&c->lru_list, lru, next) {
+ l = container_of(lru, cache_link, lru_link);
+ list_del(lru);
+ list_del(&l->link);
+ c->entries--;
+ c->lru_entries--;
+ c->freed(l);
+ delcount--;
+ if (delcount <= 0)
+ break;
+ }
+ }
+
+ c->entries++;
+ list_item_init(&elem->lru_link); /* Mark it not in the LRU list */
+ list_add_after(&c->lists[hash], &elem->link);
+}
+
+static inline void
+cache_item_set_unused(listcache *c, cache_link *elem)
+{
+ list_add_before(&c->lru_list, &elem->lru_link);
+ c->lru_entries++;
+}
+
+static inline cache_link *
+cache_find(listcache *c, unsigned int val)
+{
+ unsigned int hash = val % CACHE_LISTS;
+ list_elem *elem;
+
+ list_for_each_elem(&c->lists[hash], elem) {
+ cache_link *l = container_of(elem, cache_link, link);
+ if (c->elem_val(l) == val) {
+ if (!list_empty(&l->lru_link)) {
+ /* It's in the unused list, remove it. */
+ list_del(&l->lru_link);
+ list_item_init(&l->lru_link);
+ c->lru_entries--;
+ }
+ return l;
+ }
+ }
+ return NULL;
+}
+
+static inline int
+cache_flush(listcache *c)
+{
+ list_elem *elem, *next;
+ cache_link *l;
+ int i;
+
+ list_for_each_elem_safe(&c->lru_list, elem, next) {
+ l = container_of(elem, cache_link, lru_link);
+ list_del(elem);
+ list_del(&l->link);
+ c->entries--;
+ c->lru_entries--;
+ c->freed(l);
+ }
+
+ for (i = 0; i < CACHE_LISTS; i++) {
+ list_for_each_elem_safe(&c->lists[i], elem, next) {
+ l = container_of(elem, cache_link, link);
+ list_del(&l->link);
+ c->entries--;
+ c->freed(l);
+ }
+ }
+
+ return c->entries || c->lru_entries;
+}
+
+static inline void
+cache_init(listcache *c, unsigned int max_free_entries,
+ unsigned int (*elem_val)(cache_link *elem),
+ void (*freed)(cache_link *elem))
+{
+ int i;
+
+ c->entries = 0;
+ c->lru_entries = 0;
+ c->max_free_entries = max_free_entries;
+ list_init(&c->lru_list);
+ for (i = 0; i < CACHE_LISTS; i++)
+ list_init(&c->lists[i]);
+ c->elem_val = elem_val;
+ c->freed = freed;
+}
+
+#endif /* __CACHE_H__ */
diff --git a/genext2fs.c b/genext2fs.c
index 51403a2..f79438d 100644
--- a/genext2fs.c
+++ b/genext2fs.c
@@ -142,6 +142,8 @@
# include <limits.h>
#endif
+#include "cache.h"
+
struct stats {
unsigned long nblocks;
unsigned long ninodes;
@@ -600,6 +602,7 @@ struct hdlinks_s
#if BLOCKSIZE == 1024
typedef struct
{
+ FILE *f;
uint8 *data;
superblock *sb;
groupdescriptor *gd;
@@ -607,6 +610,10 @@ typedef struct
int swapit;
int32 hdlink_cnt;
struct hdlinks_s hdlinks;
+
+ listcache blks;
+ listcache inodes;
+ listcache blkmaps;
} filesystem;
#else
#error UNHANDLED BLOCKSIZE
@@ -848,45 +855,150 @@ allocated(block b, uint32 item)
// by the user.
typedef struct
{
- int dummy;
+ cache_link link;
+
+ filesystem *fs;
+ uint32 blk;
+ uint8 *b;
+ uint32 usecount;
} blk_info;
+#define MAX_FREE_CACHE_BLOCKS 100
+
+static uint32
+blk_elem_val(cache_link *elem)
+{
+ blk_info *bi = container_of(elem, blk_info, link);
+ return bi->blk;
+}
+
+static void
+blk_freed(cache_link *elem)
+{
+ blk_info *bi = container_of(elem, blk_info, link);
+
+ if (fseeko(bi->fs->f, ((off_t) bi->blk) * BLOCKSIZE, SEEK_SET))
+ perror_msg_and_die("fseek");
+ if (fwrite(bi->b, BLOCKSIZE, 1, bi->fs->f) != 1)
+ perror_msg_and_die("get_blk: write");
+ free(bi->b);
+ free(bi);
+}
+
// Return a given block from a filesystem. Make sure to call
// put_blk when you are done with it.
static inline uint8 *
get_blk(filesystem *fs, uint32 blk, blk_info **rbi)
{
- return fs->data + blk*BLOCKSIZE;
+ cache_link *curr;
+ blk_info *bi;
+
+ if (blk < fs->nheadblocks)
+ error_msg_and_die("Internal error, request for head block");
+ if (blk >= fs->sb->s_blocks_count)
+ error_msg_and_die("Internal error, block out of range");
+
+ curr = cache_find(&fs->blks, blk);
+ if (curr) {
+ bi = container_of(curr, blk_info, link);
+ bi->usecount++;
+ goto out;
+ }
+
+ bi = malloc(sizeof(*bi));
+ if (!bi)
+ error_msg_and_die("get_blk: out of memory");
+ bi->fs = fs;
+ bi->blk = blk;
+ bi->usecount = 1;
+ bi->b = malloc(BLOCKSIZE);
+ if (!bi->b)
+ error_msg_and_die("get_blk: out of memory");
+ cache_add(&fs->blks, &bi->link);
+ if (fseeko(fs->f, ((off_t) blk) * BLOCKSIZE, SEEK_SET))
+ perror_msg_and_die("fseek");
+ if (fread(bi->b, BLOCKSIZE, 1, fs->f) != 1) {
+ if (ferror(fs->f))
+ perror_msg_and_die("fread");
+ memset(bi->b, 0, BLOCKSIZE);
+ }
+
+out:
+ *rbi = bi;
+ return bi->b;
}
static inline void
put_blk(blk_info *bi)
{
+ if (bi->usecount == 0)
+ error_msg_and_die("Internal error: put_blk usecount zero");
+ bi->usecount--;
+ if (bi->usecount == 0)
+ /* Free happens in the cache code */
+ cache_item_set_unused(&bi->fs->blks, &bi->link);
}
// Used by get_blkmap/put_blkmap to hold information about an block map
// owned by the user.
typedef struct
{
+ cache_link link;
+
filesystem *fs;
+ uint32 blk;
uint8 *b;
blk_info *bi;
+ uint32 usecount;
} blkmap_info;
+#define MAX_FREE_CACHE_BLOCKMAPS 100
+
+static uint32
+blkmap_elem_val(cache_link *elem)
+{
+ blkmap_info *bmi = container_of(elem, blkmap_info, link);
+ return bmi->blk;
+}
+
+static void
+blkmap_freed(cache_link *elem)
+{
+ blkmap_info *bmi = container_of(elem, blkmap_info, link);
+
+ if (bmi->fs->swapit)
+ swap_block(bmi->b);
+ put_blk(bmi->bi);
+ free(bmi);
+}
+
// Return a given block map from a filesystem. Make sure to call
// put_blkmap when you are done with it.
static inline uint32 *
get_blkmap(filesystem *fs, uint32 blk, blkmap_info **rbmi)
{
blkmap_info *bmi;
+ cache_link *curr;
+
+ curr = cache_find(&fs->blkmaps, blk);
+ if (curr) {
+ bmi = container_of(curr, blkmap_info, link);
+ bmi->usecount++;
+ goto out;
+ }
bmi = malloc(sizeof(*bmi));
if (!bmi)
error_msg_and_die("get_blkmap: out of memory");
bmi->fs = fs;
+ bmi->blk = blk;
bmi->b = get_blk(fs, blk, &bmi->bi);
- if (bmi->fs->swapit)
+ bmi->usecount = 1;
+ cache_add(&fs->blkmaps, &bmi->link);
+
+ if (fs->swapit)
swap_block(bmi->b);
+out:
*rbmi = bmi;
return (uint32 *) bmi->b;
}
@@ -894,42 +1006,83 @@ get_blkmap(filesystem *fs, uint32 blk, blkmap_info **rbmi)
static inline void
put_blkmap(blkmap_info *bmi)
{
- if (bmi->fs->swapit)
- swap_block(bmi->b);
- put_blk(bmi->bi);
- free(bmi);
+ if (bmi->usecount == 0)
+ error_msg_and_die("Internal error: put_blkmap usecount zero");
+
+ bmi->usecount--;
+ if (bmi->usecount == 0)
+ /* Free happens in the cache code */
+ cache_item_set_unused(&bmi->fs->blkmaps, &bmi->link);
}
// Used by get_nod/put_nod to hold information about an inode owned
// by the user.
typedef struct
{
+ cache_link link;
+
filesystem *fs;
+ uint32 nod;
+ uint8 *b;
blk_info *bi;
inode *itab;
+ uint32 usecount;
} nod_info;
+#define MAX_FREE_CACHE_INODES 100
+
+static uint32
+inode_elem_val(cache_link *elem)
+{
+ nod_info *ni = container_of(elem, nod_info, link);
+ return ni->nod;
+}
+
+static void
+inode_freed(cache_link *elem)
+{
+ nod_info *ni = container_of(elem, nod_info, link);
+
+ if (ni->fs->swapit)
+ swap_nod(ni->itab);
+ put_blk(ni->bi);
+ free(ni);
+}
+
// Return a given inode from a filesystem. Make sure to call put_nod()
// when you are done with the inode.
static inline inode *
get_nod(filesystem *fs, uint32 nod, nod_info **rni)
{
int grp, offset, boffset;
+ cache_link *curr;
nod_info *ni;
- uint8 *b;
- offset = GRP_IBM_OFFSET(fs,nod) - 1;
- boffset = offset / (BLOCKSIZE / sizeof(inode));
- offset %= BLOCKSIZE / sizeof(inode);
- grp = GRP_GROUP_OF_INODE(fs,nod);
+ curr = cache_find(&fs->inodes, nod);
+ if (curr) {
+ ni = container_of(curr, nod_info, link);
+ ni->usecount++;
+ goto out;
+ }
+
ni = malloc(sizeof(*ni));
if (!ni)
error_msg_and_die("get_nod: out of memory");
ni->fs = fs;
- b = get_blk(fs, fs->gd[grp].bg_inode_table + boffset, &ni->bi);
- ni->itab = ((inode *) b) + offset;
+ ni->nod = nod;
+ ni->usecount = 1;
+ cache_add(&fs->inodes, &ni->link);
+
+ offset = GRP_IBM_OFFSET(fs, nod) - 1;
+ boffset = offset / (BLOCKSIZE / sizeof(inode));
+ offset %= BLOCKSIZE / sizeof(inode);
+ grp = GRP_GROUP_OF_INODE(fs,nod);
+ ni->b = get_blk(fs, fs->gd[grp].bg_inode_table + boffset, &ni->bi);
+ ni->itab = ((inode *) ni->b) + offset;
if (fs->swapit)
swap_nod(ni->itab);
+
+out:
*rni = ni;
return ni->itab;
}
@@ -937,10 +1090,13 @@ get_nod(filesystem *fs, uint32 nod, nod_info **rni)
static inline void
put_nod(nod_info *ni)
{
- if (ni->fs->swapit)
- swap_nod(ni->itab);
- put_blk(ni->bi);
- free(ni);
+ if (ni->usecount == 0)
+ error_msg_and_die("Internal error: put_nod usecount zero");
+
+ ni->usecount--;
+ if (ni->usecount == 0)
+ /* Free happens in the cache code */
+ cache_item_set_unused(&ni->fs->inodes, &ni->link);
}
// Used to hold state information while walking a directory inode.
@@ -2090,40 +2246,61 @@ add2fs_from_dir(filesystem *fs, uint32 this_nod, int squash_uids, int squash_per
closedir(dh);
}
-// endianness swap of the whole filesystem
static void
-swap_goodfs(filesystem *fs)
+swap_gds(filesystem *fs)
{
uint32 i;
-
for(i=0;i<GRP_NBGROUPS(fs);i++)
swap_gd(&(fs->gd[i]));
- swap_sb(fs->sb);
}
+// Copy size blocks from src to dst, putting holes in the output
+// file (if possible) if the input block is all zeros.
static void
-swap_badfs(filesystem *fs)
+copy_file(filesystem *fs, FILE *dst, FILE *src, size_t size)
{
- uint32 i;
- swap_sb(fs->sb);
- for(i=0;i<GRP_NBGROUPS(fs);i++)
- swap_gd(&(fs->gd[i]));
+ uint8 *b;
+
+ b = malloc(BLOCKSIZE);
+ if (!b)
+ error_msg_and_die("copy_file: out of memory");
+ if (fseek(src, 0, SEEK_SET))
+ perror_msg_and_die("fseek");
+ if (ftruncate(fileno(dst), 0))
+ perror_msg_and_die("copy_file: ftruncate");
+ while (size > 0) {
+ if (fread(b, BLOCKSIZE, 1, src) != 1)
+ perror_msg_and_die("copy failed on read");
+ if ((dst != stdout) && is_blk_empty(b)) {
+ /* Empty block, just skip it */
+ if (fseek(dst, BLOCKSIZE, SEEK_CUR))
+ perror_msg_and_die("fseek");
+ } else {
+ if (fwrite(b, BLOCKSIZE, 1, dst) != 1)
+ perror_msg_and_die("copy failed on write");
+ }
+ size --;
+ }
}
// Allocate a new filesystem structure, allocate internal memory,
// and initialize the contents.
static filesystem *
-alloc_fs(uint32 nbblocks, int swapit)
+alloc_fs(int swapit, char *fname, uint32 nbblocks, FILE *srcfile)
{
filesystem *fs;
+ struct stat srcstat, dststat;
fs = malloc(sizeof(*fs));
if (!fs)
error_msg_and_die("not enough memory for filesystem");
memset(fs, 0, sizeof(*fs));
fs->swapit = swapit;
- if(!(fs->data = calloc(nbblocks, BLOCKSIZE)))
- error_msg_and_die("not enough memory for filesystem");
+ cache_init(&fs->blks, MAX_FREE_CACHE_BLOCKS, blk_elem_val, blk_freed);
+ cache_init(&fs->blkmaps, MAX_FREE_CACHE_BLOCKMAPS,
+ blkmap_elem_val, blkmap_freed);
+ cache_init(&fs->inodes, MAX_FREE_CACHE_INODES,
+ inode_elem_val, inode_freed);
fs->hdlink_cnt = HDLINK_CNT;
fs->hdlinks.hdl = calloc(sizeof(struct hdlink_s), fs->hdlink_cnt);
if (!fs->hdlinks.hdl)
@@ -2131,12 +2308,44 @@ alloc_fs(uint32 nbblocks, int swapit)
fs->hdlinks.count = 0 ;
fs->sb = (superblock *) (fs->data + BLOCKSIZE);
fs->gd = (groupdescriptor *) (fs->sb + 1);
+
+ if (strcmp(fname, "-") == 0)
+ fs->f = tmpfile();
+ else if (srcfile) {
+ if (fstat(fileno(srcfile), &srcstat))
+ perror_msg_and_die("fstat srcfile");
+ if (stat(fname, &dststat))
+ perror_msg_and_die("stat-ing %s", fname);
+ if (srcstat.st_ino == dststat.st_ino) {
+ // source and destination are the same file, don't
+ // truncate or copy, just use the file.
+ fs->f = fopen(fname, "r+b");
+ } else {
+ fs->f = fopen(fname, "w+b");
+ if (fs->f)
+ copy_file(fs, fs->f, srcfile,
+ nbblocks * BLOCKSIZE);
+ }
+ } else
+ fs->f = fopen(fname, "w+b");
+ if (!fs->f)
+ perror_msg_and_die("opening %s", fname);
return fs;
}
+/* Make sure the output file is the right size */
+static void
+set_file_size(filesystem *fs)
+{
+ if (ftruncate(fileno(fs->f),
+ ((off_t) fs->sb->s_blocks_count) * BLOCKSIZE))
+ perror_msg_and_die("set_file_size: ftruncate");
+}
+
// initialize an empty filesystem
static filesystem *
-init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp, int swapit)
+init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes,
+ uint32 fs_timestamp, int swapit, char *fname)
{
uint32 i;
filesystem *fs;
@@ -2184,10 +2393,16 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
free_blocks = nbblocks - overhead_per_group*nbgroups - 1 /*boot block*/;
free_blocks_per_group = nbblocks_per_group - overhead_per_group;
- fs = alloc_fs(nbblocks, swapit);
+ fs = alloc_fs(swapit, fname, nbblocks, NULL);
fs->nheadblocks = (((nbgroups * sizeof(groupdescriptor))
+ sizeof(superblock) + (BLOCKSIZE - 1))
/ BLOCKSIZE);
+ fs->sb = (superblock *) malloc(BLOCKSIZE);
+ if (!fs->sb)
+ error_msg_and_die("error allocating header memory");
+ fs->gd = (groupdescriptor *) calloc(fs->nheadblocks - 1, BLOCKSIZE);
+ if (!fs->gd)
+ error_msg_and_die("error allocating header memory");
// create the superblock for an empty filesystem
fs->sb->s_inodes_count = nbinodes_per_group * nbgroups;
@@ -2205,6 +2420,10 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
fs->sb->s_magic = EXT2_MAGIC_NUMBER;
fs->sb->s_lastcheck = fs_timestamp;
+ fs->sb->s_reserved[200] = 0;
+
+ set_file_size(fs);
+
// set up groupdescriptors
for(i=0, bbmpos=gdsz+2, ibmpos=bbmpos+1, itblpos=ibmpos+1;
i<nbgroups;
@@ -2315,27 +2534,49 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
// loads a filesystem from disk
static filesystem *
-load_fs(FILE * fh, int swapit)
+load_fs(FILE * fh, int swapit, char *fname)
{
- size_t fssize;
+ off_t fssize;
filesystem *fs;
- if((fseek(fh, 0, SEEK_END) < 0) || ((ssize_t)(fssize = ftell(fh)) == -1))
+
+ if((fseek(fh, 0, SEEK_END) < 0) || ((fssize = ftello(fh)) == -1))
perror_msg_and_die("input filesystem image");
rewind(fh);
- fssize = (fssize + BLOCKSIZE - 1) / BLOCKSIZE;
+ if ((fssize % BLOCKSIZE) != 0)
+ error_msg_and_die("Input file not a multiple of block size");
+ fssize /= BLOCKSIZE;
if(fssize < 16) // totally arbitrary
error_msg_and_die("too small filesystem");
- fs = alloc_fs(fssize, swapit);
- if(fread(fs->data, BLOCKSIZE, fssize, fh) != fssize)
- perror_msg_and_die("input filesystem image");
-
+ fs = alloc_fs(swapit, fname, fssize, fh);
+
+ /* Read and check the superblock, then read the superblock
+ * and all the group descriptors */
+ fs->sb = malloc(BLOCKSIZE);
+ if (!fs->sb)
+ error_msg_and_die("error allocating header memory");
+ if (fseek(fs->f, BLOCKSIZE, SEEK_SET))
+ perror_msg_and_die("fseek");
+ if (fread(fs->sb, BLOCKSIZE, 1, fs->f) != 1)
+ perror_msg_and_die("fread filesystem image superblock");
if(swapit)
- swap_badfs(fs);
+ swap_sb(fs->sb);
if(fs->sb->s_rev_level || (fs->sb->s_magic != EXT2_MAGIC_NUMBER))
error_msg_and_die("not a suitable ext2 filesystem");
fs->nheadblocks = (((GRP_NBGROUPS(fs) * sizeof(groupdescriptor))
+ sizeof(superblock) + (BLOCKSIZE - 1))
/ BLOCKSIZE);
+
+ fs->gd = calloc(fs->nheadblocks - 1, BLOCKSIZE);
+ if (!fs->gd)
+ error_msg_and_die("error allocating header memory");
+ if (fread(fs->gd, BLOCKSIZE, fs->nheadblocks - 1, fs->f)
+ != (fs->nheadblocks - 1))
+ perror_msg_and_die("fread filesystem image group descriptors");
+
+ if(swapit)
+ swap_gds(fs);
+
+ set_file_size(fs);
return fs;
}
@@ -2343,7 +2584,9 @@ static void
free_fs(filesystem *fs)
{
free(fs->hdlinks.hdl);
- free(fs->data);
+ fclose(fs->f);
+ free(fs->sb);
+ free(fs->gd);
free(fs);
}
@@ -2631,16 +2874,30 @@ print_fs(filesystem *fs)
}
static void
-dump_fs(filesystem *fs, FILE * fh, int swapit)
-{
- uint32 nbblocks = fs->sb->s_blocks_count;
+finish_fs(filesystem *fs)
+{
+ if (cache_flush(&fs->inodes))
+ error_msg_and_die("entry mismatch on inode cache flush");
+ if (cache_flush(&fs->blkmaps))
+ error_msg_and_die("entry mismatch on blockmap cache flush");
+ if (cache_flush(&fs->blks))
+ error_msg_and_die("entry mismatch on block cache flush");
fs->sb->s_reserved[200] = 0;
- if(swapit)
- swap_goodfs(fs);
- if(fwrite(fs->data, BLOCKSIZE, nbblocks, fh) < nbblocks)
- perror_msg_and_die("output filesystem image");
- if(swapit)
- swap_badfs(fs);
+ if(fs->swapit) {
+ swap_sb(fs->sb);
+ swap_gds(fs);
+ }
+ if (fseek(fs->f, BLOCKSIZE, SEEK_SET))
+ perror_msg_and_die("fseek");
+ if(fwrite(fs->sb, BLOCKSIZE, 1, fs->f) != 1)
+ perror_msg_and_die("output filesystem superblock");
+ if(fwrite(fs->gd, BLOCKSIZE, fs->nheadblocks - 1, fs->f)
+ != (fs->nheadblocks - 1))
+ perror_msg_and_die("output filesystem group descriptors");
+ if(fs->swapit) {
+ swap_sb(fs->sb);
+ swap_gds(fs);
+ }
}
static void
@@ -2851,11 +3108,11 @@ main(int argc, char **argv)
if(strcmp(fsin, "-"))
{
FILE * fh = xfopen(fsin, "rb");
- fs = load_fs(fh, bigendian);
+ fs = load_fs(fh, bigendian, fsout);
fclose(fh);
}
else
- fs = load_fs(stdin, bigendian);
+ fs = load_fs(stdin, bigendian, fsout);
}
else
{
@@ -2886,7 +3143,7 @@ main(int argc, char **argv)
if(fs_timestamp == -1)
fs_timestamp = time(NULL);
fs = init_fs(nbblocks, nbinodes, nbresrvd, holes, fs_timestamp,
- bigendian);
+ bigendian, fsout);
}
populate_fs(fs, dopt, didx, squash_uids, squash_perms, fs_timestamp, NULL);
@@ -2925,14 +3182,10 @@ main(int argc, char **argv)
flist_blocks(fs, nod, fh);
fclose(fh);
}
- if(strcmp(fsout, "-"))
- {
- FILE * fh = xfopen(fsout, "wb");
- dump_fs(fs, fh, bigendian);
- fclose(fh);
- }
- else
- dump_fs(fs, stdout, bigendian);
+ finish_fs(fs);
+ if(strcmp(fsout, "-") == 0)
+ copy_file(fs, stdout, fs->f, fs->sb->s_blocks_count);
+
free_fs(fs);
return 0;
}
diff --git a/list.h b/list.h
new file mode 100644
index 0000000..52bb181
--- /dev/null
+++ b/list.h
@@ -0,0 +1,78 @@
+#ifndef __LIST_H__
+#define __LIST_H__
+
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+# if HAVE_STDDEF_H
+# include <stddef.h>
+# endif
+#endif
+
+#ifndef offsetof
+#define offsetof(st, m) \
+ ((size_t) ( (char *)&((st *)(0))->m - (char *)0 ))
+#endif
+
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+typedef struct list_elem
+{
+ struct list_elem *next;
+ struct list_elem *prev;
+} list_elem;
+
+static inline void list_init(list_elem *list)
+{
+ list->next = list;
+ list->prev = list;
+}
+
+static inline void list_add_after(list_elem *pos, list_elem *elem)
+{
+ elem->next = pos->next;
+ elem->prev = pos;
+ pos->next->prev = elem;
+ pos->next = elem;
+}
+
+static inline void list_add_before(list_elem *pos, list_elem *elem)
+{
+ elem->prev = pos->prev;
+ elem->next = pos;
+ pos->prev->next = elem;
+ pos->prev = elem;
+}
+
+static inline void list_del(list_elem *elem)
+{
+ elem->next->prev = elem->prev;
+ elem->prev->next = elem->next;
+}
+
+static inline void list_item_init(list_elem *elem)
+{
+ elem->next = elem;
+ elem->prev = elem;
+}
+
+static inline int list_empty(list_elem *elem)
+{
+ return elem->next == elem;
+}
+
+#define list_for_each_elem(list, curr) \
+ for ((curr) = (list)->next; (curr) != (list); (curr) = (curr)->next)
+
+#define list_for_each_elem_safe(list, curr, next) \
+ for ((curr) = (list)->next, (next) = (curr)->next; \
+ (curr) != (list); \
+ (curr) = (next), (next) = (curr)->next)
+
+#endif /* __LIST_H__ */
--
1.7.4.1

View File

@ -0,0 +1,103 @@
Upstream-Status: inappropriate
From 0a7d5b11e62e54f88ce3a49d0c2327d537b3f531 Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Sun, 5 Jun 2011 15:42:24 -0500
Subject: [PATCH 11/19] Copy files into the filesystem a piece at a time
Instead of malloc-ing and entire files-worth of memory, reading it in,
and writing it to the filesystem, do it a piece at a time. This allows
very large files to be supported.
Also, use off_t and make it 64-bits so it supports filesystems and files
larger than 2GB. Full support for >2GB files is not quite here, that
requires rev 1 filesystem support, which is coming later.
---
genext2fs.c | 35 +++++++++++++++++++++++------------
1 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/genext2fs.c b/genext2fs.c
index f79438d..8a7f589 100644
--- a/genext2fs.c
+++ b/genext2fs.c
@@ -53,6 +53,12 @@
// along with -q, -P, -U
+/*
+ * Allow fseeko/off_t to be 64-bit offsets to allow filesystems and
+ * individual files >2GB.
+ */
+#define _FILE_OFFSET_BITS 64
+
#include <config.h>
#include <stdio.h>
@@ -603,7 +609,6 @@ struct hdlinks_s
typedef struct
{
FILE *f;
- uint8 *data;
superblock *sb;
groupdescriptor *gd;
uint32 nheadblocks;
@@ -1907,30 +1912,38 @@ mklink_fs(filesystem *fs, uint32 parent_nod, const char *name, size_t size, uint
return nod;
}
+#define COPY_BLOCKS 16
+#define CB_SIZE (COPY_BLOCKS * BLOCKSIZE)
+
// make a file from a FILE*
static uint32
-mkfile_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode, size_t size, FILE *f, uid_t uid, gid_t gid, uint32 ctime, uint32 mtime)
+mkfile_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode, off_t size, FILE *f, uid_t uid, gid_t gid, uint32 ctime, uint32 mtime)
{
uint8 * b;
uint32 nod = mknod_fs(fs, parent_nod, name, mode|FM_IFREG, uid, gid, 0, 0, ctime, mtime);
nod_info *ni;
inode *node = get_nod(fs, nod, &ni);
+ size_t readbytes;
inode_pos ipos;
+
+ b = malloc(CB_SIZE);
+ if (!b)
+ error_msg_and_die("mkfile_fs: out of memory");
inode_pos_init(fs, &ipos, nod, INODE_POS_TRUNCATE, NULL);
node->i_size = size;
- if (size) {
- if(!(b = (uint8*)calloc(rndup(size, BLOCKSIZE), 1)))
- error_msg_and_die("not enough mem to read file '%s'", name);
- if(f)
- if (fread(b, size, 1, f) != 1) // FIXME: ugly. use mmap() ...
- error_msg_and_die("fread failed");
+ while (size) {
+ readbytes = fread(b, 1, CB_SIZE, f);
+ if ((size < CB_SIZE && readbytes != size)
+ || (size >= CB_SIZE && readbytes != CB_SIZE))
+ error_msg_and_die("fread failed");
extend_inode_blk(fs, &ipos, b,
- rndup(size, BLOCKSIZE) / BLOCKSIZE);
- free(b);
+ rndup(readbytes, BLOCKSIZE) / BLOCKSIZE);
+ size -= readbytes;
}
inode_pos_finish(fs, &ipos);
put_nod(ni);
+ free(b);
return nod;
}
@@ -2306,8 +2319,6 @@ alloc_fs(int swapit, char *fname, uint32 nbblocks, FILE *srcfile)
if (!fs->hdlinks.hdl)
error_msg_and_die("Not enough memory");
fs->hdlinks.count = 0 ;
- fs->sb = (superblock *) (fs->data + BLOCKSIZE);
- fs->gd = (groupdescriptor *) (fs->sb + 1);
if (strcmp(fname, "-") == 0)
fs->f = tmpfile();
--
1.7.4.1

View File

@ -0,0 +1,211 @@
Upstream-Status: inappropriate
From fbcbbba3b65402bd43a9e36593d544ff3451620e Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Fri, 3 Jun 2011 21:09:25 -0500
Subject: [PATCH 12/19] Add rev 1 support, large file support, and rework holes
Add support for individual files larger than 2GB, which requires some
rev 1 filesystem support.
Also, since we have a non-overly filesystem structure, rework the
OP_HOLES hack and just put that flag in the filesystem structure.
This avoid having to mess around with the reserved bytes (which
changed with rev 1 support).
---
genext2fs.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 56 insertions(+), 13 deletions(-)
diff --git a/genext2fs.c b/genext2fs.c
index 8a7f589..e420bba 100644
--- a/genext2fs.c
+++ b/genext2fs.c
@@ -233,10 +233,6 @@ struct stats {
#define FM_IWOTH 0000002 // write
#define FM_IXOTH 0000001 // execute
-// options
-
-#define OP_HOLES 0x01 // make files with holes
-
/* Defines for accessing group details */
// Number of groups in the filesystem
@@ -485,7 +481,22 @@ is_blk_empty(uint8 *b)
udecl32(s_creator_os) /* Indicator of which OS created the filesystem */ \
udecl32(s_rev_level) /* The revision level of the filesystem */ \
udecl16(s_def_resuid) /* The default uid for reserved blocks */ \
- udecl16(s_def_resgid) /* The default gid for reserved blocks */
+ udecl16(s_def_resgid) /* The default gid for reserved blocks */ \
+ /* rev 1 version fields start here */ \
+ udecl32(s_first_ino) /* First non-reserved inode */ \
+ udecl16(s_inode_size) /* size of inode structure */ \
+ udecl16(s_block_group_nr) /* block group # of this superblock */ \
+ udecl32(s_feature_compat) /* compatible feature set */ \
+ udecl32(s_feature_incompat) /* incompatible feature set */ \
+ udecl32(s_feature_ro_compat) /* readonly-compatible feature set */ \
+ utdecl8(s_uuid,16) /* 128-bit uuid for volume */ \
+ utdecl8(s_volume_name,16) /* volume name */ \
+ utdecl8(s_last_mounted,64) /* directory where last mounted */ \
+ udecl32(s_algorithm_usage_bitmap) /* For compression */
+
+#define EXT2_GOOD_OLD_FIRST_INO 11
+#define EXT2_GOOD_OLD_INODE_SIZE 128
+#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
#define groupdescriptor_decl \
udecl32(bg_block_bitmap) /* Block number of the block bitmap */ \
@@ -525,6 +536,7 @@ is_blk_empty(uint8 *b)
#define decl8(x) int8 x;
#define udecl8(x) uint8 x;
+#define utdecl8(x,n) uint8 x[n];
#define decl16(x) int16 x;
#define udecl16(x) uint16 x;
#define decl32(x) int32 x;
@@ -534,7 +546,7 @@ is_blk_empty(uint8 *b)
typedef struct
{
superblock_decl
- uint32 s_reserved[235]; // Reserved
+ uint32 s_reserved[205]; // Reserved
} superblock;
typedef struct
@@ -616,6 +628,8 @@ typedef struct
int32 hdlink_cnt;
struct hdlinks_s hdlinks;
+ int holes;
+
listcache blks;
listcache inodes;
listcache blkmaps;
@@ -628,6 +642,7 @@ typedef struct
#undef decl8
#undef udecl8
+#undef utdecl8
#undef decl16
#undef udecl16
#undef decl32
@@ -636,6 +651,7 @@ typedef struct
#define decl8(x)
#define udecl8(x)
+#define utdecl8(x,n)
#define decl16(x) this->x = swab16(this->x);
#define udecl16(x) this->x = swab16(this->x);
#define decl32(x) this->x = swab32(this->x);
@@ -700,6 +716,7 @@ swap_block(block b)
#undef decl8
#undef udecl8
+#undef utdecl8
#undef decl16
#undef udecl16
#undef decl32
@@ -1695,7 +1712,7 @@ extend_inode_blk(filesystem *fs, inode_pos *ipos, block b, int amount)
for (pos = 0; amount; pos += BLOCKSIZE)
{
- int hole = ((fs->sb->s_reserved[200] & OP_HOLES) && is_blk_empty(b + pos));
+ int hole = (fs->holes && is_blk_empty(b + pos));
bk = walk_bw(fs, ipos->nod, &ipos->bw, &amount, hole);
if (bk == WALK_END)
@@ -1912,6 +1929,14 @@ mklink_fs(filesystem *fs, uint32 parent_nod, const char *name, size_t size, uint
return nod;
}
+static void
+fs_upgrade_rev1_largefile(filesystem *fs)
+{
+ fs->sb->s_rev_level = 1;
+ fs->sb->s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
+ fs->sb->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
+}
+
#define COPY_BLOCKS 16
#define CB_SIZE (COPY_BLOCKS * BLOCKSIZE)
@@ -1926,11 +1951,16 @@ mkfile_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode, off_
size_t readbytes;
inode_pos ipos;
-
b = malloc(CB_SIZE);
if (!b)
error_msg_and_die("mkfile_fs: out of memory");
inode_pos_init(fs, &ipos, nod, INODE_POS_TRUNCATE, NULL);
+ if (size > 0x7fffffff) {
+ if (fs->sb->s_rev_level < 1)
+ fs_upgrade_rev1_largefile(fs);
+ fs->sb->s_feature_ro_compat |= EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
+ }
+ node->i_dir_acl = size >> 32;
node->i_size = size;
while (size) {
readbytes = fread(b, 1, CB_SIZE, f);
@@ -2269,6 +2299,8 @@ swap_gds(filesystem *fs)
// Copy size blocks from src to dst, putting holes in the output
// file (if possible) if the input block is all zeros.
+// Copy size blocks from src to dst, putting holes in the output
+// file (if possible) if the input block is all zeros.
static void
copy_file(filesystem *fs, FILE *dst, FILE *src, size_t size)
{
@@ -2284,7 +2316,7 @@ copy_file(filesystem *fs, FILE *dst, FILE *src, size_t size)
while (size > 0) {
if (fread(b, BLOCKSIZE, 1, src) != 1)
perror_msg_and_die("copy failed on read");
- if ((dst != stdout) && is_blk_empty(b)) {
+ if ((dst != stdout) && fs->holes && is_blk_empty(b)) {
/* Empty block, just skip it */
if (fseek(dst, BLOCKSIZE, SEEK_CUR))
perror_msg_and_die("fseek");
@@ -2537,8 +2569,7 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes,
fs->sb->s_max_mnt_count = 20;
// options for me
- if(holes)
- fs->sb->s_reserved[200] |= OP_HOLES;
+ fs->holes = holes;
return fs;
}
@@ -2571,8 +2602,21 @@ load_fs(FILE * fh, int swapit, char *fname)
perror_msg_and_die("fread filesystem image superblock");
if(swapit)
swap_sb(fs->sb);
- if(fs->sb->s_rev_level || (fs->sb->s_magic != EXT2_MAGIC_NUMBER))
+ if((fs->sb->s_rev_level > 1) || (fs->sb->s_magic != EXT2_MAGIC_NUMBER))
error_msg_and_die("not a suitable ext2 filesystem");
+ if (fs->sb->s_rev_level > 0) {
+ if (fs->sb->s_first_ino != EXT2_GOOD_OLD_FIRST_INO)
+ error_msg_and_die("First inode incompatible");
+ if (fs->sb->s_inode_size != EXT2_GOOD_OLD_INODE_SIZE)
+ error_msg_and_die("inode size incompatible");
+ if (fs->sb->s_feature_compat)
+ error_msg_and_die("Unsupported compat features");
+ if (fs->sb->s_feature_incompat)
+ error_msg_and_die("Unsupported incompat features");
+ if (fs->sb->s_feature_ro_compat
+ & ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE)
+ error_msg_and_die("Unsupported ro compat features");
+ }
fs->nheadblocks = (((GRP_NBGROUPS(fs) * sizeof(groupdescriptor))
+ sizeof(superblock) + (BLOCKSIZE - 1))
/ BLOCKSIZE);
@@ -2893,7 +2937,6 @@ finish_fs(filesystem *fs)
error_msg_and_die("entry mismatch on blockmap cache flush");
if (cache_flush(&fs->blks))
error_msg_and_die("entry mismatch on block cache flush");
- fs->sb->s_reserved[200] = 0;
if(fs->swapit) {
swap_sb(fs->sb);
swap_gds(fs);
--
1.7.4.1

View File

@ -0,0 +1,86 @@
Upstream-Status: inappropriate
From 3b9edc3e7c809f64dc164d73b64ab4a606ccfea1 Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Fri, 3 Jun 2011 21:24:49 -0500
Subject: [PATCH 13/19] Add volume id support.
Add support for setting the volume id of the filesystem. This is
functionally the same as the patch from OpenEmbedded, but is built
on previous changes in this patch set.
---
genext2fs.8 | 3 +++
genext2fs.c | 12 ++++++++++--
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/genext2fs.8 b/genext2fs.8
index 0f77e7c..8b8db25 100644
--- a/genext2fs.8
+++ b/genext2fs.8
@@ -61,6 +61,9 @@ Size of the image in blocks.
.BI "\-N, \-\-number\-of\-inodes inodes"
Maximum number of inodes.
.TP
+.BI "\-L, \-\-volume\-id name"
+Set the volume id (volume name) for the filesystem.
+.TP
.BI "\-i, \-\-bytes\-per\-inode ratio"
Used to calculate the maximum number of inodes from the available blocks.
.TP
diff --git a/genext2fs.c b/genext2fs.c
index e420bba..4d01bc4 100644
--- a/genext2fs.c
+++ b/genext2fs.c
@@ -3058,6 +3058,7 @@ main(int argc, char **argv)
int squash_perms = 0;
uint16 endian = 1;
int bigendian = !*(char*)&endian;
+ char *volumelabel = NULL;
filesystem *fs;
int i;
int c;
@@ -3071,6 +3072,7 @@ main(int argc, char **argv)
{ "size-in-blocks", required_argument, NULL, 'b' },
{ "bytes-per-inode", required_argument, NULL, 'i' },
{ "number-of-inodes", required_argument, NULL, 'N' },
+ { "volume-label", required_argument, NULL, 'L' },
{ "reserved-percentage", required_argument, NULL, 'm' },
{ "block-map", required_argument, NULL, 'g' },
{ "fill-value", required_argument, NULL, 'e' },
@@ -3087,11 +3089,11 @@ main(int argc, char **argv)
app_name = argv[0];
- while((c = getopt_long(argc, argv, "x:d:D:b:i:N:m:g:e:zfqUPhVv", longopts, NULL)) != EOF) {
+ while((c = getopt_long(argc, argv, "x:d:D:b:i:N:L:m:g:e:zfqUPhVv", longopts, NULL)) != EOF) {
#else
app_name = argv[0];
- while((c = getopt(argc, argv, "x:d:D:b:i:N:m:g:e:zfqUPhVv")) != EOF) {
+ while((c = getopt(argc, argv, "x:d:D:b:i:N:L:m:g:e:zfqUPhVv")) != EOF) {
#endif /* HAVE_GETOPT_LONG */
switch(c)
{
@@ -3111,6 +3113,9 @@ main(int argc, char **argv)
case 'N':
nbinodes = SI_atof(optarg);
break;
+ case 'L':
+ volumelabel = optarg;
+ break;
case 'm':
reserved_frac = SI_atof(optarg) / 100;
break;
@@ -3199,6 +3204,9 @@ main(int argc, char **argv)
fs = init_fs(nbblocks, nbinodes, nbresrvd, holes, fs_timestamp,
bigendian, fsout);
}
+ if (volumelabel != NULL)
+ strncpy((char *)fs->sb->s_volume_name, volumelabel,
+ sizeof(fs->sb->s_volume_name));
populate_fs(fs, dopt, didx, squash_uids, squash_perms, fs_timestamp, NULL);
--
1.7.4.1

View File

@ -0,0 +1,28 @@
Upstream-Status: inappropriate
From d20116479700bdc8a3b63b0025562671292728d6 Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Mon, 6 Jun 2011 13:39:50 -0500
Subject: [PATCH 14/19] Remove unneeded setting of s_reserved.
This was missed in the previous patch to remove OP_HOLES.
---
genext2fs.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/genext2fs.c b/genext2fs.c
index 4d01bc4..b466a6d 100644
--- a/genext2fs.c
+++ b/genext2fs.c
@@ -2463,8 +2463,6 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes,
fs->sb->s_magic = EXT2_MAGIC_NUMBER;
fs->sb->s_lastcheck = fs_timestamp;
- fs->sb->s_reserved[200] = 0;
-
set_file_size(fs);
// set up groupdescriptors
--
1.7.4.1

View File

@ -0,0 +1,57 @@
Upstream-Status: inappropriate
From 34a2d139e3cbc9fec1b07171fd13684d4239aa6b Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Mon, 6 Jun 2011 13:51:50 -0500
Subject: [PATCH 15/19] Rework creating the lost+found directory
For some reason the lost+found directory was being created with
the size of the number of reserved blocks. I can't find any rationale
for that, mke2fs creates it with 16 blocks. So just create it with
16 blocks, too.
---
genext2fs.c | 15 ++++++---------
1 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/genext2fs.c b/genext2fs.c
index b466a6d..fc7fe5f 100644
--- a/genext2fs.c
+++ b/genext2fs.c
@@ -2537,28 +2537,25 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes,
inode_pos_finish(fs, &ipos);
put_dir(&dw);
- // make lost+found directory and reserve blocks
+ // make lost+found directory
if(fs->sb->s_r_blocks_count)
{
inode *node;
uint8 *b;
- nod = mkdir_fs(fs, EXT2_ROOT_INO, "lost+found", FM_IRWXU, 0, 0, fs_timestamp, fs_timestamp);
+ nod = mkdir_fs(fs, EXT2_ROOT_INO, "lost+found", FM_IRWXU,
+ 0, 0, fs_timestamp, fs_timestamp);
b = get_workblk();
memset(b, 0, BLOCKSIZE);
((directory*)b)->d_rec_len = BLOCKSIZE;
- /* We run into problems with e2fsck if directory lost+found grows
- * bigger than this. Need to find out why this happens - sundar
- */
- if (fs->sb->s_r_blocks_count > fs->sb->s_blocks_count * MAX_RESERVED_BLOCKS )
- fs->sb->s_r_blocks_count = fs->sb->s_blocks_count * MAX_RESERVED_BLOCKS;
inode_pos_init(fs, &ipos, nod, INODE_POS_EXTEND, NULL);
- for(i = 1; i < fs->sb->s_r_blocks_count; i++)
+ // It is always 16 blocks to start out with
+ for(i = 0; i < 16; i++)
extend_inode_blk(fs, &ipos, b, 1);
inode_pos_finish(fs, &ipos);
free_workblk(b);
node = get_nod(fs, nod, &ni);
- node->i_size = fs->sb->s_r_blocks_count * BLOCKSIZE;
+ node->i_size = 16 * BLOCKSIZE;
put_nod(ni);
}
--
1.7.4.1

View File

@ -0,0 +1,29 @@
Upstream-Status: inappropriate
From 1b5007ee27b9dbf5e84341dceadb83b96e6530d5 Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Mon, 6 Jun 2011 13:58:57 -0500
Subject: [PATCH 16/19] Fix the documentation for the new -L option
---
genext2fs.8 | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/genext2fs.8 b/genext2fs.8
index 8b8db25..35e1588 100644
--- a/genext2fs.8
+++ b/genext2fs.8
@@ -61,8 +61,8 @@ Size of the image in blocks.
.BI "\-N, \-\-number\-of\-inodes inodes"
Maximum number of inodes.
.TP
-.BI "\-L, \-\-volume\-id name"
-Set the volume id (volume name) for the filesystem.
+.BI "\-L, \-\-volume\-label name"
+Set the volume label for the filesystem.
.TP
.BI "\-i, \-\-bytes\-per\-inode ratio"
Used to calculate the maximum number of inodes from the available blocks.
--
1.7.4.1

View File

@ -0,0 +1,30 @@
Upstream-Status: inappropriate
From 33c92a0b663d16d2260b391d39aa745acd4b360e Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Tue, 7 Jun 2011 07:23:23 -0500
Subject: [PATCH 17/19] Fix "file same" comparison
It's not enough to check the inode, you also have to check the device
to make sure a file is the same.
---
genext2fs.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/genext2fs.c b/genext2fs.c
index fc7fe5f..485393c 100644
--- a/genext2fs.c
+++ b/genext2fs.c
@@ -2359,7 +2359,8 @@ alloc_fs(int swapit, char *fname, uint32 nbblocks, FILE *srcfile)
perror_msg_and_die("fstat srcfile");
if (stat(fname, &dststat))
perror_msg_and_die("stat-ing %s", fname);
- if (srcstat.st_ino == dststat.st_ino) {
+ if (srcstat.st_ino == dststat.st_ino
+ && srcstat.st_dev == dststat.st_dev) {
// source and destination are the same file, don't
// truncate or copy, just use the file.
fs->f = fopen(fname, "r+b");
--
1.7.4.1

View File

@ -0,0 +1,89 @@
Upstream-Status: inappropriate
From fd1f52c435099eab199f2b06eb411aab337d7f47 Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Tue, 7 Jun 2011 07:29:53 -0500
Subject: [PATCH 18/19] Handle files changing while we are working
Files may change or be deleted between the lstat and the actual
operation to read them and put them into the target filesystem.
Handle this more gracefully. Warn on file deletions, and handle
whatever size is read, not whatever size happens to be in the
inode when we stat-ed it.
Also clear the data to the end of an file's last block, to keep
things clean.
---
genext2fs.c | 30 ++++++++++++++++++------------
1 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/genext2fs.c b/genext2fs.c
index 485393c..28ba94f 100644
--- a/genext2fs.c
+++ b/genext2fs.c
@@ -1942,19 +1942,30 @@ fs_upgrade_rev1_largefile(filesystem *fs)
// make a file from a FILE*
static uint32
-mkfile_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode, off_t size, FILE *f, uid_t uid, gid_t gid, uint32 ctime, uint32 mtime)
+mkfile_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode, FILE *f, uid_t uid, gid_t gid, uint32 ctime, uint32 mtime)
{
uint8 * b;
uint32 nod = mknod_fs(fs, parent_nod, name, mode|FM_IFREG, uid, gid, 0, 0, ctime, mtime);
nod_info *ni;
inode *node = get_nod(fs, nod, &ni);
+ off_t size = 0;
size_t readbytes;
inode_pos ipos;
+ int fullsize;
b = malloc(CB_SIZE);
if (!b)
error_msg_and_die("mkfile_fs: out of memory");
inode_pos_init(fs, &ipos, nod, INODE_POS_TRUNCATE, NULL);
+ readbytes = fread(b, 1, CB_SIZE, f);
+ while (readbytes) {
+ fullsize = rndup(readbytes, BLOCKSIZE);
+ // Fill to end of block with zeros.
+ memset(b + readbytes, 0, fullsize - readbytes);
+ extend_inode_blk(fs, &ipos, b, fullsize / BLOCKSIZE);
+ size += readbytes;
+ readbytes = fread(b, 1, CB_SIZE, f);
+ }
if (size > 0x7fffffff) {
if (fs->sb->s_rev_level < 1)
fs_upgrade_rev1_largefile(fs);
@@ -1962,15 +1973,6 @@ mkfile_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode, off_
}
node->i_dir_acl = size >> 32;
node->i_size = size;
- while (size) {
- readbytes = fread(b, 1, CB_SIZE, f);
- if ((size < CB_SIZE && readbytes != size)
- || (size >= CB_SIZE && readbytes != CB_SIZE))
- error_msg_and_die("fread failed");
- extend_inode_blk(fs, &ipos, b,
- rndup(readbytes, BLOCKSIZE) / BLOCKSIZE);
- size -= readbytes;
- }
inode_pos_finish(fs, &ipos);
put_nod(ni);
free(b);
@@ -2256,8 +2258,12 @@ add2fs_from_dir(filesystem *fs, uint32 this_nod, int squash_uids, int squash_per
free(lnk);
break;
case S_IFREG:
- fh = xfopen(dent->d_name, "rb");
- nod = mkfile_fs(fs, this_nod, name, mode, st.st_size, fh, uid, gid, ctime, mtime);
+ fh = fopen(dent->d_name, "rb");
+ if (!fh) {
+ error_msg("Unable to open file %s", dent->d_name);
+ break;
+ }
+ nod = mkfile_fs(fs, this_nod, name, mode, fh, uid, gid, ctime, mtime);
fclose(fh);
break;
case S_IFDIR:
--
1.7.4.1

View File

@ -0,0 +1,42 @@
Upstream-Status: inappropriate
From a263cdabad01ba99581b26d1753cd459f2669413 Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Tue, 7 Jun 2011 09:14:19 -0500
Subject: [PATCH 19/19] Make sure superblock is clear on allocation
Use calloc, not malloc, so the allocated superblock is zero-ed. Also,
get rid of some unnecessary casts.
---
genext2fs.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/genext2fs.c b/genext2fs.c
index 28ba94f..fab90be 100644
--- a/genext2fs.c
+++ b/genext2fs.c
@@ -2447,10 +2447,10 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes,
fs->nheadblocks = (((nbgroups * sizeof(groupdescriptor))
+ sizeof(superblock) + (BLOCKSIZE - 1))
/ BLOCKSIZE);
- fs->sb = (superblock *) malloc(BLOCKSIZE);
+ fs->sb = calloc(1, BLOCKSIZE);
if (!fs->sb)
error_msg_and_die("error allocating header memory");
- fs->gd = (groupdescriptor *) calloc(fs->nheadblocks - 1, BLOCKSIZE);
+ fs->gd = calloc(fs->nheadblocks - 1, BLOCKSIZE);
if (!fs->gd)
error_msg_and_die("error allocating header memory");
@@ -2595,7 +2595,7 @@ load_fs(FILE * fh, int swapit, char *fname)
/* Read and check the superblock, then read the superblock
* and all the group descriptors */
- fs->sb = malloc(BLOCKSIZE);
+ fs->sb = calloc(1, BLOCKSIZE);
if (!fs->sb)
error_msg_and_die("error allocating header memory");
if (fseek(fs->f, BLOCKSIZE, SEEK_SET))
--
1.7.4.1

View File

@ -11,11 +11,13 @@ int tmp_nbinodes = nbblocks * BLOCKSIZE / bytes_per_inode;
Upstream-Status: Submitted
Signed-off-by: Saul Wold <sgw@linux.intel.com>
Rebased by Dexuan Cui <dexuan.cui@intel.com>
Index: genext2fs-1.4.1/genext2fs.c
===================================================================
--- genext2fs-1.4.1.orig/genext2fs.c
+++ genext2fs-1.4.1/genext2fs.c
@@ -2447,7 +2447,7 @@ extern int optind, opterr, optopt;
--- a/genext2fs.c 2012-03-29 00:07:20.308856017 +0800
+++ b/genext2fs.c 2012-03-29 00:09:06.848856005 +0800
@@ -3041,7 +3041,7 @@
int
main(int argc, char **argv)
{
@ -24,12 +26,12 @@ Index: genext2fs-1.4.1/genext2fs.c
int nbinodes = -1;
int nbresrvd = -1;
float bytes_per_inode = -1;
@@ -2609,7 +2609,7 @@ main(int argc, char **argv)
@@ -3203,7 +3203,7 @@
}
if(fs_timestamp == -1)
fs_timestamp = time(NULL);
- fs = init_fs(nbblocks, nbinodes, nbresrvd, holes, fs_timestamp);
+ fs = init_fs((int)nbblocks, nbinodes, nbresrvd, holes, fs_timestamp);
- fs = init_fs(nbblocks, nbinodes, nbresrvd, holes, fs_timestamp,
+ fs = init_fs((int)nbblocks, nbinodes, nbresrvd, holes, fs_timestamp,
bigendian, fsout);
}
populate_fs(fs, dopt, didx, squash_uids, squash_perms, fs_timestamp, NULL);
if (volumelabel != NULL)

View File

@ -0,0 +1,119 @@
See http://genext2fs.cvs.sourceforge.net/viewvc/genext2fs/genext2fs/genext2fs.c?view=log
The latest version of genext2fs.c is the v1.95 in the cvs repo:
http://genext2fs.cvs.sourceforge.net/viewvc/genext2fs/genext2fs/genext2fs.c?revision=1.95
First let's upgrade to the version.
Upstream-Status: inappropriate
Signed-off-by: Dexuan Cui <dexuan.cui@intel.com>
--- a/genext2fs.c 2007-03-26 22:19:59.000000000 +0800
+++ b/genext2fs.c 2012-03-28 22:15:03.678856820 +0800
@@ -286,7 +286,9 @@
// older solaris. Note that this is still not very portable, in that
// the return value cannot be trusted.
-#if SCANF_CAN_MALLOC
+#if 0 // SCANF_CAN_MALLOC
+// C99 define "a" for floating point, so you can have runtime surprise
+// according the library versions
# define SCANF_PREFIX "a"
# define SCANF_STRING(s) (&s)
#else
@@ -778,7 +780,7 @@
if(hdlinks.hdl[i].src_inode == inode)
return i;
}
- return -1;
+ return -1;
}
// printf helper macro
@@ -1356,20 +1358,23 @@
return nod;
}
+// chmod an inode
+void
+chmod_fs(filesystem *fs, uint32 nod, uint16 mode, uint16 uid, uint16 gid)
+{
+ inode *node;
+ node = get_nod(fs, nod);
+ node->i_mode = (node->i_mode & ~FM_IMASK) | (mode & FM_IMASK);
+ node->i_uid = uid;
+ node->i_gid = gid;
+}
+
// create a simple inode
static uint32
mknod_fs(filesystem *fs, uint32 parent_nod, const char *name, uint16 mode, uint16 uid, uint16 gid, uint8 major, uint8 minor, uint32 ctime, uint32 mtime)
{
uint32 nod;
inode *node;
- if((nod = find_dir(fs, parent_nod, name)))
- {
- node = get_nod(fs, nod);
- if((node->i_mode & FM_IFMT) != (mode & FM_IFMT))
- error_msg_and_die("node '%s' already exists and isn't of the same type", name);
- node->i_mode = mode;
- }
- else
{
nod = alloc_nod(fs);
node = get_nod(fs, nod);
@@ -1591,13 +1596,24 @@
dname = malloc(len + 1);
for(i = start; i < count; i++)
{
+ uint32 oldnod;
SNPRINTF(dname, len, "%s%lu", name, i);
- mknod_fs(fs, nod, dname, mode, uid, gid, major, minor + (i * increment - start), ctime, mtime);
+ oldnod = find_dir(fs, nod, dname);
+ if(oldnod)
+ chmod_fs(fs, oldnod, mode, uid, gid);
+ else
+ mknod_fs(fs, nod, dname, mode, uid, gid, major, minor + (i * increment - start), ctime, mtime);
}
free(dname);
}
else
- mknod_fs(fs, nod, name, mode, uid, gid, major, minor, ctime, mtime);
+ {
+ uint32 oldnod = find_dir(fs, nod, name);
+ if(oldnod)
+ chmod_fs(fs, oldnod, mode, uid, gid);
+ else
+ mknod_fs(fs, nod, name, mode, uid, gid, major, minor, ctime, mtime);
+ }
}
}
if (line)
@@ -1664,6 +1680,17 @@
}
else
{
+ if((nod = find_dir(fs, this_nod, name)))
+ {
+ error_msg("ignoring duplicate entry %s", name);
+ if(S_ISDIR(st.st_mode)) {
+ if(chdir(dent->d_name) < 0)
+ perror_msg_and_die(name);
+ add2fs_from_dir(fs, nod, squash_uids, squash_perms, fs_timestamp, stats);
+ chdir("..");
+ }
+ continue;
+ }
save_nod = 0;
/* Check for hardlinks */
if (!S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode) && st.st_nlink > 1) {
@@ -1994,7 +2021,7 @@
//system blocks
for(j = 1; j <= overhead_per_group; j++)
allocate(bbm, j);
-
+
/* Inode bitmap */
ibm = get_blk(fs,fs->gd[i].bg_inode_bitmap);
//non-filesystem inodes

View File

@ -1,8 +1,28 @@
require genext2fs.inc
PR = "r1"
PR = "r2"
SRC_URI += "file://fix-nbblocks-cast.patch"
SRC_URI += "file://update_to_1.95.patch \
file://0001-Fix-warnings-remove-some-unused-macros.patch \
file://0002-Add-put_blk-and-put_nod-routines.patch \
file://0003-Add-get_blkmap-and-put_blkmap.patch \
file://0004-Add-a-dirwalker-for-walking-through-directory-entrie.patch \
file://0005-Make-filesystem-struct-not-an-overloay.patch \
file://0006-Improve-the-efficiency-of-extend_blk.patch \
file://0007-Move-hdlinks-into-the-filesystem-structure.patch \
file://0008-Separate-out-the-creation-of-the-filesystem-structur.patch \
file://0009-Move-byte-swapping-into-the-get-put-routines.patch \
file://0010-Convert-over-to-keeping-the-filesystem-on-disk.patch \
file://0011-Copy-files-into-the-filesystem-a-piece-at-a-time.patch \
file://0012-Add-rev-1-support-large-file-support-and-rework-hole.patch \
file://0013-Add-volume-id-support.patch \
file://0014-Remove-unneeded-setting-of-s_reserved.patch \
file://0015-Rework-creating-the-lost-found-directory.patch \
file://0016-Fix-the-documentation-for-the-new-L-option.patch \
file://0017-Fix-file-same-comparison.patch \
file://0018-Handle-files-changing-while-we-are-working.patch \
file://0019-Make-sure-superblock-is-clear-on-allocation.patch \
file://fix-nbblocks-cast.patch"
SRC_URI[md5sum] = "b7b6361bcce2cedff1ae437fadafe53b"
SRC_URI[sha256sum] = "404dbbfa7a86a6c3de8225c8da254d026b17fd288e05cec4df2cc7e1f4feecfc"