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);
 }
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to