Le mer. 16 août 2023, 12:50, Stuart Henderson <s...@spacehopper.org> a
écrit :

> On 2023/08/15 18:16, Vladimir 'phcoder' Serbinenko wrote:
> > Did I do something wrong and should send it to another list, CC someone
> or
> > did I do something stupid? 64-bit incompat feature is enabled on new
> ext4's
> > by default, at least on Ubuntu
>
> It's the right list. However as ext2fs support is not much used by
> developers and there's no "maintainer" for this bit of code it's going
> to be more difficult to find a reviewer.
>
>
> > Le lun. 3 juil. 2023, 02:49, Vladimir 'phcoder' Serbinenko <
> > phco...@gmail.com> a écrit :
> >
> > > Hello, all attached patch implements feature 64-bit for ext2. This was
> > > enabled implicitly on my Ubuntu and probably on many other systems.
> Since
> > > it's an incompat feature lack of its support prevented the mount
> > > altogether. With this patch I was able to load install sets from my
> Ubuntu
> > > partition.
>
> I'm not a good person to comment on the code changes, but the diff
> doesn't follow style(9), at least there are over-long lines, and while
> I didn't find anything in particular in style(9) about the alignment
> around = in blocks of setting a bunch of variables (like in e2fs_cgload),
> it's more common in the kernel to use "var = assignment" without extra
> spaces to align.
>
Thank you for pointing this out. I send an amended patch

>
>
>
commit 3af72556491644953b1660540bc05936083bb6ff
Author: phcoder <phco...@qemu-obsd.my.domain>
Date:   Sun Jul 2 13:19:05 2023 +0200

    ext2: Support feature 64bit

diff --git sys/ufs/ext2fs/ext2fs.h sys/ufs/ext2fs/ext2fs.h
index 647270d80..ac3fcd39a 100644
--- sys/ufs/ext2fs/ext2fs.h
+++ sys/ufs/ext2fs/ext2fs.h
@@ -176,6 +176,7 @@ struct m_ext2fs {
        int32_t e2fs_ngdb;      /* number of group descriptor block */
        int32_t e2fs_ipb;       /* number of inodes per block */
        int32_t e2fs_itpg;      /* number of inode table per group */
+       u_int8_t e2fs_group_desc_shift; /* binary log group desc size */
        off_t   e2fs_maxfilesize;       /* depends on LARGE/HUGE flags */
        struct  ext2_gd *e2fs_gd; /* group descriptors */
 };
@@ -277,7 +278,8 @@ static const struct ext2_feature incompat[] = {
 #define EXT4F_RO_INCOMPAT_SUPP         (EXT2F_INCOMPAT_EXTENTS | \
                                         EXT2F_INCOMPAT_FLEX_BG | \
                                         EXT2F_INCOMPAT_META_BG | \
-                                        EXT2F_INCOMPAT_RECOVER)
+                                        EXT2F_INCOMPAT_RECOVER | \
+                                        EXT2F_INCOMPAT_64BIT)
 
 /*
  * Definitions of behavior on errors
@@ -311,6 +313,14 @@ struct ext2_gd {
        u_int16_t ext2bgd_ndirs;        /* number of directories */
        u_int16_t reserved;
        u_int32_t reserved2[3];
+       u_int32_t ext2bgd_b_bitmap_hi;  /* blocks bitmap block (high bits) */
+       u_int32_t ext2bgd_i_bitmap_hi;  /* inodes bitmap block (high bits) */
+       u_int32_t ext2bgd_i_tables_hi;  /* inodes table block (high bits)  */
+       u_int16_t ext2bgd_nbfree_hi;    /* number of free blocks (high bits) */
+       u_int16_t ext2bgd_nifree_hi;    /* number of free inodes (high bits) */
+       u_int16_t ext2bgd_ndirs_hi;     /* number of directories (high bits) */
+       u_int16_t reserved_hi;
+       u_int32_t reserved2_hi[3];
 };
 
 /*
@@ -339,18 +349,17 @@ cg_has_sb(int i)
  * Ext2 metadata is stored in little-endian byte order.
  * JBD2 journal used in ext3 and ext4 is big-endian!
  */
