svn commit: r282331 - head/sys/ofed/include/linux
Mark Johnston
markj at FreeBSD.org
Sat May 2 00:26:39 UTC 2015
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);
}
More information about the svn-src-head
mailing list