changeset 12901:7977d17e3193

6894195 race condition between ident_alloc() and ident_release() 6904790 More races in ldi. Bug 6894195 does not give the full picture.
author Suhasini Peddada <Suhasini.Peddada@Sun.COM>
date Thu, 22 Jul 2010 12:31:36 -0700
parents 8c8b525b1ad6
children 16985853e3aa
files usr/src/uts/common/os/driver_lyr.c
diffstat 1 files changed, 10 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/os/driver_lyr.c	Thu Jul 22 10:05:16 2010 +0100
+++ b/usr/src/uts/common/os/driver_lyr.c	Thu Jul 22 12:31:36 2010 -0700
@@ -213,7 +213,7 @@
 static struct ldi_ident *
 ident_alloc(char *mod_name, dev_info_t *dip, dev_t dev, major_t major)
 {
-	struct ldi_ident	*lip, **lipp;
+	struct ldi_ident	*lip, **lipp, *retlip;
 	modid_t			modid;
 	uint_t			index;
 
@@ -235,9 +235,10 @@
 		/* we found an ident in the hash */
 		ASSERT(strcmp((*lipp)->li_modname, mod_name) == 0);
 		(*lipp)->li_ref++;
+		retlip = *lipp;
 		mutex_exit(&ldi_ident_hash_lock[index]);
 		kmem_free(lip, sizeof (struct ldi_ident));
-		return (*lipp);
+		return (retlip);
 	}
 
 	/* initialize the new ident */
@@ -331,20 +332,20 @@
 static struct ldi_handle *
 handle_find(vnode_t *vp, struct ldi_ident *ident)
 {
-	struct ldi_handle	**lhpp;
+	struct ldi_handle	**lhpp, *retlhp;
 	int			index = LH_HASH(vp);
 
 	mutex_enter(&ldi_handle_hash_lock[index]);
 	lhpp = handle_find_ref_nolock(vp, ident);
+	retlhp = *lhpp;
 	mutex_exit(&ldi_handle_hash_lock[index]);
-	ASSERT(lhpp != NULL);
-	return (*lhpp);
+	return (retlhp);
 }
 
 static struct ldi_handle *
 handle_alloc(vnode_t *vp, struct ldi_ident *ident)
 {
-	struct ldi_handle	*lhp, **lhpp;
+	struct ldi_handle	*lhp, **lhpp, *retlhp;
 	uint_t			index;
 
 	ASSERT((vp != NULL) && (ident != NULL));
@@ -360,16 +361,17 @@
 	if (*lhpp != NULL) {
 		/* we found a handle in the hash */
 		(*lhpp)->lh_ref++;
+		retlhp = *lhpp;
 		mutex_exit(&ldi_handle_hash_lock[index]);
 
 		LDI_ALLOCFREE((CE_WARN, "ldi handle alloc: dup "
 		    "lh=0x%p, ident=0x%p, vp=0x%p, drv=%s, minor=0x%x",
-		    (void *)*lhpp, (void *)ident, (void *)vp,
+		    (void *)retlhp, (void *)ident, (void *)vp,
 		    mod_major_to_name(getmajor(vp->v_rdev)),
 		    getminor(vp->v_rdev)));
 
 		kmem_free(lhp, sizeof (struct ldi_handle));
-		return (*lhpp);
+		return (retlhp);
 	}
 
 	/* initialize the new handle */