+void e2fs_cgload(const char *ondisk, struct ext2_gd *inmemory,
+                int shift_cg_entry_size, int cg_size);
+void e2fs_cgsave(const struct ext2_gd *inmemory, char *ondisk,
+                int shift_cg_entry_size, int cg_size);
 #if BYTE_ORDER == LITTLE_ENDIAN
 #define e2fs_sbload(old, new) memcpy((new), (old), SBSIZE);
-#define e2fs_cgload(old, new, size) memcpy((new), (old), (size));
 #define e2fs_sbsave(old, new) memcpy((new), (old), SBSIZE);
-#define e2fs_cgsave(old, new, size) memcpy((new), (old), (size));
 #else
 void e2fs_sb_bswap(struct ext2fs *, struct ext2fs *);
-void e2fs_cg_bswap(struct ext2_gd *, struct ext2_gd *, int);
 #define e2fs_sbload(old, new) e2fs_sb_bswap((old), (new))
-#define e2fs_cgload(old, new, size) e2fs_cg_bswap((old), (new), (size));
 #define e2fs_sbsave(old, new) e2fs_sb_bswap((old), (new))
-#define e2fs_cgsave(old, new, size) e2fs_cg_bswap((old), (new), (size));
 #endif
 
 /*
@@ -358,6 +367,8 @@ void e2fs_cg_bswap(struct ext2_gd *, struct ext2_gd *, int);
  * This maps file system blocks to device size blocks.
  */
 #define fsbtodb(fs, b) ((b) << (fs)->e2fs_fsbtodb)
+#define fsbtodb64(fs, b, b_hi) (((b) | (((u_int64_t)(b_hi)) << 32)) \
+                                << (fs)->e2fs_fsbtodb)
 #define dbtofsb(fs, b) ((b) >> (fs)->e2fs_fsbtodb)
 
 /*
@@ -369,7 +380,8 @@ void e2fs_cg_bswap(struct ext2_gd *, struct ext2_gd *, int);
 #define        ino_to_cg(fs, x)        (((x) - 1) / (fs)->e2fs.e2fs_ipg)
 #define        ino_to_fsba(fs, x)                                              
\
        ((fs)->e2fs_gd[ino_to_cg(fs, x)].ext2bgd_i_tables + \
-       (((x)-1) % (fs)->e2fs.e2fs_ipg)/(fs)->e2fs_ipb)
+        (((u_int64_t)((fs)->e2fs_gd[ino_to_cg(fs, x)].ext2bgd_i_tables_hi)) \
+         << 32) + (((x)-1) % (fs)->e2fs.e2fs_ipg)/(fs)->e2fs_ipb)
 #define        ino_to_fsbo(fs, x)      (((x)-1) % (fs)->e2fs_ipb)
 
 /*
diff --git sys/ufs/ext2fs/ext2fs_alloc.c sys/ufs/ext2fs/ext2fs_alloc.c
index ca71d8adf..930c2927d 100644
--- sys/ufs/ext2fs/ext2fs_alloc.c
+++ sys/ufs/ext2fs/ext2fs_alloc.c
@@ -195,13 +195,19 @@ ext2fs_dirpref(struct m_ext2fs *fs)
        avgifree = fs->e2fs.e2fs_ficount / fs->e2fs_ncg;
        maxspace = 0;
        mincg = -1;
-       for (cg = 0; cg < fs->e2fs_ncg; cg++)
-               if ( fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree) {
-                       if (mincg == -1 || fs->e2fs_gd[cg].ext2bgd_nbfree > 
maxspace) {
+       for (cg = 0; cg < fs->e2fs_ncg; cg++) {
+               u_int32_t nifree = (fs->e2fs_gd[cg].ext2bgd_nifree_hi << 16)
+                       | fs->e2fs_gd[cg].ext2bgd_nifree;
+               if (nifree >= avgifree) {
+                       u_int32_t nbfree
+                               = (fs->e2fs_gd[cg].ext2bgd_nbfree_hi << 16)
+                               | fs->e2fs_gd[cg].ext2bgd_nbfree;
+                       if (mincg == -1 || nbfree > maxspace) {
                                mincg = cg;
-                               maxspace = fs->e2fs_gd[cg].ext2bgd_nbfree;
+                               maxspace = nbfree;
                        }
                }
+       }
        return mincg;
 }
 
@@ -318,11 +324,14 @@ ext2fs_alloccg(struct inode *ip, int cg, u_int32_t bpref, 
int size)
        int error, start, end, loc;
 
        fs = ip->i_e2fs;
-       if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0)
+       if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0
+           && fs->e2fs_gd[cg].ext2bgd_nbfree_hi == 0)
                return (0);
-       error = bread(ip->i_devvp, fsbtodb(fs,
-           fs->e2fs_gd[cg].ext2bgd_b_bitmap), (int)fs->e2fs_bsize, &bp);
-       if (error || fs->e2fs_gd[cg].ext2bgd_nbfree == 0) {
+       error = bread(ip->i_devvp, fsbtodb64(fs,
+           fs->e2fs_gd[cg].ext2bgd_b_bitmap,
+           fs->e2fs_gd[cg].ext2bgd_b_bitmap_hi), (int)fs->e2fs_bsize, &bp);
+       if (error || (fs->e2fs_gd[cg].ext2bgd_nbfree == 0
+                     && fs->e2fs_gd[cg].ext2bgd_nbfree_hi == 0)) {
                brelse(bp);
                return (0);
        }
@@ -374,7 +383,11 @@ ext2fs_alloccg(struct inode *ip, int cg, u_int32_t bpref, 
int size)
 #endif
        setbit(bbp, bno);
        fs->e2fs.e2fs_fbcount--;
-       fs->e2fs_gd[cg].ext2bgd_nbfree--;
+       u_int32_t nbfree = fs->e2fs_gd[cg].ext2bgd_nbfree
+               | (fs->e2fs_gd[cg].ext2bgd_nbfree_hi << 16);
+       nbfree--;
+       fs->e2fs_gd[cg].ext2bgd_nbfree = nbfree;
+       fs->e2fs_gd[cg].ext2bgd_nbfree_hi = nbfree >> 16;
        fs->e2fs_fmod = 1;
        bdwrite(bp);
        return (cg * fs->e2fs.e2fs_fpg + fs->e2fs.e2fs_first_dblock + bno);
@@ -399,10 +412,12 @@ ext2fs_nodealloccg(struct inode *ip, int cg, ufsino_t 
ipref, int mode)
 
        ipref--; /* to avoid a lot of (ipref -1) */
        fs = ip->i_e2fs;
