summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarkj <markj@FreeBSD.org>2015-05-29 03:47:35 +0000
committermarkj <markj@FreeBSD.org>2015-05-29 03:47:35 +0000
commitaff03409ef10bf1363e2ad798c623229bcd51f20 (patch)
treedee95bdafefc75f9223861df9ed36db94e0c4731
parent444aa14df480136b6e47df9fef098b29ab1e5819 (diff)
downloadFreeBSD-src-aff03409ef10bf1363e2ad798c623229bcd51f20.zip
FreeBSD-src-aff03409ef10bf1363e2ad798c623229bcd51f20.tar.gz
MFC r282331:
Don't drop the idr lock before verifying that the newly-inserted element is present in the tree. MFC r282741: find_next_bit() and find_next_zero_bit(): if the caller-specified offset lies within the last block of the bit set and no bits are set beyond the offset, terminate the search immediately instead of continuing as though there are further blocks in the set and subsequently returning an incorrect result. MFC r282743: Ensure that msecs_to_jiffies(0) == 0.
-rw-r--r--sys/ofed/include/linux/bitops.h4
-rw-r--r--sys/ofed/include/linux/jiffies.h2
-rw-r--r--sys/ofed/include/linux/linux_idr.c30
3 files changed, 25 insertions, 11 deletions
diff --git a/sys/ofed/include/linux/bitops.h b/sys/ofed/include/linux/bitops.h
index f225fdc..d3f82fe 100644
--- a/sys/ofed/include/linux/bitops.h
+++ b/sys/ofed/include/linux/bitops.h
@@ -165,6 +165,8 @@ find_next_bit(unsigned long *addr, unsigned long size, unsigned long offset)
mask = (*addr) & ~BIT_MASK(offs);
if (mask)
return (bit + __ffsl(mask));
+ if (size - bit <= BITS_PER_LONG)
+ return (size);
bit += BITS_PER_LONG;
addr++;
}
@@ -203,6 +205,8 @@ find_next_zero_bit(unsigned long *addr, unsigned long size,
mask = ~(*addr) & ~BIT_MASK(offs);
if (mask)
return (bit + __ffsl(mask));
+ if (size - bit <= BITS_PER_LONG)
+ return (size);
bit += BITS_PER_LONG;
addr++;
}
diff --git a/sys/ofed/include/linux/jiffies.h b/sys/ofed/include/linux/jiffies.h
index b8757bb..dce2e15 100644
--- a/sys/ofed/include/linux/jiffies.h
+++ b/sys/ofed/include/linux/jiffies.h
@@ -42,7 +42,7 @@ msecs_to_jiffies(int msec)
tv.tv_sec = msec / 1000;
tv.tv_usec = (msec % 1000) * 1000;
- return (tvtohz(&tv));
+ return (tvtohz(&tv) - 1);
}
#define jiffies ticks
diff --git a/sys/ofed/include/linux/linux_idr.c b/sys/ofed/include/linux/linux_idr.c
index 273f2ea..715a7d7 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