Add flex_bg/meta_bg features RW support.
Reviewed by: pfg MFC after: 6 months Differential Revision: https://reviews.freebsd.org/D13964
This commit is contained in:
parent
595109196a
commit
c0f16c65cd
@ -755,49 +755,68 @@ ext2_hashalloc(struct inode *ip, int cg, long pref, int size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long
|
static unsigned long
|
||||||
ext2_cg_num_gdb(struct m_ext2fs *fs, int cg)
|
ext2_cg_number_gdb_nometa(struct m_ext2fs *fs, int cg)
|
||||||
{
|
{
|
||||||
int gd_per_block, metagroup, first, last;
|
|
||||||
|
|
||||||
gd_per_block = fs->e2fs_bsize / sizeof(struct ext2_gd);
|
if (!ext2_cg_has_sb(fs, cg))
|
||||||
metagroup = cg / gd_per_block;
|
return (0);
|
||||||
first = metagroup * gd_per_block;
|
|
||||||
last = first + gd_per_block - 1;
|
|
||||||
|
|
||||||
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) ||
|
if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG))
|
||||||
metagroup < fs->e2fs->e3fs_first_meta_bg) {
|
return (fs->e2fs->e3fs_first_meta_bg);
|
||||||
if (!ext2_cg_has_sb(fs, cg))
|
|
||||||
return (0);
|
return ((fs->e2fs_gcount + EXT2_DESCS_PER_BLOCK(fs) - 1) /
|
||||||
if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG))
|
EXT2_DESCS_PER_BLOCK(fs));
|
||||||
return (fs->e2fs->e3fs_first_meta_bg);
|
}
|
||||||
return (fs->e2fs_gdbcount);
|
|
||||||
}
|
static unsigned long
|
||||||
|
ext2_cg_number_gdb_meta(struct m_ext2fs *fs, int cg)
|
||||||
|
{
|
||||||
|
unsigned long metagroup;
|
||||||
|
int first, last;
|
||||||
|
|
||||||
|
metagroup = cg / EXT2_DESCS_PER_BLOCK(fs);
|
||||||
|
first = metagroup * EXT2_DESCS_PER_BLOCK(fs);
|
||||||
|
last = first + EXT2_DESCS_PER_BLOCK(fs) - 1;
|
||||||
|
|
||||||
if (cg == first || cg == first + 1 || cg == last)
|
if (cg == first || cg == first + 1 || cg == last)
|
||||||
return (1);
|
return (1);
|
||||||
return (0);
|
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long
|
||||||
|
ext2_cg_number_gdb(struct m_ext2fs *fs, int cg)
|
||||||
|
{
|
||||||
|
unsigned long first_meta_bg, metagroup;
|
||||||
|
|
||||||
|
first_meta_bg = fs->e2fs->e3fs_first_meta_bg;
|
||||||
|
metagroup = cg / EXT2_DESCS_PER_BLOCK(fs);
|
||||||
|
|
||||||
|
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) ||
|
||||||
|
metagroup < first_meta_bg)
|
||||||
|
return (ext2_cg_number_gdb_nometa(fs, cg));
|
||||||
|
|
||||||
|
return ext2_cg_number_gdb_meta(fs, cg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ext2_num_base_meta_blocks(struct m_ext2fs *fs, int cg)
|
ext2_number_base_meta_blocks(struct m_ext2fs *fs, int cg)
|
||||||
{
|
{
|
||||||
int num, gd_per_block;
|
int number;
|
||||||
|
|
||||||
gd_per_block = fs->e2fs_bsize / sizeof(struct ext2_gd);
|
number = ext2_cg_has_sb(fs, cg);
|
||||||
num = ext2_cg_has_sb(fs, cg);
|
|
||||||
|
|
||||||
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) ||
|
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) ||
|
||||||
cg < fs->e2fs->e3fs_first_meta_bg * gd_per_block) {
|
cg < fs->e2fs->e3fs_first_meta_bg * EXT2_DESCS_PER_BLOCK(fs)) {
|
||||||
if (num) {
|
if (number) {
|
||||||
num += ext2_cg_num_gdb(fs, cg);
|
number += ext2_cg_number_gdb(fs, cg);
|
||||||
num += fs->e2fs->e2fs_reserved_ngdb;
|
number += fs->e2fs->e2fs_reserved_ngdb;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
num += ext2_cg_num_gdb(fs, cg);
|
number += ext2_cg_number_gdb(fs, cg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (num);
|
return (number);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -814,6 +833,20 @@ ext2_mark_bitmap_end(int start_bit, int end_bit, char *bitmap)
|
|||||||
memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3);
|
memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ext2_get_group_number(struct m_ext2fs *fs, e4fs_daddr_t block)
|
||||||
|
{
|
||||||
|
|
||||||
|
return ((block - fs->e2fs->e2fs_first_dblock) / fs->e2fs_bsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ext2_block_in_group(struct m_ext2fs *fs, e4fs_daddr_t block, int cg)
|
||||||
|
{
|
||||||
|
|
||||||
|
return ((ext2_get_group_number(fs, block) == cg) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ext2_cg_block_bitmap_init(struct m_ext2fs *fs, int cg, struct buf *bp)
|
ext2_cg_block_bitmap_init(struct m_ext2fs *fs, int cg, struct buf *bp)
|
||||||
{
|
{
|
||||||
@ -825,7 +858,7 @@ ext2_cg_block_bitmap_init(struct m_ext2fs *fs, int cg, struct buf *bp)
|
|||||||
|
|
||||||
memset(bp->b_data, 0, fs->e2fs_bsize);
|
memset(bp->b_data, 0, fs->e2fs_bsize);
|
||||||
|
|
||||||
bit_max = ext2_num_base_meta_blocks(fs, cg);
|
bit_max = ext2_number_base_meta_blocks(fs, cg);
|
||||||
if ((bit_max >> 3) >= fs->e2fs_bsize)
|
if ((bit_max >> 3) >= fs->e2fs_bsize)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
@ -837,12 +870,12 @@ ext2_cg_block_bitmap_init(struct m_ext2fs *fs, int cg, struct buf *bp)
|
|||||||
/* Set bits for block and inode bitmaps, and inode table. */
|
/* Set bits for block and inode bitmaps, and inode table. */
|
||||||
tmp = e2fs_gd_get_b_bitmap(&fs->e2fs_gd[cg]);
|
tmp = e2fs_gd_get_b_bitmap(&fs->e2fs_gd[cg]);
|
||||||
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) ||
|
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) ||
|
||||||
cg == dtogd(fs, tmp))
|
ext2_block_in_group(fs, tmp, cg))
|
||||||
setbit(bp->b_data, tmp - start);
|
setbit(bp->b_data, tmp - start);
|
||||||
|
|
||||||
tmp = e2fs_gd_get_i_bitmap(&fs->e2fs_gd[cg]);
|
tmp = e2fs_gd_get_i_bitmap(&fs->e2fs_gd[cg]);
|
||||||
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) ||
|
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) ||
|
||||||
cg == dtogd(fs, tmp))
|
ext2_block_in_group(fs, tmp, cg))
|
||||||
setbit(bp->b_data, tmp - start);
|
setbit(bp->b_data, tmp - start);
|
||||||
|
|
||||||
tmp = e2fs_gd_get_i_tables(&fs->e2fs_gd[cg]);
|
tmp = e2fs_gd_get_i_tables(&fs->e2fs_gd[cg]);
|
||||||
@ -850,7 +883,7 @@ ext2_cg_block_bitmap_init(struct m_ext2fs *fs, int cg, struct buf *bp)
|
|||||||
while( tmp < e2fs_gd_get_i_tables(&fs->e2fs_gd[cg]) +
|
while( tmp < e2fs_gd_get_i_tables(&fs->e2fs_gd[cg]) +
|
||||||
fs->e2fs->e2fs_ipg / inodes_per_block ) {
|
fs->e2fs->e2fs_ipg / inodes_per_block ) {
|
||||||
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) ||
|
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG) ||
|
||||||
cg == dtogd(fs, tmp))
|
ext2_block_in_group(fs, tmp, cg))
|
||||||
setbit(bp->b_data, tmp - start);
|
setbit(bp->b_data, tmp - start);
|
||||||
tmp++;
|
tmp++;
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,8 @@ ext2_mount(struct mount *mp)
|
|||||||
if (mp->mnt_flag & MNT_FORCE)
|
if (mp->mnt_flag & MNT_FORCE)
|
||||||
flags |= FORCECLOSE;
|
flags |= FORCECLOSE;
|
||||||
error = ext2_flushfiles(mp, flags, td);
|
error = ext2_flushfiles(mp, flags, td);
|
||||||
if (error == 0 && fs->e2fs_wasvalid && ext2_cgupdate(ump, MNT_WAIT) == 0) {
|
if (error == 0 && fs->e2fs_wasvalid &&
|
||||||
|
ext2_cgupdate(ump, MNT_WAIT) == 0) {
|
||||||
fs->e2fs->e2fs_state |= E2FS_ISCLEAN;
|
fs->e2fs->e2fs_state |= E2FS_ISCLEAN;
|
||||||
ext2_sbupdate(ump, MNT_WAIT);
|
ext2_sbupdate(ump, MNT_WAIT);
|
||||||
}
|
}
|
||||||
@ -318,6 +319,36 @@ ext2_check_sb_compat(struct ext2fs *es, struct cdev *dev, int ronly)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static e4fs_daddr_t
|
||||||
|
cg_location(struct m_ext2fs *fs, int number)
|
||||||
|
{
|
||||||
|
int cg, descpb, logical_sb, has_super = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adjust logical superblock block 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;
|
||||||
|
|
||||||
|
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) ||
|
||||||
|
number < fs->e2fs->e3fs_first_meta_bg)
|
||||||
|
return (logical_sb + number + 1);
|
||||||
|
|
||||||
|
if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT))
|
||||||
|
descpb = fs->e2fs_bsize / sizeof(struct ext2_gd);
|
||||||
|
else
|
||||||
|
descpb = fs->e2fs_bsize / E2FS_REV0_GD_SIZE;
|
||||||
|
|
||||||
|
cg = descpb * number;
|
||||||
|
|
||||||
|
if (ext2_cg_has_sb(fs, cg))
|
||||||
|
has_super = 1;
|
||||||
|
|
||||||
|
return (has_super + cg * (e4fs_daddr_t)EXT2_BLOCKS_PER_GROUP(fs) +
|
||||||
|
fs->e2fs->e2fs_first_dblock);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This computes the fields of the m_ext2fs structure from the
|
* This computes the fields of the m_ext2fs structure from the
|
||||||
* data in the ext2fs structure read in.
|
* data in the ext2fs structure read in.
|
||||||
@ -328,7 +359,6 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es,
|
|||||||
{
|
{
|
||||||
int g_count = 0, error;
|
int g_count = 0, error;
|
||||||
int i, j;
|
int i, j;
|
||||||
int logic_sb_block = 1; /* XXX for now */
|
|
||||||
struct buf *bp;
|
struct buf *bp;
|
||||||
uint32_t e2fs_descpb, e2fs_gdbcount_alloc;
|
uint32_t e2fs_descpb, e2fs_gdbcount_alloc;
|
||||||
|
|
||||||
@ -385,6 +415,12 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es,
|
|||||||
es->e3fs_desc_size);
|
es->e3fs_desc_size);
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
}
|
}
|
||||||
|
/* Check for group size */
|
||||||
|
if (fs->e2fs_bpg != fs->e2fs_bsize * 8) {
|
||||||
|
printf("ext2fs: non-standard group size unsupported %d\n",
|
||||||
|
fs->e2fs_bpg);
|
||||||
|
return (EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs);
|
fs->e2fs_ipb = fs->e2fs_bsize / EXT2_INODE_SIZE(fs);
|
||||||
fs->e2fs_itpg = fs->e2fs_ipg / fs->e2fs_ipb;
|
fs->e2fs_itpg = fs->e2fs_ipg / fs->e2fs_ipb;
|
||||||
@ -405,16 +441,9 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es,
|
|||||||
fs->e2fs_contigdirs = malloc(fs->e2fs_gcount *
|
fs->e2fs_contigdirs = malloc(fs->e2fs_gcount *
|
||||||
sizeof(*fs->e2fs_contigdirs), M_EXT2MNT, M_WAITOK | M_ZERO);
|
sizeof(*fs->e2fs_contigdirs), M_EXT2MNT, M_WAITOK | M_ZERO);
|
||||||
|
|
||||||
/*
|
|
||||||
* Adjust logic_sb_block.
|
|
||||||
* Godmar thinks: if the blocksize is greater than 1024, then
|
|
||||||
* the superblock is logically part of block zero.
|
|
||||||
*/
|
|
||||||
if (fs->e2fs_bsize > SBSIZE)
|
|
||||||
logic_sb_block = 0;
|
|
||||||
for (i = 0; i < fs->e2fs_gdbcount; i++) {
|
for (i = 0; i < fs->e2fs_gdbcount; i++) {
|
||||||
error = bread(devvp,
|
error = bread(devvp,
|
||||||
fsbtodb(fs, logic_sb_block + i + 1),
|
fsbtodb(fs, cg_location(fs, i)),
|
||||||
fs->e2fs_bsize, NOCRED, &bp);
|
fs->e2fs_bsize, NOCRED, &bp);
|
||||||
if (error) {
|
if (error) {
|
||||||
free(fs->e2fs_contigdirs, M_EXT2MNT);
|
free(fs->e2fs_contigdirs, M_EXT2MNT);
|
||||||
@ -1151,8 +1180,8 @@ ext2_cgupdate(struct ext2mount *mp, int waitfor)
|
|||||||
|
|
||||||
for (i = 0; i < fs->e2fs_gdbcount; i++) {
|
for (i = 0; i < fs->e2fs_gdbcount; i++) {
|
||||||
bp = getblk(mp->um_devvp, fsbtodb(fs,
|
bp = getblk(mp->um_devvp, fsbtodb(fs,
|
||||||
fs->e2fs->e2fs_first_dblock +
|
cg_location(fs, i)),
|
||||||
1 /* superblock */ + i), fs->e2fs_bsize, 0, 0, 0);
|
fs->e2fs_bsize, 0, 0, 0);
|
||||||
if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
|
if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
|
||||||
memcpy(bp->b_data, &fs->e2fs_gd[
|
memcpy(bp->b_data, &fs->e2fs_gd[
|
||||||
i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
|
i * fs->e2fs_bsize / sizeof(struct ext2_gd)],
|
||||||
|
@ -334,12 +334,12 @@ static const struct ext2_feature incompat[] = {
|
|||||||
EXT2F_ROCOMPAT_HUGE_FILE | \
|
EXT2F_ROCOMPAT_HUGE_FILE | \
|
||||||
EXT2F_ROCOMPAT_EXTRA_ISIZE)
|
EXT2F_ROCOMPAT_EXTRA_ISIZE)
|
||||||
#define EXT2F_INCOMPAT_SUPP (EXT2F_INCOMPAT_FTYPE | \
|
#define EXT2F_INCOMPAT_SUPP (EXT2F_INCOMPAT_FTYPE | \
|
||||||
|
EXT2F_INCOMPAT_META_BG | \
|
||||||
EXT2F_INCOMPAT_EXTENTS | \
|
EXT2F_INCOMPAT_EXTENTS | \
|
||||||
EXT2F_INCOMPAT_64BIT | \
|
EXT2F_INCOMPAT_64BIT | \
|
||||||
EXT2F_INCOMPAT_CSUM_SEED)
|
|
||||||
#define EXT4F_RO_INCOMPAT_SUPP (EXT2F_INCOMPAT_RECOVER | \
|
|
||||||
EXT2F_INCOMPAT_FLEX_BG | \
|
EXT2F_INCOMPAT_FLEX_BG | \
|
||||||
EXT2F_INCOMPAT_META_BG )
|
EXT2F_INCOMPAT_CSUM_SEED)
|
||||||
|
#define EXT4F_RO_INCOMPAT_SUPP EXT2F_INCOMPAT_RECOVER
|
||||||
|
|
||||||
/* Assume that user mode programs are passing in an ext2fs superblock, not
|
/* Assume that user mode programs are passing in an ext2fs superblock, not
|
||||||
* a kernel struct super_block. This will allow us to call the feature-test
|
* a kernel struct super_block. This will allow us to call the feature-test
|
||||||
@ -423,5 +423,8 @@ struct ext2_gd {
|
|||||||
* Macro-instructions used to manage group descriptors
|
* Macro-instructions used to manage group descriptors
|
||||||
*/
|
*/
|
||||||
#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->e2fs_bpg)
|
#define EXT2_BLOCKS_PER_GROUP(s) (EXT2_SB(s)->e2fs_bpg)
|
||||||
|
#define EXT2_DESCS_PER_BLOCK(s) (EXT2_HAS_INCOMPAT_FEATURE((s), \
|
||||||
|
EXT2F_INCOMPAT_64BIT) ? ((s)->e2fs_bsize / sizeof(struct ext2_gd)) : \
|
||||||
|
((s)->e2fs_bsize / E2FS_REV0_GD_SIZE))
|
||||||
|
|
||||||
#endif /* !_FS_EXT2FS_EXT2FS_H_ */
|
#endif /* !_FS_EXT2FS_EXT2FS_H_ */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user