Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/ext2fs/ext2_alloc.c
Show First 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | #ifdef INVARIANTS | ||||
if ((u_int)size > fs->e2fs_bsize || blkoff(fs, size) != 0) { | if ((u_int)size > fs->e2fs_bsize || blkoff(fs, size) != 0) { | ||||
vn_printf(ip->i_devvp, "bsize = %lu, size = %d, fs = %s\n", | vn_printf(ip->i_devvp, "bsize = %lu, size = %d, fs = %s\n", | ||||
(long unsigned int)fs->e2fs_bsize, size, fs->e2fs_fsmnt); | (long unsigned int)fs->e2fs_bsize, size, fs->e2fs_fsmnt); | ||||
panic("ext2_alloc: bad size"); | panic("ext2_alloc: bad size"); | ||||
} | } | ||||
if (cred == NOCRED) | if (cred == NOCRED) | ||||
panic("ext2_alloc: missing credential"); | panic("ext2_alloc: missing credential"); | ||||
#endif /* INVARIANTS */ | #endif /* INVARIANTS */ | ||||
if (size == fs->e2fs_bsize && fs->e2fs->e2fs_fbcount == 0) | if (size == fs->e2fs_bsize && fs->e2fs_fbcount == 0) | ||||
goto nospace; | goto nospace; | ||||
if (cred->cr_uid != 0 && | if (cred->cr_uid != 0 && | ||||
fs->e2fs->e2fs_fbcount < fs->e2fs->e2fs_rbcount) | fs->e2fs_fbcount < fs->e2fs_rbcount) | ||||
goto nospace; | goto nospace; | ||||
if (bpref >= fs->e2fs->e2fs_bcount) | if (bpref >= fs->e2fs_bcount) | ||||
bpref = 0; | bpref = 0; | ||||
if (bpref == 0) | if (bpref == 0) | ||||
cg = ino_to_cg(fs, ip->i_number); | cg = ino_to_cg(fs, ip->i_number); | ||||
else | else | ||||
cg = dtog(fs, bpref); | cg = dtog(fs, bpref); | ||||
bno = (daddr_t)ext2_hashalloc(ip, cg, bpref, fs->e2fs_bsize, | bno = (daddr_t)ext2_hashalloc(ip, cg, bpref, fs->e2fs_bsize, | ||||
ext2_alloccg); | ext2_alloccg); | ||||
if (bno > 0) { | if (bno > 0) { | ||||
▲ Show 20 Lines • Show All 327 Lines • ▼ Show 20 Lines | |||||
printf("ext2_valloc: allocated inode %d\n", ino); | printf("ext2_valloc: allocated inode %d\n", ino); | ||||
*/ | */ | ||||
return (0); | return (0); | ||||
noinodes: | noinodes: | ||||
EXT2_UNLOCK(ump); | EXT2_UNLOCK(ump); | ||||
ext2_fserr(fs, cred->cr_uid, "out of inodes"); | ext2_fserr(fs, cred->cr_uid, "out of inodes"); | ||||
uprintf("\n%s: create/symlink failed, no inodes free\n", fs->e2fs_fsmnt); | uprintf("\n%s: create/symlink failed, no inodes free\n", fs->e2fs_fsmnt); | ||||
return (ENOSPC); | return (ENOSPC); | ||||
} | } | ||||
pfg: How about making these inlines in a header, perhaps ext2fs.h? | |||||
Not Done Inline ActionsI tried to keep ext2fs.h more clean, but ok, will move it. fsu: I tried to keep ext2fs.h more clean, but ok, will move it. | |||||
Not Done Inline ActionsHmm.. perhaps the extents header, then? pfg: Hmm.. perhaps the extents header, then? | |||||
/* | /* | ||||
* 64-bit compatible getters and setters for struct ext2_gd from ext2fs.h | |||||
*/ | |||||
static uint64_t | |||||
e2fs_gd_get_b_bitmap(struct ext2_gd *gd) | |||||
{ | |||||
return (((uint64_t)(gd->ext4bgd_b_bitmap_hi) << 32) | | |||||
gd->ext2bgd_b_bitmap); | |||||
} | |||||
static uint64_t | |||||
e2fs_gd_get_i_bitmap(struct ext2_gd *gd) | |||||
{ | |||||
return (((uint64_t)(gd->ext4bgd_i_bitmap_hi) << 32) | | |||||
gd->ext2bgd_i_bitmap); | |||||
} | |||||
uint64_t | |||||
e2fs_gd_get_i_tables(struct ext2_gd *gd) | |||||
{ | |||||
return (((uint64_t)(gd->ext4bgd_i_tables_hi) << 32) | | |||||
gd->ext2bgd_i_tables); | |||||
} | |||||
static uint32_t | |||||
e2fs_gd_get_nbfree(struct ext2_gd *gd) | |||||
{ | |||||
return (((uint32_t)(gd->ext4bgd_nbfree_hi) << 16) | | |||||
gd->ext2bgd_nbfree); | |||||
} | |||||
static void | |||||
e2fs_gd_set_nbfree(struct ext2_gd *gd, uint32_t val) | |||||
{ | |||||
gd->ext2bgd_nbfree = val & 0xffff; | |||||
gd->ext4bgd_nbfree_hi = val >> 16; | |||||
} | |||||
static uint32_t | |||||
e2fs_gd_get_nifree(struct ext2_gd *gd) | |||||
{ | |||||
return (((uint32_t)(gd->ext4bgd_nifree_hi) << 16) | | |||||
gd->ext2bgd_nifree); | |||||
} | |||||
static void | |||||
e2fs_gd_set_nifree(struct ext2_gd *gd, uint32_t val) | |||||
{ | |||||
gd->ext2bgd_nifree = val & 0xffff; | |||||
gd->ext4bgd_nifree_hi = val >> 16; | |||||
} | |||||
uint32_t | |||||
e2fs_gd_get_ndirs(struct ext2_gd *gd) | |||||
{ | |||||
return (((uint32_t)(gd->ext4bgd_ndirs_hi) << 16) | | |||||
gd->ext2bgd_ndirs); | |||||
} | |||||
static void | |||||
e2fs_gd_set_ndirs(struct ext2_gd *gd, uint32_t val) | |||||
{ | |||||
gd->ext2bgd_ndirs = val & 0xffff; | |||||
gd->ext4bgd_ndirs_hi = val >> 16; | |||||
} | |||||
static uint32_t | |||||
e2fs_gd_get_i_unused(struct ext2_gd *gd) | |||||
{ | |||||
return (((uint32_t)(gd->ext4bgd_i_unused_hi) << 16) | | |||||
gd->ext4bgd_i_unused); | |||||
} | |||||
static void | |||||
e2fs_gd_set_i_unused(struct ext2_gd *gd, uint32_t val) | |||||
{ | |||||
gd->ext4bgd_i_unused = val & 0xffff; | |||||
gd->ext4bgd_i_unused_hi = val >> 16; | |||||
} | |||||
/* | |||||
* Find a cylinder to place a directory. | * Find a cylinder to place a directory. | ||||
* | * | ||||
* The policy implemented by this algorithm is to allocate a | * The policy implemented by this algorithm is to allocate a | ||||
* directory inode in the same cylinder group as its parent | * directory inode in the same cylinder group as its parent | ||||
* directory, but also to reserve space for its files inodes | * directory, but also to reserve space for its files inodes | ||||
* and data. Restrict the number of directories which may be | * and data. Restrict the number of directories which may be | ||||
* allocated one after another in the same cylinder group | * allocated one after another in the same cylinder group | ||||
* without intervening allocation of files. | * without intervening allocation of files. | ||||
* | * | ||||
* If we allocate a first level directory then force allocation | * If we allocate a first level directory then force allocation | ||||
* in another cylinder group. | * in another cylinder group. | ||||
* | * | ||||
*/ | */ | ||||
static u_long | static u_long | ||||
ext2_dirpref(struct inode *pip) | ext2_dirpref(struct inode *pip) | ||||
{ | { | ||||
struct m_ext2fs *fs; | struct m_ext2fs *fs; | ||||
int cg, prefcg, cgsize; | int cg, prefcg, cgsize; | ||||
u_int avgifree, avgbfree, avgndir, curdirsize; | uint64_t avgbfree, minbfree; | ||||
pfgUnsubmitted Not Done Inline ActionsBumping these serves no purpose: Bumping these is unecessary, unless you want to set them to uint32_t. pfg: Bumping these serves no purpose:
On line 485, avgbfree cannot overflow: e2fs_fbcount is… | |||||
fsuAuthorUnsubmitted Not Done Inline ActionsLittle bit incorrect. fsu: Little bit incorrect.
avgbfree same as minbfree can overflow because e2fs_fbcount is 64bit. | |||||
pfgUnsubmitted Not Done Inline ActionsOops.. dejavu moment here. pfg: Oops.. dejavu moment here.
The opengrok instant that I use never caught up with this change. | |||||
u_int minifree, minbfree, maxndir; | u_int avgifree, avgndir, curdirsize; | ||||
u_int minifree, maxndir; | |||||
u_int mincg, minndir; | u_int mincg, minndir; | ||||
u_int dirsize, maxcontigdirs; | u_int dirsize, maxcontigdirs; | ||||
mtx_assert(EXT2_MTX(pip->i_ump), MA_OWNED); | mtx_assert(EXT2_MTX(pip->i_ump), MA_OWNED); | ||||
fs = pip->i_e2fs; | fs = pip->i_e2fs; | ||||
avgifree = fs->e2fs->e2fs_ficount / fs->e2fs_gcount; | avgifree = fs->e2fs->e2fs_ficount / fs->e2fs_gcount; | ||||
avgbfree = fs->e2fs->e2fs_fbcount / fs->e2fs_gcount; | avgbfree = fs->e2fs_fbcount / fs->e2fs_gcount; | ||||
avgndir = fs->e2fs_total_dir / fs->e2fs_gcount; | avgndir = fs->e2fs_total_dir / fs->e2fs_gcount; | ||||
/* | /* | ||||
* Force allocation in another cg if creating a first level dir. | * Force allocation in another cg if creating a first level dir. | ||||
*/ | */ | ||||
ASSERT_VOP_LOCKED(ITOV(pip), "ext2fs_dirpref"); | ASSERT_VOP_LOCKED(ITOV(pip), "ext2fs_dirpref"); | ||||
if (ITOV(pip)->v_vflag & VV_ROOT) { | if (ITOV(pip)->v_vflag & VV_ROOT) { | ||||
prefcg = arc4random() % fs->e2fs_gcount; | prefcg = arc4random() % fs->e2fs_gcount; | ||||
mincg = prefcg; | mincg = prefcg; | ||||
minndir = fs->e2fs_ipg; | minndir = fs->e2fs_ipg; | ||||
for (cg = prefcg; cg < fs->e2fs_gcount; cg++) | for (cg = prefcg; cg < fs->e2fs_gcount; cg++) | ||||
if (fs->e2fs_gd[cg].ext2bgd_ndirs < minndir && | if (e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) < minndir && | ||||
fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree && | e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= avgifree && | ||||
fs->e2fs_gd[cg].ext2bgd_nbfree >= avgbfree) { | e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) >= avgbfree) { | ||||
mincg = cg; | mincg = cg; | ||||
minndir = fs->e2fs_gd[cg].ext2bgd_ndirs; | minndir = e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]); | ||||
} | } | ||||
for (cg = 0; cg < prefcg; cg++) | for (cg = 0; cg < prefcg; cg++) | ||||
if (fs->e2fs_gd[cg].ext2bgd_ndirs < minndir && | if (e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) < minndir && | ||||
fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree && | e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= avgifree && | ||||
fs->e2fs_gd[cg].ext2bgd_nbfree >= avgbfree) { | e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) >= avgbfree) { | ||||
mincg = cg; | mincg = cg; | ||||
minndir = fs->e2fs_gd[cg].ext2bgd_ndirs; | minndir = e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]); | ||||
} | } | ||||
return (mincg); | return (mincg); | ||||
} | } | ||||
/* | /* | ||||
* Count various limits which used for | * Count various limits which used for | ||||
* optimal allocation of a directory inode. | * optimal allocation of a directory inode. | ||||
*/ | */ | ||||
maxndir = min(avgndir + fs->e2fs_ipg / 16, fs->e2fs_ipg); | maxndir = min(avgndir + fs->e2fs_ipg / 16, fs->e2fs_ipg); | ||||
Show All 15 Lines | ext2_dirpref(struct inode *pip) | ||||
/* | /* | ||||
* Limit number of dirs in one cg and reserve space for | * Limit number of dirs in one cg and reserve space for | ||||
* regular files, but only if we have no deficit in | * regular files, but only if we have no deficit in | ||||
* inodes or space. | * inodes or space. | ||||
*/ | */ | ||||
prefcg = ino_to_cg(fs, pip->i_number); | prefcg = ino_to_cg(fs, pip->i_number); | ||||
for (cg = prefcg; cg < fs->e2fs_gcount; cg++) | for (cg = prefcg; cg < fs->e2fs_gcount; cg++) | ||||
if (fs->e2fs_gd[cg].ext2bgd_ndirs < maxndir && | if (e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) < maxndir && | ||||
fs->e2fs_gd[cg].ext2bgd_nifree >= minifree && | e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= minifree && | ||||
fs->e2fs_gd[cg].ext2bgd_nbfree >= minbfree) { | e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) >= minbfree) { | ||||
if (fs->e2fs_contigdirs[cg] < maxcontigdirs) | if (fs->e2fs_contigdirs[cg] < maxcontigdirs) | ||||
return (cg); | return (cg); | ||||
} | } | ||||
for (cg = 0; cg < prefcg; cg++) | for (cg = 0; cg < prefcg; cg++) | ||||
if (fs->e2fs_gd[cg].ext2bgd_ndirs < maxndir && | if (e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) < maxndir && | ||||
fs->e2fs_gd[cg].ext2bgd_nifree >= minifree && | e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= minifree && | ||||
fs->e2fs_gd[cg].ext2bgd_nbfree >= minbfree) { | e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) >= minbfree) { | ||||
if (fs->e2fs_contigdirs[cg] < maxcontigdirs) | if (fs->e2fs_contigdirs[cg] < maxcontigdirs) | ||||
return (cg); | return (cg); | ||||
} | } | ||||
/* | /* | ||||
* This is a backstop when we have deficit in space. | * This is a backstop when we have deficit in space. | ||||
*/ | */ | ||||
for (cg = prefcg; cg < fs->e2fs_gcount; cg++) | for (cg = prefcg; cg < fs->e2fs_gcount; cg++) | ||||
if (fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree) | if (e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= avgifree) | ||||
return (cg); | return (cg); | ||||
for (cg = 0; cg < prefcg; cg++) | for (cg = 0; cg < prefcg; cg++) | ||||
if (fs->e2fs_gd[cg].ext2bgd_nifree >= avgifree) | if (e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) >= avgifree) | ||||
break; | break; | ||||
return (cg); | return (cg); | ||||
} | } | ||||
/* | /* | ||||
* Select the desired position for the next block in a file. | * Select the desired position for the next block in a file. | ||||
* | * | ||||
* we try to mimic what Remy does in inode_getblk/block_getblk | * we try to mimic what Remy does in inode_getblk/block_getblk | ||||
▲ Show 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | if (!EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_META_BG) || | ||||
} | } | ||||
} else { | } else { | ||||
num += ext2_cg_num_gdb(fs, cg); | num += ext2_cg_num_gdb(fs, cg); | ||||
} | } | ||||
return (num); | return (num); | ||||
} | } | ||||
static int | |||||
ext2_get_cg_number(struct m_ext2fs *fs, daddr_t blk) | |||||
{ | |||||
int cg; | |||||
if (fs->e2fs->e2fs_bpg == fs->e2fs_bsize * 8) | |||||
cg = (blk - fs->e2fs->e2fs_first_dblock) / (fs->e2fs_bsize * 8); | |||||
else | |||||
cg = blk - fs->e2fs->e2fs_first_dblock; | |||||
return (cg); | |||||
} | |||||
static void | static void | ||||
ext2_mark_bitmap_end(int start_bit, int end_bit, char *bitmap) | ext2_mark_bitmap_end(int start_bit, int end_bit, char *bitmap) | ||||
{ | { | ||||
int i; | int i; | ||||
if (start_bit >= end_bit) | if (start_bit >= end_bit) | ||||
return; | return; | ||||
for (i = start_bit; i < ((start_bit + 7) & ~7UL); i++) | for (i = start_bit; i < ((start_bit + 7) & ~7UL); i++) | ||||
setbit(bitmap, i); | setbit(bitmap, i); | ||||
if (i < end_bit) | if (i < end_bit) | ||||
memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3); | memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3); | ||||
} | } | ||||
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) | ||||
{ | { | ||||
int bit, bit_max, inodes_per_block; | int bit, bit_max, inodes_per_block; | ||||
uint32_t start, tmp; | uint64_t start, tmp; | ||||
if (!EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM) || | if (!(fs->e2fs_gd[cg].ext4bgd_flags & EXT2_BG_BLOCK_UNINIT)) | ||||
!(fs->e2fs_gd[cg].ext4bgd_flags & EXT2_BG_BLOCK_UNINIT)) | |||||
return (0); | return (0); | ||||
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_num_base_meta_blocks(fs, cg); | ||||
if ((bit_max >> 3) >= fs->e2fs_bsize) | if ((bit_max >> 3) >= fs->e2fs_bsize) | ||||
return (EINVAL); | return (EINVAL); | ||||
for (bit = 0; bit < bit_max; bit++) | for (bit = 0; bit < bit_max; bit++) | ||||
setbit(bp->b_data, bit); | setbit(bp->b_data, bit); | ||||
start = cg * fs->e2fs->e2fs_bpg + fs->e2fs->e2fs_first_dblock; | start = (uint64_t)cg * fs->e2fs->e2fs_bpg + fs->e2fs->e2fs_first_dblock; | ||||
/* Set bits for block and inode bitmaps, and inode table */ | /* Set bits for block and inode bitmaps, and inode table. */ | ||||
tmp = fs->e2fs_gd[cg].ext2bgd_b_bitmap; | 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) || | ||||
tmp == ext2_get_cg_number(fs, cg)) | cg == dtogd(fs, tmp)) | ||||
setbit(bp->b_data, tmp - start); | setbit(bp->b_data, tmp - start); | ||||
tmp = fs->e2fs_gd[cg].ext2bgd_i_bitmap; | 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) || | ||||
tmp == ext2_get_cg_number(fs, cg)) | cg == dtogd(fs, tmp)) | ||||
setbit(bp->b_data, tmp - start); | setbit(bp->b_data, tmp - start); | ||||
tmp = fs->e2fs_gd[cg].ext2bgd_i_tables; | tmp = e2fs_gd_get_i_tables(&fs->e2fs_gd[cg]); | ||||
inodes_per_block = fs->e2fs_bsize/EXT2_INODE_SIZE(fs); | inodes_per_block = fs->e2fs_bsize/EXT2_INODE_SIZE(fs); | ||||
while( tmp < fs->e2fs_gd[cg].ext2bgd_i_tables + | 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) || | ||||
tmp == ext2_get_cg_number(fs, cg)) | cg == dtogd(fs, tmp)) | ||||
setbit(bp->b_data, tmp - start); | setbit(bp->b_data, tmp - start); | ||||
tmp++; | tmp++; | ||||
} | } | ||||
/* | /* | ||||
* Also if the number of blocks within the group is less than | * Also if the number of blocks within the group is less than | ||||
* the blocksize * 8 ( which is the size of bitmap ), set rest | * the blocksize * 8 ( which is the size of bitmap ), set rest | ||||
* of the block bitmap to 1 | * of the block bitmap to 1 | ||||
Show All 20 Lines | ext2_alloccg(struct inode *ip, int cg, daddr_t bpref, int size) | ||||
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 (fs->e2fs_gd[cg].ext2bgd_nbfree == 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, | ||||
fs->e2fs_gd[cg].ext2bgd_b_bitmap), | 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); | brelse(bp); | ||||
EXT2_LOCK(ump); | EXT2_LOCK(ump); | ||||
return (0); | return (0); | ||||
} | } | ||||
if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM)) { | if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM)) { | ||||
error = ext2_cg_block_bitmap_init(fs, cg, bp); | error = ext2_cg_block_bitmap_init(fs, cg, bp); | ||||
if (error) { | if (error) { | ||||
brelse(bp); | brelse(bp); | ||||
EXT2_LOCK(ump); | EXT2_LOCK(ump); | ||||
return (0); | return (0); | ||||
} | } | ||||
} | } | ||||
if (fs->e2fs_gd[cg].ext2bgd_nbfree == 0) { | if (e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) == 0) { | ||||
/* | /* | ||||
* Another thread allocated the last block in this | * Another thread allocated the last block in this | ||||
* group while we were waiting for the buffer. | * group while we were waiting for the buffer. | ||||
*/ | */ | ||||
brelse(bp); | brelse(bp); | ||||
EXT2_LOCK(ump); | EXT2_LOCK(ump); | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | 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->e2fs_fbcount--; | fs->e2fs_fbcount--; | ||||
fs->e2fs_gd[cg].ext2bgd_nbfree--; | e2fs_gd_set_nbfree(&fs->e2fs_gd[cg], | ||||
e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) - 1); | |||||
fs->e2fs_fmod = 1; | fs->e2fs_fmod = 1; | ||||
EXT2_UNLOCK(ump); | EXT2_UNLOCK(ump); | ||||
bdwrite(bp); | bdwrite(bp); | ||||
return (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); | ||||
} | } | ||||
/* | /* | ||||
* 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) | ||||
{ | { | ||||
struct m_ext2fs *fs; | struct m_ext2fs *fs; | ||||
struct ext2mount *ump; | struct ext2mount *ump; | ||||
struct buf *bp; | struct buf *bp; | ||||
char *bbp; | char *bbp; | ||||
int bit, error, got, i, loc, run; | int bit, error, got, i, loc, run; | ||||
int32_t *lp; | int32_t *lp; | ||||
daddr_t bno; | daddr_t bno; | ||||
fs = ip->i_e2fs; | fs = ip->i_e2fs; | ||||
ump = ip->i_ump; | ump = ip->i_ump; | ||||
if (fs->e2fs_maxcluster[cg] < len) | if (fs->e2fs_maxcluster[cg] < len) | ||||
return (0); | return (0); | ||||
EXT2_UNLOCK(ump); | EXT2_UNLOCK(ump); | ||||
error = bread(ip->i_devvp, | error = bread(ip->i_devvp, | ||||
fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap), | fsbtodb(fs, 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) | ||||
goto fail_lock; | goto fail_lock; | ||||
bbp = (char *)bp->b_data; | bbp = (char *)bp->b_data; | ||||
EXT2_LOCK(ump); | EXT2_LOCK(ump); | ||||
/* | /* | ||||
* Check to see if a cluster of the needed size (or bigger) is | * Check to see if a cluster of the needed size (or bigger) is | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | ext2_clusteralloc(struct inode *ip, int cg, daddr_t bpref, int len) | ||||
bno = got - run + 1; | bno = got - run + 1; | ||||
if (bno >= fs->e2fs->e2fs_fpg) | if (bno >= fs->e2fs->e2fs_fpg) | ||||
panic("ext2_clusteralloc: allocated out of group"); | panic("ext2_clusteralloc: allocated out of group"); | ||||
EXT2_LOCK(ump); | EXT2_LOCK(ump); | ||||
for (i = 0; i < len; i += fs->e2fs_fpb) { | for (i = 0; i < len; i += fs->e2fs_fpb) { | ||||
setbit(bbp, bno + i); | setbit(bbp, bno + i); | ||||
ext2_clusteracct(fs, bbp, cg, bno + i, -1); | ext2_clusteracct(fs, bbp, cg, bno + i, -1); | ||||
fs->e2fs->e2fs_fbcount--; | fs->e2fs_fbcount--; | ||||
fs->e2fs_gd[cg].ext2bgd_nbfree--; | e2fs_gd_set_nbfree(&fs->e2fs_gd[cg], | ||||
e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) - 1); | |||||
} | } | ||||
fs->e2fs_fmod = 1; | fs->e2fs_fmod = 1; | ||||
EXT2_UNLOCK(ump); | EXT2_UNLOCK(ump); | ||||
bdwrite(bp); | bdwrite(bp); | ||||
return (cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock + bno); | return (cg * fs->e2fs->e2fs_fpg + fs->e2fs->e2fs_first_dblock + bno); | ||||
fail_lock: | fail_lock: | ||||
Show All 14 Lines | ext2_zero_inode_table(struct inode *ip, int cg) | ||||
if (fs->e2fs_gd[cg].ext4bgd_flags & EXT2_BG_INODE_ZEROED) | if (fs->e2fs_gd[cg].ext4bgd_flags & EXT2_BG_INODE_ZEROED) | ||||
return (0); | return (0); | ||||
all_blks = fs->e2fs->e2fs_inode_size * fs->e2fs->e2fs_ipg / | all_blks = fs->e2fs->e2fs_inode_size * fs->e2fs->e2fs_ipg / | ||||
fs->e2fs_bsize; | fs->e2fs_bsize; | ||||
used_blks = howmany(fs->e2fs->e2fs_ipg - | used_blks = howmany(fs->e2fs->e2fs_ipg - | ||||
fs->e2fs_gd[cg].ext4bgd_i_unused, | e2fs_gd_get_i_unused(&fs->e2fs_gd[cg]), | ||||
fs->e2fs_bsize / EXT2_INODE_SIZE(fs)); | fs->e2fs_bsize / EXT2_INODE_SIZE(fs)); | ||||
for (i = 0; i < all_blks - used_blks; i++) { | for (i = 0; i < all_blks - used_blks; i++) { | ||||
bp = getblk(ip->i_devvp, fsbtodb(fs, | bp = getblk(ip->i_devvp, fsbtodb(fs, | ||||
fs->e2fs_gd[cg].ext2bgd_i_tables + used_blks + i), | e2fs_gd_get_i_tables(&fs->e2fs_gd[cg]) + used_blks + i), | ||||
fs->e2fs_bsize, 0, 0, 0); | fs->e2fs_bsize, 0, 0, 0); | ||||
if (!bp) | if (!bp) | ||||
return (EIO); | return (EIO); | ||||
vfs_bio_bzero_buf(bp, 0, fs->e2fs_bsize); | vfs_bio_bzero_buf(bp, 0, fs->e2fs_bsize); | ||||
bawrite(bp); | bawrite(bp); | ||||
} | } | ||||
Show All 17 Lines | ext2_nodealloccg(struct inode *ip, int cg, daddr_t ipref, int mode) | ||||
int error, start, len; | int error, start, len; | ||||
char *ibp, *loc; | char *ibp, *loc; | ||||
ipref--; /* to avoid a lot of (ipref -1) */ | ipref--; /* to avoid a lot of (ipref -1) */ | ||||
if (ipref == -1) | if (ipref == -1) | ||||
ipref = 0; | ipref = 0; | ||||
fs = ip->i_e2fs; | fs = ip->i_e2fs; | ||||
ump = ip->i_ump; | ump = ip->i_ump; | ||||
if (fs->e2fs_gd[cg].ext2bgd_nifree == 0) | if (e2fs_gd_get_nifree(&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, | ||||
fs->e2fs_gd[cg].ext2bgd_i_bitmap), | e2fs_gd_get_i_bitmap(&fs->e2fs_gd[cg])), | ||||
(int)fs->e2fs_bsize, NOCRED, &bp); | (int)fs->e2fs_bsize, NOCRED, &bp); | ||||
if (error) { | if (error) { | ||||
brelse(bp); | brelse(bp); | ||||
EXT2_LOCK(ump); | EXT2_LOCK(ump); | ||||
return (0); | return (0); | ||||
} | } | ||||
if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM)) { | if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM)) { | ||||
if (fs->e2fs_gd[cg].ext4bgd_flags & EXT2_BG_INODE_UNINIT) { | if (fs->e2fs_gd[cg].ext4bgd_flags & EXT2_BG_INODE_UNINIT) { | ||||
memset(bp->b_data, 0, fs->e2fs_bsize); | memset(bp->b_data, 0, fs->e2fs_bsize); | ||||
fs->e2fs_gd[cg].ext4bgd_flags &= ~EXT2_BG_INODE_UNINIT; | fs->e2fs_gd[cg].ext4bgd_flags &= ~EXT2_BG_INODE_UNINIT; | ||||
} | } | ||||
error = ext2_zero_inode_table(ip, cg); | error = ext2_zero_inode_table(ip, cg); | ||||
if (error) { | if (error) { | ||||
brelse(bp); | brelse(bp); | ||||
EXT2_LOCK(ump); | EXT2_LOCK(ump); | ||||
return (0); | return (0); | ||||
} | } | ||||
} | } | ||||
if (fs->e2fs_gd[cg].ext2bgd_nifree == 0) { | if (e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) == 0) { | ||||
/* | /* | ||||
* Another thread allocated the last i-node in this | * Another thread allocated the last i-node in this | ||||
* group while we were waiting for the buffer. | * group while we were waiting for the buffer. | ||||
*/ | */ | ||||
brelse(bp); | brelse(bp); | ||||
EXT2_LOCK(ump); | EXT2_LOCK(ump); | ||||
return (0); | return (0); | ||||
} | } | ||||
Show All 16 Lines | if (loc == NULL) { | ||||
panic("ext2fs_nodealloccg: map corrupted"); | panic("ext2fs_nodealloccg: map corrupted"); | ||||
/* NOTREACHED */ | /* NOTREACHED */ | ||||
} | } | ||||
} | } | ||||
ipref = (loc - ibp) * NBBY + ffs(~*loc) - 1; | ipref = (loc - ibp) * NBBY + ffs(~*loc) - 1; | ||||
gotit: | gotit: | ||||
setbit(ibp, ipref); | setbit(ibp, ipref); | ||||
EXT2_LOCK(ump); | EXT2_LOCK(ump); | ||||
fs->e2fs_gd[cg].ext2bgd_nifree--; | e2fs_gd_set_nifree(&fs->e2fs_gd[cg], | ||||
e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) - 1); | |||||
if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM)) | if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM)) | ||||
fs->e2fs_gd[cg].ext4bgd_i_unused--; | e2fs_gd_set_i_unused(&fs->e2fs_gd[cg], | ||||
e2fs_gd_get_i_unused(&fs->e2fs_gd[cg]) - 1); | |||||
fs->e2fs->e2fs_ficount--; | fs->e2fs->e2fs_ficount--; | ||||
fs->e2fs_fmod = 1; | fs->e2fs_fmod = 1; | ||||
if ((mode & IFMT) == IFDIR) { | if ((mode & IFMT) == IFDIR) { | ||||
fs->e2fs_gd[cg].ext2bgd_ndirs++; | e2fs_gd_set_ndirs(&fs->e2fs_gd[cg], | ||||
e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) + 1); | |||||
fs->e2fs_total_dir++; | fs->e2fs_total_dir++; | ||||
} | } | ||||
EXT2_UNLOCK(ump); | EXT2_UNLOCK(ump); | ||||
bdwrite(bp); | bdwrite(bp); | ||||
return (cg * fs->e2fs->e2fs_ipg + ipref + 1); | return ((uint64_t)cg * fs->e2fs_ipg + ipref + 1); | ||||
} | } | ||||
/* | /* | ||||
* Free a block or fragment. | * Free a block or fragment. | ||||
* | * | ||||
*/ | */ | ||||
void | void | ||||
ext2_blkfree(struct inode *ip, e4fs_daddr_t bno, long size) | ext2_blkfree(struct inode *ip, e4fs_daddr_t bno, long size) | ||||
{ | { | ||||
struct m_ext2fs *fs; | struct m_ext2fs *fs; | ||||
struct buf *bp; | struct buf *bp; | ||||
struct ext2mount *ump; | struct ext2mount *ump; | ||||
int cg, error; | int cg, error; | ||||
char *bbp; | char *bbp; | ||||
fs = ip->i_e2fs; | fs = ip->i_e2fs; | ||||
ump = ip->i_ump; | ump = ip->i_ump; | ||||
cg = dtog(fs, bno); | cg = dtog(fs, bno); | ||||
if (bno >= fs->e2fs->e2fs_bcount) { | if (bno >= fs->e2fs_bcount) { | ||||
printf("bad block %lld, ino %ju\n", (long long)bno, | printf("bad block %lld, ino %ju\n", (long long)bno, | ||||
(uintmax_t)ip->i_number); | (uintmax_t)ip->i_number); | ||||
ext2_fserr(fs, ip->i_uid, "bad block"); | ext2_fserr(fs, ip->i_uid, "bad block"); | ||||
return; | return; | ||||
} | } | ||||
error = bread(ip->i_devvp, | error = bread(ip->i_devvp, | ||||
fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_b_bitmap), | fsbtodb(fs, 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); | brelse(bp); | ||||
return; | return; | ||||
} | } | ||||
bbp = (char *)bp->b_data; | bbp = (char *)bp->b_data; | ||||
bno = dtogd(fs, bno); | bno = dtogd(fs, bno); | ||||
if (isclr(bbp, bno)) { | if (isclr(bbp, bno)) { | ||||
printf("block = %lld, fs = %s\n", | printf("block = %lld, fs = %s\n", | ||||
(long long)bno, fs->e2fs_fsmnt); | (long long)bno, fs->e2fs_fsmnt); | ||||
panic("ext2_blkfree: freeing free block"); | panic("ext2_blkfree: freeing free block"); | ||||
} | } | ||||
clrbit(bbp, bno); | clrbit(bbp, bno); | ||||
EXT2_LOCK(ump); | EXT2_LOCK(ump); | ||||
ext2_clusteracct(fs, bbp, cg, bno, 1); | ext2_clusteracct(fs, bbp, cg, bno, 1); | ||||
fs->e2fs->e2fs_fbcount++; | fs->e2fs_fbcount++; | ||||
fs->e2fs_gd[cg].ext2bgd_nbfree++; | e2fs_gd_set_nbfree(&fs->e2fs_gd[cg], | ||||
e2fs_gd_get_nbfree(&fs->e2fs_gd[cg]) + 1); | |||||
fs->e2fs_fmod = 1; | fs->e2fs_fmod = 1; | ||||
EXT2_UNLOCK(ump); | EXT2_UNLOCK(ump); | ||||
bdwrite(bp); | bdwrite(bp); | ||||
} | } | ||||
/* | /* | ||||
* Free an inode. | * Free an inode. | ||||
* | * | ||||
Show All 12 Lines | ext2_vfree(struct vnode *pvp, ino_t ino, int mode) | ||||
fs = pip->i_e2fs; | fs = pip->i_e2fs; | ||||
ump = pip->i_ump; | ump = pip->i_ump; | ||||
if ((u_int)ino > fs->e2fs_ipg * fs->e2fs_gcount) | if ((u_int)ino > fs->e2fs_ipg * fs->e2fs_gcount) | ||||
panic("ext2_vfree: range: devvp = %p, ino = %ju, fs = %s", | panic("ext2_vfree: range: devvp = %p, ino = %ju, fs = %s", | ||||
pip->i_devvp, (uintmax_t)ino, fs->e2fs_fsmnt); | pip->i_devvp, (uintmax_t)ino, fs->e2fs_fsmnt); | ||||
cg = ino_to_cg(fs, ino); | cg = ino_to_cg(fs, ino); | ||||
error = bread(pip->i_devvp, | error = bread(pip->i_devvp, | ||||
fsbtodb(fs, fs->e2fs_gd[cg].ext2bgd_i_bitmap), | fsbtodb(fs, e2fs_gd_get_i_bitmap(&fs->e2fs_gd[cg])), | ||||
(int)fs->e2fs_bsize, NOCRED, &bp); | (int)fs->e2fs_bsize, NOCRED, &bp); | ||||
if (error) { | if (error) { | ||||
brelse(bp); | brelse(bp); | ||||
return (0); | return (0); | ||||
} | } | ||||
ibp = (char *)bp->b_data; | ibp = (char *)bp->b_data; | ||||
ino = (ino - 1) % fs->e2fs->e2fs_ipg; | ino = (ino - 1) % fs->e2fs->e2fs_ipg; | ||||
if (isclr(ibp, ino)) { | if (isclr(ibp, ino)) { | ||||
printf("ino = %llu, fs = %s\n", | printf("ino = %llu, fs = %s\n", | ||||
(unsigned long long)ino, fs->e2fs_fsmnt); | (unsigned long long)ino, fs->e2fs_fsmnt); | ||||
if (fs->e2fs_ronly == 0) | if (fs->e2fs_ronly == 0) | ||||
panic("ext2_vfree: freeing free inode"); | panic("ext2_vfree: freeing free inode"); | ||||
} | } | ||||
clrbit(ibp, ino); | clrbit(ibp, ino); | ||||
EXT2_LOCK(ump); | EXT2_LOCK(ump); | ||||
fs->e2fs->e2fs_ficount++; | fs->e2fs->e2fs_ficount++; | ||||
fs->e2fs_gd[cg].ext2bgd_nifree++; | e2fs_gd_set_nifree(&fs->e2fs_gd[cg], | ||||
e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) + 1); | |||||
if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM)) | if (EXT2_HAS_RO_COMPAT_FEATURE(fs, EXT2F_ROCOMPAT_GDT_CSUM)) | ||||
fs->e2fs_gd[cg].ext4bgd_i_unused++; | e2fs_gd_set_i_unused(&fs->e2fs_gd[cg], | ||||
e2fs_gd_get_i_unused(&fs->e2fs_gd[cg]) + 1); | |||||
if ((mode & IFMT) == IFDIR) { | if ((mode & IFMT) == IFDIR) { | ||||
fs->e2fs_gd[cg].ext2bgd_ndirs--; | e2fs_gd_set_ndirs(&fs->e2fs_gd[cg], | ||||
e2fs_gd_get_ndirs(&fs->e2fs_gd[cg]) - 1); | |||||
fs->e2fs_total_dir--; | fs->e2fs_total_dir--; | ||||
} | } | ||||
fs->e2fs_fmod = 1; | fs->e2fs_fmod = 1; | ||||
EXT2_UNLOCK(ump); | EXT2_UNLOCK(ump); | ||||
bdwrite(bp); | bdwrite(bp); | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 78 Lines • Show Last 20 Lines |
How about making these inlines in a header, perhaps ext2fs.h?