DragonFlyBSD Kernel Audit
DF-0928 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/vfs/ufs/ufsmount.h b/sys/vfs/ufs/ufsmount.h
--- a/sys/vfs/ufs/ufsmount.h
+++ b/sys/vfs/ufs/ufsmount.h
@@ -86,6 +86,7 @@
 	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 */
+	struct lwkt_token um_ihash_token;	/* guards um_ihashtbl + i_next */
 };
 
 /*
diff --git a/sys/vfs/ufs/ufs_ihash.c b/sys/vfs/ufs/ufs_ihash.c
--- a/sys/vfs/ufs/ufs_ihash.c
+++ b/sys/vfs/ufs/ufs_ihash.c
@@ -33,6 +33,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/thread.h>
 #include <sys/lock.h>
 #include <sys/vnode.h>
 #include <sys/malloc.h>
@@ -55,20 +56,25 @@
 void
 ufs_ihashinit(struct ufsmount *ump)
 {
+	lwkt_token_init(&ump->um_ihash_token, "ufsihash");
+	lwkt_gettoken(&ump->um_ihash_token);
 	ump->um_ihash = vfs_inodehashsize();
 	ump->um_ihashtbl = kmalloc(sizeof(void *) * ump->um_ihash,
 				   M_UFSIHASH,
 				   M_WAITOK|M_ZERO);
 	--ump->um_ihash;
+	lwkt_reltoken(&ump->um_ihash_token);
 }
 
 void
 ufs_ihashuninit(struct ufsmount *ump)
 {
+	lwkt_gettoken(&ump->um_ihash_token);
 	if (ump->um_ihashtbl) {
 		kfree(ump->um_ihashtbl, M_UFSIHASH);
 		ump->um_ihashtbl = NULL;
 	}
+	lwkt_reltoken(&ump->um_ihash_token);
 }
 
 /*
@@ -80,12 +86,16 @@
 {
 	struct inode *ip = NULL;
 
+	lwkt_gettoken(&ump->um_ihash_token);
 	for (ip = *INOHASH(ump, inum); ip; ip = ip->i_next) {
 		if (inum == ip->i_number && dev == ip->i_dev)
 			break;
 	}
-	if (ip)
+	if (ip) {
+		lwkt_reltoken(&ump->um_ihash_token);
 		return (ITOV(ip));
+	}
+	lwkt_reltoken(&ump->um_ihash_token);
 	return (NULLVP);
 }
 
@@ -101,6 +111,7 @@
 	struct inode *ip;
 	struct vnode *vp;
 
+	lwkt_gettoken(&ump->um_ihash_token);
 loop:
 	for (ip = *INOHASH(ump, inum); ip; ip = ip->i_next) {
 		if (inum != ip->i_number || dev != ip->i_dev)
@@ -120,8 +131,10 @@
 			vput(vp);
 			goto loop;
 		}
+		lwkt_reltoken(&ump->um_ihash_token);
 		return (vp);
 	}
+	lwkt_reltoken(&ump->um_ihash_token);
 	return (NULL);
 }
 
@@ -135,10 +148,12 @@
 {
 	struct inode *ip;
 
+	lwkt_gettoken(&ump->um_ihash_token);
 	for (ip = *INOHASH(ump, inum); ip; ip = ip->i_next) {
 		if (inum == ip->i_number && dev == ip->i_dev)
 			break;
 	}
+	lwkt_reltoken(&ump->um_ihash_token);
 	return(ip ? 1 : 0);
 }
 
@@ -152,9 +167,11 @@
 	struct inode *iq;
 
 	KKASSERT((ip->i_flag & IN_HASHED) == 0);
+	lwkt_gettoken(&ump->um_ihash_token);
 	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(&ump->um_ihash_token);
 			return(EBUSY);
 		}
 		ipp = &iq->i_next;
@@ -162,6 +179,7 @@
 	ip->i_next = NULL;
 	*ipp = ip;
 	ip->i_flag |= IN_HASHED;
+	lwkt_reltoken(&ump->um_ihash_token);
 	return(0);
 }
 
@@ -174,6 +192,7 @@
 	struct inode **ipp;
 	struct inode *iq;
 
+	lwkt_gettoken(&ump->um_ihash_token);
 	if (ip->i_flag & IN_HASHED) {
 		ipp = INOHASH(ump, ip->i_number);
 		while ((iq = *ipp) != NULL) {
@@ -186,5 +205,6 @@
 		ip->i_next = NULL;
 		ip->i_flag &= ~IN_HASHED;
 	}
+	lwkt_reltoken(&ump->um_ihash_token);
 }