mirror of
https://github.com/opnsense/src.git
synced 2026-06-03 22:02:58 -04:00
Cleanups to fsck_ffs(8).
When checking an inode ensure that it does not have a negative size. Stop scaning a directory when an unallocated block is found. Fully clear an inode when it is first allocated. Ensure that an inode is marked dirty whenever it is updated and that it has a correct check hash when it is released. MFC-after: 1 week Sponsored-by: The FreeBSD Foundation
This commit is contained in:
parent
a94018e200
commit
5267120645
2 changed files with 16 additions and 4 deletions
|
|
@ -725,6 +725,7 @@ changeino(ino_t dir, const char *name, ino_t newnum, int depth)
|
|||
ginode(dir, &ip);
|
||||
if (((error = ckinode(ip.i_dp, &idesc)) & ALTERED) && newnum != 0) {
|
||||
DIP_SET(ip.i_dp, di_dirdepth, depth);
|
||||
inodirty(&ip);
|
||||
getinoinfo(dir)->i_depth = depth;
|
||||
}
|
||||
free(idesc.id_name);
|
||||
|
|
@ -879,6 +880,7 @@ expanddir(struct inode *ip, char *name)
|
|||
DIP_SET(dp, di_ib[0], indirblk);
|
||||
DIP_SET(dp, di_blocks,
|
||||
DIP(dp, di_blocks) + btodb(sblock.fs_bsize));
|
||||
inodirty(ip);
|
||||
}
|
||||
IBLK_SET(nbp, lastlbn - UFS_NDADDR, newblk);
|
||||
dirty(nbp);
|
||||
|
|
@ -969,6 +971,7 @@ allocdir(ino_t parent, ino_t request, int mode)
|
|||
} else {
|
||||
inp->i_depth = parentinp->i_depth + 1;
|
||||
DIP_SET(dp, di_dirdepth, inp->i_depth);
|
||||
inodirty(&ip);
|
||||
}
|
||||
inoinfo(ino)->ino_type = DT_DIR;
|
||||
inoinfo(ino)->ino_state = inoinfo(parent)->ino_state;
|
||||
|
|
|
|||
|
|
@ -90,6 +90,10 @@ ckinode(union dinode *dp, struct inodesc *idesc)
|
|||
dino.dp1 = dp->dp1;
|
||||
else
|
||||
dino.dp2 = dp->dp2;
|
||||
if (DIP(&dino, di_size) < 0) {
|
||||
pfatal("NEGATIVE INODE SIZE %jd\n", DIP(&dino, di_size));
|
||||
return (STOP);
|
||||
}
|
||||
ndb = howmany(DIP(&dino, di_size), sblock.fs_bsize);
|
||||
for (i = 0; i < UFS_NDADDR; i++) {
|
||||
idesc->id_lbn++;
|
||||
|
|
@ -116,6 +120,7 @@ ckinode(union dinode *dp, struct inodesc *idesc)
|
|||
inodirty(&ip);
|
||||
irelse(&ip);
|
||||
}
|
||||
return (STOP);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
@ -498,6 +503,11 @@ irelse(struct inode *ip)
|
|||
/* Check for failed inode read */
|
||||
if (ip->i_bp == NULL)
|
||||
return;
|
||||
if (debug && sblock.fs_magic == FS_UFS2_MAGIC &&
|
||||
ffs_verify_dinode_ckhash(&sblock, (struct ufs2_dinode *)ip->i_dp)) {
|
||||
pwarn("irelse: releasing inode with bad check-hash");
|
||||
prtinode(ip);
|
||||
}
|
||||
if (ip->i_bp->b_refcnt <= 0)
|
||||
pfatal("irelse: releasing unreferenced ino %ju\n",
|
||||
(uintmax_t) ip->i_number);
|
||||
|
|
@ -1419,21 +1429,20 @@ retry:
|
|||
cgdirty(cgbp);
|
||||
ginode(ino, &ip);
|
||||
dp = ip.i_dp;
|
||||
memset(dp, 0, ((sblock.fs_magic == FS_UFS1_MAGIC) ?
|
||||
sizeof(struct ufs1_dinode) : sizeof(struct ufs2_dinode)));
|
||||
DIP_SET(dp, di_db[0], allocblk(ino_to_cg(&sblock, ino), (long)1,
|
||||
std_checkblkavail));
|
||||
if (DIP(dp, di_db[0]) == 0) {
|
||||
inoinfo(ino)->ino_state = USTATE;
|
||||
inodirty(&ip);
|
||||
irelse(&ip);
|
||||
return (0);
|
||||
}
|
||||
DIP_SET(dp, di_mode, type);
|
||||
DIP_SET(dp, di_flags, 0);
|
||||
DIP_SET(dp, di_atime, time(NULL));
|
||||
DIP_SET(dp, di_ctime, DIP(dp, di_atime));
|
||||
DIP_SET(dp, di_mtime, DIP(dp, di_ctime));
|
||||
DIP_SET(dp, di_mtimensec, 0);
|
||||
DIP_SET(dp, di_ctimensec, 0);
|
||||
DIP_SET(dp, di_atimensec, 0);
|
||||
DIP_SET(dp, di_size, sblock.fs_fsize);
|
||||
DIP_SET(dp, di_blocks, btodb(sblock.fs_fsize));
|
||||
n_files++;
|
||||
|
|
|
|||
Loading…
Reference in a new issue