Author: fsu
Date: Fri Jan  5 10:04:01 2018
New Revision: 327584
URL: https://svnweb.freebsd.org/changeset/base/327584

Log:
  Add 64bit feature support.
  
  Reviewed by:    kevlo, pfg (mentor)
  Approved by:    pfg (mentor)
  MFC after:      6 months
  
  Differential Revision:    https://reviews.freebsd.org/D11530

Modified:
  head/sys/fs/ext2fs/ext2_alloc.c
  head/sys/fs/ext2fs/ext2_balloc.c
  head/sys/fs/ext2fs/ext2_csum.c
  head/sys/fs/ext2fs/ext2_extents.c
  head/sys/fs/ext2fs/ext2_extents.h
  head/sys/fs/ext2fs/ext2_extern.h
  head/sys/fs/ext2fs/ext2_hash.c
  head/sys/fs/ext2fs/ext2_subr.c
  head/sys/fs/ext2fs/ext2_vfsops.c
  head/sys/fs/ext2fs/ext2_vnops.c
  head/sys/fs/ext2fs/ext2fs.h
  head/sys/fs/ext2fs/fs.h

Modified: head/sys/fs/ext2fs/ext2_alloc.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_alloc.c     Fri Jan  5 09:31:41 2018        
(r327583)
+++ head/sys/fs/ext2fs/ext2_alloc.c     Fri Jan  5 10:04:01 2018        
(r327584)
@@ -103,12 +103,12 @@ ext2_alloc(struct inode *ip, daddr_t lbn, e4fs_daddr_t
        if (cred == NOCRED)
                panic("ext2_alloc: missing credential");
 #endif         /* INVARIANTS */
-       if (size == fs->e2fs_bsize && fs->e2fs->e2fs_fbcount == 0)
+       if (size == fs->e2fs_bsize && fs->e2fs_fbcount == 0)
                goto nospace;
        if (cred->cr_uid != 0 &&
-           fs->e2fs->e2fs_fbcount < fs->e2fs->e2fs_rbcount)
+           fs->e2fs_fbcount < fs->e2fs_rbcount)
                goto nospace;
-       if (bpref >= fs->e2fs->e2fs_bcount)
+       if (bpref >= fs->e2fs_bcount)
                bpref = 0;
        if (bpref == 0)
                cg = ino_to_cg(fs, ip->i_number);
@@ -455,6 +455,96 @@ noinodes:
 }
 
 /*
+ * 64-bit compatible getters and setters for struct ext2_gd from ext2fs.h
+ */
+static uint64_t
+e2fs_gd_get_b_bitmap(struct ext2_gd *gd)
+{
+
+       return (((uint64_t)(gd->ext4bgd_b_bitmap_hi) << 32) |
+           gd->ext2bgd_b_bitmap);
+}
+
+static uint64_t
+e2fs_gd_get_i_bitmap(struct ext2_gd *gd)
+{
+
+       return (((uint64_t)(gd->ext4bgd_i_bitmap_hi) << 32) |
+           gd->ext2bgd_i_bitmap);
+}
+
+uint64_t
+e2fs_gd_get_i_tables(struct ext2_gd *gd)
+{
+
+       return (((uint64_t)(gd->ext4bgd_i_tables_hi) << 32) |
+           gd->ext2bgd_i_tables);
+}
+
+static uint32_t
+e2fs_gd_get_nbfree(struct ext2_gd *gd)
+{
+
+       return (((uint32_t)(gd->ext4bgd_nbfree_hi) << 16) |
+           gd->ext2bgd_nbfree);
+}
+
+static void
+e2fs_gd_set_nbfree(struct ext2_gd *gd, uint32_t val)
+{
+
+       gd->ext2bgd_nbfree = val & 0xffff;
+       gd->ext4bgd_nbfree_hi = val >> 16;
+}
+
+static uint32_t
+e2fs_gd_get_nifree(struct ext2_gd *gd)
+{
+
+       return (((uint32_t)(gd->ext4bgd_nifree_hi) << 16) |
+           gd->ext2bgd_nifree);
+}
+
+static void
+e2fs_gd_set_nifree(struct ext2_gd *gd, uint32_t val)
+{
+
+       gd->ext2bgd_nifree = val & 0xffff;
+       gd->ext4bgd_nifree_hi = val >> 16;
+}
+
+uint32_t
+e2fs_gd_get_ndirs(struct ext2_gd *gd)
+{
+
+       return (((uint32_t)(gd->ext4bgd_ndirs_hi) << 16) |
+           gd->ext2bgd_ndirs);
+}
+
+static void
+e2fs_gd_set_ndirs(struct ext2_gd *gd, uint32_t val)
+{
+
+       gd->ext2bgd_ndirs = val & 0xffff;
+       gd->ext4bgd_ndirs_hi = val >> 16;
+}
+
+static uint32_t
+e2fs_gd_get_i_unused(struct ext2_gd *gd)
+{
+       return (((uint32_t)(gd->ext4bgd_i_unused_hi) << 16) |
+           gd->ext4bgd_i_unused);
+}
+
+static void
+e2fs_gd_set_i_unused(struct ext2_gd *gd, uint32_t val)
+{
+
+       gd->ext4bgd_i_unused = val & 0xffff;
+       gd->ext4bgd_i_unused_hi = val >> 16;
+}
+
+/*
  * Find a cylinder to place a directory.
  *
  * The policy implemented by this algorithm is to allocate a
@@ -473,8 +563,9 @@ ext2_dirpref(struct inode *pip)
 {
        struct m_ext2fs *fs;
        int cg, prefcg, cgsize;
-       u_int avgifree, avgbfree, avgndir, curdirsize;
-       u_int minifree, minbfree, maxndir;
+       uint64_t avgbfree, minbfree;
+       u_int avgifree, avgndir, curdirsize;
+       u_int minifree, maxndir;
        u_int mincg, minndir;
        u_int dirsize, maxcontigdirs;
 
@@ -482,7 +573,7 @@ ext2_dirpref(struct inode *pip)
        fs = pip->i_e2fs;
 
        avgifree = fs->e2fs->e2fs_ficount / fs->e2fs_gcount;
-       avgbfree = fs->e2fs->e2fs_fbcount / fs->e2fs_gcount;
+       avgbfree = fs->e2fs_fbcount / fs->e2fs_gcount;
        avgndir = fs->e2fs_total_dir / fs->e2fs_gcount;
 
        /*
@@ -494,18 +585,18 @@ ext2_dirpref(struct inode *pip)
                mincg = prefcg;
                minndir = fs->e2fs_ipg;
                for (cg = prefcg; cg < fs->e2fs_gcount; cg++)
-                       if (fs->e2fs_gd[cg].ext2bgd_ndirs < minndir &&
-                           fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree &&
-                           fs->e2fs_gd[cg].ext2bgd_nbfree >= avgbfree) {
+                       if (e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) < minndir &&
+                           e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= avgifree &&
+                           e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) >= avgbfree) {
                                mincg = cg;
-                               minndir = fs->e2fs_gd[cg].ext2bgd_ndirs;
+                               minndir = e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]);
                        }
                for (cg = 0; cg < prefcg; cg++)
-                       if (fs->e2fs_gd[cg].ext2bgd_ndirs < minndir &&
-                           fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree &&
-                           fs->e2fs_gd[cg].ext2bgd_nbfree >= avgbfree) {
+                       if (e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) < minndir &&
+                           e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= avgifree &&
+                           e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) >= avgbfree) {
                                mincg = cg;
-                               minndir = fs->e2fs_gd[cg].ext2bgd_ndirs;
+                               minndir = e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]);
                        }
                return (mincg);
        }
@@ -537,16 +628,16 @@ ext2_dirpref(struct inode *pip)
         */
        prefcg = ino_to_cg(fs, pip->i_number);
        for (cg = prefcg; cg < fs->e2fs_gcount; cg++)
