Issue #2470 has been updated by Venkatesh Srinivas. Status changed from New to Closed
Committed as f0accfd0be644e06d9ca3f5202198aeafcea60a9. ---------------------------------------- Submit #2470: [PATCH] kernel -- ffs: Move inode hash to per-mount structure. http://bugs.dragonflybsd.org/issues/2470 Author: Venkatesh Srinivas Status: Closed Priority: Normal Assignee: Category: Target version: 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 -- You have received this notification because you have either subscribed to it, or are involved in it. To change your notification preferences, please click here: http://bugs.dragonflybsd.org/my/account
