ext2fs: Add large sectorsize disks support

The ext2fs does not support disks with sectorsize more 512 bytes.
The main issue is in reading/writing superblock, which is not aligned
with 4k value. Reimplement the superblock reading logic to make it
indifferent to disk logical sector size. The logical sector size
more then page size is not supported, like it is doing on Linux side.

PR:             271105
Reported by:    k(at)vodka.home.kg
Reviewed by:    pfg
MFC after:      2 week
Differential Revision:  https://reviews.freebsd.org/D40047
This commit is contained in:
Fedor Uporov 2023-05-08 19:14:02 +03:00
parent 525dd4acaa
commit 50be18cc77
2 changed files with 30 additions and 24 deletions

View File

@ -111,7 +111,7 @@ static int ext2_check_sb_compat(struct ext2fs *es, struct cdev *dev,
static int ext2_compute_sb_data(struct vnode * devvp,
struct ext2fs * es, struct m_ext2fs * fs);
static const char *ext2_opts[] = { "acls", "async", "noatime", "noclusterr",
static const char *ext2_opts[] = { "acls", "async", "noatime", "noclusterr",
"noclusterw", "noexec", "export", "force", "from", "multilabel",
"suiddir", "nosymfollow", "sync", "union", NULL };
@ -343,7 +343,7 @@ ext2_cg_location(struct m_ext2fs *fs, int number)
* Godmar thinks: if the blocksize is greater than 1024, then
* the superblock is logically part of block zero.
*/
logical_sb = fs->e2fs_bsize > SBSIZE ? 0 : 1;
logical_sb = fs->e2fs_bsize > SBLOCKSIZE ? 0 : 1;
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) ||
number < le32toh(fs->e2fs->e3fs_first_meta_bg))
@ -760,9 +760,9 @@ ext2_reload(struct mount *mp, struct thread *td)
* Step 2: re-read superblock from disk.
* constants have been adjusted for ext2
*/
if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
if ((error = bread(devvp, SBLOCK, SBLOCKBLKSIZE, NOCRED, &bp)) != 0)
return (error);
es = (struct ext2fs *)bp->b_data;
es = (struct ext2fs *)((char *)bp->b_data + SBLOCKOFFSET);
if (ext2_check_sb_compat(es, devvp->v_rdev, 0) != 0) {
brelse(bp);
return (EIO); /* XXX needs translation */
@ -774,10 +774,7 @@ ext2_reload(struct mount *mp, struct thread *td)
brelse(bp);
return (error);
}
#ifdef UNKLAR
if (fs->fs_sbsize < SBSIZE)
bp->b_flags |= B_INVAL;
#endif
brelse(bp);
/*
@ -852,6 +849,9 @@ ext2_mountfs(struct vnode *devvp, struct mount *mp)
int32_t *lp;
int32_t e2fs_maxcontig;
bp = NULL;
ump = NULL;
ronly = vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0);
/* XXX: use VOP_ACESS to check FS perms */
g_topology_lock();
@ -861,13 +861,16 @@ ext2_mountfs(struct vnode *devvp, struct mount *mp)
if (error)
return (error);
/* XXX: should we check for some sectorsize or 512 instead? */
if (((SBSIZE % cp->provider->sectorsize) != 0) ||
(SBSIZE < cp->provider->sectorsize)) {
g_topology_lock();
g_vfs_close(cp);
g_topology_unlock();
return (EINVAL);
if (PAGE_SIZE != SBLOCKBLKSIZE) {
printf("WARNING: Unsupported page size %d\n", PAGE_SIZE);
error = EINVAL;
goto out;
}
if (cp->provider->sectorsize > PAGE_SIZE) {
printf("WARNING: Device sectorsize(%d) is more than %d\n",
cp->provider->sectorsize, PAGE_SIZE);
error = EINVAL;
goto out;
}
bo = &devvp->v_bufobj;
@ -877,12 +880,9 @@ ext2_mountfs(struct vnode *devvp, struct mount *mp)
mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max;
if (mp->mnt_iosize_max > maxphys)
mp->mnt_iosize_max = maxphys;
bp = NULL;
ump = NULL;
if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0)
if ((error = bread(devvp, SBLOCK, SBLOCKBLKSIZE, NOCRED, &bp)) != 0)
goto out;
es = (struct ext2fs *)bp->b_data;
es = (struct ext2fs *)((char *)bp->b_data + SBLOCKOFFSET);
if (ext2_check_sb_compat(es, dev, ronly) != 0) {
error = EINVAL; /* XXX needs translation */
goto out;
@ -1377,8 +1377,12 @@ ext2_sbupdate(struct ext2mount *mp, int waitfor)
if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM))
ext2_sb_csum_set(fs);
bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0, 0);
bcopy((caddr_t)es, bp->b_data, (u_int)sizeof(struct ext2fs));
error = bread(mp->um_devvp, SBLOCK, SBLOCKBLKSIZE, NOCRED, &bp);
if (error != 0)
return (error);
memcpy((char *)bp->b_data + SBLOCKOFFSET, (caddr_t)es,
(u_int)sizeof(struct ext2fs));
if (waitfor == MNT_WAIT)
error = bwrite(bp);
else

View File

@ -56,8 +56,10 @@
* The first boot and super blocks are given in absolute disk addresses.
* The byte-offset forms are preferred, as they don't imply a sector size.
*/
#define SBSIZE 1024
#define SBLOCK 2
#define SBLOCK 0
#define SBLOCKSIZE 1024
#define SBLOCKOFFSET 1024
#define SBLOCKBLKSIZE 4096
/*
* The path name on which the file system is mounted is maintained