-               if (fs->e2fs_gd[cg].ext2bgd_ndirs < maxndir &&
-                   fs->e2fs_gd[cg].ext2bgd_nifree >= minifree &&
-                   fs->e2fs_gd[cg].ext2bgd_nbfree >= minbfree) {
+               if (e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) < maxndir &&
+                   e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= minifree &&
+                   e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) >= minbfree) {
                        if (fs->e2fs_contigdirs[cg] < maxcontigdirs)
                                return (cg);
                }
        for (cg = 0; cg < prefcg; cg++)
-               if (fs->e2fs_gd[cg].ext2bgd_ndirs < maxndir &&
-                   fs->e2fs_gd[cg].ext2bgd_nifree >= minifree &&
-                   fs->e2fs_gd[cg].ext2bgd_nbfree >= minbfree) {
+               if (e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) < maxndir &&
+                   e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= minifree &&
+                   e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) >= minbfree) {
                        if (fs->e2fs_contigdirs[cg] < maxcontigdirs)
                                return (cg);
                }
@@ -554,10 +645,10 @@ ext2_dirpref(struct inode *pip)
         * This is a backstop when we have deficit in space.
         */
        for (cg = prefcg; cg < fs->e2fs_gcount; cg++)
-               if (fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree)
+               if (e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= avgifree)
                        return (cg);
        for (cg = 0; cg < prefcg; cg++)
-               if (fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree)
+               if (e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= avgifree)
                        break;
        return (cg);
 }
@@ -709,19 +800,6 @@ ext2_num_base_meta_blocks(struct m_ext2fs *fs, int cg)
        return (num);
 }
 
-static int
-ext2_get_cg_number(struct m_ext2fs *fs, daddr_t blk)
-{
-       int cg;
-
-       if (fs->e2fs->e2fs_bpg == fs->e2fs_bsize * 8)
-               cg = (blk - fs->e2fs->e2fs_first_dblock) / (fs->e2fs_bsize * 8);
-       else
-               cg = blk - fs->e2fs->e2fs_first_dblock;
-
-       return (cg);
-}
-
 static void
 ext2_mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
 {
@@ -740,10 +818,9 @@ static int
 ext2_cg_block_bitmap_init(struct m_ext2fs *fs, int cg, struct buf *bp)
 {
        int bit, bit_max, inodes_per_block;
-       uint32_t start, tmp;
+       uint64_t start, tmp;
 
-       if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM) ||
-           !(fs->e2fs_gd[cg].ext4bgd_flags & EXT2_BG_BLOCK_UNINIT))
+       if (!(fs->e2fs_gd[cg].ext4bgd_flags & EXT2_BG_BLOCK_UNINIT))
                return (0);
 
        memset(bp->b_data, 0, fs->e2fs_bsize);
@@ -755,25 +832,25 @@ ext2_cg_block_bitmap_init(struct m_ext2fs *fs, int cg,
        for (bit = 0; bit < bit_max; bit++)
                setbit(bp->b_data, bit);
 
-       start = cg * fs->e2fs->e2fs_bpg + fs->e2fs->e2fs_first_dblock;
+       start = (uint64_t)cg * fs->e2fs->e2fs_bpg + fs->e2fs->e2fs_first_dblock;
 
-       /* Set bits for block and inode bitmaps, and inode table */
-       tmp = fs->e2fs_gd[cg].ext2bgd_b_bitmap;
+       /* Set bits for block and inode bitmaps, and inode table. */
+       tmp = e2fs_gd_get_b_bitmap(&fs->e2fs_gd[cg]);
        if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) ||
