summaryrefslogtreecommitdiffstats
path: root/sys/ofed
diff options
context:
space:
mode:
authormarkj <markj@FreeBSD.org>2015-05-02 00:26:38 +0000
committermarkj <markj@FreeBSD.org>2015-05-02 00:26:38 +0000
commit713ce9cc6803907124e157f7243f1adfef1c05cb (patch)
tree911852b96b3a4d0759ca6b426da07bf6c3fdfc96 /sys/ofed
parentaeb0d2a45d79b0b3df20c20610021ce84ece4a3e (diff)
downloadFreeBSD-src-713ce9cc6803907124e157f7243f1adfef1c05cb.zip
FreeBSD-src-713ce9cc6803907124e157f7243f1adfef1c05cb.tar.gz
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
Diffstat (limited to 'sys/ofed')
-rw-r--r--sys/ofed/include/linux/linux_idr.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/sys/ofed/include/linux/linux_idr.c b/sys/ofed/include/linux/linux_idr.c
index 809e178..a692fb8 100644
--- a/sys/ofed/include/linux/linux_idr.c
+++ b/sys/ofed/include/linux/linux_idr.c
@@ -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, int *idp)
}
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);
}
OpenPOWER on IntegriCloud