Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/ext2fs/ext2_alloc.c
Show First 20 Lines • Show All 896 Lines • ▼ Show 20 Lines | ext2_mark_bitmap_end(fs->e2fs->e2fs_bpg, fs->e2fs_bsize * 8, | ||||
bp->b_data); | bp->b_data); | ||||
/* Clean the flag */ | /* Clean the flag */ | ||||
fs->e2fs_gd[cg].ext4bgd_flags &= ~EXT2_BG_BLOCK_UNINIT; | fs->e2fs_gd[cg].ext4bgd_flags &= ~EXT2_BG_BLOCK_UNINIT; | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | |||||
ext2_b_bitmap_validate(struct m_ext2fs *fs, struct buf *bp, int cg) | |||||
{ | |||||
struct ext2_gd *gd; | |||||
uint64_t group_first_block; | |||||
unsigned int offset, max_bit; | |||||
if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG)) { | |||||
/* | /* | ||||
* It is not possible to check block bitmap in case of this feature, | |||||
* because the inode and block bitmaps and inode table | |||||
* blocks may not be in the group at all. | |||||
* So, skip check in this case. | |||||
*/ | |||||
return (0); | |||||
} | |||||
gd = &fs->e2fs_gd[cg]; | |||||
max_bit = fs->e2fs_fpg; | |||||
group_first_block = ((uint64_t)cg) * fs->e2fs->e2fs_fpg + | |||||
fs->e2fs->e2fs_first_dblock; | |||||
/* Check block bitmap block number */ | |||||
offset = e2fs_gd_get_b_bitmap(gd) - group_first_block; | |||||
if (offset >= max_bit || !isset(bp->b_data, offset)) { | |||||
printf("ext2fs: bad block bitmap, group %d\n", cg); | |||||
return (EINVAL); | |||||
} | |||||
/* Check inode bitmap block number */ | |||||
offset = e2fs_gd_get_i_bitmap(gd) - group_first_block; | |||||
if (offset >= max_bit || !isset(bp->b_data, offset)) { | |||||
printf("ext2fs: bad inode bitmap, group %d\n", cg); | |||||
return (EINVAL); | |||||
} | |||||
/* Check inode table */ | |||||
offset = e2fs_gd_get_i_tables(gd) - group_first_block; | |||||
if (offset >= max_bit || offset + fs->e2fs_itpg >= max_bit) { | |||||
printf("ext2fs: bad inode table, group %d\n", cg); | |||||
return (EINVAL); | |||||
} | |||||
return (0); | |||||
} | |||||
/* | |||||
* Determine whether a block can be allocated. | * Determine whether a block can be allocated. | ||||
* | * | ||||
* Check to see if a block of the appropriate size is available, | * Check to see if a block of the appropriate size is available, | ||||
* and if it is, allocate it. | * and if it is, allocate it. | ||||
*/ | */ | ||||
static daddr_t | static daddr_t | ||||
ext2_alloccg(struct inode *ip, int cg, daddr_t bpref, int size) | ext2_alloccg(struct inode *ip, int cg, daddr_t bpref, int size) | ||||
{ | { | ||||
struct m_ext2fs *fs; | struct m_ext2fs *fs; | ||||
struct buf *bp; | struct buf *bp; | ||||
struct ext2mount *ump; | struct ext2mount *ump; | ||||
daddr_t bno, runstart, runlen; | daddr_t bno, runstart, runlen; | ||||
int bit, loc, end, error, start; | int bit, loc, end, error, start; | ||||
char *bbp; | char *bbp; | ||||
/* XXX ondisk32 */ | /* XXX ondisk32 */ | ||||
fs = ip->i_e2fs; | fs = ip->i_e2fs; | ||||
ump = ip->i_ump; | ump = ip->i_ump; | ||||
if (e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) == 0) | if (e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) == 0) | ||||
return (0); | return (0); | ||||
EXT2_UNLOCK(ump); | EXT2_UNLOCK(ump); | ||||
error = bread(ip->i_devvp, fsbtodb(fs, | error = bread(ip->i_devvp, fsbtodb(fs, | ||||
e2fs_gd_get_b_bitmap(&fs->e2fs_gd[cg])), | e2fs_gd_get_b_bitmap(&fs->e2fs_gd[cg])), | ||||
(int)fs->e2fs_bsize, NOCRED, &bp); | (int)fs->e2fs_bsize, NOCRED, &bp); | ||||
if (error) { | if (error) | ||||
brelse(bp); | goto fail; | ||||
EXT2_LOCK(ump); | |||||
return (0); | |||||
} | |||||
if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM) || | if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM) || | ||||
EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM)) { | EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_METADATA_CKSUM)) { | ||||
error = ext2_cg_block_bitmap_init(fs, cg, bp); | error = ext2_cg_block_bitmap_init(fs, cg, bp); | ||||
if (error) { | if (error) | ||||
brelse(bp); | goto fail; | ||||
EXT2_LOCK(ump); | |||||
return (0); | |||||
} | |||||
ext2_gd_b_bitmap_csum_set(fs, cg, bp); | ext2_gd_b_bitmap_csum_set(fs, cg, bp); | ||||
} | } | ||||
error = ext2_gd_b_bitmap_csum_verify(fs, cg, bp); | error = ext2_gd_b_bitmap_csum_verify(fs, cg, bp); | ||||
if (error) { | if (error) | ||||
brelse(bp); | goto fail; | ||||
EXT2_LOCK(ump); | |||||
return (0); | error = ext2_b_bitmap_validate(fs,bp, cg); | ||||
} | if (error) | ||||
if (e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) == 0) { | goto fail; | ||||
/* | /* | ||||
* Another thread allocated the last block in this | * Check, that another thread did not not allocate the last block in this | ||||
* group while we were waiting for the buffer. | * group while we were waiting for the buffer. | ||||
*/ | */ | ||||
brelse(bp); | if (e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) == 0) | ||||
EXT2_LOCK(ump); | goto fail; | ||||
return (0); | |||||
} | |||||
bbp = (char *)bp->b_data; | bbp = (char *)bp->b_data; | ||||
if (dtog(fs, bpref) != cg) | if (dtog(fs, bpref) != cg) | ||||
bpref = 0; | bpref = 0; | ||||
if (bpref != 0) { | if (bpref != 0) { | ||||
bpref = dtogd(fs, bpref); | bpref = dtogd(fs, bpref); | ||||
/* | /* | ||||
* if the requested block is available, use it | * if the requested block is available, use it | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | for (loc = start; loc < end; loc++) { | ||||
} | } | ||||
} | } | ||||
if (start != 0) { | if (start != 0) { | ||||
end = start; | end = start; | ||||
start = 0; | start = 0; | ||||
goto retry; | goto retry; | ||||
} | } | ||||
bno = ext2_mapsearch(fs, bbp, bpref); | bno = ext2_mapsearch(fs, bbp, bpref); | ||||
if (bno < 0) { | if (bno < 0) | ||||
brelse(bp); | goto fail; | ||||
EXT2_LOCK(ump); | |||||
return (0); | |||||
} | |||||
gotit: | gotit: | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
if (isset(bbp, bno)) { | if (isset(bbp, bno)) { | ||||
printf("ext2fs_alloccgblk: cg=%d bno=%jd fs=%s\n", | printf("ext2fs_alloccgblk: cg=%d bno=%jd fs=%s\n", | ||||
cg, (intmax_t)bno, fs->e2fs_fsmnt); | cg, (intmax_t)bno, fs->e2fs_fsmnt); | ||||
panic("ext2fs_alloccg: dup alloc"); | panic("ext2fs_alloccg: dup alloc"); | ||||
} | } | ||||
#endif | #endif | ||||
setbit(bbp, bno); | setbit(bbp, bno); | ||||
EXT2_LOCK(ump); | EXT2_LOCK(ump); | ||||
ext2_clusteracct(fs, bbp, cg, bno, -1); | ext2_clusteracct(fs, bbp, cg, bno, -1); | ||||
fs->e2fs_fbcount--; | fs->e2fs_fbcount--; | ||||
e2fs_gd_set_nbfree(&fs->e2fs_gd[cg], | e2fs_gd_set_nbfree(&fs->e2fs_gd[cg], | ||||
e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) - 1); | e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) - 1); | ||||
fs->e2fs_fmod = 1; | fs->e2fs_fmod = 1; | ||||
EXT2_UNLOCK(ump); | EXT2_UNLOCK(ump); | ||||
ext2_gd_b_bitmap_csum_set(fs, cg, bp); | ext2_gd_b_bitmap_csum_set(fs, cg, bp); | ||||
bdwrite(bp); | bdwrite(bp); | ||||
return (((uint64_t)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); | ||||
fail: | |||||
brelse(bp); | |||||
EXT2_LOCK(ump); | |||||
return (0); | |||||
} | } | ||||
/* | /* | ||||
* Determine whether a cluster can be allocated. | * Determine whether a cluster can be allocated. | ||||
*/ | */ | ||||
static daddr_t | static daddr_t | ||||
ext2_clusteralloc(struct inode *ip, int cg, daddr_t bpref, int len) | ext2_clusteralloc(struct inode *ip, int cg, daddr_t bpref, int len) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 424 Lines • Show Last 20 Lines |