aboutsummaryrefslogtreecommitdiffstats
path: root/meta
diff options
context:
space:
mode:
authorDexuan Cui <dexuan.cui@intel.com>2012-03-29 00:35:09 +0800
committerRichard Purdie <richard.purdie@linuxfoundation.org>2012-04-02 04:26:09 +0100
commit8f17e499cf91191727c8767e839738cb39c21655 (patch)
treeff928b8e77c62375328841aaa822a1d95ce5dd04 /meta
parentb3ccc630e6c12a75111b1f7ca877e17d8d4e1dc7 (diff)
downloadopenembedded-core-contrib-8f17e499cf91191727c8767e839738cb39c21655.tar.gz
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 Signed-off-by: Dexuan Cui <dexuan.cui@intel.com>
Diffstat (limited to 'meta')
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0001-Fix-warnings-remove-some-unused-macros.patch72
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0002-Add-put_blk-and-put_nod-routines.patch1123
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0003-Add-get_blkmap-and-put_blkmap.patch222
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0004-Add-a-dirwalker-for-walking-through-directory-entrie.patch357
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0005-Make-filesystem-struct-not-an-overloay.patch374
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0006-Improve-the-efficiency-of-extend_blk.patch272
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0007-Move-hdlinks-into-the-filesystem-structure.patch175
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0008-Separate-out-the-creation-of-the-filesystem-structur.patch95
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0009-Move-byte-swapping-into-the-get-put-routines.patch421
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0010-Convert-over-to-keeping-the-filesystem-on-disk.patch839
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0011-Copy-files-into-the-filesystem-a-piece-at-a-time.patch103
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0012-Add-rev-1-support-large-file-support-and-rework-hole.patch211
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0013-Add-volume-id-support.patch86
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0014-Remove-unneeded-setting-of-s_reserved.patch28
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0015-Rework-creating-the-lost-found-directory.patch57
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0016-Fix-the-documentation-for-the-new-L-option.patch29
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0017-Fix-file-same-comparison.patch30
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0018-Handle-files-changing-while-we-are-working.patch89
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0019-Make-sure-superblock-is-clear-on-allocation.patch42
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/fix-nbblocks-cast.patch18
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs-1.4.1/update_to_1.95.patch119
-rw-r--r--meta/recipes-devtools/genext2fs/genext2fs_1.4.1.bb24
22 files changed, 4776 insertions, 10 deletions
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0001-Fix-warnings-remove-some-unused-macros.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0001-Fix-warnings-remove-some-unused-macros.patch
new file mode 100644
index 0000000000..f981b449ba
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0001-Fix-warnings-remove-some-unused-macros.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0002-Add-put_blk-and-put_nod-routines.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0002-Add-put_blk-and-put_nod-routines.patch
new file mode 100644
index 0000000000..ddcd052edc
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0002-Add-put_blk-and-put_nod-routines.patch
@@ -0,0 +1,1123 @@
+Upstream-Status: inappropriate
+
+From 8dd6e604777ffeb4d30921592f199cd9bcc8a3e2 Mon Sep 17 00:00:00 2001
+From: Corey Minyard <cminyard@mvista.com>
+Date: Sat, 4 Jun 2011 15:23:29 -0500
+Subject: [PATCH 02/19] Add put_blk and put_nod routines
+
+Add the routines to mark that we are done with a block or inode, and
+add the info structures so that get and put will work. This doesn't
+do anything functionally, just getting ready for future changes.
+
+Most of the changes are pretty straightforward. There were changes in
+get_nod() because it could use a later block than the one actually
+fetches. And walk_bw() needed some special handling to avoid using data
+after the put routine.
+---
+ genext2fs.c | 480 ++++++++++++++++++++++++++++++++++++++++-------------------
+ 1 files changed, 330 insertions(+), 150 deletions(-)
+
+diff --git a/genext2fs.c b/genext2fs.c
+index 284862d..bd06369 100644
+--- a/genext2fs.c
++++ b/genext2fs.c
+@@ -236,18 +236,22 @@ struct stats {
+ (((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 group block bitmap (bbm) given the group number
+-#define GRP_GET_GROUP_BBM(fs,grp) ( get_blk((fs),(fs)->gd[(grp)].bg_block_bitmap) )
++// 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)) )
++#define GRP_PUT_GROUP_BBM(bi) ( put_blk((bi)) )
+
+-// Get group inode bitmap (ibm) given the group number
+-#define GRP_GET_GROUP_IBM(fs,grp) ( get_blk((fs),(fs)->gd[(grp)].bg_inode_bitmap) )
++// Get/put group inode bitmap (ibm) given the group number
++#define GRP_GET_GROUP_IBM(fs,grp,bi) ( get_blk((fs),(fs)->gd[(grp)].bg_inode_bitmap,(bi)) )
++#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)
+
+-//Given an inode number get the inode bitmap that covers it
+-#define GRP_GET_INODE_BITMAP(fs,nod) \
+- ( GRP_GET_GROUP_IBM((fs),GRP_GROUP_OF_INODE((fs),(nod))) )
++//Given an inode number get/put the inode bitmap that covers it
++#define GRP_GET_INODE_BITMAP(fs,nod,bi) \
++ ( GRP_GET_GROUP_IBM((fs),GRP_GROUP_OF_INODE((fs),(nod)),(bi)) )
++#define GRP_PUT_INODE_BITMAP(bi) \
++ ( GRP_PUT_GROUP_IBM((bi)) )
+
+ //Given an inode number find its offset within the inode bitmap that covers it
+ #define GRP_IBM_OFFSET(fs,nod) \
+@@ -256,9 +260,11 @@ struct stats {
+ // 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)
+
+-//Given a block number get the block bitmap that covers it
+-#define GRP_GET_BLOCK_BITMAP(fs,blk) \
+- ( GRP_GET_GROUP_BBM((fs),GRP_GROUP_OF_BLOCK((fs),(blk))) )
++//Given a block number get/put the block bitmap that covers it
++#define GRP_GET_BLOCK_BITMAP(fs,blk,bi) \
++ ( GRP_GET_GROUP_BBM((fs),GRP_GROUP_OF_BLOCK((fs),(blk)),(bi)) )
++#define GRP_PUT_BLOCK_BITMAP(bi) \
++ ( GRP_PUT_GROUP_BBM((bi)) )
+
+ //Given a block number find its offset within the block bitmap that covers it
+ #define GRP_BBM_OFFSET(fs,blk) \
+@@ -811,24 +817,59 @@ allocated(block b, uint32 item)
+ return b[(item-1) / 8] & (1 << ((item-1) % 8));
+ }
+
+-// return a given block from a filesystem
++// Used by get_blk/put_blk to hold information about a block owned
++// by the user.
++typedef struct
++{
++ int dummy;
++} blk_info;
++
++// 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)
++get_blk(filesystem *fs, uint32 blk, blk_info **rbi)
+ {
+ return (uint8*)fs + blk*BLOCKSIZE;
+ }
+
+-// return a given inode from a filesystem
++static inline void
++put_blk(blk_info *bi)
++{
++}
++
++// Used by get_nod/put_nod to hold information about an inode owned
++// by the user.
++typedef struct
++{
++ blk_info *bi;
++} nod_info;
++
++// 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)
++get_nod(filesystem *fs, uint32 nod, nod_info **rni)
+ {
+- int grp,offset;
++ int grp, offset, boffset;
+ inode *itab;
++ nod_info *ni;
+
+- offset = GRP_IBM_OFFSET(fs,nod);
++ offset = GRP_IBM_OFFSET(fs,nod) - 1;
++ boffset = offset / (BLOCKSIZE / sizeof(inode));
++ offset %= BLOCKSIZE / sizeof(inode);
+ grp = GRP_GROUP_OF_INODE(fs,nod);
+- itab = (inode *)get_blk(fs, fs->gd[grp].bg_inode_table);
+- return itab+offset-1;
++ 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);
++ *rni = ni;
++ return itab+offset;
++}
++
++static inline void
++put_nod(nod_info *ni)
++{
++ put_blk(ni->bi);
++ free(ni);
+ }
+
+ // allocate a given block/inode in the bitmap
+@@ -870,12 +911,17 @@ alloc_blk(filesystem *fs, uint32 nod)
+ {
+ uint32 bk=0;
+ uint32 grp,nbgroups;
++ blk_info *bi;
+
+ grp = GRP_GROUP_OF_INODE(fs,nod);
+ nbgroups = GRP_NBGROUPS(fs);
+- if(!(bk = allocate(get_blk(fs,fs->gd[grp].bg_block_bitmap), 0))) {
+- for(grp=0;grp<nbgroups && !bk;grp++)
+- bk=allocate(get_blk(fs,fs->gd[grp].bg_block_bitmap),0);
++ bk = allocate(get_blk(fs, fs->gd[grp].bg_block_bitmap, &bi), 0);
++ put_blk(bi);
++ if (!bk) {
++ for (grp=0; grp<nbgroups && !bk; grp++) {
++ bk = allocate(get_blk(fs, fs->gd[grp].bg_block_bitmap, &bi), 0);
++ put_blk(bi);
++ }
+ grp--;
+ }
+ if (!bk)
+@@ -892,10 +938,12 @@ static void
+ 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;
+- deallocate(get_blk(fs,fs->gd[grp].bg_block_bitmap), bk);
++ 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++;
+ }
+@@ -906,6 +954,7 @@ alloc_nod(filesystem *fs)
+ {
+ uint32 nod,best_group=0;
+ uint32 grp,nbgroups,avefreei;
++ blk_info *bi;
+
+ nbgroups = GRP_NBGROUPS(fs);
+
+@@ -923,8 +972,10 @@ alloc_nod(filesystem *fs)
+ fs->gd[grp].bg_free_blocks_count > fs->gd[best_group].bg_free_blocks_count)
+ best_group = grp;
+ }
+- if (!(nod = allocate(get_blk(fs,fs->gd[best_group].bg_inode_bitmap),0)))
++ if (!(nod = allocate(get_blk(fs, fs->gd[best_group].bg_inode_bitmap,
++ &bi), 0)))
+ error_msg_and_die("couldn't allocate an inode (no free inode)");
++ 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--))
+@@ -968,24 +1019,35 @@ static uint32
+ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
+ {
+ uint32 *bkref = 0;
++ uint32 bk = 0;
+ 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;
+- if(bw->bnum >= get_nod(fs, nod)->i_blocks / INOBLK)
++ inod = get_nod(fs, nod, &ni);
++ if(bw->bnum >= inod->i_blocks / INOBLK)
+ {
+ if(create && (*create) > 0)
+ {
+ (*create)--;
+ extend = 1;
+ }
+- else
++ else
++ {
++ put_nod(ni);
+ return WALK_END;
++ }
+ }
++ iblk = inod->i_block;
+ // first direct block
+ if(bw->bpdir == EXT2_INIT_BLOCK)
+ {
+- bkref = &get_nod(fs, nod)->i_block[bw->bpdir = 0];
++ bkref = &iblk[bw->bpdir = 0];
+ if(extend) // allocate first block
+ *bkref = hole ? 0 : alloc_blk(fs,nod);
+ if(reduce) // free first block
+@@ -994,7 +1056,7 @@ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
+ // direct block
+ else if(bw->bpdir < EXT2_NDIR_BLOCKS)
+ {
+- bkref = &get_nod(fs, nod)->i_block[++bw->bpdir];
++ bkref = &iblk[++bw->bpdir];
+ if(extend) // allocate block
+ *bkref = hole ? 0 : alloc_blk(fs,nod);
+ if(reduce) // free block
+@@ -1007,10 +1069,10 @@ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
+ bw->bpdir = EXT2_IND_BLOCK;
+ bw->bpind = 0;
+ if(extend) // allocate indirect block
+- get_nod(fs, nod)->i_block[bw->bpdir] = alloc_blk(fs,nod);
++ iblk[bw->bpdir] = alloc_blk(fs,nod);
+ if(reduce) // free indirect block
+- free_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
+- b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
++ free_blk(fs, iblk[bw->bpdir]);
++ b = (uint32*)get_blk(fs, iblk[bw->bpdir], &bi1);
+ bkref = &b[bw->bpind];
+ if(extend) // allocate first block
+ *bkref = hole ? 0 : alloc_blk(fs,nod);
+@@ -1021,7 +1083,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, get_nod(fs, nod)->i_block[bw->bpdir]);
++ b = (uint32*)get_blk(fs, iblk[bw->bpdir], &bi1);
+ bkref = &b[bw->bpind];
+ if(extend) // allocate block
+ *bkref = hole ? 0 : alloc_blk(fs,nod);
+@@ -1036,15 +1098,15 @@ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
+ bw->bpind = 0;
+ bw->bpdind = 0;
+ if(extend) // allocate double indirect block
+- get_nod(fs, nod)->i_block[bw->bpdir] = alloc_blk(fs,nod);
++ iblk[bw->bpdir] = alloc_blk(fs,nod);
+ if(reduce) // free double indirect block
+- free_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
+- b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
++ free_blk(fs, iblk[bw->bpdir]);
++ b = (uint32*)get_blk(fs, iblk[bw->bpdir], &bi1);
+ 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]);
++ b = (uint32*)get_blk(fs, b[bw->bpind], &bi1);
+ bkref = &b[bw->bpdind];
+ if(extend) // allocate first block
+ *bkref = hole ? 0 : alloc_blk(fs,nod);
+@@ -1055,8 +1117,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, get_nod(fs, nod)->i_block[bw->bpdir]);
+- b = (uint32*)get_blk(fs, b[bw->bpind]);
++ b = (uint32*)get_blk(fs, iblk[bw->bpdir], &bi1);
++ b = (uint32*)get_blk(fs, b[bw->bpind], &bi2);
+ bkref = &b[bw->bpdind];
+ if(extend) // allocate block
+ *bkref = hole ? 0 : alloc_blk(fs,nod);
+@@ -1069,12 +1131,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, get_nod(fs, nod)->i_block[bw->bpdir]);
++ b = (uint32*)get_blk(fs, iblk[bw->bpdir], &bi1);
+ 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]);
++ b = (uint32*)get_blk(fs, b[bw->bpind], &bi2);
+ bkref = &b[bw->bpdind];
+ if(extend) // allocate first block
+ *bkref = hole ? 0 : alloc_blk(fs,nod);
+@@ -1094,20 +1156,20 @@ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
+ bw->bpdind = 0;
+ bw->bptind = 0;
+ if(extend) // allocate triple indirect block
+- get_nod(fs, nod)->i_block[bw->bpdir] = alloc_blk(fs,nod);
++ iblk[bw->bpdir] = alloc_blk(fs,nod);
+ if(reduce) // free triple indirect block
+- free_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
+- b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
++ free_blk(fs, iblk[bw->bpdir]);
++ b = (uint32*)get_blk(fs, iblk[bw->bpdir], &bi1);
+ 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]);
++ b = (uint32*)get_blk(fs, b[bw->bpind], &bi2);
+ 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]);
++ b = (uint32*)get_blk(fs, b[bw->bpdind], &bi3);
+ bkref = &b[bw->bptind];
+ if(extend) // allocate first data block
+ *bkref = hole ? 0 : alloc_blk(fs,nod);
+@@ -1121,9 +1183,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, get_nod(fs, nod)->i_block[bw->bpdir]);
+- b = (uint32*)get_blk(fs, b[bw->bpind]);
+- b = (uint32*)get_blk(fs, b[bw->bpdind]);
++ 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);
+ bkref = &b[bw->bptind];
+ if(extend) // allocate data block
+ *bkref = hole ? 0 : alloc_blk(fs,nod);
+@@ -1140,13 +1202,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, get_nod(fs, nod)->i_block[bw->bpdir]);
+- b = (uint32*)get_blk(fs, b[bw->bpind]);
++ b = (uint32*)get_blk(fs, iblk[bw->bpdir], &bi1);
++ b = (uint32*)get_blk(fs, b[bw->bpind], &bi2);
+ 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]);
++ b = (uint32*)get_blk(fs, b[bw->bpdind], &bi3);
+ bkref = &b[bw->bptind];
+ if(extend) // allocate first data block
+ *bkref = hole ? 0 : alloc_blk(fs,nod);
+@@ -1163,17 +1225,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, get_nod(fs, nod)->i_block[bw->bpdir]);
++ b = (uint32*)get_blk(fs, iblk[bw->bpdir], &bi1);
+ 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]);
++ b = (uint32*)get_blk(fs, b[bw->bpind], &bi2);
+ 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]);
++ b = (uint32*)get_blk(fs, b[bw->bpdind], &bi3);
+ bkref = &b[bw->bptind];
+ if(extend) // allocate first block
+ *bkref = hole ? 0 : alloc_blk(fs,nod);
+@@ -1184,15 +1246,28 @@ walk_bw(filesystem *fs, uint32 nod, blockwalker *bw, int32 *create, uint32 hole)
+ error_msg_and_die("file too big !");
+ /* End change for walking triple indirection */
+
+- if(*bkref)
++ bk = *bkref;
++ if (bi3)
++ put_blk(bi3);
++ if (bi2)
++ put_blk(bi2);
++ if (bi1)
++ put_blk(bi1);
++
++ if(bk)
+ {
++ blk_info *bi;
++ uint8 *block;
+ bw->bnum++;
+- if(!reduce && !allocated(GRP_GET_BLOCK_BITMAP(fs,*bkref), GRP_BBM_OFFSET(fs,*bkref)))
+- error_msg_and_die("[block %d of inode %d is unallocated !]", *bkref, nod);
++ block = GRP_GET_BLOCK_BITMAP(fs,bk,&bi);
++ if(!reduce && !allocated(block, GRP_BBM_OFFSET(fs,bk)))
++ error_msg_and_die("[block %d of inode %d is unallocated !]", bk, nod);
++ GRP_PUT_BLOCK_BITMAP(bi);
+ }
+ if(extend)
+- get_nod(fs, nod)->i_blocks = bw->bnum * INOBLK;
+- return *bkref;
++ inod->i_blocks = bw->bnum * INOBLK;
++ put_nod(ni);
++ return bk;
+ }
+
+ // add blocks to an inode (file/dir/etc...)
+@@ -1202,15 +1277,19 @@ extend_blk(filesystem *fs, uint32 nod, block b, int amount)
+ int create = amount;
+ blockwalker bw, lbw;
+ uint32 bk;
++ nod_info *ni;
++ inode *inod;
++
++ inod = get_nod(fs, nod, &ni);
+ init_bw(&bw);
+ if(amount < 0)
+ {
+ uint32 i;
+- for(i = 0; i < get_nod(fs, nod)->i_blocks / INOBLK + amount; 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)
+ /*nop*/;
+- get_nod(fs, nod)->i_blocks += amount * INOBLK;
++ inod->i_blocks += amount * INOBLK;
+ }
+ else
+ {
+@@ -1232,8 +1311,11 @@ extend_blk(filesystem *fs, uint32 nod, block b, int amount)
+ }
+ if((bk = walk_bw(fs, nod, &bw, &create, !copyb)) == WALK_END)
+ break;
+- if(copyb)
+- memcpy(get_blk(fs, bk), b + BLOCKSIZE * (amount - create - 1), BLOCKSIZE);
++ if(copyb) {
++ blk_info *bi;
++ memcpy(get_blk(fs, bk, &bi), b + BLOCKSIZE * (amount - create - 1), BLOCKSIZE);
++ put_blk(bi);
++ }
+ }
+ }
+ }
+@@ -1245,12 +1327,14 @@ add2dir(filesystem *fs, uint32 dnod, uint32 nod, const char* name)
+ blockwalker bw;
+ uint32 bk;
+ uint8 *b;
++ blk_info *bi;
+ directory *d;
+ int reclen, nlen;
+ inode *node;
+ inode *pnode;
++ nod_info *dni, *ni;
+
+- pnode = get_nod(fs, dnod);
++ pnode = get_nod(fs, dnod, &dni);
+ if((pnode->i_mode & FM_IFMT) != FM_IFDIR)
+ error_msg_and_die("can't add '%s' to a non-directory", name);
+ if(!*name)
+@@ -1264,7 +1348,7 @@ add2dir(filesystem *fs, uint32 dnod, uint32 nod, const char* name)
+ init_bw(&bw);
+ while((bk = walk_bw(fs, dnod, &bw, 0, 0)) != WALK_END) // for all blocks in dir
+ {
+- b = get_blk(fs, bk);
++ 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))
+ {
+@@ -1272,11 +1356,12 @@ add2dir(filesystem *fs, uint32 dnod, uint32 nod, const char* name)
+ if((!d->d_inode) && (d->d_rec_len >= reclen))
+ {
+ d->d_inode = nod;
+- node = get_nod(fs, nod);
++ node = get_nod(fs, nod, &ni);
+ node->i_links_count++;
+ d->d_name_len = nlen;
+ strncpy(d->d_name, name, nlen);
+- return;
++ 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))
+@@ -1287,11 +1372,12 @@ add2dir(filesystem *fs, uint32 dnod, uint32 nod, const char* name)
+ d = (directory*) (((int8*)d) + d->d_rec_len);
+ d->d_rec_len = reclen;
+ d->d_inode = nod;
+- node = get_nod(fs, nod);
++ node = get_nod(fs, nod, &ni);
+ node->i_links_count++;
+ d->d_name_len = nlen;
+ strncpy(d->d_name, name, nlen);
+- return;
++ put_nod(ni);
++ goto out;
+ }
+ }
+ }
+@@ -1300,14 +1386,17 @@ add2dir(filesystem *fs, uint32 dnod, uint32 nod, const char* name)
+ error_msg_and_die("get_workblk() failed.");
+ d = (directory*)b;
+ d->d_inode = nod;
+- node = get_nod(fs, nod);
++ node = get_nod(fs, nod, &ni);
+ 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);
+- get_nod(fs, dnod)->i_size += BLOCKSIZE;
++ pnode->i_size += BLOCKSIZE;
+ free_workblk(b);
++out:
++ put_nod(dni);
+ }
+
+ // find an entry in a directory
+@@ -1316,16 +1405,20 @@ 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);
++ 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))
++ if(d->d_inode && (nlen == d->d_name_len) && !strncmp(d->d_name, name, nlen)) {
++ put_blk(bi);
+ return d->d_inode;
++ }
++ put_blk(bi);
+ }
+ return 0;
+ }
+@@ -1361,10 +1454,12 @@ void
+ chmod_fs(filesystem *fs, uint32 nod, uint16 mode, uint16 uid, uint16 gid)
+ {
+ inode *node;
+- node = get_nod(fs, nod);
++ nod_info *ni;
++ node = get_nod(fs, nod, &ni);
+ node->i_mode = (node->i_mode & ~FM_IMASK) | (mode & FM_IMASK);
+ node->i_uid = uid;
+ node->i_gid = gid;
++ put_nod(ni);
+ }
+
+ // create a simple inode
+@@ -1373,33 +1468,34 @@ mknod_fs(filesystem *fs, uint32 parent_nod, const char *name, uint16 mode, uint1
+ {
+ uint32 nod;
+ inode *node;
++ nod_info *ni;
++
++ nod = alloc_nod(fs);
++ node = get_nod(fs, nod, &ni);
++ node->i_mode = mode;
++ add2dir(fs, parent_nod, nod, name);
++ switch(mode & FM_IFMT)
+ {
+- nod = alloc_nod(fs);
+- node = get_nod(fs, nod);
+- node->i_mode = mode;
+- add2dir(fs, parent_nod, nod, name);
+- switch(mode & FM_IFMT)
+- {
+- case FM_IFLNK:
+- mode = FM_IFLNK | FM_IRWXU | FM_IRWXG | FM_IRWXO;
+- break;
+- case FM_IFBLK:
+- case FM_IFCHR:
+- ((uint8*)get_nod(fs, nod)->i_block)[0] = minor;
+- ((uint8*)get_nod(fs, nod)->i_block)[1] = major;
+- break;
+- case FM_IFDIR:
+- add2dir(fs, nod, nod, ".");
+- add2dir(fs, nod, parent_nod, "..");
+- fs->gd[GRP_GROUP_OF_INODE(fs,nod)].bg_used_dirs_count++;
+- break;
+- }
++ case FM_IFLNK:
++ mode = FM_IFLNK | FM_IRWXU | FM_IRWXG | FM_IRWXO;
++ break;
++ case FM_IFBLK:
++ case FM_IFCHR:
++ ((uint8*)node->i_block)[0] = minor;
++ ((uint8*)node->i_block)[1] = major;
++ break;
++ case FM_IFDIR:
++ add2dir(fs, nod, nod, ".");
++ add2dir(fs, nod, parent_nod, "..");
++ fs->gd[GRP_GROUP_OF_INODE(fs,nod)].bg_used_dirs_count++;
++ break;
+ }
+ node->i_uid = uid;
+ node->i_gid = gid;
+ node->i_atime = mtime;
+ node->i_ctime = ctime;
+ node->i_mtime = mtime;
++ put_nod(ni);
+ return nod;
+ }
+
+@@ -1416,14 +1512,19 @@ static uint32
+ mklink_fs(filesystem *fs, uint32 parent_nod, const char *name, size_t size, uint8 *b, uid_t uid, gid_t gid, uint32 ctime, uint32 mtime)
+ {
+ uint32 nod = mknod_fs(fs, parent_nod, name, FM_IFLNK | FM_IRWXU | FM_IRWXG | FM_IRWXO, uid, gid, 0, 0, ctime, mtime);
+- extend_blk(fs, nod, 0, - (int)get_nod(fs, nod)->i_blocks / INOBLK);
+- get_nod(fs, nod)->i_size = size;
++ nod_info *ni;
++ inode *node = get_nod(fs, nod, &ni);
++
++ extend_blk(fs, nod, 0, - (int)node->i_blocks / INOBLK);
++ node->i_size = size;
+ if(size <= 4 * (EXT2_TIND_BLOCK+1))
+ {
+- strncpy((char*)get_nod(fs, nod)->i_block, (char*)b, size);
++ strncpy((char *)node->i_block, (char *)b, size);
++ put_nod(ni);
+ return nod;
+ }
+ extend_blk(fs, nod, b, rndup(size, BLOCKSIZE) / BLOCKSIZE);
++ put_nod(ni);
+ return nod;
+ }
+
+@@ -1433,8 +1534,11 @@ mkfile_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode, size
+ {
+ uint8 * b;
+ uint32 nod = mknod_fs(fs, parent_nod, name, mode|FM_IFREG, uid, gid, 0, 0, ctime, mtime);
+- extend_blk(fs, nod, 0, - (int)get_nod(fs, nod)->i_blocks / INOBLK);
+- get_nod(fs, nod)->i_size = size;
++ nod_info *ni;
++ inode *node = get_nod(fs, nod, &ni);
++
++ extend_blk(fs, nod, 0, - (int)node->i_blocks / INOBLK);
++ 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);
+@@ -1444,6 +1548,7 @@ mkfile_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode, size
+ extend_blk(fs, nod, b, rndup(size, BLOCKSIZE) / BLOCKSIZE);
+ free(b);
+ }
++ put_nod(ni);
+ return nod;
+ }
+
+@@ -1766,6 +1871,7 @@ 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))
+@@ -1773,7 +1879,8 @@ swap_goodblocks(filesystem *fs, inode *nod)
+ 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]));
++ 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
+@@ -1791,29 +1898,37 @@ swap_goodblocks(filesystem *fs, inode *nod)
+ // 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]))[i]));
+- swap_block(get_blk(fs, nod->i_block[EXT2_DIND_BLOCK]));
++ 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]);
++ 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]);
++ 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]));
++ 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;
+ }
+
+@@ -1823,6 +1938,7 @@ 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))
+@@ -1830,35 +1946,44 @@ swap_badblocks(filesystem *fs, inode *nod)
+ 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]));
++ 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]));
++ 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]))[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]);
++ 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]);
++ 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]));
++ 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;
+ }
+
+@@ -1867,9 +1992,11 @@ 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);
++ inode *nod = get_nod(fs, i, &ni);
+ if(nod->i_mode & FM_IFDIR)
+ {
+ blockwalker bw;
+@@ -1879,13 +2006,16 @@ swap_goodfs(filesystem *fs)
+ {
+ directory *d;
+ uint8 *b;
+- b = get_blk(fs, bk);
++ 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]));
+@@ -1901,7 +2031,8 @@ swap_badfs(filesystem *fs)
+ swap_gd(&(fs->gd[i]));
+ for(i = 1; i < fs->sb.s_inodes_count; i++)
+ {
+- inode *nod = get_nod(fs, i);
++ nod_info *ni;
++ inode *nod = get_nod(fs, i, &ni);
+ swap_nod(nod);
+ swap_badblocks(fs, nod);
+ if(nod->i_mode & FM_IFDIR)
+@@ -1913,9 +2044,11 @@ swap_badfs(filesystem *fs)
+ {
+ directory *d;
+ uint8 *b;
+- b = get_blk(fs, bk);
++ 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);
+ }
+ }
+ }
+@@ -1936,6 +2069,8 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
+ uint32 j;
+ uint8 *bbm,*ibm;
+ inode *itab0;
++ blk_info *bi;
++ nod_info *ni;
+
+ if(nbresrvd < 0)
+ error_msg_and_die("reserved blocks value is invalid. Note: options have changed, see --help or the man page.");
+@@ -2014,9 +2149,8 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
+ /* Mark non-filesystem blocks and inodes as allocated */
+ /* Mark system blocks and inodes as allocated */
+ for(i = 0; i<nbgroups;i++) {
+-
+ /* Block bitmap */
+- bbm = get_blk(fs,fs->gd[i].bg_block_bitmap);
++ bbm = get_blk(fs,fs->gd[i].bg_block_bitmap, &bi);
+ //non-filesystem blocks
+ for(j = fs->gd[i].bg_free_blocks_count
+ + overhead_per_group + 1; j <= BLOCKSIZE * 8; j++)
+@@ -2024,9 +2158,10 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
+ //system blocks
+ for(j = 1; j <= overhead_per_group; j++)
+ allocate(bbm, j);
++ put_blk(bi);
+
+ /* Inode bitmap */
+- ibm = get_blk(fs,fs->gd[i].bg_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++)
+ allocate(ibm, j);
+@@ -2035,6 +2170,7 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
+ if(i == 0)
+ for(j = 1; j < EXT2_FIRST_INO; j++)
+ allocate(ibm, j);
++ put_blk(bi);
+ }
+
+ // make root inode and directory
+@@ -2042,13 +2178,14 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
+ /* Also increment the directory count for group 0 */
+ fs->gd[0].bg_free_inodes_count--;
+ fs->gd[0].bg_used_dirs_count = 1;
+- itab0 = (inode *)get_blk(fs,fs->gd[0].bg_inode_table);
+- itab0[EXT2_ROOT_INO-1].i_mode = FM_IFDIR | FM_IRWXU | FM_IRGRP | FM_IROTH | FM_IXGRP | FM_IXOTH;
+- itab0[EXT2_ROOT_INO-1].i_ctime = fs_timestamp;
+- itab0[EXT2_ROOT_INO-1].i_mtime = fs_timestamp;
+- itab0[EXT2_ROOT_INO-1].i_atime = fs_timestamp;
+- itab0[EXT2_ROOT_INO-1].i_size = BLOCKSIZE;
+- itab0[EXT2_ROOT_INO-1].i_links_count = 2;
++ itab0 = get_nod(fs, EXT2_ROOT_INO, &ni);
++ itab0->i_mode = FM_IFDIR | FM_IRWXU | FM_IRGRP | FM_IROTH | FM_IXGRP | FM_IXOTH;
++ itab0->i_ctime = fs_timestamp;
++ itab0->i_mtime = fs_timestamp;
++ itab0->i_atime = fs_timestamp;
++ itab0->i_size = BLOCKSIZE;
++ itab0->i_links_count = 2;
++ put_nod(ni);
+
+ if(!(b = get_workblk()))
+ error_msg_and_die("get_workblk() failed.");
+@@ -2067,6 +2204,8 @@ init_fs(int nbblocks, int nbinodes, int nbresrvd, int holes, uint32 fs_timestamp
+ // make lost+found directory and reserve blocks
+ if(fs->sb.s_r_blocks_count)
+ {
++ inode *node;
++
+ nod = mkdir_fs(fs, EXT2_ROOT_INO, "lost+found", FM_IRWXU, 0, 0, fs_timestamp, fs_timestamp);
+ memset(b, 0, BLOCKSIZE);
+ ((directory*)b)->d_rec_len = BLOCKSIZE;
+@@ -2077,7 +2216,9 @@ 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);
+- get_nod(fs, nod)->i_size = fs->sb.s_r_blocks_count * BLOCKSIZE;
++ node = get_nod(fs, nod, &ni);
++ node->i_size = fs->sb.s_r_blocks_count * BLOCKSIZE;
++ put_nod(ni);
+ }
+ free_workblk(b);
+
+@@ -2153,16 +2294,23 @@ write_blocks(filesystem *fs, uint32 nod, FILE* f)
+ {
+ blockwalker bw;
+ uint32 bk;
+- int32 fsize = get_nod(fs, nod)->i_size;
++ nod_info *ni;
++ inode *node = get_nod(fs, nod, &ni);
++ int32 fsize = node->i_size;
++ blk_info *bi;
++
+ init_bw(&bw);
+ while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END)
+ {
+ if(fsize <= 0)
+ error_msg_and_die("wrong size while saving inode %d", nod);
+- if(fwrite(get_blk(fs, bk), (fsize > BLOCKSIZE) ? BLOCKSIZE : fsize, 1, f) != 1)
++ if(fwrite(get_blk(fs, bk, &bi),
++ (fsize > BLOCKSIZE) ? BLOCKSIZE : fsize, 1, f) != 1)
+ error_msg_and_die("error while saving inode %d", nod);
++ put_blk(bi);
+ fsize -= BLOCKSIZE;
+ }
++ put_nod(ni);
+ }
+
+
+@@ -2171,8 +2319,11 @@ static void
+ print_dev(filesystem *fs, uint32 nod)
+ {
+ int minor, major;
+- minor = ((uint8*)get_nod(fs, nod)->i_block)[0];
+- major = ((uint8*)get_nod(fs, nod)->i_block)[1];
++ nod_info *ni;
++ inode *node = get_nod(fs, nod, &ni);
++ minor = ((uint8*)node->i_block)[0];
++ major = ((uint8*)node->i_block)[1];
++ put_nod(ni);
+ printf("major: %d, minor: %d\n", major, minor);
+ }
+
+@@ -2188,7 +2339,8 @@ print_dir(filesystem *fs, uint32 nod)
+ {
+ directory *d;
+ uint8 *b;
+- b = get_blk(fs, bk);
++ 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))
+ if(d->d_inode)
+ {
+@@ -2198,6 +2350,7 @@ print_dir(filesystem *fs, uint32 nod)
+ putchar(d->d_name[i]);
+ printf("' (inode %d): rec_len: %d (name_len: %d)\n", d->d_inode, d->d_rec_len, d->d_name_len);
+ }
++ put_blk(bi);
+ }
+ }
+
+@@ -2205,14 +2358,18 @@ print_dir(filesystem *fs, uint32 nod)
+ static void
+ print_link(filesystem *fs, uint32 nod)
+ {
+- if(!get_nod(fs, nod)->i_blocks)
+- printf("links to '%s'\n", (char*)get_nod(fs, nod)->i_block);
++ nod_info *ni;
++ inode *node = get_nod(fs, nod, &ni);
++
++ if(!node->i_blocks)
++ printf("links to '%s'\n", (char*)node->i_block);
+ else
+ {
+ printf("links to '");
+ write_blocks(fs, nod, stdout);
+ printf("'\n");
+ }
++ put_nod(ni);
+ }
+
+ // make a ls-like printout of permissions
+@@ -2281,8 +2438,12 @@ print_inode(filesystem *fs, uint32 nod)
+ {
+ char *s;
+ char perms[11];
+- if(!get_nod(fs, nod)->i_mode)
+- return;
++ nod_info *ni;
++ inode *node = get_nod(fs, nod, &ni);
++ blk_info *bi;
++
++ if(!node->i_mode)
++ goto out;
+ switch(nod)
+ {
+ case EXT2_BAD_INO:
+@@ -2304,15 +2465,18 @@ print_inode(filesystem *fs, uint32 nod)
+ default:
+ s = (nod >= EXT2_FIRST_INO) ? "normal" : "unknown reserved";
+ }
+- printf("inode %d (%s, %d links): ", nod, s, get_nod(fs, nod)->i_links_count);
+- if(!allocated(GRP_GET_INODE_BITMAP(fs,nod), GRP_IBM_OFFSET(fs,nod)))
++ printf("inode %d (%s, %d links): ", nod, s, node->i_links_count);
++ if(!allocated(GRP_GET_INODE_BITMAP(fs,nod,&bi), GRP_IBM_OFFSET(fs,nod)))
+ {
++ GRP_PUT_INODE_BITMAP(bi);
+ printf("unallocated\n");
+- return;
++ goto out;
+ }
+- make_perms(get_nod(fs, nod)->i_mode, perms);
+- printf("%s, size: %d byte%s (%d block%s)\n", perms, plural(get_nod(fs, nod)->i_size), plural(get_nod(fs, nod)->i_blocks / INOBLK));
+- switch(get_nod(fs, nod)->i_mode & FM_IFMT)
++ GRP_PUT_INODE_BITMAP(bi);
++ make_perms(node->i_mode, perms);
++ printf("%s, size: %d byte%s (%d block%s)\n", perms,
++ plural(node->i_size), plural(node->i_blocks / INOBLK));
++ switch(node->i_mode & FM_IFMT)
+ {
+ case FM_IFSOCK:
+ list_blocks(fs, nod);
+@@ -2340,6 +2504,8 @@ print_inode(filesystem *fs, uint32 nod)
+ list_blocks(fs, nod);
+ }
+ printf("Done with inode %d\n",nod);
++out:
++ put_nod(ni);
+ }
+
+ // describes various fields in a filesystem
+@@ -2347,6 +2513,7 @@ static void
+ print_fs(filesystem *fs)
+ {
+ uint32 i;
++ blk_info *bi;
+ uint8 *ibm;
+
+ printf("%d blocks (%d free, %d reserved), first data block: %d\n",
+@@ -2369,13 +2536,16 @@ print_fs(filesystem *fs)
+ fs->gd[i].bg_block_bitmap, fs->gd[i].bg_inode_bitmap,
+ fs->gd[i].bg_inode_table);
+ printf("block bitmap allocation:\n");
+- print_bm(GRP_GET_GROUP_BBM(fs, i),fs->sb.s_blocks_per_group);
++ print_bm(GRP_GET_GROUP_BBM(fs, i, &bi),
++ fs->sb.s_blocks_per_group);
++ GRP_PUT_GROUP_BBM(bi);
+ printf("inode bitmap allocation:\n");
+- ibm = GRP_GET_GROUP_IBM(fs, i);
++ 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++)
+ if (allocated(ibm, i))
+ print_inode(fs, i);
++ GRP_PUT_GROUP_IBM(bi);
+ }
+ }
+
+@@ -2646,9 +2816,17 @@ main(int argc, char **argv)
+
+ if(emptyval) {
+ uint32 b;
+- for(b = 1; b < fs->sb.s_blocks_count; b++)
+- if(!allocated(GRP_GET_BLOCK_BITMAP(fs,b),GRP_BBM_OFFSET(fs,b)))
+- memset(get_blk(fs, b), emptyval, BLOCKSIZE);
++ 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))) {
++ blk_info *bi2;
++ memset(get_blk(fs, b, &bi2), emptyval,
++ BLOCKSIZE);
++ put_blk(bi2);
++ }
++ GRP_PUT_BLOCK_BITMAP(bi);
++ }
+ }
+ if(verbose)
+ print_fs(fs);
+@@ -2658,13 +2836,15 @@ main(int argc, char **argv)
+ char fname[MAX_FILENAME];
+ char *p;
+ FILE *fh;
++ nod_info *ni;
+ if(!(nod = find_path(fs, EXT2_ROOT_INO, gopt[i])))
+ error_msg_and_die("path %s not found in filesystem", gopt[i]);
+ while((p = strchr(gopt[i], '/')))
+ *p = '_';
+ SNPRINTF(fname, MAX_FILENAME-1, "%s.blk", gopt[i]);
+ fh = xfopen(fname, "wb");
+- fprintf(fh, "%d:", get_nod(fs, nod)->i_size);
++ fprintf(fh, "%d:", get_nod(fs, nod, &ni)->i_size);
++ put_nod(ni);
+ flist_blocks(fs, nod, fh);
+ fclose(fh);
+ }
+--
+1.7.4.1
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0003-Add-get_blkmap-and-put_blkmap.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0003-Add-get_blkmap-and-put_blkmap.patch
new file mode 100644
index 0000000000..1442dfaaed
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0003-Add-get_blkmap-and-put_blkmap.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0004-Add-a-dirwalker-for-walking-through-directory-entrie.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0004-Add-a-dirwalker-for-walking-through-directory-entrie.patch
new file mode 100644
index 0000000000..014a69409f
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0004-Add-a-dirwalker-for-walking-through-directory-entrie.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0005-Make-filesystem-struct-not-an-overloay.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0005-Make-filesystem-struct-not-an-overloay.patch
new file mode 100644
index 0000000000..ccc33feaac
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0005-Make-filesystem-struct-not-an-overloay.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0006-Improve-the-efficiency-of-extend_blk.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0006-Improve-the-efficiency-of-extend_blk.patch
new file mode 100644
index 0000000000..494e3f9e8d
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0006-Improve-the-efficiency-of-extend_blk.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0007-Move-hdlinks-into-the-filesystem-structure.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0007-Move-hdlinks-into-the-filesystem-structure.patch
new file mode 100644
index 0000000000..52215c8e7a
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0007-Move-hdlinks-into-the-filesystem-structure.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0008-Separate-out-the-creation-of-the-filesystem-structur.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0008-Separate-out-the-creation-of-the-filesystem-structur.patch
new file mode 100644
index 0000000000..25adeb63c0
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0008-Separate-out-the-creation-of-the-filesystem-structur.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0009-Move-byte-swapping-into-the-get-put-routines.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0009-Move-byte-swapping-into-the-get-put-routines.patch
new file mode 100644
index 0000000000..028fbb6b28
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0009-Move-byte-swapping-into-the-get-put-routines.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0010-Convert-over-to-keeping-the-filesystem-on-disk.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0010-Convert-over-to-keeping-the-filesystem-on-disk.patch
new file mode 100644
index 0000000000..79e82c8c73
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0010-Convert-over-to-keeping-the-filesystem-on-disk.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0011-Copy-files-into-the-filesystem-a-piece-at-a-time.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0011-Copy-files-into-the-filesystem-a-piece-at-a-time.patch
new file mode 100644
index 0000000000..52dec56d5f
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0011-Copy-files-into-the-filesystem-a-piece-at-a-time.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0012-Add-rev-1-support-large-file-support-and-rework-hole.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0012-Add-rev-1-support-large-file-support-and-rework-hole.patch
new file mode 100644
index 0000000000..2de6608c0c
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0012-Add-rev-1-support-large-file-support-and-rework-hole.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0013-Add-volume-id-support.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0013-Add-volume-id-support.patch
new file mode 100644
index 0000000000..1777dd6b0f
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0013-Add-volume-id-support.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0014-Remove-unneeded-setting-of-s_reserved.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0014-Remove-unneeded-setting-of-s_reserved.patch
new file mode 100644
index 0000000000..de196b0716
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0014-Remove-unneeded-setting-of-s_reserved.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0015-Rework-creating-the-lost-found-directory.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0015-Rework-creating-the-lost-found-directory.patch
new file mode 100644
index 0000000000..fbde366854
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0015-Rework-creating-the-lost-found-directory.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0016-Fix-the-documentation-for-the-new-L-option.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0016-Fix-the-documentation-for-the-new-L-option.patch
new file mode 100644
index 0000000000..8c24db107e
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0016-Fix-the-documentation-for-the-new-L-option.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0017-Fix-file-same-comparison.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0017-Fix-file-same-comparison.patch
new file mode 100644
index 0000000000..40a7807b0d
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0017-Fix-file-same-comparison.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0018-Handle-files-changing-while-we-are-working.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0018-Handle-files-changing-while-we-are-working.patch
new file mode 100644
index 0000000000..3ea877c4d4
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0018-Handle-files-changing-while-we-are-working.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0019-Make-sure-superblock-is-clear-on-allocation.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0019-Make-sure-superblock-is-clear-on-allocation.patch
new file mode 100644
index 0000000000..a75a8128cc
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/0019-Make-sure-superblock-is-clear-on-allocation.patch
@@ -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
+
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/fix-nbblocks-cast.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/fix-nbblocks-cast.patch
index 3fd15e058b..05b095edf0 100644
--- a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/fix-nbblocks-cast.patch
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/fix-nbblocks-cast.patch
@@ -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)
diff --git a/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/update_to_1.95.patch b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/update_to_1.95.patch
new file mode 100644
index 0000000000..ea2b16ccf9
--- /dev/null
+++ b/meta/recipes-devtools/genext2fs/genext2fs-1.4.1/update_to_1.95.patch
@@ -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
diff --git a/meta/recipes-devtools/genext2fs/genext2fs_1.4.1.bb b/meta/recipes-devtools/genext2fs/genext2fs_1.4.1.bb
index 012ec6c4fb..702245ff75 100644
--- a/meta/recipes-devtools/genext2fs/genext2fs_1.4.1.bb
+++ b/meta/recipes-devtools/genext2fs/genext2fs_1.4.1.bb
@@ -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"