-           tmp == ext2_get_cg_number(fs, cg))
+           cg == dtogd(fs, tmp))
                setbit(bp->b_data, tmp - start);
 
-       tmp = fs->e2fs_gd[cg].ext2bgd_i_bitmap;
+       tmp = e2fs_gd_get_i_bitmap(&fs->e2fs_gd[cg]);
        if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) ||
-           tmp == ext2_get_cg_number(fs, cg))
+           cg == dtogd(fs, tmp))
                setbit(bp->b_data, tmp - start);
 
-       tmp = fs->e2fs_gd[cg].ext2bgd_i_tables;
+       tmp = e2fs_gd_get_i_tables(&fs->e2fs_gd[cg]);
        inodes_per_block = fs->e2fs_bsize/EXT2_INODE_SIZE(fs);
-       while( tmp < fs->e2fs_gd[cg].ext2bgd_i_tables +
+       while( tmp < e2fs_gd_get_i_tables(&fs->e2fs_gd[cg]) +
            fs->e2fs->e2fs_ipg / inodes_per_block ) {
                if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) ||
-                   tmp == ext2_get_cg_number(fs, cg))
+                   cg == dtogd(fs, tmp))
                        setbit(bp->b_data, tmp - start);
                tmp++;
        }
@@ -810,11 +887,11 @@ ext2_alloccg(struct inode *ip, int cg, daddr_t bpref, 
        /* XXX ondisk32 */
        fs = ip->i_e2fs;
        ump = ip->i_ump;
-       if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0)
+       if (e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) == 0)
                return (0);
        EXT2_UNLOCK(ump);
        error = bread(ip->i_devvp, fsbtodb(fs,
-           fs->e2fs_gd[cg].ext2bgd_b_bitmap),
+           e2fs_gd_get_b_bitmap(&fs->e2fs_gd[cg])),
            (int)fs->e2fs_bsize, NOCRED, &bp);
        if (error) {
                brelse(bp);
@@ -829,7 +906,7 @@ ext2_alloccg(struct inode *ip, int cg, daddr_t bpref, 
                        return (0);
                }
        }
