Project

General

Profile

Actions

Submit #2470

closed

[PATCH] kernel -- ffs: Move inode hash to per-mount structure.

Added by vsrinivas over 11 years ago. Updated over 11 years ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Category:
-
Target version:
-
Start date:
Due date:
% Done:

0%

Estimated time:

Description

FFS uses a hash table to map inode number to per-inode data. The
hash table was global, rather than per-mount, and was keyed off of
(inode number, per-mount device minor number). This patch converts
it to a per-mount table, sychronized by the per-mount token.
---
sys/vfs/ufs/ffs_alloc.c | 8 ++--
sys/vfs/ufs/ffs_softdep.c | 7 +
+--
sys/vfs/ufs/ffs_vfsops.c | 24 ++++--------
sys/vfs/ufs/ufs_extern.h | 14 +++-----
sys/vfs/ufs/ufs_ihash.c | 80 +
+++++++++++++++------------------------------
sys/vfs/ufs/ufs_inode.c | 5 +-
sys/vfs/ufs/ufs_vfsops.c | 1
sys/vfs/ufs/ufsmount.h | 11 +
----
8 files changed, 64 insertions(+), 86 deletions(-)

diff --git a/sys/vfs/ufs/ffs_alloc.c b/sys/vfs/ufs/ffs_alloc.c
index afcde72..5a1f8f8 100644
--- a/sys/vfs/ufs/ffs_alloc.c
+++ b/sys/vfs/ufs/ffs_alloc.c
@ -1354,6 +1354,7 @ fail:
static ino_t
ffs_nodealloccg(struct inode *ip, int cg, ufs_daddr_t ipref, int mode) {
+ struct ufsmount *ump;
struct fs *fs;
struct cg *cgp;
struct buf *bp;
@ -1362,7 +1363,10 @ ffs_nodealloccg(struct inode *ip, int cg, ufs_daddr_t ipref, int mode)
int error, len, arraysize, i;
int icheckmiss;
ufs_daddr_t ibase;
+ struct vnode *vp;

+ vp = ITOV;
+ ump = VFSTOUFS;
fs = ip->i_fs;
if (fs->fs_cs(fs, cg).cs_nifree == 0)
return (0);
@ -1388,7 +1392,7 @ ffs_nodealloccg(struct inode *ip, int cg, ufs_daddr_t ipref, int mode)
if (ipref) {
ipref %= fs->fs_ipg;
if (isclr(inosused, ipref)) {
- if (ufs_ihashcheck(ip->i_dev, ibase + ipref) 0)
+ if (ufs_ihashcheck(ump, ip->i_dev, ibase + ipref) 0)
goto gotit;
}
}
@ -1422,7 +1426,7 @ ffs_nodealloccg(struct inode *ip, int cg, ufs_daddr_t ipref, int mode) * quick-check up above.
*/
if ((map & (1 << i)) 0) {
- if (ufs_ihashcheck(ip->i_dev, ibase + (ipref << 3) + i) 0) {
+ if (ufs_ihashcheck(ump, ip->i_dev, ibase + (ipref << 3) + i) == 0) {
ipref = (ipref << 3) + i;
cgp->cg_irotor = (ipref + 1) % fs->fs_ipg;
goto gotit;
diff --git a/sys/vfs/ufs/ffs_softdep.c b/sys/vfs/ufs/ffs_softdep.c
index b6a8cbf..2e9788d 100644
--- a/sys/vfs/ufs/ffs_softdep.c
+++ b/sys/vfs/ufs/ffs_softdep.c
@ -592,6 +592,7 @ done:
static int
process_worklist_item(struct mount *matchmnt, int flags) {
+ struct ufsmount *ump;
struct worklist *wk;
struct dirrem *dirrem;
struct fs *matchfs;
@ -612,8 +613,10 @ process_worklist_item(struct mount *matchmnt, int flags)
if ((flags & LK_NOWAIT) == 0 || wk->wk_type != D_DIRREM)
break;
dirrem = WK_DIRREM(wk);
- vp = ufs_ihashlookup(VFSTOUFS->um_dev,
- dirrem->dm_oldinum);
+ ump = VFSTOUFS;
+ lwkt_gettoken(&ump->um_mountp->mnt_token);
+ vp = ufs_ihashlookup(ump, ump->um_dev, dirrem->dm_oldinum);
+ lwkt_reltoken(&ump->um_mountp->mnt_token);
if (vp == NULL || !vn_islocked(vp))
break;
}
diff --git a/sys/vfs/ufs/ffs_vfsops.c b/sys/vfs/ufs/ffs_vfsops.c
index 92c008b..d62f5b3 100644
--- a/sys/vfs/ufs/ffs_vfsops.c
+++ b/sys/vfs/ufs/ffs_vfsops.c
@ -84,7 +84,6 @ static struct vfsops ufs_vfsops = {
.vfs_checkexp = ufs_check_export,
.vfs_vptofh = ffs_vptofh,
.vfs_init = ffs_init,
- .vfs_uninit = ufs_uninit
};

VFS_SET(ufs_vfsops, ufs, 0);
@ -768,6 +767,7 @ ffs_mountfs(struct vnode *devvp, struct mount *mp, struct malloc_type *mtype)
mp->mnt_time = fs->fs_time;
}

+ ufs_ihashinit(ump);
ump->um_savedmaxfilesize = fs->fs_maxfilesize; /* XXX /
maxfilesize = (uint64_t)0x40000000 * fs->fs_bsize - 1; /
XXX /
/
Enforce limit caused by vm object backing (32 bits vm_pindex_t). */
@ -796,6 +796,7 @ out:
brelse(bp);
VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE);
if (ump) {
+ ufs_ihashuninit(ump);
kfree(ump->um_fs, M_UFSMNT);
kfree(ump, M_UFSMNT);
mp->mnt_data = (qaddr_t)0;
@ -871,6 +872,7 @ ffs_unmount(struct mount *mp, int mntflags)

vrele(ump->um_devvp);

+ ufs_ihashuninit(ump);
kfree(fs->fs_csp, M_UFSMNT);
kfree(fs, M_UFSMNT);
kfree(ump, M_UFSMNT);
@ -1085,8 +1087,8 @ ffs_vget(struct mount *mp, struct vnode *dvp, ino_t ino, struct vnode **vpp)

ump = VFSTOUFS(mp);
dev = ump->um_dev;
restart:
if ((*vpp = ufs_ihashget(dev, ino)) != NULL) {
+
+ if ((*vpp = ufs_ihashget(ump, dev, ino)) != NULL) {
return (0);
}

@ -1100,7 +1102,8 @ restart: * XXX this may no longer be true since getnewvnode returns a * VX locked vnode now.
*/
- ip = kmalloc(sizeof(struct inode), ump->um_malloctype, M_WAITOK);
+ ip = kmalloc(sizeof(struct inode), ump->um_malloctype,
+ M_WAITOK | M_ZERO);

/* Allocate a new vnode/inode. */
error = getnewvnode(VT_UFS, mp, &vp, VLKTIMEOUT, LK_CANRECURSE);
@ -1109,7 +1112,6 @ restart:
kfree(ip, ump->um_malloctype);
return (error);
}
- bzero((caddr_t)ip, sizeof(struct inode));
ip->i_vnode = vp;
ip->i_fs = fs = ump->um_fs;
ip->i_dev = dev;
@ -1123,16 +1125,10 @ restart:
#endif
/*
- * Insert it into the inode hash table and check for a collision.
- * If a collision occurs, throw away the vnode and try again.
+ * Insert it into the inode hash table.
*/
- if (ufs_ihashins(ip) != 0) {
- kprintf("debug: ufs ihashins collision, retrying inode %ld\n",
- (long)ip->i_number);
- vp->v_type = VBAD;
- vx_put(vp);
- kfree(ip, ump->um_malloctype);
- goto restart;
+ if (ufs_ihashins(ump, ip) != 0) {
+ panic("duplicate inode in inohash");
}
vp->v_data = ip;

diff --git a/sys/vfs/ufs/ufs_extern.h b/sys/vfs/ufs/ufs_extern.h
index d05c350..6f681b6 100644
--- a/sys/vfs/ufs/ufs_extern.h
++ b/sys/vfs/ufs/ufs_extern.h
@ -78,16 +78,16 @ int ufs_dirremove(struct vnode *, struct inode *, int, int);
int ufs_dirrewrite(struct inode *, struct inode *, ino_t, int, int);
int ufs_getlbns(struct vnode *, ufs_daddr_t, struct indir *, int *);
struct vnode *
- ufs_ihashget(cdev_t, ino_t);
int ufs_ihashcheck(cdev_t, ino_t);
-void ufs_ihashinit(void);
-int ufs_ihashins(struct inode *);
ufs_ihashget(struct ufsmount *, cdev_t, ino_t);
int ufs_ihashcheck(struct ufsmount *, cdev_t, ino_t);
+void ufs_ihashinit(struct ufsmount *);
+void ufs_ihashuninit(struct ufsmount *);
+int ufs_ihashins(struct ufsmount *, struct inode *);
struct vnode *
ufs_ihashlookup(cdev_t, ino_t);
void ufs_ihashrem(struct inode *);
ufs_ihashlookup(struct ufsmount *, cdev_t, ino_t);
void ufs_ihashrem(struct ufsmount *, struct inode *);
int ufs_inactive(struct vop_inactive_args *);
int ufs_init(struct vfsconf *);
-int ufs_uninit(struct vfsconf *);
void ufs_itimes(struct vnode *vp);
int ufs_lookup(struct vop_old_lookup_args *);
int ufs_reclaim(struct vop_reclaim_args *);
diff --git a/sys/vfs/ufs/ufs_ihash.c b/sys/vfs/ufs/ufs_ihash.c
index 277bcf2..426b2d4 100644
-- a/sys/vfs/ufs/ufs_ihash.c
++ b/sys/vfs/ufs/ufs_ihash.c
@ -32,7 +32,6 @ * * @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95 * $FreeBSD: src/sys/ufs/ufs/ufs_ihash.c,v 1.20 1999/08/28 00:52:29 peter Exp $
- * $DragonFly: src/sys/vfs/ufs/ufs_ihash.c,v 1.20 2006/10/14 16:26:40 dillon Exp $
*/

#include &lt;sys/param.h&gt;
@ -42,60 +41,52 @
#include &lt;sys/vnode.h&gt;
#include &lt;sys/malloc.h&gt;
#include &lt;sys/proc.h&gt;
+#include &lt;sys/mount.h&gt;
#include "quota.h" 
#include "inode.h"
#include "ufs_extern.h"
+#include "ufsmount.h"
static MALLOC_DEFINE(M_UFSIHASH, "UFS ihash", "UFS Inode hash tables");
/*
* Structures associated with inode cacheing.
- /
-static struct inode **ihashtbl;
-static u_long ihash; /
size of hash table - 1 */
-static struct lwkt_token ufs_ihash_token;

#define INOHASH (&ihashtbl[(minor(device) + (inum)) & ihash])
#define INOHASH \
(&ump
>um_ihashtbl[inum & ump->um_ihash])

/*
 * Initialize inode hash table.
*/
void
-ufs_ihashinit(void)
+ufs_ihashinit(struct ufsmount *ump) {
- ihash = 16;
- while (ihash < desiredvnodes)
- ihash <<= 1;
- ihashtbl = kmalloc(sizeof(void *) * ihash, M_UFSIHASH, M_WAITOK|M_ZERO);
- --ihash;
- lwkt_token_init(&ufs_ihash_token, "ufsihash");
+ ump->um_ihash = 16;
+ while (ump->um_ihash < desiredvnodes)
+ ump->um_ihash <<= 1;
+ ump->um_ihashtbl = kmalloc(sizeof(void *) * ump->um_ihash, M_UFSIHASH,
+ M_WAITOK|M_ZERO);
+ --ump->um_ihash;
}

-int
-ufs_uninit(struct vfsconf *vfc)
+void
+ufs_ihashuninit(struct ufsmount *ump) {
- lwkt_gettoken(&ufs_ihash_token);
- if (ihashtbl)
- kfree(ihashtbl, M_UFSIHASH);
- lwkt_reltoken(&ufs_ihash_token);

return (0);
+ if (ump->um_ihashtbl)
+ kfree(ump->um_ihashtbl, M_UFSIHASH);
}
+
/* * Use the device/inum pair to find the incore inode, and return a pointer * to it. If it is in core, return it, even if it is locked.
*/
struct vnode *
-ufs_ihashlookup(cdev_t dev, ino_t inum)
+ufs_ihashlookup(struct ufsmount *ump, cdev_t dev, ino_t inum) {
- struct inode *ip;
+ struct inode *ip = NULL;

- lwkt_gettoken(&ufs_ihash_token);
- for (ip = *INOHASH; ip; ip = ip->i_next) {
+ for (ip = *INOHASH; ip; ip = ip->i_next) {
if (inum ip->i_number && dev ip->i_dev)
break;
}
- lwkt_reltoken(&ufs_ihash_token);
if (ip)
return (ITOV);
return (NULLVP);
@ -105,20 +96,16 @ ufs_ihashlookup(cdev_t dev, ino_t inum) * Use the device/inum pair to find the incore inode, and return a pointer * to it. If it is in core, but locked, wait for it. *
- * Note that the serializing tokens do not prevent other processes from
- * playing with the data structure being protected while we are blocked.
- * They do protect us from preemptive interrupts which might try to
- * play with the protected data structure.
+ * This subroutine may block.
*/
struct vnode *
-ufs_ihashget(cdev_t dev, ino_t inum)
+ufs_ihashget(struct ufsmount *ump, cdev_t dev, ino_t inum) {
struct inode *ip;
struct vnode *vp;

- lwkt_gettoken(&ufs_ihash_token);
loop:
- for (ip = *INOHASH; ip; ip = ip->i_next) {
+ for (ip = *INOHASH; ip; ip = ip->i_next) {
if (inum != ip->i_number || dev != ip->i_dev)
continue;
vp = ITOV;
@ -128,7 +115,7 @ loop: * We must check to see if the inode has been ripped * out from under us after blocking.
*/
- for (ip = *INOHASH; ip; ip = ip->i_next) {
+ for (ip = *INOHASH; ip; ip = ip->i_next) {
if (inum ip->i_number && dev ip->i_dev)
break;
}
@ -136,10 +123,8 @ loop:
vput(vp);
goto loop;
}
- lwkt_reltoken(&ufs_ihash_token);
return (vp);
}
- lwkt_reltoken(&ufs_ihash_token);
return (NULL);
}

@ -149,16 +134,14 @ loop: * reallocate of its inode number before we have had a chance to recycle it.
*/
int
-ufs_ihashcheck(cdev_t dev, ino_t inum)
+ufs_ihashcheck(struct ufsmount *ump, cdev_t dev, ino_t inum) {
struct inode *ip;

- lwkt_gettoken(&ufs_ihash_token);
- for (ip = *INOHASH; ip; ip = ip->i_next) {
+ for (ip = *INOHASH; ip; ip = ip->i_next) {
if (inum ip->i_number && dev ip->i_dev)
break;
}
- lwkt_reltoken(&ufs_ihash_token);
return(ip ? 1 : 0);
}

@ -166,17 +149,15 @ ufs_ihashcheck(cdev_t dev, ino_t inum) * Insert the inode into the hash table, and return it locked.
*/
int
-ufs_ihashins(struct inode *ip)
+ufs_ihashins(struct ufsmount *ump, struct inode *ip) {
struct inode **ipp;
struct inode *iq;

KKASSERT((ip->i_flag & IN_HASHED) == 0);
- lwkt_gettoken(&ufs_ihash_token);
- ipp = INOHASH(ip->i_dev, ip->i_number);
+ ipp = INOHASH(ump, ip->i_number);
while ((iq = *ipp) != NULL) {
if (ip->i_dev iq->i_dev && ip->i_number iq->i_number) {
- lwkt_reltoken(&ufs_ihash_token);
return(EBUSY);
}
ipp = &iq->i_next;
@ -184,7 +165,6 @ ufs_ihashins(struct inode *ip)
ip->i_next = NULL;
*ipp = ip;
ip->i_flag |= IN_HASHED;
- lwkt_reltoken(&ufs_ihash_token);
return(0);
}

@ -192,14 +172,13 @ ufs_ihashins(struct inode *ip) * Remove the inode from the hash table.
*/
void
-ufs_ihashrem(struct inode *ip)
+ufs_ihashrem(struct ufsmount *ump, struct inode *ip) {
struct inode **ipp;
struct inode *iq;

- lwkt_gettoken(&ufs_ihash_token);
if (ip->i_flag & IN_HASHED) {
- ipp = INOHASH;
+ ipp = INOHASH;
while ((iq = *ipp) != NULL) {
if (ip == iq)
break;
@ -210,6 +189,5 @ ufs_ihashrem(struct inode *ip)
ip->i_next = NULL;
ip->i_flag &= ~IN_HASHED;
}
- lwkt_reltoken(&ufs_ihash_token);
}

diff --git a/sys/vfs/ufs/ufs_inode.c b/sys/vfs/ufs/ufs_inode.c
index 9b51bd5..6ccd0c4 100644
--- a/sys/vfs/ufs/ufs_inode.c
+++ b/sys/vfs/ufs/ufs_inode.c
@ -116,10 +116,13 @ ufs_reclaim(struct vop_reclaim_args *ap) {
struct inode *ip;
struct vnode *vp = ap->a_vp;
+ struct ufsmount *ump;
#ifdef QUOTA
int i;
#endif

+ ump = VFSTOUFS;

if (prtactive && vp->v_sysref.refcnt > 1)
vprint("ufs_reclaim: pushing active", vp);
ip = VTOI;
@ -146,7 +149,7 @ ufs_reclaim(struct vop_reclaim_args *ap)
*/
vp->v_data = NULL;
if (ip) {
- ufs_ihashrem(ip);
ufs_ihashrem(ump, ip);
if (ip->i_devvp) {
vrele(ip->i_devvp);
ip->i_devvp = 0;
diff --git a/sys/vfs/ufs/ufs_vfsops.c b/sys/vfs/ufs/ufs_vfsops.c
index bf1ef52..315eed8 100644
--- a/sys/vfs/ufs/ufs_vfsops.c
++ b/sys/vfs/ufs/ufs_vfsops.c
@ -192,7 +192,6 @ ufs_init(struct vfsconf *vfsp)
if (done)
return (0);
done = 1;
- ufs_ihashinit();
#ifdef QUOTA
ufs_dqinit();
#endif
diff --git a/sys/vfs/ufs/ufsmount.h b/sys/vfs/ufs/ufsmount.h
index 1a07f1d..c789428 100644
--- a/sys/vfs/ufs/ufsmount.h
++ b/sys/vfs/ufs/ufsmount.h
@ -32,7 +32,6 @ * * @(#)ufsmount.h 8.6 (Berkeley) 3/30/95 * $FreeBSD: src/sys/ufs/ufs/ufsmount.h,v 1.17 1999/12/29 04:55:06 peter Exp $
- * $DragonFly: src/sys/vfs/ufs/ufsmount.h,v 1.11 2008/08/04 18:15:47 dillon Exp $
*/

#ifndef VFS_UFS_UFSMOUNT_H
@ -76,13 +75,7 @ struct ufsmount {
cdev_t um_dev; /* device mounted /
struct vnode *um_devvp; /
block device mounted vnode */

- union { /* pointer to superblock /
- struct fs *fs; /
FFS /
- struct ext2_sb_info *e2fs; /
EXT2FS /
- } ufsmount_u;
# define um_fs ufsmount_u.fs
# define um_e2fs ufsmount_u.e2fs
# define um_e2fsb ufsmount_u.e2fs>s_es
+ struct fs *um_fs; /
FFS /
struct vnode *um_quotas[MAXQUOTAS]; /
pointer to quota files /
struct ucred *um_cred[MAXQUOTAS]; /
quota file access cred /
u_long um_nindir; /
indirect ptrs per block /
@ -95,6 +88,8 @ struct ufsmount {
int64_t um_savedmaxfilesize; /
XXX - limit maxfilesize /
struct malloc_type *um_malloctype; /
The inodes malloctype /
int um_i_effnlink_valid; /
i_effnlink valid? /
+ struct inode **um_ihashtbl; /
inum to inode map /
+ u_long um_ihash; /
size of hash table - 1 */
};

/*
--
1.7.12.1.382.gb0576a6

--
-- vs

Actions #1

Updated by vsrinivas over 11 years ago

  • Status changed from New to Closed

Committed as f0accfd0be644e06d9ca3f5202198aeafcea60a9.

Actions

Also available in: Atom PDF