Give vm_radix_lookupn() a way to specify that the whole range has been

exhausted while searching and when a "maximum" value is passed as end
(or end == 0).
This allow for avoiding starting address overflow while searching
through and avoids livelock with "start" wrapping up to "end".

Reported by:	pho (supposedly)
This commit is contained in:
attilio 2012-06-23 01:30:51 +00:00
parent 1053e2db44
commit a8dc1f5270
3 changed files with 31 additions and 12 deletions

View File

@ -679,6 +679,7 @@ vm_object_terminate(vm_object_t object)
vm_page_t pa[VM_RADIX_STACK];
vm_page_t p;
vm_pindex_t start;
u_int exhausted;
int n, i;
VM_OBJECT_LOCK_ASSERT(object, MA_OWNED);
@ -725,8 +726,10 @@ vm_object_terminate(vm_object_t object)
* the object, the page and object are reset to any empty state.
*/
start = 0;
while ((n = vm_radix_lookupn(&object->rtree, start, 0, VM_RADIX_ANY,
(void **)pa, VM_RADIX_STACK, &start)) != 0) {
exhausted = 0;
while (exhausted == 0 && (n = vm_radix_lookupn(&object->rtree, start,
0, VM_RADIX_ANY, (void **)pa, VM_RADIX_STACK, &start,
&exhausted)) != 0) {
for (i = 0; i < n; i++) {
p = pa[i];
/*
@ -1315,6 +1318,7 @@ vm_object_split(vm_map_entry_t entry)
vm_object_t orig_object, new_object, source;
vm_pindex_t idx, offidxstart, start;
vm_size_t size;
u_int exhausted;
int i, n;
orig_object = entry->object.vm_object;
@ -1370,9 +1374,10 @@ vm_object_split(vm_map_entry_t entry)
}
start = offidxstart;
retry:
while ((n = vm_radix_lookupn(&orig_object->rtree, start,
offidxstart + size, VM_RADIX_ANY, (void **)ma, VM_RADIX_STACK,
&start)) != 0) {
exhausted = 0;
while (exhausted == 0 && (n = vm_radix_lookupn(&orig_object->rtree,
start, offidxstart + size, VM_RADIX_ANY, (void **)ma,
VM_RADIX_STACK, &start, &exhausted)) != 0) {
for (i = 0; i < n; i++) {
m = ma[i];
idx = m->pindex - offidxstart;
@ -1457,6 +1462,7 @@ vm_object_backing_scan(vm_object_t object, int op)
vm_object_t backing_object;
vm_pindex_t backing_offset_index, new_pindex;
vm_pindex_t start;
u_int exhausted;
int color, i, n;
int r = 1;
@ -1495,13 +1501,15 @@ vm_object_backing_scan(vm_object_t object, int op)
restart:
start = 0;
i = n = VM_RADIX_STACK;
exhausted = 0;
for (;;) {
if (i == n) {
if (n < VM_RADIX_STACK)
break;
if ((n = vm_radix_lookupn(&backing_object->rtree,
if (exhausted != 0 &&
(n = vm_radix_lookupn(&backing_object->rtree,
start, 0, color, (void **)pa, VM_RADIX_STACK,
&start)) == 0)
&start, &exhausted)) == 0)
break;
i = 0;
}
@ -1909,6 +1917,7 @@ vm_object_page_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end,
struct vnode *vp;
vm_page_t pa[VM_RADIX_STACK];
vm_page_t p;
u_int exhausted;
int i, n;
int wirings;
@ -1921,8 +1930,10 @@ vm_object_page_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end,
vp = NULL;
vm_object_pip_add(object, 1);
restart:
while ((n = vm_radix_lookupn(&object->rtree, start, end, VM_RADIX_ANY,
(void **)pa, VM_RADIX_STACK, &start)) != 0) {
exhausted = 0;
while (exhausted == 0 && (n = vm_radix_lookupn(&object->rtree, start,
end, VM_RADIX_ANY, (void **)pa, VM_RADIX_STACK, &start,
&exhausted)) != 0) {
for (i = 0; i < n; i++) {
p = pa[i];
/*

View File

@ -726,7 +726,8 @@ vm_radix_leaf(struct vm_radix *rtree, vm_pindex_t *startp, vm_pindex_t end)
*/
int
vm_radix_lookupn(struct vm_radix *rtree, vm_pindex_t start,
vm_pindex_t end, int color, void **out, int cnt, vm_pindex_t *next)
vm_pindex_t end, int color, void **out, int cnt, vm_pindex_t *next,
u_int *exhausted)
{
struct vm_radix_node *rnode;
void *val;
@ -736,6 +737,8 @@ vm_radix_lookupn(struct vm_radix *rtree, vm_pindex_t start,
CTR5(KTR_VM, "lookupn: tree %p, " KFRMT64(start) ", " KFRMT64(end),
rtree, KSPLT64L(start), KSPLT64H(start), KSPLT64L(end),
KSPLT64H(end));
if (end == 0)
*exhausted = 0;
if (rtree->rt_root == 0)
return (0);
outidx = 0;
@ -760,6 +763,8 @@ vm_radix_lookupn(struct vm_radix *rtree, vm_pindex_t start,
*/
if ((VM_RADIX_MAXVAL - start) == 0) {
start++;
if (end == 0)
*exhausted = 1;
goto out;
}
continue;
@ -771,6 +776,8 @@ vm_radix_lookupn(struct vm_radix *rtree, vm_pindex_t start,
if (++outidx == cnt ||
(VM_RADIX_MAXVAL - start) == 0) {
start++;
if (end == 0)
*exhausted = 1;
goto out;
}
}

View File

@ -60,7 +60,7 @@ int vm_radix_insert(struct vm_radix *, vm_pindex_t, void *);
void *vm_radix_color(struct vm_radix *, vm_pindex_t, int);
void *vm_radix_lookup(struct vm_radix *, vm_pindex_t, int);
int vm_radix_lookupn(struct vm_radix *, vm_pindex_t, vm_pindex_t, int,
void **, int, vm_pindex_t *);
void **, int, vm_pindex_t *, u_int *);
void *vm_radix_lookup_le(struct vm_radix *, vm_pindex_t, int);
void vm_radix_reclaim_allnodes(struct vm_radix *);
void vm_radix_remove(struct vm_radix *, vm_pindex_t, int);
@ -72,8 +72,9 @@ static inline void *
vm_radix_lookup_ge(struct vm_radix *rtree, vm_pindex_t index, int color)
{
void *val;
u_int dummy;
if (vm_radix_lookupn(rtree, index, 0, color, &val, 1, &index))
if (vm_radix_lookupn(rtree, index, 0, color, &val, 1, &index, &dummy))
return (val);
return (NULL);
}