-       if (fs->e2fs_gd[cg].ext2bgd_nifree == 0)
+       if (fs->e2fs_gd[cg].ext2bgd_nifree == 0
+           && fs->e2fs_gd[cg].ext2bgd_nifree_hi == 0)
                return (0);
-       error = bread(ip->i_devvp, fsbtodb(fs,
-           fs->e2fs_gd[cg].ext2bgd_i_bitmap), (int)fs->e2fs_bsize, &bp);
+       error = bread(ip->i_devvp, fsbtodb64(fs,
+           fs->e2fs_gd[cg].ext2bgd_i_bitmap,
+           fs->e2fs_gd[cg].ext2bgd_i_bitmap_hi), (int)fs->e2fs_bsize, &bp);
        if (error) {
                brelse(bp);
                return (0);
@@ -441,10 +456,19 @@ ext2fs_nodealloccg(struct inode *ip, int cg, ufsino_t 
ipref, int mode)
  gotit:
        setbit(ibp, ipref);
        fs->e2fs.e2fs_ficount--;
-       fs->e2fs_gd[cg].ext2bgd_nifree--;
+
+       u_int32_t nifree = fs->e2fs_gd[cg].ext2bgd_nifree
+               | (fs->e2fs_gd[cg].ext2bgd_nifree_hi << 16);
+       nifree--;
+       fs->e2fs_gd[cg].ext2bgd_nifree = nifree;
+       fs->e2fs_gd[cg].ext2bgd_nifree_hi = nifree >> 16;
        fs->e2fs_fmod = 1;
        if ((mode & IFMT) == IFDIR) {
-               fs->e2fs_gd[cg].ext2bgd_ndirs++;
+               u_int32_t ndirs = fs->e2fs_gd[cg].ext2bgd_ndirs
+                       | (fs->e2fs_gd[cg].ext2bgd_ndirs_hi << 16);
+               ndirs++;
+               fs->e2fs_gd[cg].ext2bgd_ndirs = ndirs;
+               fs->e2fs_gd[cg].ext2bgd_ndirs_hi = ndirs >> 16;
        }
        bdwrite(bp);
        return (cg * fs->e2fs.e2fs_ipg + ipref + 1);
@@ -472,7 +496,8 @@ ext2fs_blkfree(struct inode *ip, u_int32_t bno)
                return;
        }
        error = bread(ip->i_devvp,
-           fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
+           fsbtodb64(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap,
+                     fs->e2fs_gd[cg].ext2bgd_b_bitmap_hi),
            (int)fs->e2fs_bsize, &bp);
        if (error) {
                brelse(bp);
@@ -486,7 +511,11 @@ ext2fs_blkfree(struct inode *ip, u_int32_t bno)
 
        clrbit(bbp, bno);
        fs->e2fs.e2fs_fbcount++;
-       fs->e2fs_gd[cg].ext2bgd_nbfree++;
+       u_int32_t nbfree = fs->e2fs_gd[cg].ext2bgd_nbfree
+               | (fs->e2fs_gd[cg].ext2bgd_nbfree_hi << 16);
+       nbfree++;
+       fs->e2fs_gd[cg].ext2bgd_nbfree = nbfree;
+       fs->e2fs_gd[cg].ext2bgd_nbfree_hi = nbfree >> 16;
 
        fs->e2fs_fmod = 1;
        bdwrite(bp);
@@ -511,7 +540,7 @@ ext2fs_inode_free(struct inode *pip, ufsino_t ino, mode_t 
mode)
                    pip->i_dev, ino, fs->e2fs_fsmnt);
        cg = ino_to_cg(fs, ino);
        error = bread(pip->i_devvp,
-           fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap),
+           fsbtodb64(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap, 
fs->e2fs_gd[cg].ext2bgd_i_bitmap_hi),
            (int)fs->e2fs_bsize, &bp);
        if (error) {
                brelse(bp);
@@ -527,9 +556,16 @@ ext2fs_inode_free(struct inode *pip, ufsino_t ino, mode_t 
mode)
        }
        clrbit(ibp, ino);
        fs->e2fs.e2fs_ficount++;