-       if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0) {
+       if (e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) == 0) {
                /*
                 * Another thread allocated the last block in this
                 * group while we were waiting for the buffer.
@@ -926,12 +1003,13 @@ gotit:
        setbit(bbp, bno);
        EXT2_LOCK(ump);
        ext2_clusteracct(fs, bbp, cg, bno, -1);
-       fs->e2fs->e2fs_fbcount--;
-       fs->e2fs_gd[cg].ext2bgd_nbfree--;
+       fs->e2fs_fbcount--;
+       e2fs_gd_set_nbfree(&fs->e2fs_gd[cg],
+           e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) - 1);
        fs->e2fs_fmod = 1;
        EXT2_UNLOCK(ump);
        bdwrite(bp);
-       return (cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock + bno);
+       return (((uint64_t)cg) * fs->e2fs->e2fs_fpg + 
fs->e2fs->e2fs_first_dblock + bno);
 }
 
 /*
@@ -956,7 +1034,7 @@ ext2_clusteralloc(struct inode *ip, int cg, daddr_t bp
 
        EXT2_UNLOCK(ump);
        error = bread(ip->i_devvp,
-           fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
+           fsbtodb(fs, e2fs_gd_get_b_bitmap(&fs->e2fs_gd[cg])),
            (int)fs->e2fs_bsize, NOCRED, &bp);
        if (error)
                goto fail_lock;
@@ -1026,8 +1104,9 @@ ext2_clusteralloc(struct inode *ip, int cg, daddr_t bp
        for (i = 0; i < len; i += fs->e2fs_fpb) {
                setbit(bbp, bno + i);
                ext2_clusteracct(fs, bbp, cg, bno + i, -1);
-               fs->e2fs->e2fs_fbcount--;
-               fs->e2fs_gd[cg].ext2bgd_nbfree--;
+               fs->e2fs_fbcount--;
+               e2fs_gd_set_nbfree(&fs->e2fs_gd[cg],
+                   e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) - 1);
        }
        fs->e2fs_fmod = 1;
        EXT2_UNLOCK(ump);
@@ -1058,12 +1137,12 @@ ext2_zero_inode_table(struct inode *ip, int cg)
            fs->e2fs_bsize;
 
        used_blks = howmany(fs->e2fs->e2fs_ipg -
-           fs->e2fs_gd[cg].ext4bgd_i_unused,
+           e2fs_gd_get_i_unused(&fs->e2fs_gd[cg]),
            fs->e2fs_bsize / EXT2_INODE_SIZE(fs));
 
        for (i = 0; i < all_blks - used_blks; i++) {
                bp = getblk(ip->i_devvp, fsbtodb(fs,
-                   fs->e2fs_gd[cg].ext2bgd_i_tables + used_blks + i),
+                   e2fs_gd_get_i_tables(&fs->e2fs_gd[cg]) + used_blks + i),
                    fs->e2fs_bsize, 0, 0, 0);
                if (!bp)
                        return (EIO);
@@ -1097,11 +1176,11 @@ ext2_nodealloccg(struct inode *ip, int cg, daddr_t ipr
                ipref = 0;
        fs = ip->i_e2fs;
        ump = ip->i_ump;
-       if (fs->e2fs_gd[cg].ext2bgd_nifree == 0)
+       if (e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) == 0)
                return (0);
        EXT2_UNLOCK(ump);
        error = bread(ip->i_devvp, fsbtodb(fs,
-           fs->e2fs_gd[cg].ext2bgd_i_bitmap),
+           e2fs_gd_get_i_bitmap(&fs->e2fs_gd[cg])),
            (int)fs->e2fs_bsize, NOCRED, &bp);
        if (error) {
                brelse(bp);
@@ -1120,7 +1199,7 @@ ext2_nodealloccg(struct inode *ip, int cg, daddr_t ipr
                        return (0);
                }
        }
-       if (fs->e2fs_gd[cg].ext2bgd_nifree == 0) {
+       if (e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) == 0) {
                /*
                 * Another thread allocated the last i-node in this
                 * group while we were waiting for the buffer.
@@ -1153,18 +1232,21 @@ ext2_nodealloccg(struct inode *ip, int cg, daddr_t ipr
 gotit:
        setbit(ibp, ipref);
        EXT2_LOCK(ump);
-       fs->e2fs_gd[cg].ext2bgd_nifree--;
+       e2fs_gd_set_nifree(&fs->e2fs_gd[cg],
+           e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) - 1);
        if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM))
-               fs->e2fs_gd[cg].ext4bgd_i_unused--;
+               e2fs_gd_set_i_unused(&fs->e2fs_gd[cg],
+                   e2fs_gd_get_i_unused(&fs->e2fs_gd[cg]) - 1);
        fs->e2fs->e2fs_ficount--;
        fs->e2fs_fmod = 1;
        if ((mode & IFMT) == IFDIR) {
-               fs->e2fs_gd[cg].ext2bgd_ndirs++;
+               e2fs_gd_set_ndirs(&fs->e2fs_gd[cg],
+                   e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) + 1);
                fs->e2fs_total_dir++;
        }
        EXT2_UNLOCK(ump);
        bdwrite(bp);
-       return (cg * fs->e2fs->e2fs_ipg + ipref + 1);
+       return ((uint64_t)cg * fs->e2fs_ipg + ipref + 1);
 }
 
 /*
@@ -1183,14 +1265,14 @@ ext2_blkfree(struct inode *ip, e4fs_daddr_t bno, long 
        fs = ip->i_e2fs;
        ump = ip->i_ump;
        cg = dtog(fs, bno);
-       if (bno >= fs->e2fs->e2fs_bcount) {
+       if (bno >= fs->e2fs_bcount) {
                printf("bad block %lld, ino %ju\n", (long long)bno,
                    (uintmax_t)ip->i_number);
                ext2_fserr(fs, ip->i_uid, "bad block");
                return;
        }
        error = bread(ip->i_devvp,
-           fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap),
+           fsbtodb(fs, e2fs_gd_get_b_bitmap(&fs->e2fs_gd[cg])),
            (int)fs->e2fs_bsize, NOCRED, &bp);
        if (error) {
                brelse(bp);
@@ -1206,8 +1288,9 @@ ext2_blkfree(struct inode *ip, e4fs_daddr_t bno, long 
        clrbit(bbp, bno);
        EXT2_LOCK(ump);
        ext2_clusteracct(fs, bbp, cg, bno, 1);
-       fs->e2fs->e2fs_fbcount++;
-       fs->e2fs_gd[cg].ext2bgd_nbfree++;
+       fs->e2fs_fbcount++;
+       e2fs_gd_set_nbfree(&fs->e2fs_gd[cg],
+           e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) + 1);
        fs->e2fs_fmod = 1;
        EXT2_UNLOCK(ump);
        bdwrite(bp);
@@ -1236,7 +1319,7 @@ ext2_vfree(struct vnode *pvp, ino_t ino, int mode)
 
        cg = ino_to_cg(fs, ino);
        error = bread(pip->i_devvp,
-           fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap),
+           fsbtodb(fs, e2fs_gd_get_i_bitmap(&fs->e2fs_gd[cg])),
            (int)fs->e2fs_bsize, NOCRED, &bp);
        if (error) {
                brelse(bp);
@@ -1253,11 +1336,14 @@ ext2_vfree(struct vnode *pvp, ino_t ino, int mode)
        clrbit(ibp, ino);
        EXT2_LOCK(ump);
        fs->e2fs->e2fs_ficount++;
-       fs->e2fs_gd[cg].ext2bgd_nifree++;
+       e2fs_gd_set_nifree(&fs->e2fs_gd[cg],
+           e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) + 1);
        if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM))
-               fs->e2fs_gd[cg].ext4bgd_i_unused++;
+               e2fs_gd_set_i_unused(&fs->e2fs_gd[cg],
+                   e2fs_gd_get_i_unused(&fs->e2fs_gd[cg]) + 1);
        if ((mode & IFMT) == IFDIR) {
-               fs->e2fs_gd[cg].ext2bgd_ndirs--;
+               e2fs_gd_set_ndirs(&fs->e2fs_gd[cg],
+                   e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) - 1);
                fs->e2fs_total_dir--;
        }
        fs->e2fs_fmod = 1;

Modified: head/sys/fs/ext2fs/ext2_balloc.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_balloc.c    Fri Jan  5 09:31:41 2018        
(r327583)
+++ head/sys/fs/ext2fs/ext2_balloc.c    Fri Jan  5 10:04:01 2018        
(r327584)
@@ -42,6 +42,7 @@
 #include <sys/systm.h>
 #include <sys/bio.h>
 #include <sys/buf.h>
+#include <sys/limits.h>
 #include <sys/lock.h>
 #include <sys/mount.h>
 #include <sys/vnode.h>
@@ -60,13 +61,13 @@ ext2_ext_balloc(struct inode *ip, uint32_t lbn, int si
        struct m_ext2fs *fs;
        struct buf *bp = NULL;
        struct vnode *vp = ITOV(ip);
-       uint32_t nb;
+       daddr_t newblk;
        int osize, nsize, blks, error, allocated;
 
        fs = ip->i_e2fs;
        blks = howmany(size, fs->e2fs_bsize);
 
-       error = ext4_ext_get_blocks(ip, lbn, blks, cred, NULL, &allocated, &nb);
+       error = ext4_ext_get_blocks(ip, lbn, blks, cred, NULL, &allocated, 
&newblk);
        if (error)
                return (error);
 
@@ -80,7 +81,7 @@ ext2_ext_balloc(struct inode *ip, uint32_t lbn, int si
                if(!bp)
                        return (EIO);
 
-               bp->b_blkno = fsbtodb(fs, nb);
+               bp->b_blkno = fsbtodb(fs, newblk);
                if (flags & BA_CLRBUF)
                        vfs_bio_clrbuf(bp);
        } else {
@@ -91,7 +92,7 @@ ext2_ext_balloc(struct inode *ip, uint32_t lbn, int si
                                brelse(bp);
                                return (error);
                        }
-                       bp->b_blkno = fsbtodb(fs, nb);
+                       bp->b_blkno = fsbtodb(fs, newblk);
                        *bpp = bp;
                        return (0);
                }
@@ -101,21 +102,15 @@ ext2_ext_balloc(struct inode *ip, uint32_t lbn, int si
                 */
                osize = fragroundup(fs, blkoff(fs, ip->i_size));
                nsize = fragroundup(fs, size);
-               if (nsize <= osize) {
+               if (nsize <= osize)
                        error = bread(vp, lbn, osize, NOCRED, &bp);
-                       if (error) {
-                               brelse(bp);
-                               return (error);
-                       }
-                       bp->b_blkno = fsbtodb(fs, nb);
-               } else {
+               else
                        error = bread(vp, lbn, fs->e2fs_bsize, NOCRED, &bp);
-                       if (error) {
-                               brelse(bp);
-                               return (error);
-                       }
-                       bp->b_blkno = fsbtodb(fs, nb);
+               if (error) {
+                       brelse(bp);
+                       return (error);
                }
+               bp->b_blkno = fsbtodb(fs, newblk);
        }
 
        *bpp = bp;
@@ -218,6 +213,12 @@ ext2_balloc(struct inode *ip, e2fs_lbn_t lbn, int size
                            nsize, cred, &newb);
                        if (error)
                                return (error);
+                       /*
+                        * If the newly allocated block exceeds 32-bit limit,
+                        * we can not use it in file block maps.
+                        */
+                       if (newb > UINT_MAX)
+                               return (EFBIG);
                        bp = getblk(vp, lbn, nsize, 0, 0, 0);
                        bp->b_blkno = fsbtodb(fs, newb);
                        if (flags & BA_CLRBUF)
@@ -250,6 +251,8 @@ ext2_balloc(struct inode *ip, e2fs_lbn_t lbn, int size
                if ((error = ext2_alloc(ip, lbn, pref, fs->e2fs_bsize, cred,
                    &newb)))
                        return (error);
+               if (newb > UINT_MAX)
+                       return (EFBIG);
                nb = newb;
                bp = getblk(vp, indirs[1].in_lbn, fs->e2fs_bsize, 0, 0, 0);
                bp->b_blkno = fsbtodb(fs, newb);
@@ -293,6 +296,8 @@ ext2_balloc(struct inode *ip, e2fs_lbn_t lbn, int size
                        brelse(bp);
                        return (error);
                }
+               if (newb > UINT_MAX)
+                       return (EFBIG);
                nb = newb;
                nbp = getblk(vp, indirs[i].in_lbn, fs->e2fs_bsize, 0, 0, 0);
                nbp->b_blkno = fsbtodb(fs, nb);
@@ -332,6 +337,8 @@ ext2_balloc(struct inode *ip, e2fs_lbn_t lbn, int size
                        brelse(bp);
                        return (error);
                }
+               if (newb > UINT_MAX)
+                       return (EFBIG);
                nb = newb;
                nbp = getblk(vp, lbn, fs->e2fs_bsize, 0, 0, 0);
                nbp->b_blkno = fsbtodb(fs, nb);

Modified: head/sys/fs/ext2fs/ext2_csum.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_csum.c      Fri Jan  5 09:31:41 2018        
(r327583)
+++ head/sys/fs/ext2fs/ext2_csum.c      Fri Jan  5 10:04:01 2018        
(r327584)
@@ -110,7 +110,7 @@ ext2_gd_csum(struct m_ext2fs *fs, uint32_t block_group
                if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT) &&
                    offset < fs->e2fs->e3fs_desc_size)
                        crc = ext2_crc16(crc, (uint8_t *)gd + offset,
-                                        fs->e2fs->e3fs_desc_size - offset);
+                           fs->e2fs->e3fs_desc_size - offset);
                return (crc);
        }
 

