Index: head/sys/fs/ext2fs/ext2_alloc.c =================================================================== --- head/sys/fs/ext2fs/ext2_alloc.c +++ head/sys/fs/ext2fs/ext2_alloc.c @@ -103,12 +103,12 @@ 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 @@ } /* + * 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 @@ { 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 @@ 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 @@ 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 @@ */ 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 @@ * 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 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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_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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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; Index: head/sys/fs/ext2fs/ext2_balloc.c =================================================================== --- head/sys/fs/ext2fs/ext2_balloc.c +++ head/sys/fs/ext2fs/ext2_balloc.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -60,13 +61,13 @@ 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 @@ 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 @@ brelse(bp); return (error); } - bp->b_blkno = fsbtodb(fs, nb); + bp->b_blkno = fsbtodb(fs, newblk); *bpp = bp; return (0); } @@ -101,21 +102,15 @@ */ 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 @@ 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 @@ 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 @@ 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 @@ 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); Index: head/sys/fs/ext2fs/ext2_csum.c =================================================================== --- head/sys/fs/ext2fs/ext2_csum.c +++ head/sys/fs/ext2fs/ext2_csum.c @@ -110,7 +110,7 @@ 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); } Index: head/sys/fs/ext2fs/ext2_extents.h =================================================================== --- head/sys/fs/ext2fs/ext2_extents.h +++ head/sys/fs/ext2fs/ext2_extents.h @@ -120,7 +120,8 @@ 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 Index: head/sys/fs/ext2fs/ext2_extents.c =================================================================== --- head/sys/fs/ext2fs/ext2_extents.c +++ head/sys/fs/ext2fs/ext2_extents.c @@ -1188,7 +1188,7 @@ 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; Index: head/sys/fs/ext2fs/ext2_extern.h =================================================================== --- head/sys/fs/ext2fs/ext2_extern.h +++ head/sys/fs/ext2fs/ext2_extern.h @@ -102,6 +102,8 @@ 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); Index: head/sys/fs/ext2fs/ext2_hash.c =================================================================== --- head/sys/fs/ext2fs/ext2_hash.c +++ head/sys/fs/ext2fs/ext2_hash.c @@ -60,6 +60,7 @@ #include #include +#include #include #include #include Index: head/sys/fs/ext2fs/ext2_subr.c =================================================================== --- head/sys/fs/ext2fs/ext2_subr.c +++ head/sys/fs/ext2fs/ext2_subr.c @@ -49,8 +49,8 @@ #include #include -#include #include +#include #include #include #include Index: head/sys/fs/ext2fs/ext2_vfsops.c =================================================================== --- head/sys/fs/ext2fs/ext2_vfsops.c +++ head/sys/fs/ext2fs/ext2_vfsops.c @@ -326,12 +326,20 @@ 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 @@ 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 @@ */ 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 @@ 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 @@ 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 @@ 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 @@ { 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 @@ 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 Index: head/sys/fs/ext2fs/ext2_vnops.c =================================================================== --- head/sys/fs/ext2fs/ext2_vnops.c +++ head/sys/fs/ext2fs/ext2_vnops.c @@ -84,8 +84,8 @@ #include #include #include -#include #include +#include #include #include #include Index: head/sys/fs/ext2fs/ext2fs.h =================================================================== --- head/sys/fs/ext2fs/ext2fs.h +++ head/sys/fs/ext2fs/ext2fs.h @@ -156,6 +156,9 @@ 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 @@ 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 @@ 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 Index: head/sys/fs/ext2fs/fs.h =================================================================== --- head/sys/fs/ext2fs/fs.h +++ head/sys/fs/ext2fs/fs.h @@ -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 */