-       fs->e2fs_gd[cg].ext2bgd_nifree++;
+
+       u_int32_t nifree = fs->e2fs_gd[cg].ext2bgd_nifree | 
(fs->e2fs_gd[cg].ext2bgd_nifree_hi << 16);
+       nifree++;
+       fs->e2fs_gd[cg].ext2bgd_nifree = nifree;
+       fs->e2fs_gd[cg].ext2bgd_nifree_hi = nifree >> 16;
        if ((mode & IFMT) == IFDIR) {
-               fs->e2fs_gd[cg].ext2bgd_ndirs--;
+               u_int32_t ndirs = fs->e2fs_gd[cg].ext2bgd_ndirs | 
(fs->e2fs_gd[cg].ext2bgd_ndirs_hi << 16);
+               ndirs--;
+               fs->e2fs_gd[cg].ext2bgd_ndirs = ndirs;
+               fs->e2fs_gd[cg].ext2bgd_ndirs_hi = ndirs >> 16;
        }
        fs->e2fs_fmod = 1;
        bdwrite(bp);
diff --git sys/ufs/ext2fs/ext2fs_bswap.c sys/ufs/ext2fs/ext2fs_bswap.c
index c4f36ba3d..4aa168de5 100644
--- sys/ufs/ext2fs/ext2fs_bswap.c
+++ sys/ufs/ext2fs/ext2fs_bswap.c
@@ -95,20 +95,6 @@ e2fs_sb_bswap(struct ext2fs *old, struct ext2fs *new)
        new->e2fs_mkfs_time     =       swap32(old->e2fs_mkfs_time);
 }
 
