[DragonFlyBSD - Submit #2470] (Closed) [PATCH] kernel -- ffs: Move inode hash to per-mount structure.

Venkatesh Srinivas via Redmine bugtracker-admin at leaf.dragonflybsd.org
Mon Dec 10 18:21:32 PST 2012


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



More information about the Submit mailing list