Modified: head/sys/fs/ext2fs/ext2_extents.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_extents.c   Fri Jan  5 09:31:41 2018        
(r327583)
+++ head/sys/fs/ext2fs/ext2_extents.c   Fri Jan  5 10:04:01 2018        
(r327584)
@@ -1188,7 +1188,7 @@ ext4_new_blocks(struct inode *ip, daddr_t lbn, e4fs_da
 int
 ext4_ext_get_blocks(struct inode *ip, e4fs_daddr_t iblk,
     unsigned long max_blocks, struct ucred *cred, struct buf **bpp,
-    int *pallocated, uint32_t *nb)
+    int *pallocated, daddr_t *nb)
 {
        struct m_ext2fs *fs;
        struct buf *bp = NULL;

Modified: head/sys/fs/ext2fs/ext2_extents.h
==============================================================================
--- head/sys/fs/ext2fs/ext2_extents.h   Fri Jan  5 09:31:41 2018        
(r327583)
+++ head/sys/fs/ext2fs/ext2_extents.h   Fri Jan  5 10:04:01 2018        
(r327584)
@@ -120,7 +120,8 @@ void ext4_ext_path_free(struct ext4_extent_path *path)
 int ext4_ext_remove_space(struct inode *ip, off_t length, int flags,
     struct ucred *cred, struct thread *td);
 int ext4_ext_get_blocks(struct inode *ip, int64_t iblock,
-    unsigned long max_blocks, struct ucred *cred, struct buf **bpp, int 
*allocate, uint32_t *);
+    unsigned long max_blocks, struct ucred *cred, struct buf **bpp,
+    int *allocate, daddr_t *);
 #ifdef EXT2FS_DEBUG
 void ext4_ext_print_extent_tree_status(struct inode * ip);
 #endif