-void
-e2fs_cg_bswap(struct ext2_gd *old, struct ext2_gd *new, int size)
-{
-       int i;
-       for (i=0; i < (size / sizeof(struct  ext2_gd)); i++) {
-               new[i].ext2bgd_b_bitmap = swap32(old[i].ext2bgd_b_bitmap);
-               new[i].ext2bgd_i_bitmap = swap32(old[i].ext2bgd_i_bitmap);
-               new[i].ext2bgd_i_tables = swap32(old[i].ext2bgd_i_tables);
-               new[i].ext2bgd_nbfree   = swap16(old[i].ext2bgd_nbfree);
-               new[i].ext2bgd_nifree   = swap16(old[i].ext2bgd_nifree);
-               new[i].ext2bgd_ndirs    = swap16(old[i].ext2bgd_ndirs);
-       }
-}
-
 void
 e2fs_i_bswap(struct m_ext2fs *fs, struct ext2fs_dinode *old,
     struct ext2fs_dinode *new)
diff --git sys/ufs/ext2fs/ext2fs_vfsops.c sys/ufs/ext2fs/ext2fs_vfsops.c
index 3baea804c..1ce1763d9 100644
--- sys/ufs/ext2fs/ext2fs_vfsops.c
+++ sys/ufs/ext2fs/ext2fs_vfsops.c
@@ -373,16 +373,28 @@ e2fs_sbfill(struct vnode *devvp, struct m_ext2fs *fs)
        fs->e2fs_ipb = fs->e2fs_bsize / EXT2_DINODE_SIZE(fs);
        fs->e2fs_itpg = fs->e2fs.e2fs_ipg / fs->e2fs_ipb;
 
+       if (!(fs->e2fs.e2fs_features_incompat & EXT2F_INCOMPAT_64BIT) ||
+           (fs->e2fs.e2fs_rev == E2FS_REV0))
+               fs->e2fs_group_desc_shift = 5;
+       else {
+               for (fs->e2fs_group_desc_shift = 0;
+                    (1 << fs->e2fs_group_desc_shift)
+                      < fs->e2fs.e2fs_gdesc_size;
+                    fs->e2fs_group_desc_shift++);
+       }
+
        /* Re-read group descriptors from the disk. */
        fs->e2fs_ngdb = howmany(fs->e2fs_ncg,
-           fs->e2fs_bsize / sizeof(struct ext2_gd));
-       fs->e2fs_gd = mallocarray(fs->e2fs_ngdb, fs->e2fs_bsize,
+           fs->e2fs_bsize >> fs->e2fs_group_desc_shift);
+       fs->e2fs_gd = mallocarray(fs->e2fs_ngdb,
+                                 (fs->e2fs_bsize >> fs->e2fs_group_desc_shift)
+                                 * sizeof(struct ext2_gd),
            M_UFSMNT, M_WAITOK);
 
        for (i = 0; i < fs->e2fs_ngdb; ++i) {
                daddr_t dblk = ((fs->e2fs_bsize > 1024) ? 0 : 1) + i + 1;
-               size_t gdesc = i * fs->e2fs_bsize / sizeof(struct ext2_gd);
-               struct ext2_gd *gd;
+               size_t gdesc = i * (fs->e2fs_bsize
+                                   >> fs->e2fs_group_desc_shift);
 
                error = bread(devvp, fsbtodb(fs, dblk), fs->e2fs_bsize, &bp);
                if (error) {
@@ -394,8 +406,8 @@ e2fs_sbfill(struct vnode *devvp, struct m_ext2fs *fs)
                        return (error);
                }
 
-               gd = (struct ext2_gd *) bp->b_data;
-               e2fs_cgload(gd, fs->e2fs_gd + gdesc, fs->e2fs_bsize);
+               e2fs_cgload(bp->b_data, fs->e2fs_gd + gdesc, fs->e2fs_bsize,
+                           fs->e2fs_group_desc_shift);
                brelse(bp);
                bp = NULL;
        }
