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
59f27534cc
commit
0a2aa6292e
@ -755,49 +755,68 @@ ext2_hashalloc(struct inode *ip, int cg, long pref, int size,
|
||||
}
|
||||
|
||||
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);
|
||||
metagroup = cg / gd_per_block;
|
||||
first = metagroup * gd_per_block;
|
||||
last = first + gd_per_block - 1;
|
||||
if (!ext2_cg_has_sb(fs, cg))
|
||||
return (0);
|
||||
|
||||
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) ||
|
||||
metagroup < fs->e2fs->e3fs_first_meta_bg) {
|
||||
if (!ext2_cg_has_sb(fs, cg))
|
||||
return (0);
|
||||
if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG))
|
||||
return (fs->e2fs->e3fs_first_meta_bg);
|
||||
return (fs->e2fs_gdbcount);
|
||||
}
|
||||
if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG))
|
||||
return (fs->e2fs->e3fs_first_meta_bg);
|
||||
|
||||
return ((fs->e2fs_gcount + EXT2_DESCS_PER_BLOCK(fs) - 1) /
|
||||
EXT2_DESCS_PER_BLOCK(fs));
|
||||
}
|
||||
|
||||
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)
|
||||
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
|
||||
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);
|
||||
num = ext2_cg_has_sb(fs, cg);
|
||||
number = ext2_cg_has_sb(fs, cg);
|
||||
|
||||
if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) ||
|
||||
cg < fs->e2fs->e3fs_first_meta_bg * gd_per_block) {
|
||||
if (num) {
|
||||
num += ext2_cg_num_gdb(fs, cg);
|
||||
num += fs->e2fs->e2fs_reserved_ngdb;
|
||||
cg < fs->e2fs->e3fs_first_meta_bg * EXT2_DESCS_PER_BLOCK(fs)) {
|
||||
if (number) {
|
||||
number += ext2_cg_number_gdb(fs, cg);
|
||||
number += fs->e2fs->e2fs_reserved_ngdb;
|
||||
}
|
||||
} else {
|
||||
num += ext2_cg_num_gdb(fs, cg);
|
||||
number += ext2_cg_number_gdb(fs, cg);
|
||||
}
|
||||
|
||||
return (num);
|
||||
|
||||
return (number);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
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);
|
||||
|
||||
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)
|
||||
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. */
|
||||
tmp = e2fs_gd_get_b_bitmap(&fs->e2fs_gd[cg]);
|
||||
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);
|
||||
|
||||
tmp = e2fs_gd_get_i_bitmap(&fs->e2fs_gd[cg]);
|
||||
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);
|
||||
|
||||
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]) +
|
||||
fs->e2fs->e2fs_ipg / inodes_per_block ) {
|
||||
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);
|
||||
tmp++;
|
||||
}
|
||||
|
@ -154,7 +154,8 @@ ext2_mount(struct mount *mp)
|
||||
if (mp->mnt_flag & MNT_FORCE)
|
||||
flags |= FORCECLOSE;
|
||||
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;
|
||||
ext2_sbupdate(ump, MNT_WAIT);
|
||||
}
|
||||
@ -318,6 +319,36 @@ ext2_check_sb_compat(struct ext2fs *es, struct cdev *dev, int ronly)
|
||||
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
|
||||
* 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 i, j;
|
||||
int logic_sb_block = 1; /* XXX for now */
|
||||
struct buf *bp;
|
||||
uint32_t e2fs_descpb, e2fs_gdbcount_alloc;
|
||||
|
||||
@ -385,6 +415,12 @@ compute_sb_data(struct vnode *devvp, struct ext2fs *es,
|
||||
es->e3fs_desc_size);
|
||||
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_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 *
|
||||
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++) {
|
||||
error = bread(devvp,
|
||||
fsbtodb(fs, logic_sb_block + i + 1),
|
||||
fsbtodb(fs, cg_location(fs, i)),
|
||||
fs->e2fs_bsize, NOCRED, &bp);
|
||||
if (error) {
|
||||
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++) {
|
||||
bp = getblk(mp->um_devvp, fsbtodb(fs,
|
||||
fs->e2fs->e2fs_first_dblock +
|
||||
1 /* superblock */ + i), fs->e2fs_bsize, 0, 0, 0);
|
||||
cg_location(fs, i)),
|
||||
fs->e2fs_bsize, 0, 0, 0);
|
||||
if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_64BIT)) {
|
||||
memcpy(bp->b_data, &fs->e2fs_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_EXTRA_ISIZE)
|
||||
#define EXT2F_INCOMPAT_SUPP (EXT2F_INCOMPAT_FTYPE | \
|
||||
EXT2F_INCOMPAT_META_BG | \
|
||||
EXT2F_INCOMPAT_EXTENTS | \
|
||||
EXT2F_INCOMPAT_64BIT | \
|
||||
EXT2F_INCOMPAT_CSUM_SEED)
|
||||
#define EXT4F_RO_INCOMPAT_SUPP (EXT2F_INCOMPAT_RECOVER | \
|
||||
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
|
||||
* 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
|
||||
*/
|
||||
#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_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user