Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/ext2fs/ext2_alloc.c
Show All 36 Lines | |||||
* @(#)ffs_alloc.c 8.8 (Berkeley) 2/21/94 | * @(#)ffs_alloc.c 8.8 (Berkeley) 2/21/94 | ||||
* $FreeBSD$ | * $FreeBSD$ | ||||
*/ | */ | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/conf.h> | #include <sys/conf.h> | ||||
#include <sys/vnode.h> | #include <sys/vnode.h> | ||||
#include <sys/sdt.h> | |||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <sys/mount.h> | #include <sys/mount.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/syslog.h> | #include <sys/syslog.h> | ||||
#include <sys/buf.h> | #include <sys/buf.h> | ||||
#include <sys/endian.h> | #include <sys/endian.h> | ||||
#include <fs/ext2fs/fs.h> | #include <fs/ext2fs/fs.h> | ||||
#include <fs/ext2fs/inode.h> | #include <fs/ext2fs/inode.h> | ||||
#include <fs/ext2fs/ext2_mount.h> | #include <fs/ext2fs/ext2_mount.h> | ||||
#include <fs/ext2fs/ext2fs.h> | #include <fs/ext2fs/ext2fs.h> | ||||
#include <fs/ext2fs/ext2_extern.h> | #include <fs/ext2fs/ext2_extern.h> | ||||
SDT_PROVIDER_DEFINE(ext2fs); | |||||
/* | |||||
* ext2fs trace probe: | |||||
* arg0: verbosity. Higher numbers give more verbose messages | |||||
* arg1: Textual message | |||||
*/ | |||||
SDT_PROBE_DEFINE2(ext2fs, , alloc, trace, "int", "char*"); | |||||
pfg: I see these ", ," a lot. Is the empty parameter fine or perhaps we should have some form of… | |||||
fsuAuthorUnsubmitted Done Inline ActionsNope, we should not. The argument could be empty. fsu: Nope, we should not. The argument could be empty.
See SDT_PROBE_DEFINE2 definition in the sdt.h. | |||||
static daddr_t ext2_alloccg(struct inode *, int, daddr_t, int); | static daddr_t ext2_alloccg(struct inode *, int, daddr_t, int); | ||||
static daddr_t ext2_clusteralloc(struct inode *, int, daddr_t, int); | static daddr_t ext2_clusteralloc(struct inode *, int, daddr_t, int); | ||||
static u_long ext2_dirpref(struct inode *); | static u_long ext2_dirpref(struct inode *); | ||||
static e4fs_daddr_t ext2_hashalloc(struct inode *, int, long, int, | static e4fs_daddr_t ext2_hashalloc(struct inode *, int, long, int, | ||||
daddr_t (*)(struct inode *, int, daddr_t, | daddr_t (*)(struct inode *, int, daddr_t, | ||||
int)); | int)); | ||||
static daddr_t ext2_nodealloccg(struct inode *, int, daddr_t, int); | static daddr_t ext2_nodealloccg(struct inode *, int, daddr_t, int); | ||||
static daddr_t ext2_mapsearch(struct m_ext2fs *, char *, daddr_t); | static daddr_t ext2_mapsearch(struct m_ext2fs *, char *, daddr_t); | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | if (bno > 0) { | ||||
ip->i_blocks += btodb(fs->e2fs_bsize); | ip->i_blocks += btodb(fs->e2fs_bsize); | ||||
ip->i_flag |= IN_CHANGE | IN_UPDATE; | ip->i_flag |= IN_CHANGE | IN_UPDATE; | ||||
*bnp = bno; | *bnp = bno; | ||||
return (0); | return (0); | ||||
} | } | ||||
nospace: | nospace: | ||||
EXT2_UNLOCK(ump); | EXT2_UNLOCK(ump); | ||||
ext2_fserr(fs, cred->cr_uid, "filesystem full"); | SDT_PROBE2(ext2fs, , alloc, trace, 1, "cannot allocate data block"); | ||||
uprintf("\n%s: write failed, filesystem is full\n", fs->e2fs_fsmnt); | |||||
return (ENOSPC); | return (ENOSPC); | ||||
} | } | ||||
/* | /* | ||||
* Allocate EA's block for inode. | * Allocate EA's block for inode. | ||||
*/ | */ | ||||
e4fs_daddr_t | e4fs_daddr_t | ||||
ext2_alloc_meta(struct inode *ip) | ext2_alloc_meta(struct inode *ip) | ||||
{ | { | ||||
struct m_ext2fs *fs; | struct m_ext2fs *fs; | ||||
daddr_t blk; | daddr_t blk; | ||||
fs = ip->i_e2fs; | fs = ip->i_e2fs; | ||||
EXT2_LOCK(ip->i_ump); | EXT2_LOCK(ip->i_ump); | ||||
blk = ext2_hashalloc(ip, ino_to_cg(fs, ip->i_number), 0, fs->e2fs_bsize, | blk = ext2_hashalloc(ip, ino_to_cg(fs, ip->i_number), 0, fs->e2fs_bsize, | ||||
ext2_alloccg); | ext2_alloccg); | ||||
if (0 == blk) | if (0 == blk) { | ||||
EXT2_UNLOCK(ip->i_ump); | EXT2_UNLOCK(ip->i_ump); | ||||
SDT_PROBE2(ext2fs, , alloc, trace, 1, "cannot allocate meta block"); | |||||
} | |||||
return (blk); | return (blk); | ||||
} | } | ||||
/* | /* | ||||
* Reallocate a sequence of blocks into a contiguous sequence of blocks. | * Reallocate a sequence of blocks into a contiguous sequence of blocks. | ||||
* | * | ||||
* The vnode and an array of buffer pointers for a range of sequential | * The vnode and an array of buffer pointers for a range of sequential | ||||
Show All 14 Lines | |||||
SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, | SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, | ||||
"Use asychronous writes to update block pointers when freeing blocks"); | "Use asychronous writes to update block pointers when freeing blocks"); | ||||
static int doreallocblks = 0; | static int doreallocblks = 0; | ||||
SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doreallocblks, CTLFLAG_RW, &doreallocblks, 0, ""); | SYSCTL_INT(_vfs_ext2fs, OID_AUTO, doreallocblks, CTLFLAG_RW, &doreallocblks, 0, ""); | ||||
SDT_PROBE_DEFINE3(ext2fs, , alloc, ext2_reallocblks_realloc, | |||||
"ino_t", "e2fs_lbn_t", "e2fs_lbn_t"); | |||||
SDT_PROBE_DEFINE1(ext2fs, , alloc, ext2_reallocblks_bap, "uint32_t"); | |||||
SDT_PROBE_DEFINE1(ext2fs, , alloc, ext2_reallocblks_blkno, "e2fs_daddr_t"); | |||||
int | int | ||||
ext2_reallocblks(struct vop_reallocblks_args *ap) | ext2_reallocblks(struct vop_reallocblks_args *ap) | ||||
{ | { | ||||
struct m_ext2fs *fs; | struct m_ext2fs *fs; | ||||
struct inode *ip; | struct inode *ip; | ||||
struct vnode *vp; | struct vnode *vp; | ||||
struct buf *sbp, *ebp; | struct buf *sbp, *ebp; | ||||
uint32_t *bap, *sbap, *ebap; | uint32_t *bap, *sbap, *ebap; | ||||
▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
/* | /* | ||||
* We have found a new contiguous block. | * We have found a new contiguous block. | ||||
* | * | ||||
* First we have to replace the old block pointers with the new | * First we have to replace the old block pointers with the new | ||||
* block pointers in the inode and indirect blocks associated | * block pointers in the inode and indirect blocks associated | ||||
* with the file. | * with the file. | ||||
*/ | */ | ||||
#ifdef DEBUG | SDT_PROBE3(ext2fs, , alloc, ext2_reallocblks_realloc, | ||||
printf("realloc: ino %ju, lbns %jd-%jd\n\told:", | ip->i_number, start_lbn, end_lbn); | ||||
(uintmax_t)ip->i_number, (intmax_t)start_lbn, (intmax_t)end_lbn); | |||||
#endif /* DEBUG */ | |||||
blkno = newblk; | blkno = newblk; | ||||
for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->e2fs_fpb) { | for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->e2fs_fpb) { | ||||
if (i == ssize) { | if (i == ssize) { | ||||
bap = ebap; | bap = ebap; | ||||
soff = -i; | soff = -i; | ||||
} | } | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
if (buflist->bs_children[i]->b_blkno != fsbtodb(fs, *bap)) | if (buflist->bs_children[i]->b_blkno != fsbtodb(fs, *bap)) | ||||
panic("ext2_reallocblks: alloc mismatch"); | panic("ext2_reallocblks: alloc mismatch"); | ||||
#endif | #endif | ||||
#ifdef DEBUG | SDT_PROBE1(ext2fs, , alloc, ext2_reallocblks_bap, *bap); | ||||
printf(" %d,", *bap); | |||||
#endif /* DEBUG */ | |||||
*bap++ = blkno; | *bap++ = blkno; | ||||
} | } | ||||
/* | /* | ||||
* Next we must write out the modified inode and indirect blocks. | * Next we must write out the modified inode and indirect blocks. | ||||
* For strict correctness, the writes should be synchronous since | * For strict correctness, the writes should be synchronous since | ||||
* the old block values may have been written to disk. In practise | * the old block values may have been written to disk. In practise | ||||
* they are almost never written, but if we are concerned about | * they are almost never written, but if we are concerned about | ||||
* strict correctness, the `doasyncfree' flag should be set to zero. | * strict correctness, the `doasyncfree' flag should be set to zero. | ||||
Show All 19 Lines | if (ssize < len) { | ||||
if (doasyncfree) | if (doasyncfree) | ||||
bdwrite(ebp); | bdwrite(ebp); | ||||
else | else | ||||
bwrite(ebp); | bwrite(ebp); | ||||
} | } | ||||
/* | /* | ||||
* Last, free the old blocks and assign the new blocks to the buffers. | * Last, free the old blocks and assign the new blocks to the buffers. | ||||
*/ | */ | ||||
#ifdef DEBUG | |||||
printf("\n\tnew:"); | |||||
#endif /* DEBUG */ | |||||
for (blkno = newblk, i = 0; i < len; i++, blkno += fs->e2fs_fpb) { | for (blkno = newblk, i = 0; i < len; i++, blkno += fs->e2fs_fpb) { | ||||
ext2_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno), | ext2_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno), | ||||
fs->e2fs_bsize); | fs->e2fs_bsize); | ||||
buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno); | buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno); | ||||
#ifdef DEBUG | SDT_PROBE1(ext2fs, , alloc, ext2_reallocblks_blkno, blkno); | ||||
printf(" %d,", blkno); | |||||
#endif /* DEBUG */ | |||||
} | } | ||||
#ifdef DEBUG | |||||
printf("\n"); | |||||
#endif /* DEBUG */ | |||||
return (0); | return (0); | ||||
fail: | fail: | ||||
if (ssize < len) | if (ssize < len) | ||||
brelse(ebp); | brelse(ebp); | ||||
if (sbap != &ip->i_db[0]) | if (sbap != &ip->i_db[0]) | ||||
brelse(sbp); | brelse(sbp); | ||||
return (ENOSPC); | return (ENOSPC); | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | ext2_valloc(struct vnode *pvp, int mode, struct ucred *cred, struct vnode **vpp) | ||||
ip->i_birthnsec = ts.tv_nsec; | ip->i_birthnsec = ts.tv_nsec; | ||||
*vpp = vp; | *vpp = vp; | ||||
return (0); | return (0); | ||||
noinodes: | noinodes: | ||||
EXT2_UNLOCK(ump); | EXT2_UNLOCK(ump); | ||||
ext2_fserr(fs, cred->cr_uid, "out of inodes"); | SDT_PROBE2(ext2fs, , alloc, trace, 1, "out of inodes"); | ||||
uprintf("\n%s: create/symlink failed, no inodes free\n", fs->e2fs_fsmnt); | |||||
return (ENOSPC); | return (ENOSPC); | ||||
} | } | ||||
/* | /* | ||||
* 64-bit compatible getters and setters for struct ext2_gd from ext2fs.h | * 64-bit compatible getters and setters for struct ext2_gd from ext2fs.h | ||||
*/ | */ | ||||
uint64_t | uint64_t | ||||
e2fs_gd_get_b_bitmap(struct ext2_gd *gd) | e2fs_gd_get_b_bitmap(struct ext2_gd *gd) | ||||
▲ Show 20 Lines • Show All 435 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); | ||||
} | } | ||||
SDT_PROBE_DEFINE2(ext2fs, , alloc, ext2_b_bitmap_validate_error, "char*", "int"); | |||||
static int | static int | ||||
ext2_b_bitmap_validate(struct m_ext2fs *fs, struct buf *bp, int cg) | ext2_b_bitmap_validate(struct m_ext2fs *fs, struct buf *bp, int cg) | ||||
{ | { | ||||
struct ext2_gd *gd; | struct ext2_gd *gd; | ||||
uint64_t group_first_block; | uint64_t group_first_block; | ||||
unsigned int offset, max_bit; | unsigned int offset, max_bit; | ||||
if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG)) { | if (EXT2_HAS_INCOMPAT_FEATURE(fs, EXT2F_INCOMPAT_FLEX_BG)) { | ||||
Show All 9 Lines | ext2_b_bitmap_validate(struct m_ext2fs *fs, struct buf *bp, int cg) | ||||
gd = &fs->e2fs_gd[cg]; | gd = &fs->e2fs_gd[cg]; | ||||
max_bit = fs->e2fs_fpg; | max_bit = fs->e2fs_fpg; | ||||
group_first_block = ((uint64_t)cg) * fs->e2fs->e2fs_fpg + | group_first_block = ((uint64_t)cg) * fs->e2fs->e2fs_fpg + | ||||
fs->e2fs->e2fs_first_dblock; | fs->e2fs->e2fs_first_dblock; | ||||
/* Check block bitmap block number */ | /* Check block bitmap block number */ | ||||
offset = e2fs_gd_get_b_bitmap(gd) - group_first_block; | offset = e2fs_gd_get_b_bitmap(gd) - group_first_block; | ||||
if (offset >= max_bit || !isset(bp->b_data, offset)) { | if (offset >= max_bit || !isset(bp->b_data, offset)) { | ||||
printf("ext2fs: bad block bitmap, group %d\n", cg); | SDT_PROBE2(ext2fs, , alloc, ext2_b_bitmap_validate_error, | ||||
"bad block bitmap, group", cg); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* Check inode bitmap block number */ | /* Check inode bitmap block number */ | ||||
offset = e2fs_gd_get_i_bitmap(gd) - group_first_block; | offset = e2fs_gd_get_i_bitmap(gd) - group_first_block; | ||||
if (offset >= max_bit || !isset(bp->b_data, offset)) { | if (offset >= max_bit || !isset(bp->b_data, offset)) { | ||||
printf("ext2fs: bad inode bitmap, group %d\n", cg); | SDT_PROBE2(ext2fs, , alloc, ext2_b_bitmap_validate_error, | ||||
"bad inode bitmap", cg); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* Check inode table */ | /* Check inode table */ | ||||
offset = e2fs_gd_get_i_tables(gd) - group_first_block; | offset = e2fs_gd_get_i_tables(gd) - group_first_block; | ||||
if (offset >= max_bit || offset + fs->e2fs_itpg >= max_bit) { | if (offset >= max_bit || offset + fs->e2fs_itpg >= max_bit) { | ||||
printf("ext2fs: bad inode table, group %d\n", cg); | SDT_PROBE2(ext2fs, , alloc, ext2_b_bitmap_validate_error, | ||||
"bad inode table, group", cg); | |||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Determine whether a block can be allocated. | * Determine whether a block can be allocated. | ||||
▲ Show 20 Lines • Show All 286 Lines • ▼ Show 20 Lines | for (i = 0; i < all_blks - used_blks; i++) { | ||||
bawrite(bp); | bawrite(bp); | ||||
} | } | ||||
fs->e2fs_gd[cg].ext4bgd_flags |= EXT2_BG_INODE_ZEROED; | fs->e2fs_gd[cg].ext4bgd_flags |= EXT2_BG_INODE_ZEROED; | ||||
return (0); | return (0); | ||||
} | } | ||||
SDT_PROBE_DEFINE3(ext2fs, , alloc, ext2_nodealloccg_bmap_corrupted, | |||||
"int", "daddr_t", "char*"); | |||||
/* | /* | ||||
* Determine whether an inode can be allocated. | * Determine whether an inode can be allocated. | ||||
* | * | ||||
* Check to see if an inode is available, and if it is, | * Check to see if an inode is available, and if it is, | ||||
* allocate it using tode in the specified cylinder group. | * allocate it using tode in the specified cylinder group. | ||||
*/ | */ | ||||
static daddr_t | static daddr_t | ||||
ext2_nodealloccg(struct inode *ip, int cg, daddr_t ipref, int mode) | ext2_nodealloccg(struct inode *ip, int cg, daddr_t ipref, int mode) | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | ext2_nodealloccg(struct inode *ip, int cg, daddr_t ipref, int mode) | ||||
start = ipref / NBBY; | start = ipref / NBBY; | ||||
len = howmany(fs->e2fs->e2fs_ipg - ipref, NBBY); | len = howmany(fs->e2fs->e2fs_ipg - ipref, NBBY); | ||||
loc = memcchr(&ibp[start], 0xff, len); | loc = memcchr(&ibp[start], 0xff, len); | ||||
if (loc == NULL) { | if (loc == NULL) { | ||||
len = start + 1; | len = start + 1; | ||||
start = 0; | start = 0; | ||||
loc = memcchr(&ibp[start], 0xff, len); | loc = memcchr(&ibp[start], 0xff, len); | ||||
if (loc == NULL) { | if (loc == NULL) { | ||||
printf("ext2fs: inode bitmap corrupted: " | SDT_PROBE3(ext2fs, , alloc, ext2_nodealloccg_bmap_corrupted, | ||||
"cg = %d, ipref = %lld, fs = %s - run fsck\n", | cg, ipref, fs->e2fs_fsmnt); | ||||
cg, (long long)ipref, fs->e2fs_fsmnt); | |||||
brelse(bp); | brelse(bp); | ||||
EXT2_LOCK(ump); | EXT2_LOCK(ump); | ||||
return (0); | return (0); | ||||
} | } | ||||
} | } | ||||
ipref = (loc - ibp) * NBBY + ffs(~*loc) - 1; | ipref = (loc - ibp) * NBBY + ffs(~*loc) - 1; | ||||
gotit: | gotit: | ||||
setbit(ibp, ipref); | setbit(ibp, ipref); | ||||
Show All 15 Lines | if ((mode & IFMT) == IFDIR) { | ||||
fs->e2fs_total_dir++; | fs->e2fs_total_dir++; | ||||
} | } | ||||
EXT2_UNLOCK(ump); | EXT2_UNLOCK(ump); | ||||
ext2_gd_i_bitmap_csum_set(fs, cg, bp); | ext2_gd_i_bitmap_csum_set(fs, cg, bp); | ||||
bdwrite(bp); | bdwrite(bp); | ||||
return ((uint64_t)cg * fs->e2fs_ipg + ipref + 1); | return ((uint64_t)cg * fs->e2fs_ipg + ipref + 1); | ||||
} | } | ||||
SDT_PROBE_DEFINE2(ext2fs, , alloc, ext2_blkfree_bad_block, "ino_t", "e4fs_daddr_t"); | |||||
/* | /* | ||||
* 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_bcount) { | if (bno >= fs->e2fs_bcount) { | ||||
printf("bad block %lld, ino %ju\n", (long long)bno, | SDT_PROBE2(ext2fs, , alloc, ext2_blkfree_bad_block, ip->i_number, bno); | ||||
(uintmax_t)ip->i_number); | |||||
ext2_fserr(fs, ip->i_uid, "bad block"); | |||||
return; | return; | ||||
} | } | ||||
error = bread(ip->i_devvp, | error = bread(ip->i_devvp, | ||||
fsbtodb(fs, e2fs_gd_get_b_bitmap(&fs->e2fs_gd[cg])), | 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", | panic("ext2_blkfree: freeing free block %lld, fs=%s", | ||||
(long long)bno, fs->e2fs_fsmnt); | (long long)bno, fs->e2fs_fsmnt); | ||||
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_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); | ||||
} | } | ||||
SDT_PROBE_DEFINE2(ext2fs, , alloc, ext2_vfree_doublefree, "char*", "ino_t"); | |||||
/* | /* | ||||
* Free an inode. | * Free an inode. | ||||
* | * | ||||
*/ | */ | ||||
int | int | ||||
ext2_vfree(struct vnode *pvp, ino_t ino, int mode) | ext2_vfree(struct vnode *pvp, ino_t ino, int mode) | ||||
{ | { | ||||
struct m_ext2fs *fs; | struct m_ext2fs *fs; | ||||
Show All 16 Lines | error = bread(pip->i_devvp, | ||||
(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 = %ju, fs = %s\n", | SDT_PROBE2(ext2fs, , alloc, ext2_vfree_doublefree, | ||||
ino, fs->e2fs_fsmnt); | fs->e2fs_fsmnt, ino); | ||||
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++; | ||||
e2fs_gd_set_nifree(&fs->e2fs_gd[cg], | e2fs_gd_set_nifree(&fs->e2fs_gd[cg], | ||||
e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) + 1); | e2fs_gd_get_nifree(&fs->e2fs_gd[cg]) + 1); | ||||
Show All 31 Lines | else | ||||
start = 0; | start = 0; | ||||
len = howmany(fs->e2fs->e2fs_fpg, NBBY) - start; | len = howmany(fs->e2fs->e2fs_fpg, NBBY) - start; | ||||
loc = memcchr(&bbp[start], 0xff, len); | loc = memcchr(&bbp[start], 0xff, len); | ||||
if (loc == NULL) { | if (loc == NULL) { | ||||
len = start + 1; | len = start + 1; | ||||
start = 0; | start = 0; | ||||
loc = memcchr(&bbp[start], 0xff, len); | loc = memcchr(&bbp[start], 0xff, len); | ||||
if (loc == NULL) { | if (loc == NULL) { | ||||
printf("start = %d, len = %d, fs = %s\n", | panic("ext2_mapsearch: map corrupted: start=%d, len=%d, fs=%s", | ||||
start, len, fs->e2fs_fsmnt); | start, len, fs->e2fs_fsmnt); | ||||
panic("ext2_mapsearch: map corrupted"); | |||||
/* NOTREACHED */ | /* NOTREACHED */ | ||||
} | } | ||||
} | } | ||||
return ((loc - bbp) * NBBY + ffs(~*loc) - 1); | return ((loc - bbp) * NBBY + ffs(~*loc) - 1); | ||||
} | |||||
/* | |||||
* Fserr prints the name of a filesystem with an error diagnostic. | |||||
* | |||||
* The form of the error message is: | |||||
* fs: error message | |||||
*/ | |||||
void | |||||
ext2_fserr(struct m_ext2fs *fs, uid_t uid, char *cp) | |||||
{ | |||||
log(LOG_ERR, "uid %u on %s: %s\n", uid, fs->e2fs_fsmnt, cp); | |||||
} | } | ||||
int | int | ||||
ext2_cg_has_sb(struct m_ext2fs *fs, int cg) | ext2_cg_has_sb(struct m_ext2fs *fs, int cg) | ||||
{ | { | ||||
int a3, a5, a7; | int a3, a5, a7; | ||||
if (cg == 0) | if (cg == 0) | ||||
Show All 23 Lines |
I see these ", ," a lot. Is the empty parameter fine or perhaps we should have some form of NULL there?