Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 2 May 2015 00:26:39 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r282331 - head/sys/ofed/include/linux
Message-ID:  <201505020026.t420QdH1080616@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markj
Date: Sat May  2 00:26:38 2015
New Revision: 282331
URL: https://svnweb.freebsd.org/changeset/base/282331

Log:
  Don't drop the idr lock before verifying that the newly-inserted element
  is present in the tree. Otherwise there exists a window during which the
  element could be removed by another thread, triggering an incorrect
  assertion failure.
  
  Reviewed by:	jeff
  MFC after:	1 week
  Sponsored by:	EMC / Isilon Storage Division

Modified:
  head/sys/ofed/include/linux/linux_idr.c

Modified: head/sys/ofed/include/linux/linux_idr.c
==============================================================================
--- head/sys/ofed/include/linux/linux_idr.c	Fri May  1 23:54:09 2015	(r282330)
+++ head/sys/ofed/include/linux/linux_idr.c	Sat May  2 00:26:38 2015	(r282331)
@@ -185,27 +185,37 @@ out:
 	return (res);
 }
 
-void *
-idr_find(struct idr *idr, int id)
+static inline void *
+idr_find_locked(struct idr *idr, int id)
 {
 	struct idr_layer *il;
 	void *res;
 	int layer;
 
-	res = NULL;
+	mtx_assert(&idr->lock, MA_OWNED);
+
 	id &= MAX_ID_MASK;
-	mtx_lock(&idr->lock);
+	res = NULL;
 	il = idr->top;
 	layer = idr->layers - 1;
 	if (il == NULL || id > idr_max(idr))
-		goto out;
+		return (NULL);
 	while (layer && il) {
 		il = il->ary[idr_pos(id, layer)];
 		layer--;
 	}
 	if (il != NULL)
 		res = il->ary[id & IDR_MASK];
-out:
+	return (res);
+}
+
+void *
+idr_find(struct idr *idr, int id)
+{
+	void *res;
+
+	mtx_lock(&idr->lock);
+	res = idr_find_locked(idr, id);
 	mtx_unlock(&idr->lock);
 	return (res);
 }
@@ -331,13 +341,13 @@ idr_get_new(struct idr *idr, void *ptr, 
 	}
 	error = 0;
 out:
-	mtx_unlock(&idr->lock);
 #ifdef INVARIANTS
-	if (error == 0 && idr_find(idr, id) != ptr) {
+	if (error == 0 && idr_find_locked(idr, id) != ptr) {
 		panic("idr_get_new: Failed for idr %p, id %d, ptr %p\n",
 		    idr, id, ptr);
 	}
 #endif
+	mtx_unlock(&idr->lock);
 	return (error);
 }
 
@@ -438,12 +448,12 @@ restart:
 	}
 	error = 0;
 out:
-	mtx_unlock(&idr->lock);
 #ifdef INVARIANTS
-	if (error == 0 && idr_find(idr, id) != ptr) {
+	if (error == 0 && idr_find_locked(idr, id) != ptr) {
 		panic("idr_get_new_above: Failed for idr %p, id %d, ptr %p\n",
 		    idr, id, ptr);
 	}
 #endif
+	mtx_unlock(&idr->lock);
 	return (error);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201505020026.t420QdH1080616>