Modified: head/sys/fs/ext2fs/ext2_extern.h
==============================================================================
--- head/sys/fs/ext2fs/ext2_extern.h    Fri Jan  5 09:31:41 2018        
(r327583)
+++ head/sys/fs/ext2fs/ext2_extern.h    Fri Jan  5 10:04:01 2018        
(r327584)
@@ -102,6 +102,8 @@ int ext2_htree_lookup(struct inode *, const char *, in
            int *, doff_t *, doff_t *, doff_t *, struct ext2fs_searchslot *);
 int    ext2_search_dirblock(struct inode *, void *, int *, const char *, int,
            int *, doff_t *, doff_t *, doff_t *, struct ext2fs_searchslot *);
+uint32_t       e2fs_gd_get_ndirs(struct ext2_gd *gd);
+uint64_t       e2fs_gd_get_i_tables(struct ext2_gd *gd);
 int    ext2_gd_csum_verify(struct m_ext2fs *fs, struct cdev *dev);
 void   ext2_gd_csum_set(struct m_ext2fs *fs);
 

Modified: head/sys/fs/ext2fs/ext2_hash.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_hash.c      Fri Jan  5 09:31:41 2018        
(r327583)
+++ head/sys/fs/ext2fs/ext2_hash.c      Fri Jan  5 10:04:01 2018        
(r327584)
@@ -60,6 +60,7 @@
 #include <sys/stat.h>
 #include <sys/mount.h>
 
+#include <fs/ext2fs/ext2fs.h>
 #include <fs/ext2fs/htree.h>
 #include <fs/ext2fs/inode.h>
 #include <fs/ext2fs/ext2_mount.h>

Modified: head/sys/fs/ext2fs/ext2_subr.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_subr.c      Fri Jan  5 09:31:41 2018        
(r327583)
+++ head/sys/fs/ext2fs/ext2_subr.c      Fri Jan  5 10:04:01 2018        
(r327584)
@@ -49,8 +49,8 @@
 #include <sys/vnode.h>
 
 #include <fs/ext2fs/inode.h>
-#include <fs/ext2fs/ext2_extern.h>
 #include <fs/ext2fs/ext2fs.h>
+#include <fs/ext2fs/ext2_extern.h>
 #include <fs/ext2fs/fs.h>
 #include <fs/ext2fs/ext2_extents.h>
 #include <fs/ext2fs/ext2_mount.h>

Modified: head/sys/fs/ext2fs/ext2_vfsops.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_vfsops.c    Fri Jan  5 09:31:41 2018        
(r327583)
+++ head/sys/fs/ext2fs/ext2_vfsops.c    Fri Jan  5 10:04:01 2018        
(r327584)
@@ -326,12 +326,20 @@ static int
 compute_sb_data(struct vnode *devvp, struct ext2fs *es,
     struct m_ext2fs *fs)
 {
-       int db_count, error;
-       int i;
+       int g_count = 0, error;
+       int i, j;
        int logic_sb_block = 1; /* XXX for now */
        struct buf *bp;
-       uint32_t e2fs_descpb;
+       uint32_t e2fs_descpb, e2fs_gdbcount_alloc;
 
+       fs->e2fs_bcount = es->e2fs_bcount;
+       fs->e2fs_rbcount = es->e2fs_rbcount;
+       fs->e2fs_fbcount = es->e2fs_fbcount;
+       if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
+               fs->e2fs_bcount |= (uint64_t)(es->e4fs_bcount_hi) << 32;
+               fs->e2fs_rbcount |= (uint64_t)(es->e4fs_rbcount_hi) << 32;
+               fs->e2fs_fbcount |= (uint64_t)(es->e4fs_fbcount_hi) << 32;
+       }
        fs->e2fs_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->e2fs_log_bsize;
        fs->e2fs_bsize = 1U << fs->e2fs_bshift;
        fs->e2fs_fsbtodb = es->e2fs_log_bsize + 1;
@@ -375,13 +383,19 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es
        fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs);
        fs->e2fs_itpg = fs->e2fs_ipg / fs->e2fs_ipb;
        /* s_resuid / s_resgid ? */
