Date: Thu, 28 Jan 2010 10:22:25 -0800 (PST) From: "Pedro F. Giffuni" <giffunip@tutopia.com> To: FreeBSD-gnats-submit@FreeBSD.org, freebsd-bugs@FreeBSD.org Subject: Re: kern/142924: Small cleanup for the inode struct in ext2fs (based on UFS) Message-ID: <920788.12268.qm@web113508.mail.gq1.yahoo.com>
index | next in thread | raw e-mail
[-- Attachment #1 --]
Include two more simple patches from ufs_lookup.c:
CVS 1.54:
When compacting directories, ufs_direnter() always trusted DIRSIZ()
to supply the number of bytes to be bcopy()'d to move an entry. If
d_ino == 0 however, DIRSIZ() is not guaranteed to return a sensible
length, so ufs_direnter could end up corrupting a directory during
compaction.
CVS 1.45:
Extend the sanity checks in ufs_lookup to ensure that each directory
entry fits within its DIRBLKSIZ block.
_______
These were meant to fix issues found with dirhash on UFS but ext2fs
still works here with those changes so I think it's good to have
them, JIC we end up bringing over dirhash to ext2fs.
[-- Attachment #2 --]
diff -ru ext2fs.bsd/ext2_lookup.c ext2fs/ext2_lookup.c
--- ext2fs.bsd/ext2_lookup.c 2010-01-17 19:02:30.000000000 +0000
+++ ext2fs/ext2_lookup.c 2010-01-24 19:27:52.000000000 +0000
@@ -347,6 +347,7 @@
slotneeded = (sizeof(struct direct) - MAXNAMLEN +
cnp->cn_namelen + 3) &~ 3; */
}
+ bmask = VFSTOEXT2(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1;
/*
* If there is cached information on a previous search of
@@ -359,9 +360,8 @@
* profiling time and hence has been removed in the interest
* of simplicity.
*/
- bmask = VFSTOEXT2(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1;
if (nameiop != LOOKUP || i_diroff == 0 ||
- i_diroff > dp->i_size) {
+ i_diroff >= dp->i_size) {
entryoffsetinblock = 0;
i_offset = 0;
numdirpasses = 1;
@@ -408,9 +408,9 @@
* directory. Complete checks can be run by setting
* "vfs.e2fs.dirchk" to be true.
*/
- ep = (struct ext2fs_direct_2 *)
- ((char *)bp->b_data + entryoffsetinblock);
- if (ep->e2d_reclen == 0 ||
+ ep = (struct ext2fs_direct_2 *)((char *)bp->b_data + entryoffsetinblock);
+ if (ep->e2d_reclen == 0 || ep->e2d_reclen >
+ DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)) ||
(dirchk && ext2_dirbadentry(vdp, ep, entryoffsetinblock))) {
int i;
ext2_dirbad(dp, i_offset, "mangled entry");
@@ -550,10 +550,10 @@
* Check that directory length properly reflects presence
* of this entry.
*/
- if (entryoffsetinblock + EXT2_DIR_REC_LEN(ep->e2d_namlen)
+ if (dp->i_offset + EXT2_DIR_REC_LEN(ep->e2d_namlen)
> dp->i_size) {
ext2_dirbad(dp, i_offset, "i_size too small");
- dp->i_size = entryoffsetinblock+EXT2_DIR_REC_LEN(ep->e2d_namlen);
+ dp->i_size = dp->i_offset+EXT2_DIR_REC_LEN(ep->e2d_namlen);
dp->i_flag |= IN_CHANGE | IN_UPDATE;
}
brelse(bp);
@@ -855,17 +855,30 @@
* space.
*/
ep = (struct ext2fs_direct_2 *)dirbuf;
- dsize = EXT2_DIR_REC_LEN(ep->e2d_namlen);
+ dsize = ep->e2d_ino ? EXT2_DIR_REC_LEN(ep->e2d_namlen) : 0;
spacefree = ep->e2d_reclen - dsize;
for (loc = ep->e2d_reclen; loc < dp->i_count; ) {
nep = (struct ext2fs_direct_2 *)(dirbuf + loc);
- if (ep->e2d_ino) {
- /* trim the existing slot */
- ep->e2d_reclen = dsize;
- ep = (struct ext2fs_direct_2 *)((char *)ep + dsize);
- } else {
- /* overwrite; nothing there; header is ours */
- spacefree += dsize;
+
+ /* trim the existing slot (NB: dsize may be zero). */
+ ep->e2d_reclen = dsize;
+ ep = (struct ext2fs_direct_2 *)((char *)ep + dsize);
+
+ /* Read nep->e2d_reclen now as the bcopy() may clobber it. */
+ loc += nep->e2d_reclen;
+ if (nep->e2d_ino == 0) {
+ /*
+ * A mid-block unused entry. Such entries are
+ * never created by the kernel, but fsck
+ * can create them (and not fix them).
+ *
+ * Add up the free space, and initialise the
+ * relocated entry since we don't bcopy it.
+ */
+ spacefree += nep->e2d_reclen;
+ ep->e2d_ino = 0;
+ dsize = 0;
+ continue;
}
dsize = EXT2_DIR_REC_LEN(nep->e2d_namlen);
spacefree += nep->e2d_reclen - dsize;
diff -ru ext2fs.bsd/ext2_vfsops.c ext2fs/ext2_vfsops.c
--- ext2fs.bsd/ext2_vfsops.c 2010-01-17 19:02:56.000000000 +0000
+++ ext2fs/ext2_vfsops.c 2010-01-18 15:43:20.000000000 +0000
@@ -945,9 +945,8 @@
}
/*
- * Finish inode initialization now that aliasing has been resolved.
+ * Finish inode initialization.
*/
- ip->i_devvp = ump->um_devvp;
/*
* Set up a generation number for this inode if it does not
diff -ru ext2fs.bsd/inode.h ext2fs/inode.h
--- ext2fs.bsd/inode.h 2010-01-17 19:03:21.000000000 +0000
+++ ext2fs/inode.h 2010-01-18 15:43:20.000000000 +0000
@@ -62,7 +62,6 @@
*/
struct inode {
struct vnode *i_vnode;/* Vnode associated with this inode. */
- struct vnode *i_devvp;/* Vnode for block I/O. */
struct ext2mount *i_ump;
u_int32_t i_flag; /* flags, see below */
ino_t i_number; /* The identity of the inode. */
@@ -143,6 +142,9 @@
#define IN_SPACECOUNTED 0x0080 /* Blocks to be freed in free count. */
#define IN_LAZYACCESS 0x0100 /* Process IN_ACCESS after the
suspension finished */
+
+#define i_devvp i_ump->um_devvp
+
#ifdef _KERNEL
/*
* Structure used to pass around logical block paths generated by
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?920788.12268.qm>
