diff options
author | markj <markj@FreeBSD.org> | 2015-05-29 03:47:35 +0000 |
---|---|---|
committer | markj <markj@FreeBSD.org> | 2015-05-29 03:47:35 +0000 |
commit | aff03409ef10bf1363e2ad798c623229bcd51f20 (patch) | |
tree | dee95bdafefc75f9223861df9ed36db94e0c4731 | |
parent | 444aa14df480136b6e47df9fef098b29ab1e5819 (diff) | |
download | FreeBSD-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.h | 4 | ||||
-rw-r--r-- | sys/ofed/include/linux/jiffies.h | 2 | ||||
-rw-r--r-- | sys/ofed/include/linux/linux_idr.c | 30 |
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); } |