-       fs->e2fs_gcount = howmany(es->e2fs_bcount - es->e2fs_first_dblock,
+       fs->e2fs_gcount = howmany(fs->e2fs_bcount - es->e2fs_first_dblock,
            EXT2_BLOCKS_PER_GROUP(fs));
-       e2fs_descpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
-       db_count = howmany(fs->e2fs_gcount, e2fs_descpb);
-       fs->e2fs_gdbcount = db_count;
-       fs->e2fs_gd = malloc(db_count * fs->e2fs_bsize,
-           M_EXT2MNT, M_WAITOK);
+       if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
+               e2fs_descpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
+               e2fs_gdbcount_alloc = howmany(fs->e2fs_gcount, e2fs_descpb);
+       } else {
+               e2fs_descpb = fs->e2fs_bsize / E2FS_REV0_GD_SIZE;
+               e2fs_gdbcount_alloc = howmany(fs->e2fs_gcount,
+                   fs->e2fs_bsize / sizeof(struct ext2_gd));
+       }
+       fs->e2fs_gdbcount = howmany(fs->e2fs_gcount, e2fs_descpb);
+       fs->e2fs_gd = malloc(e2fs_gdbcount_alloc * fs->e2fs_bsize,
+           M_EXT2MNT, M_WAITOK | M_ZERO);
        fs->e2fs_contigdirs = malloc(fs->e2fs_gcount *
            sizeof(*fs->e2fs_contigdirs), M_EXT2MNT, M_WAITOK | M_ZERO);
 
@@ -392,7 +406,7 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es
         */
        if (fs->e2fs_bsize > SBSIZE)
                logic_sb_block = 0;
-       for (i = 0; i < db_count; i++) {
+       for (i = 0; i < fs->e2fs_gdbcount; i++) {
                error = bread(devvp,
                    fsbtodb(fs, logic_sb_block + i + 1),
                    fs->e2fs_bsize, NOCRED, &bp);
@@ -402,10 +416,17 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es
                        brelse(bp);
                        return (error);
                }
-               e2fs_cgload((struct ext2_gd *)bp->b_data,
-                   &fs->e2fs_gd[
-                   i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
-                   fs->e2fs_bsize);
+               if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
+                       memcpy(&fs->e2fs_gd[
+                           i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
+                           bp->b_data, fs->e2fs_bsize);
+               } else {
+                       for (j = 0; j < e2fs_descpb &&
+                           g_count < fs->e2fs_gcount; j++, g_count++)
+                               memcpy(&fs->e2fs_gd[g_count],
+                                   bp->b_data + j * E2FS_REV0_GD_SIZE,
+                                   E2FS_REV0_GD_SIZE);
+               }
                brelse(bp);
                bp = NULL;
        }
@@ -823,9 +844,9 @@ ext2_statfs(struct mount *mp, struct statfs *sbp)
 
        sbp->f_bsize = EXT2_FRAG_SIZE(fs);
        sbp->f_iosize = EXT2_BLOCK_SIZE(fs);
-       sbp->f_blocks = fs->e2fs->e2fs_bcount - overhead;
-       sbp->f_bfree = fs->e2fs->e2fs_fbcount;
-       sbp->f_bavail = sbp->f_bfree - fs->e2fs->e2fs_rbcount;
+       sbp->f_blocks = fs->e2fs_bcount - overhead;
+       sbp->f_bfree = fs->e2fs_fbcount;
+       sbp->f_bavail = sbp->f_bfree - fs->e2fs_rbcount;
        sbp->f_files = fs->e2fs->e2fs_icount;
        sbp->f_ffree = fs->e2fs->e2fs_ficount;
        return (0);
@@ -1069,6 +1090,15 @@ ext2_sbupdate(struct ext2mount *mp, int waitfor)
        struct buf *bp;
        int error = 0;
 
+       es->e2fs_bcount = fs->e2fs_bcount & 0xffffffff;
+       es->e2fs_rbcount = fs->e2fs_rbcount & 0xffffffff;
+       es->e2fs_fbcount = fs->e2fs_fbcount & 0xffffffff;
+       if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
+               es->e4fs_bcount_hi = fs->e2fs_bcount >> 32;
+               es->e4fs_rbcount_hi = fs->e2fs_rbcount >> 32;
+               es->e4fs_fbcount_hi = fs->e2fs_fbcount >> 32;
+       }
+
        bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0, 0);
        bcopy((caddr_t)es, bp->b_data, (u_int)sizeof(struct ext2fs));
        if (waitfor == MNT_WAIT)