@@ -1059,7 +1071,9 @@ ext2fs_cgupdate(struct ufsmount *mp, int waitfor)
        for (i = 0; i < fs->e2fs_ngdb; i++) {
                bp = getblk(mp->um_devvp, fsbtodb(fs, 
((fs->e2fs_bsize>1024)?0:1)+i+1),
                    fs->e2fs_bsize, 0, INFSLP);
-               e2fs_cgsave(&fs->e2fs_gd[i* fs->e2fs_bsize / sizeof(struct 
ext2_gd)], (struct ext2_gd*)bp->b_data, fs->e2fs_bsize);
+               e2fs_cgsave(&fs->e2fs_gd[i* fs->e2fs_bsize / sizeof(struct 
ext2_gd)],
+                           bp->b_data, fs->e2fs_bsize,
+                           fs->e2fs_group_desc_shift);
                if (waitfor == MNT_WAIT)
                        error = bwrite(bp);
                else
@@ -1145,3 +1159,136 @@ e2fs_sbcheck(struct ext2fs *fs, int ronly)
 
        return (0);
 }
+
+void e2fs_cgload(const char *ondisk, struct ext2_gd *inmemory,
+                int cg_size, int shift_cg_entry_size)
+{
+       const char *iptr = ondisk;
+       struct ext2_gd *optr = inmemory;
+#if BYTE_ORDER == LITTLE_ENDIAN
+       if (shift_cg_entry_size > 6) {
+               int i;
+               for (i=0; i < (cg_size >> shift_cg_entry_size); i++, optr++,
+                            iptr += (1 << shift_cg_entry_size)) {
+                       memcpy(optr, iptr, sizeof(struct ext2_gd));
+               }
+       } else if (shift_cg_entry_size == 6) {
+               memcpy(inmemory, ondisk, cg_size);
+       } else {
+               int i;
+               for (i=0; i < (cg_size >> shift_cg_entry_size); i++, optr++,
+                            iptr += (1 << shift_cg_entry_size)) {
+                       memcpy(optr, iptr, 32);
+                       memset(optr + 32, 0, sizeof(struct ext2_gd) - 32);
+               }
+       }
+#else
+       if (shift_cg_entry_size >= 6) {
+               int i;
+               for (i=0; i < (cg_size >> shift_cg_entry_size); i++, optr++,
+                            iptr += (1 << shift_cg_entry_size)) {
+                       const struct ext2_gd *is
+                         = (const struct ext2_gd *) iptr;
+                       optr->ext2bgd_b_bitmap = swap32(is->ext2bgd_b_bitmap);
+                       optr->ext2bgd_i_bitmap = swap32(is->ext2bgd_i_bitmap);
+                       optr->ext2bgd_i_tables = swap32(is->ext2bgd_i_tables);
+                       optr->ext2bgd_nbfree = swap16(is->ext2bgd_nbfree);
+                       optr->ext2bgd_nifree = swap16(is->ext2bgd_nifree);
+                       optr->ext2bgd_ndirs = swap16(is->ext2bgd_ndirs);
+
+                       optr->ext2bgd_b_bitmap_hi
+                         = swap32(is->ext2bgd_b_bitmap_hi);
+                       optr->ext2bgd_i_bitmap_hi
+                         = swap32(is->ext2bgd_i_bitmap_hi);
+                       optr->ext2bgd_i_tables_hi
+                         = swap32(is->ext2bgd_i_tables_hi);
+                       optr->ext2bgd_nbfree_hi = swap16(is->ext2bgd_nbfree_hi);
+                       optr->ext2bgd_nifree_hi = swap16(is->ext2bgd_nifree_hi);
+                       optr->ext2bgd_ndirs_hi = swap16(is->ext2bgd_ndirs_hi);
+               }
+       } else {
+               int i;
+               for (i=0; i < (num_cg >> shift_cg_entry_size); i++, optr++,
+                            iptr += (1 << shift_cg_entry_size)) {
+                       const struct ext2_gd *is
+                         = (const struct ext2_gd *) iptr;
+                       optr->ext2bgd_b_bitmap = swap32(is->ext2bgd_b_bitmap);
+                       optr->ext2bgd_i_bitmap = swap32(is->ext2bgd_i_bitmap);
+                       optr->ext2bgd_i_tables = swap32(is->ext2bgd_i_tables);
+                       optr->ext2bgd_nbfree = swap16(is->ext2bgd_nbfree);
+                       optr->ext2bgd_nifree = swap16(is->ext2bgd_nifree);
+                       optr->ext2bgd_ndirs = swap16(is->ext2bgd_ndirs);
+
+                       optr->ext2bgd_b_bitmap_hi       = 0;
+                       optr->ext2bgd_i_bitmap_hi       = 0;
+                       optr->ext2bgd_i_tables_hi       = 0;
+                       optr->ext2bgd_nbfree_hi = 0;
+                       optr->ext2bgd_nifree_hi = 0;
+                       optr->ext2bgd_ndirs_hi  = 0;
+               }
+       }
+#endif
+}
+
+void e2fs_cgsave(const struct ext2_gd *inmemory, char *ondisk,
+                int cg_size, int shift_cg_entry_size)
+{
+       const struct ext2_gd *iptr = inmemory;
+       char *optr = ondisk;
+#if BYTE_ORDER == LITTLE_ENDIAN
+       if (shift_cg_entry_size > 6) {
+               int i;
+               for (i=0; i < (cg_size >> shift_cg_entry_size); i++, iptr++,
+                            optr += (1 << shift_cg_entry_size)) {
+                       memcpy(optr, iptr, sizeof(struct ext2_gd));
+                       memset(optr + sizeof(struct ext2_gd), 0,
+                              (1 << shift_cg_entry_size)
+                              - sizeof(struct ext2_gd));
+               }
+       } else if (shift_cg_entry_size == 6) {
+               memcpy(ondisk, inmemory, cg_size);
+       } else {
+               int i;
+               for (i=0; i < (cg_size >> shift_cg_entry_size); i++, iptr++,
+                            optr += (1 << shift_cg_entry_size)) {
+                       memcpy(optr, iptr, 32);
+               }
+       }
+#else
+       if (shift_cg_entry_size >= 6) {
+               int i;
+               for (i=0; i < (cg_size >> shift_cg_entry_size); i++, iptr++,
+                            optr += (1 << shift_cg_entry_size)) {
+                       struct ext2_gd *os = (struct ext2_gd *) optr;
+                       os->ext2bgd_b_bitmap = swap32(iptr->ext2bgd_b_bitmap);
+                       os->ext2bgd_i_bitmap = swap32(iptr->ext2bgd_i_bitmap);
+                       os->ext2bgd_i_tables = swap32(iptr->ext2bgd_i_tables);
+                       os->ext2bgd_nbfree = swap16(iptr->ext2bgd_nbfree);
+                       os->ext2bgd_nifree = swap16(iptr->ext2bgd_nifree);
+                       os->ext2bgd_ndirs = swap16(iptr->ext2bgd_ndirs);
+
+                       os->ext2bgd_b_bitmap_hi
+                         = swap32(iptr->ext2bgd_b_bitmap_hi);
+                       os->ext2bgd_i_bitmap_hi
+                         = swap32(iptr->ext2bgd_i_bitmap_hi);
+                       os->ext2bgd_i_tables_hi
+                         = swap32(iptr->ext2bgd_i_tables_hi);
+                       os->ext2bgd_nbfree_hi = swap16(iptr->ext2bgd_nbfree_hi);
+                       os->ext2bgd_nifree_hi = swap16(iptr->ext2bgd_nifree_hi);
+                       os->ext2bgd_ndirs_hi = swap16(iptr->ext2bgd_ndirs_hi);
+               }
+       } else {
+               int i;
+               for (i=0; i < (num_cg >> shift_cg_entry_size); i++, iptr++,
+                            optr = (const struct ext2_gd *)
+                      ((const u_int_8 *)optr + (1 << shift_cg_entry_size))) {
+                       os->ext2bgd_b_bitmap = swap32(iptr->ext2bgd_b_bitmap);
+                       os->ext2bgd_i_bitmap = swap32(iptr->ext2bgd_i_bitmap);
+                       os->ext2bgd_i_tables = swap32(iptr->ext2bgd_i_tables);
+                       os->ext2bgd_nbfree = swap16(iptr->ext2bgd_nbfree);
+                       os->ext2bgd_nifree = swap16(iptr->ext2bgd_nifree);
+                       os->ext2bgd_ndirs = swap16(iptr->ext2bgd_ndirs);
+               }
+       }
+#endif
+}

Reply via email to