Module Name: src
Committed By: christos
Date: Fri Aug 25 16:50:23 UTC 2023
Modified Files:
src/sys/ufs/ext2fs: ext2fs.h ext2fs_alloc.c ext2fs_vfsops.c
Log Message:
Support INCOMPAT_64BIT on ext4 (Vladimir 'phcoder' Serbinenko)
To generate a diff of this commit:
cvs rdiff -u -r1.48 -r1.49 src/sys/ufs/ext2fs/ext2fs.h
cvs rdiff -u -r1.52 -r1.53 src/sys/ufs/ext2fs/ext2fs_alloc.c
cvs rdiff -u -r1.221 -r1.222 src/sys/ufs/ext2fs/ext2fs_vfsops.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/ufs/ext2fs/ext2fs.h
diff -u src/sys/ufs/ext2fs/ext2fs.h:1.48 src/sys/ufs/ext2fs/ext2fs.h:1.49
--- src/sys/ufs/ext2fs/ext2fs.h:1.48 Sat Aug 20 15:47:44 2016
+++ src/sys/ufs/ext2fs/ext2fs.h Fri Aug 25 12:50:23 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: ext2fs.h,v 1.48 2016/08/20 19:47:44 jdolecek Exp $ */
+/* $NetBSD: ext2fs.h,v 1.49 2023/08/25 16:50:23 christos Exp $ */
/*
* Copyright (c) 1982, 1986, 1993
@@ -252,6 +252,7 @@ struct m_ext2fs {
int32_t e2fs_ngdb; /* number of group descriptor blocks */
int32_t e2fs_ipb; /* number of inodes per block */
int32_t e2fs_itpg; /* number of inode table blocks per group */
+ uint8_t e2fs_group_desc_shift; /* binary log group desc size */
struct ext2_gd *e2fs_gd; /* group descriptors (data not byteswapped) */
};
@@ -370,7 +371,8 @@ struct m_ext2fs {
| EXT2F_ROCOMPAT_GDT_CSUM)
#define EXT2F_INCOMPAT_SUPP (EXT2F_INCOMPAT_FTYPE \
| EXT2F_INCOMPAT_EXTENTS \
- | EXT2F_INCOMPAT_FLEX_BG)
+ | EXT2F_INCOMPAT_FLEX_BG \
+ | EXT2F_INCOMPAT_64BIT)
/*
* Feature set definitions
@@ -432,10 +434,14 @@ struct ext2_gd {
uint16_t ext2bgd_itable_unused_lo; /* Low unused inode offset */
uint16_t ext2bgd_checksum; /* Group desc checksum */
- /*
- * XXX disk32 Further fields only exist if 64BIT feature is on
- * and superblock desc_size > 32, not supported for now.
- */
+ uint32_t ext2bgd_b_bitmap_hi; /* blocks bitmap block (high bits) */
+ uint32_t ext2bgd_i_bitmap_hi; /* inodes bitmap block (high bits) */
+ uint32_t ext2bgd_i_tables_hi; /* inodes table block (high bits) */
+ uint16_t ext2bgd_nbfree_hi; /* number of free blocks (high bits) */
+ uint16_t ext2bgd_nifree_hi; /* number of free inodes (high bits) */
+ uint16_t ext2bgd_ndirs_hi; /* number of directories (high bits) */
+ uint16_t reserved_hi;
+ uint32_t reserved2_hi[3];
};
#define E2FS_BG_INODE_UNINIT 0x0001 /* Inode bitmap not used/initialized */
@@ -492,15 +498,15 @@ void e2fs_sb_bswap(struct ext2fs *, stru
# define e2fs_sbsave(old, new) e2fs_sb_bswap((old), (new))
#endif
-/* Group descriptors are not byte swapped */
-#define e2fs_cgload(old, new, size) memcpy((new), (old), (size))
-#define e2fs_cgsave(old, new, size) memcpy((new), (old), (size))
-
/*
* Turn file system block numbers into disk block addresses.
* This maps file system blocks to device size blocks.
*/
#define EXT2_FSBTODB(fs, b) ((b) << (fs)->e2fs_fsbtodb)
+#define EXT2_FSBTODB64(fs, b, b_hi) \
+ (((((uint64_t)(b_hi)) << 32) | (b)) << (fs)->e2fs_fsbtodb)
+#define EXT2_FSBTODB64OFF(fs, b, b_hi, off) \
+ ((((((uint64_t)(b_hi)) << 32) | (b)) + (off)) << (fs)->e2fs_fsbtodb)
#define EXT2_DBTOFSB(fs, b) ((b) >> (fs)->e2fs_fsbtodb)
/*
@@ -510,9 +516,11 @@ void e2fs_sb_bswap(struct ext2fs *, stru
* inode number to file system block address.
*/
#define ino_to_cg(fs, x) (((x) - 1) / (fs)->e2fs.e2fs_ipg)
-#define ino_to_fsba(fs, x) \
- (fs2h32((fs)->e2fs_gd[ino_to_cg((fs), (x))].ext2bgd_i_tables) + \
- (((x) - 1) % (fs)->e2fs.e2fs_ipg) / (fs)->e2fs_ipb)
+#define _e2fs_gd(fs, x) (fs)->e2fs_gd[ino_to_cg((fs), (x))]
+#define ino_to_fsba(fs, x) \
+ (fs2h32(_e2fs_gd(fs, x).ext2bgd_i_tables) + \
+ (((uint64_t)fs2h32(_e2fs_gd(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)
/*
Index: src/sys/ufs/ext2fs/ext2fs_alloc.c
diff -u src/sys/ufs/ext2fs/ext2fs_alloc.c:1.52 src/sys/ufs/ext2fs/ext2fs_alloc.c:1.53
--- src/sys/ufs/ext2fs/ext2fs_alloc.c:1.52 Sun May 28 12:38:55 2017
+++ src/sys/ufs/ext2fs/ext2fs_alloc.c Fri Aug 25 12:50:23 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: ext2fs_alloc.c,v 1.52 2017/05/28 16:38:55 hannken Exp $ */
+/* $NetBSD: ext2fs_alloc.c,v 1.53 2023/08/25 16:50:23 christos Exp $ */
/*
* Copyright (c) 1982, 1986, 1989, 1993
@@ -60,7 +60,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_alloc.c,v 1.52 2017/05/28 16:38:55 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_alloc.c,v 1.53 2023/08/25 16:50:23 christos Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -90,9 +90,11 @@ static u_long ext2fs_hashalloc(struct in
daddr_t (*)(struct inode *, int, daddr_t, int));
static daddr_t ext2fs_nodealloccg(struct inode *, int, daddr_t, int);
static daddr_t ext2fs_mapsearch(struct m_ext2fs *, char *, daddr_t);
-static __inline void ext2fs_cg_update(struct m_ext2fs *, int, struct ext2_gd *, int, int, int, daddr_t);
-static uint16_t ext2fs_cg_get_csum(struct m_ext2fs *, int, struct ext2_gd *);
-static void ext2fs_init_bb(struct m_ext2fs *, int, struct ext2_gd *, char *);
+static __inline void ext2fs_cg_update(struct m_ext2fs *, int,
+ struct ext2_gd *, int, int, int, daddr_t);
+static uint16_t ext2fs_cg_get_csum(struct m_ext2fs *, int, struct ext2_gd *);
+static void ext2fs_init_bb(struct m_ext2fs *, int, struct ext2_gd *,
+ char *);
/*
* Allocate a block in the file system.
@@ -212,13 +214,21 @@ 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 (fs2h16(fs->e2fs_gd[cg].ext2bgd_nifree) >= avgifree) {
- if (mincg == -1 || fs2h16(fs->e2fs_gd[cg].ext2bgd_nbfree) > maxspace) {
- mincg = cg;
- maxspace = fs2h16(fs->e2fs_gd[cg].ext2bgd_nbfree);
- }
+ for (cg = 0; cg < fs->e2fs_ncg; cg++) {
+ uint32_t nifree =
+ (fs2h16(fs->e2fs_gd[cg].ext2bgd_nifree_hi) << 16)
+ | fs2h16(fs->e2fs_gd[cg].ext2bgd_nifree);
+ if (nifree < avgifree) {
+ continue;
}
+ uint32_t nbfree =
+ (fs2h16(fs->e2fs_gd[cg].ext2bgd_nbfree_hi) << 16)
+ | fs2h16(fs->e2fs_gd[cg].ext2bgd_nbfree);
+ if (mincg == -1 || nbfree > maxspace) {
+ mincg = cg;
+ maxspace = nbfree;
+ }
+ }
return mincg;
}
@@ -333,14 +343,15 @@ ext2fs_alloccg(struct inode *ip, int cg,
struct m_ext2fs *fs;
char *bbp;
struct buf *bp;
- /* XXX ondisk32 */
int error, bno, 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, EXT2_FSBTODB(fs,
- fs2h32(fs->e2fs_gd[cg].ext2bgd_b_bitmap)),
+ error = bread(ip->i_devvp, EXT2_FSBTODB64(fs,
+ fs2h32(fs->e2fs_gd[cg].ext2bgd_b_bitmap),
+ fs2h32(fs->e2fs_gd[cg].ext2bgd_b_bitmap_hi)),
(int)fs->e2fs_bsize, B_MODIFY, &bp);
if (error) {
return 0;
@@ -403,8 +414,8 @@ ext2fs_alloccg(struct inode *ip, int cg,
gotit:
#ifdef DIAGNOSTIC
if (isset(bbp, (daddr_t)bno)) {
- printf("ext2fs_alloccgblk: cg=%d bno=%d fs=%s\n",
- cg, bno, fs->e2fs_fsmnt);
+ printf("%s: cg=%d bno=%d fs=%s\n", __func__,
+ cg, bno, fs->e2fs_fsmnt);
panic("ext2fs_alloccg: dup alloc");
}
#endif
@@ -437,10 +448,12 @@ ext2fs_nodealloccg(struct inode *ip, int
if (ipref == -1)
ipref = 0;
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, EXT2_FSBTODB(fs,
- fs2h32(fs->e2fs_gd[cg].ext2bgd_i_bitmap)),
+ error = bread(ip->i_devvp, EXT2_FSBTODB64(fs,
+ fs2h32(fs->e2fs_gd[cg].ext2bgd_i_bitmap),
+ fs2h32(fs->e2fs_gd[cg].ext2bgd_i_bitmap_hi)),
(int)fs->e2fs_bsize, B_MODIFY, &bp);
if (error) {
return 0;
@@ -470,17 +483,17 @@ ext2fs_nodealloccg(struct inode *ip, int
start = 0;
loc = skpc(0xff, len, &ibp[0]);
if (loc == 0) {
- printf("cg = %d, ipref = %lld, fs = %s\n",
- cg, (long long)ipref, fs->e2fs_fsmnt);
- panic("ext2fs_nodealloccg: map corrupted");
+ printf("%s: cg = %d, ipref = %lld, fs = %s\n", __func__,
+ cg, (long long)ipref, fs->e2fs_fsmnt);
+ panic("%s: map corrupted", __func__);
/* NOTREACHED */
}
}
i = start + len - loc;
map = ibp[i] ^ 0xff;
if (map == 0) {
- printf("fs = %s\n", fs->e2fs_fsmnt);
- panic("ext2fs_nodealloccg: inode not in map");
+ printf("%s: fs = %s\n", __func__, fs->e2fs_fsmnt);
+ panic("%s: inode not in map", __func__);
}
ipref = i * NBBY + ffs(map) - 1;
gotit:
@@ -510,27 +523,29 @@ ext2fs_blkfree(struct inode *ip, daddr_t
fs = ip->i_e2fs;
cg = dtog(fs, bno);
- KASSERT(!E2FS_HAS_GD_CSUM(fs) || (fs->e2fs_gd[cg].ext2bgd_flags & h2fs16(E2FS_BG_BLOCK_UNINIT)) == 0);
+ KASSERT(!E2FS_HAS_GD_CSUM(fs) ||
+ (fs->e2fs_gd[cg].ext2bgd_flags & h2fs16(E2FS_BG_BLOCK_UNINIT)) == 0);
if ((u_int)bno >= fs->e2fs.e2fs_bcount) {
- printf("bad block %lld, ino %llu\n", (long long)bno,
- (unsigned long long)ip->i_number);
+ printf("%s: bad block %jd, ino %ju\n",
+ __func__, (intmax_t)bno, (uintmax_t)ip->i_number);
ext2fs_fserr(fs, ip->i_uid, "bad block");
return;
}
- error = bread(ip->i_devvp,
- EXT2_FSBTODB(fs, fs2h32(fs->e2fs_gd[cg].ext2bgd_b_bitmap)),
- (int)fs->e2fs_bsize, B_MODIFY, &bp);
+ error = bread(ip->i_devvp, EXT2_FSBTODB64(fs,
+ fs2h32(fs->e2fs_gd[cg].ext2bgd_b_bitmap),
+ fs2h32(fs->e2fs_gd[cg].ext2bgd_b_bitmap_hi)),
+ (int)fs->e2fs_bsize, B_MODIFY, &bp);
if (error) {
return;
}
bbp = (char *)bp->b_data;
bno = dtogd(fs, bno);
if (isclr(bbp, bno)) {
- printf("dev = 0x%llx, block = %lld, fs = %s\n",
- (unsigned long long)ip->i_dev, (long long)bno,
+ printf("%s: dev = %#jx, block = %jd, fs = %s\n", __func__,
+ (uintmax_t)ip->i_dev, (intmax_t)bno,
fs->e2fs_fsmnt);
- panic("blkfree: freeing free block");
+ panic("%s: freeing free block", __func__);
}
clrbit(bbp, bno);
fs->e2fs.e2fs_fbcount++;
@@ -557,28 +572,30 @@ ext2fs_vfree(struct vnode *pvp, ino_t in
fs = pip->i_e2fs;
if ((u_int)ino > fs->e2fs.e2fs_icount || (u_int)ino < EXT2_FIRSTINO)
- panic("ifree: range: dev = 0x%llx, ino = %llu, fs = %s",
- (unsigned long long)pip->i_dev, (unsigned long long)ino,
+ panic("%s: range: dev = %#jx, ino = %ju, fs = %s",
+ __func__, (uintmax_t)pip->i_dev, (uintmax_t)ino,
fs->e2fs_fsmnt);
cg = ino_to_cg(fs, ino);
- KASSERT(!E2FS_HAS_GD_CSUM(fs) || (fs->e2fs_gd[cg].ext2bgd_flags & h2fs16(E2FS_BG_INODE_UNINIT)) == 0);
+ KASSERT(!E2FS_HAS_GD_CSUM(fs) ||
+ (fs->e2fs_gd[cg].ext2bgd_flags & h2fs16(E2FS_BG_INODE_UNINIT)) == 0);
- error = bread(pip->i_devvp,
- EXT2_FSBTODB(fs, fs2h32(fs->e2fs_gd[cg].ext2bgd_i_bitmap)),
- (int)fs->e2fs_bsize, B_MODIFY, &bp);
+ error = bread(pip->i_devvp, EXT2_FSBTODB64(fs,
+ fs2h32(fs->e2fs_gd[cg].ext2bgd_i_bitmap),
+ fs2h32(fs->e2fs_gd[cg].ext2bgd_i_bitmap_hi)),
+ (int)fs->e2fs_bsize, B_MODIFY, &bp);
if (error) {
return 0;
}
ibp = (char *)bp->b_data;
ino = (ino - 1) % fs->e2fs.e2fs_ipg;
if (isclr(ibp, ino)) {
- printf("dev = 0x%llx, ino = %llu, fs = %s\n",
- (unsigned long long)pip->i_dev,
- (unsigned long long)ino, fs->e2fs_fsmnt);
+ printf("%s: dev = %#jx, ino = %ju, fs = %s\n", __func__,
+ (uintmax_t)pip->i_dev,
+ (uintmax_t)ino, fs->e2fs_fsmnt);
if (fs->e2fs_ronly == 0)
- panic("ifree: freeing free inode");
+ panic("%s: freeing free inode", __func__);
}
clrbit(ibp, ino);
fs->e2fs.e2fs_ficount++;
@@ -616,17 +633,17 @@ ext2fs_mapsearch(struct m_ext2fs *fs, ch
start = 0;
loc = skpc(0xff, len, &bbp[start]);
if (loc == 0) {
- printf("start = %d, len = %d, fs = %s\n",
- start, len, fs->e2fs_fsmnt);
- panic("ext2fs_alloccg: map corrupted");
+ printf("%s: start = %d, len = %d, fs = %s\n",
+ __func__, start, len, fs->e2fs_fsmnt);
+ panic("%s: map corrupted", __func__);
/* NOTREACHED */
}
}
i = start + len - loc;
map = bbp[i] ^ 0xff;
if (map == 0) {
- printf("fs = %s\n", fs->e2fs_fsmnt);
- panic("ext2fs_mapsearch: block not in map");
+ printf("%s: fs = %s\n", __func__, fs->e2fs_fsmnt);
+ panic("%s: block not in map", __func__);
}
return i * NBBY + ffs(map) - 1;
}
@@ -647,9 +664,12 @@ ext2fs_fserr(struct m_ext2fs *fs, u_int
static __inline void
ext2fs_cg_update(struct m_ext2fs *fs, int cg, struct ext2_gd *gd, int nbfree, int nifree, int ndirs, daddr_t ioff)
{
- /* XXX disk32 */
if (nifree) {
- gd->ext2bgd_nifree = h2fs16(fs2h16(gd->ext2bgd_nifree) + nifree);
+ uint32_t ext2bgd_nifree = fs2h16(gd->ext2bgd_nifree) |
+ (fs2h16(gd->ext2bgd_nifree_hi) << 16);
+ ext2bgd_nifree += nifree;
+ gd->ext2bgd_nifree = h2fs16(ext2bgd_nifree);
+ gd->ext2bgd_nifree_hi = h2fs16(ext2bgd_nifree >> 16);
/*
* If we allocated inode on bigger offset than what was
* ever used before, bump the itable_unused count. This
@@ -658,19 +678,34 @@ ext2fs_cg_update(struct m_ext2fs *fs, in
* time we get here the itables are already zeroed, but
* e2fstools fsck.ext4 still checks this.
*/
- if (E2FS_HAS_GD_CSUM(fs) && nifree < 0 && (ioff+1) >= (fs->e2fs.e2fs_ipg - fs2h16(gd->ext2bgd_itable_unused_lo))) {
- gd->ext2bgd_itable_unused_lo = h2fs16(fs->e2fs.e2fs_ipg - (ioff + 1));
+ if (E2FS_HAS_GD_CSUM(fs) && nifree < 0 &&
+ (ioff + 1) >= (fs->e2fs.e2fs_ipg -
+ fs2h16(gd->ext2bgd_itable_unused_lo))) {
+ gd->ext2bgd_itable_unused_lo =
+ h2fs16(fs->e2fs.e2fs_ipg - (ioff + 1));
}
- KASSERT(!E2FS_HAS_GD_CSUM(fs) || gd->ext2bgd_itable_unused_lo <= gd->ext2bgd_nifree);
+ KASSERT(!E2FS_HAS_GD_CSUM(fs) ||
+ gd->ext2bgd_itable_unused_lo <= ext2bgd_nifree);
}
- if (nbfree)
- gd->ext2bgd_nbfree = h2fs16(fs2h16(gd->ext2bgd_nbfree) + nbfree);
-
- if (ndirs)
- gd->ext2bgd_ndirs = h2fs16(fs2h16(gd->ext2bgd_ndirs) + ndirs);
+ if (nbfree) {
+ uint32_t ext2bgd_nbfree = fs2h16(gd->ext2bgd_nbfree)
+ | (fs2h16(gd->ext2bgd_nbfree_hi) << 16);
+ ext2bgd_nbfree += nbfree;
+ gd->ext2bgd_nbfree = h2fs16(ext2bgd_nbfree);
+ gd->ext2bgd_nbfree_hi = h2fs16(ext2bgd_nbfree >> 16);
+
+ }
+
+ if (ndirs) {
+ uint32_t ext2bgd_ndirs = fs2h16(gd->ext2bgd_ndirs)
+ | (fs2h16(gd->ext2bgd_ndirs_hi) << 16);
+ ext2bgd_ndirs += ndirs;
+ gd->ext2bgd_ndirs = h2fs16(ext2bgd_ndirs);
+ gd->ext2bgd_ndirs_hi = h2fs16(ext2bgd_ndirs >> 16);
+ }
if (E2FS_HAS_GD_CSUM(fs))
gd->ext2bgd_checksum = ext2fs_cg_get_csum(fs, cg, gd);
@@ -684,6 +719,7 @@ static uint16_t
ext2fs_cg_get_csum(struct m_ext2fs *fs, int cg, struct ext2_gd *gd)
{
uint16_t crc;
+ size_t cgsize = 1 << fs->e2fs_group_desc_shift;
uint32_t cg_bswapped = h2fs32((uint32_t)cg);
size_t off;
@@ -695,7 +731,7 @@ ext2fs_cg_get_csum(struct m_ext2fs *fs,
crc = crc16(~0, (uint8_t *)fs->e2fs.e2fs_uuid, sizeof(fs->e2fs.e2fs_uuid));
crc = crc16(crc, (uint8_t *)&cg_bswapped, sizeof(cg_bswapped));
crc = crc16(crc, (uint8_t *)gd, off);
- /* XXX ondisk32 */
+ crc = crc16(crc, (uint8_t *)gd + off + 2, cgsize - (off + 2));
return h2fs16(crc);
}
@@ -723,7 +759,6 @@ ext2fs_init_bb(struct m_ext2fs *fs, int
int
ext2fs_cg_verify_and_initialize(struct vnode *devvp, struct m_ext2fs *fs, int ronly)
{
- /* XXX disk32 */
struct ext2_gd *gd;
ino_t ioff;
size_t boff;
@@ -733,17 +768,20 @@ ext2fs_cg_verify_and_initialize(struct v
if (!E2FS_HAS_GD_CSUM(fs))
return 0;
- for(cg=0; cg < fs->e2fs_ncg; cg++) {
+ for(cg = 0; cg < fs->e2fs_ncg; cg++) {
gd = &fs->e2fs_gd[cg];
/* Verify checksum */
- if (gd->ext2bgd_checksum != ext2fs_cg_get_csum(fs, cg, gd)) {
- printf("ext2fs_cg_verify_and_initialize: group %d invalid csum\n", cg);
+ uint16_t csum = ext2fs_cg_get_csum(fs, cg, gd);
+ if (gd->ext2bgd_checksum != csum) {
+ printf("%s: group %d invalid csum (%#x != %#x)\n",
+ __func__, cg, gd->ext2bgd_checksum, csum);
return EINVAL;
}
/* if mounting read-write, zero itable if not already done */
- if (ronly || (gd->ext2bgd_flags & h2fs16(E2FS_BG_INODE_ZEROED)) != 0)
+ if (ronly ||
+ (gd->ext2bgd_flags & h2fs16(E2FS_BG_INODE_ZEROED)) != 0)
continue;
/*
@@ -760,23 +798,27 @@ ext2fs_cg_verify_and_initialize(struct v
for(i = ioff / fs->e2fs_ipb; i < fs->e2fs_itpg; i++) {
if (boff) {
/* partial wipe, must read old data */
- error = bread(devvp,
- EXT2_FSBTODB(fs, fs2h32(gd->ext2bgd_i_tables) + i),
- (int)fs->e2fs_bsize, B_MODIFY, &bp);
+ error = bread(devvp, EXT2_FSBTODB64OFF(fs,
+ fs2h32(gd->ext2bgd_i_tables),
+ fs2h32(gd->ext2bgd_i_tables_hi), i),
+ (int)fs->e2fs_bsize, B_MODIFY, &bp);
if (error) {
- printf("ext2fs_cg_verify_and_initialize: can't read itable block");
+ printf("%s: can't read itable block",
+ __func__);
return error;
}
- memset((char *)bp->b_data + boff, 0, fs->e2fs_bsize - boff);
+ memset((char *)bp->b_data + boff, 0,
+ fs->e2fs_bsize - boff);
boff = 0;
} else {
/*
* Complete wipe, don't need to read data. This
* assumes nothing else is changing the data.
*/
- bp = getblk(devvp,
- EXT2_FSBTODB(fs, fs2h32(gd->ext2bgd_i_tables) + i),
- (int)fs->e2fs_bsize, 0, 0);
+ bp = getblk(devvp, EXT2_FSBTODB64OFF(fs,
+ fs2h32(gd->ext2bgd_i_tables),
+ fs2h32(gd->ext2bgd_i_tables_hi), i),
+ (int)fs->e2fs_bsize, 0, 0);
clrbuf(bp);
}
Index: src/sys/ufs/ext2fs/ext2fs_vfsops.c
diff -u src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.221 src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.222
--- src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.221 Sun May 22 07:27:36 2022
+++ src/sys/ufs/ext2fs/ext2fs_vfsops.c Fri Aug 25 12:50:23 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: ext2fs_vfsops.c,v 1.221 2022/05/22 11:27:36 andvar Exp $ */
+/* $NetBSD: ext2fs_vfsops.c,v 1.222 2023/08/25 16:50:23 christos Exp $ */
/*
* Copyright (c) 1989, 1991, 1993, 1994
@@ -60,7 +60,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.221 2022/05/22 11:27:36 andvar Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.222 2023/08/25 16:50:23 christos Exp $");
#if defined(_KERNEL_OPT)
#include "opt_compat_netbsd.h"
@@ -159,6 +159,58 @@ static const struct ufs_ops ext2fs_ufsop
.uo_bufwr = ext2fs_bufwr,
};
+static void
+e2fs_cgload(const char *ondisk, struct ext2_gd *inmemory, int cg_size,
+ int shift_cg_entry_size)
+{
+
+ if (shift_cg_entry_size == 6) {
+ memcpy(inmemory, ondisk, cg_size);
+ return;
+ }
+
+ const char *iptr = ondisk;
+ struct ext2_gd *optr = inmemory;
+ int sh = 1 << shift_cg_entry_size;
+ int lim = cg_size >> shift_cg_entry_size;
+ if (shift_cg_entry_size > 6) {
+ for (int i = 0; i < lim; i++, optr++, iptr += sh) {
+ memcpy(optr, iptr, sizeof(*optr));
+ }
+ } else {
+ for (int i = 0; i < lim; i++, optr++, iptr += sh) {
+ memcpy(optr, iptr, 32);
+ memset((char *)optr + 32, 0, sizeof(*optr) - 32);
+ }
+ }
+}
+
+static void
+e2fs_cgsave(const struct ext2_gd *inmemory, char *ondisk, int cg_size,
+ int shift_cg_entry_size)
+{
+
+ if (shift_cg_entry_size == 6) {
+ memcpy(ondisk, inmemory, cg_size);
+ return;
+ }
+
+ const struct ext2_gd *iptr = inmemory;
+ char *optr = ondisk;
+ int sh = 1 << shift_cg_entry_size;
+ int lim = cg_size >> shift_cg_entry_size;
+ if (shift_cg_entry_size > 6) {
+ for (int i = 0; i < lim; i++, iptr++, optr += sh) {
+ memcpy(optr, iptr, sizeof(*iptr));
+ memset(optr + sizeof(*optr), 0, sh - sizeof(*iptr));
+ }
+ } else {
+ for (int i = 0; i < lim; i++, iptr++, optr += sh) {
+ memcpy(optr, iptr, 32);
+ }
+ }
+}
+
/* Fill in the inode uid/gid from ext2 halves. */
void
ext2fs_set_inode_guid(struct inode *ip)
@@ -506,11 +558,13 @@ ext2fs_loadvnode_content(struct m_ext2fs
struct ext2fs_dinode *din;
int error = 0;
- din = (struct ext2fs_dinode *)((char *)bp->b_data + (ino_to_fsbo(fs, ino) * EXT2_DINODE_SIZE(fs)));
+ din = (struct ext2fs_dinode *)((char *)bp->b_data +
+ (ino_to_fsbo(fs, ino) * EXT2_DINODE_SIZE(fs)));
/* sanity checks - inode data NOT byteswapped at this point */
if (EXT2_DINODE_FITS(din, e2di_extra_isize, EXT2_DINODE_SIZE(fs))
- && (EXT2_DINODE_SIZE(fs) - EXT2_REV0_DINODE_SIZE) < fs2h16(din->e2di_extra_isize))
+ && (EXT2_DINODE_SIZE(fs) - EXT2_REV0_DINODE_SIZE)
+ < fs2h16(din->e2di_extra_isize))
{
printf("ext2fs: inode %"PRIu64" bad extra_isize %u",
ino, din->e2di_extra_isize);
@@ -571,8 +625,8 @@ ext2fs_reload(struct mount *mp, kauth_cr
fs = ump->um_e2fs;
/*
- * Step 2: re-read superblock from disk. Copy in new superblock, and compute
- * in-memory values.
+ * Step 2: re-read superblock from disk. Copy in new superblock, and
+ * compute in-memory values.
*/
error = bread(devvp, SBLOCK, SBSIZE, 0, &bp);
if (error)
@@ -597,9 +651,9 @@ ext2fs_reload(struct mount *mp, kauth_cr
if (error) {
return error;
}
- e2fs_cgload((struct ext2_gd *)bp->b_data,
+ e2fs_cgload(bp->b_data,
&fs->e2fs_gd[i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
- fs->e2fs_bsize);
+ fs->e2fs_bsize, 1 << fs->e2fs_group_desc_shift);
brelse(bp, 0);
}
@@ -704,8 +758,10 @@ ext2fs_mountfs(struct vnode *devvp, stru
m_fs->e2fs_fmod = 1;
}
+ int32_t sh = m_fs->e2fs_bsize >> m_fs->e2fs_group_desc_shift;
/* XXX: should be added in ext2fs_sbfill()? */
- m_fs->e2fs_gd = kmem_alloc(m_fs->e2fs_ngdb * m_fs->e2fs_bsize, KM_SLEEP);
+ m_fs->e2fs_gd = kmem_alloc(m_fs->e2fs_ngdb * sh
+ * sizeof(struct ext2_gd), KM_SLEEP);
for (i = 0; i < m_fs->e2fs_ngdb; i++) {
error = bread(devvp,
EXT2_FSBTODB(m_fs, m_fs->e2fs.e2fs_first_dblock +
@@ -716,10 +772,8 @@ ext2fs_mountfs(struct vnode *devvp, stru
m_fs->e2fs_ngdb * m_fs->e2fs_bsize);
goto out;
}
- e2fs_cgload((struct ext2_gd *)bp->b_data,
- &m_fs->e2fs_gd[
- i * m_fs->e2fs_bsize / sizeof(struct ext2_gd)],
- m_fs->e2fs_bsize);
+ e2fs_cgload(bp->b_data, &m_fs->e2fs_gd[i * sh],
+ m_fs->e2fs_bsize, m_fs->e2fs_group_desc_shift);
brelse(bp, 0);
bp = NULL;
}
@@ -1109,7 +1163,9 @@ ext2fs_newvnode(struct mount *mp, struct
ip = VTOI(vp);
- KASSERT(!E2FS_HAS_GD_CSUM(fs) || (fs->e2fs_gd[ino_to_cg(fs, ino)].ext2bgd_flags & h2fs16(E2FS_BG_INODE_ZEROED)) != 0);
+ KASSERT(!E2FS_HAS_GD_CSUM(fs) ||
+ (fs->e2fs_gd[ino_to_cg(fs, ino)].ext2bgd_flags &
+ h2fs16(E2FS_BG_INODE_ZEROED)) != 0);
/* check for already used inode; makes sense only for ZEROED itable */
if (__predict_false(ip->i_e2fs_mode && ip->i_e2fs_nlink != 0)) {
@@ -1156,14 +1212,17 @@ ext2fs_newvnode(struct mount *mp, struct
/* Initialize extra_isize according to what is set in superblock */
if (EXT2F_HAS_ROCOMPAT_FEATURE(ip->i_e2fs, EXT2F_ROCOMPAT_EXTRA_ISIZE)
&& EXT2_DINODE_SIZE(ip->i_e2fs) > EXT2_REV0_DINODE_SIZE) {
- ip->i_din.e2fs_din->e2di_extra_isize = ip->i_e2fs->e2fs.e4fs_want_extra_isize;
+ ip->i_din.e2fs_din->e2di_extra_isize =
+ ip->i_e2fs->e2fs.e4fs_want_extra_isize;
}
/* Set create time if possible */
- if (EXT2_DINODE_FITS(ip->i_din.e2fs_din, e2di_crtime, EXT2_DINODE_SIZE(ip->i_e2fs))) {
+ if (EXT2_DINODE_FITS(ip->i_din.e2fs_din, e2di_crtime,
+ EXT2_DINODE_SIZE(ip->i_e2fs))) {
struct timespec now;
vfs_timestamp(&now);
- EXT2_DINODE_TIME_SET(&now, ip->i_din.e2fs_din, e2di_crtime, EXT2_DINODE_SIZE(ip->i_e2fs));
+ EXT2_DINODE_TIME_SET(&now, ip->i_din.e2fs_din, e2di_crtime,
+ EXT2_DINODE_SIZE(ip->i_e2fs));
}
/* Initialize the vnode from the inode. */
@@ -1277,7 +1336,7 @@ ext2fs_cgupdate(struct ufsmount *mp, int
1 /* superblock */ + i), fs->e2fs_bsize, 0, 0);
e2fs_cgsave(&fs->e2fs_gd[
i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
- (struct ext2_gd *)bp->b_data, fs->e2fs_bsize);
+ bp->b_data, fs->e2fs_bsize, fs->e2fs_group_desc_shift);
if (waitfor == MNT_WAIT)
error = bwrite(bp);
else
@@ -1305,7 +1364,8 @@ ext2fs_sbfill(struct m_ext2fs *m_fs, int
if (fs->e2fs_magic != E2FS_MAGIC)
return EINVAL;
if (fs->e2fs_rev > E2FS_REV1) {
- printf("ext2fs: unsupported revision number: %x\n", fs->e2fs_rev);
+ printf("ext2fs: unsupported revision number: %#x\n",
+ fs->e2fs_rev);
return EINVAL;
}
if (fs->e2fs_log_bsize > 2) {
@@ -1348,7 +1408,17 @@ ext2fs_sbfill(struct m_ext2fs *m_fs, int
m_fs->e2fs_qbmask = m_fs->e2fs_bsize - 1;
m_fs->e2fs_bmask = ~m_fs->e2fs_qbmask;
- if ((u32 = m_fs->e2fs_bsize / sizeof(struct ext2_gd)) == 0) {
+ if (!(fs->e2fs_features_incompat & EXT2F_INCOMPAT_64BIT) ||
+ (fs->e2fs_rev == E2FS_REV0))
+ m_fs->e2fs_group_desc_shift = 5;
+ else {
+ for (m_fs->e2fs_group_desc_shift = 0;
+ (1 << m_fs->e2fs_group_desc_shift)
+ < fs->e3fs_desc_size;
+ m_fs->e2fs_group_desc_shift++);
+ }
+
+ if ((u32 = (m_fs->e2fs_bsize >> m_fs->e2fs_group_desc_shift)) == 0) {
/* Unlikely to happen */
printf("ext2fs: invalid block size\n");
return EINVAL;
@@ -1379,7 +1449,8 @@ ext2fs_sbfill(struct m_ext2fs *m_fs, int
u32 = fs->e2fs_features_incompat & ~EXT2F_INCOMPAT_SUPP;
if (u32) {
snprintb(buf, sizeof(buf), EXT2F_INCOMPAT_BITS, u32);
- printf("ext2fs: unsupported incompat features: %s\n", buf);
+ printf("ext2fs: unsupported incompat features: %s\n",
+ buf);
#ifndef EXT2_IGNORE_INCOMPAT_FEATURES
return EINVAL;
#endif
@@ -1401,3 +1472,4 @@ ext2fs_sbfill(struct m_ext2fs *m_fs, int
return 0;
}
+