@@ -1088,7 +1118,7 @@ ext2_cgupdate(struct ext2mount *mp, int waitfor)
 {
        struct m_ext2fs *fs = mp->um_e2fs;
        struct buf *bp;
-       int i, error = 0, allerror = 0;
+       int i, j, g_count = 0, error = 0, allerror = 0;
 
        allerror = ext2_sbupdate(mp, waitfor);
 
@@ -1100,9 +1130,16 @@ ext2_cgupdate(struct ext2mount *mp, int waitfor)
                bp = getblk(mp->um_devvp, fsbtodb(fs,
                    fs->e2fs->e2fs_first_dblock +
                    1 /* superblock */ + i), fs->e2fs_bsize, 0, 0, 0);
-               e2fs_cgsave(&fs->e2fs_gd[
-                   i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
-                   (struct ext2_gd *)bp->b_data, fs->e2fs_bsize);
+               if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
+                       memcpy(bp->b_data, &fs->e2fs_gd[
+                           i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
+                           fs->e2fs_bsize);
+               } else {
+                       for (j = 0; j < fs->e2fs_bsize / E2FS_REV0_GD_SIZE &&
+                           g_count < fs->e2fs_gcount; j++, g_count++)
+                               memcpy(bp->b_data + j * E2FS_REV0_GD_SIZE,
+                                   &fs->e2fs_gd[g_count], E2FS_REV0_GD_SIZE);
+               }
                if (waitfor == MNT_WAIT)
                        error = bwrite(bp);
                else

Modified: head/sys/fs/ext2fs/ext2_vnops.c
==============================================================================
--- head/sys/fs/ext2fs/ext2_vnops.c     Fri Jan  5 09:31:41 2018        
(r327583)
+++ head/sys/fs/ext2fs/ext2_vnops.c     Fri Jan  5 10:04:01 2018        
(r327584)
@@ -84,8 +84,8 @@
 #include <fs/ext2fs/fs.h>
 #include <fs/ext2fs/inode.h>
 #include <fs/ext2fs/ext2_acl.h>
-#include <fs/ext2fs/ext2_extern.h>
 #include <fs/ext2fs/ext2fs.h>
+#include <fs/ext2fs/ext2_extern.h>
 #include <fs/ext2fs/ext2_dinode.h>
 #include <fs/ext2fs/ext2_dir.h>
 #include <fs/ext2fs/ext2_mount.h>

Modified: head/sys/fs/ext2fs/ext2fs.h
==============================================================================
--- head/sys/fs/ext2fs/ext2fs.h Fri Jan  5 09:31:41 2018        (r327583)
+++ head/sys/fs/ext2fs/ext2fs.h Fri Jan  5 10:04:01 2018        (r327584)
@@ -156,6 +156,9 @@ struct m_ext2fs {
        char     e2fs_fsmnt[MAXMNTLEN];/* name mounted on */
        char     e2fs_ronly;      /* mounted read-only flag */
        char     e2fs_fmod;       /* super block modified flag */
+       uint64_t e2fs_bcount;     /* blocks count */
+       uint64_t e2fs_rbcount;    /* reserved blocks count */
+       uint64_t e2fs_fbcount;    /* free blocks count */
        uint32_t e2fs_bsize;      /* Block size */
        uint32_t e2fs_bshift;     /* calc of logical block no */
        uint32_t e2fs_bpg;        /* Number of blocks per group */
@@ -323,7 +326,8 @@ static const struct ext2_feature incompat[] = {
                                         EXT2F_ROCOMPAT_DIR_NLINK | \
                                         EXT2F_ROCOMPAT_HUGE_FILE | \
                                         EXT2F_ROCOMPAT_EXTRA_ISIZE)
-#define        EXT2F_INCOMPAT_SUPP             EXT2F_INCOMPAT_FTYPE
+#define        EXT2F_INCOMPAT_SUPP             (EXT2F_INCOMPAT_FTYPE | \
+                                        EXT2F_INCOMPAT_64BIT)
 #define        EXT4F_RO_INCOMPAT_SUPP          (EXT2F_INCOMPAT_EXTENTS | \
                                         EXT2F_INCOMPAT_RECOVER | \
                                         EXT2F_INCOMPAT_FLEX_BG | \
@@ -375,14 +379,20 @@ struct ext2_gd {
        uint16_t ext4bgd_i_bmap_csum;   /* inode bitmap checksum */
        uint16_t ext4bgd_i_unused;      /* unused inode count */
        uint16_t ext4bgd_csum;          /* group descriptor checksum */
+       uint32_t ext4bgd_b_bitmap_hi;   /* high bits of blocks bitmap block */
+       uint32_t ext4bgd_i_bitmap_hi;   /* high bits of inodes bitmap block */
+       uint32_t ext4bgd_i_tables_hi;   /* high bits of inodes table block */
+       uint16_t ext4bgd_nbfree_hi;     /* high bits of number of free blocks */
+       uint16_t ext4bgd_nifree_hi;     /* high bits of number of free inodes */
+       uint16_t ext4bgd_ndirs_hi;      /* high bits of number of directories */
+       uint16_t ext4bgd_i_unused_hi;   /* high bits of unused inode count */
+       uint32_t ext4bgd_x_bitmap_hi;   /* high bits of snapshot exclusion */
+       uint16_t ext4bgd_b_bmap_csum_hi;/* high bits of block bitmap checksum */
+       uint16_t ext4bgd_i_bmap_csum_hi;/* high bits of inode bitmap checksum */
+       uint32_t ext4bgd_reserved;
 };
 
-/* EXT2FS metadata is stored in little-endian byte order. These macros
- * help reading it.
- */
-
-#define        e2fs_cgload(old, new, size) memcpy((new), (old), (size));
-#define        e2fs_cgsave(old, new, size) memcpy((new), (old), (size));
+#define        E2FS_REV0_GD_SIZE (sizeof(struct ext2_gd) / 2)
 
 /*
  * Macro-instructions used to manage several block sizes

Modified: head/sys/fs/ext2fs/fs.h
==============================================================================
--- head/sys/fs/ext2fs/fs.h     Fri Jan  5 09:31:41 2018        (r327583)
+++ head/sys/fs/ext2fs/fs.h     Fri Jan  5 10:04:01 2018        (r327584)
@@ -108,7 +108,7 @@
 
 /* get block containing inode from its number x */
 #define        ino_to_fsba(fs, x)                                              
\
-        ((fs)->e2fs_gd[ino_to_cg((fs), (x))].ext2bgd_i_tables +         \
+        (e2fs_gd_get_i_tables(&(fs)->e2fs_gd[ino_to_cg((fs), (x))]) +   \
         (((x) - 1) % (fs)->e2fs->e2fs_ipg) / (fs)->e2fs_ipb)
 
 /* get offset for inode in block */
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to