Submit #2470

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

Added by vsrinivas over 1 year ago. Updated over 1 year ago.

Status:ClosedStart date:
Priority:NormalDue date:
Assignee:-% Done:

0%

Category:-
Target version:-

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(ip);
+ ump = VFSTOUFS(vp->v_mount);
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(dirrem->dm_mnt)->um_dev,
- dirrem->dm_oldinum);
+ ump = VFSTOUFS(dirrem->dm_mnt);
+ 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 <sys/param.h>
@@ -42,60 +41,52 @@
#include <sys/vnode.h>
#include <sys/malloc.h>
#include <sys/proc.h>
+#include <sys/mount.h>

#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(device, inum) (&ihashtbl[(minor(device) + (inum)) & ihash])
+#define INOHASH(ump, inum) \
+ (&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(dev, inum); ip; ip = ip->i_next) {
+ for (ip = *INOHASH(ump, inum); ip; ip = ip->i_next) {
if (inum == ip->i_number && dev == ip->i_dev)
break;
}
- lwkt_reltoken(&ufs_ihash_token);
if (ip)
return (ITOV(ip));
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(dev, inum); ip; ip = ip->i_next) {
+ for (ip = *INOHASH(ump, inum); ip; ip = ip->i_next) {
if (inum != ip->i_number || dev != ip->i_dev)
continue;
vp = ITOV(ip);
@@ -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(dev, inum); ip; ip = ip->i_next) {
+ for (ip = *INOHASH(ump, inum); 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(dev, inum); ip; ip = ip->i_next) {
+ for (ip = *INOHASH(ump, inum); 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(ip->i_dev, ip->i_number);
+ ipp = INOHASH(ump, ip->i_number);
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(vp->v_mount);
+
if (prtactive && vp->v_sysref.refcnt > 1)
vprint("ufs_reclaim: pushing active", vp);
ip = VTOI(vp);
@@ -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

History

#1 Updated by vsrinivas over 1 year ago

  • Status changed from New to Closed

Committed as f0accfd0be644e06d9ca3f5202198aeafcea60a9.

Also available in: Atom PDF