buddy: fix buddy_reqs_wait_prio_adjust()

This fixes two bugs:

The most relavant was that we did not increase buddy->wait_pri if the
new priority was higher, which could lead to all kinds of weird effects,
for example:

- starvation/lock up
- LRU removing all of the cache

because there were requests waiting, but buddy_wait_work() did not see
them.

The second bug is that we also called buddy_wait_work() if there
actually was no change (the critical region could find state ==
IW_SIGNALLED).

Also, for the new assertions, we need to set the proper wait_pri for the
case that the priority is lowered.
parent 9e88cd29
......@@ -1812,8 +1812,10 @@ static inline void
buddy_reqs_wait_prio_adjust(struct buddy_reqs *reqs)
{
struct buddy_reqs_head *ohead, *nhead;
enum i_wait_state state;
struct i_wait *w;
buddy_t *buddy;
unsigned opri;
CHECK_OBJ_NOTNULL(reqs, BUDDY_REQS_MAGIC);
w = &reqs->i_wait;
......@@ -1827,11 +1829,13 @@ buddy_reqs_wait_prio_adjust(struct buddy_reqs *reqs)
buddy = reqs->buddy;
ohead = &buddy->reqs_head[w->pri];
nhead = &buddy->reqs_head[reqs->pri];
opri = w->pri;
AZ(pthread_mutex_lock(&reqs->buddy->map_mtx));
AZ(pthread_mutex_lock(&w->wait_mtx));
if (w->state == IW_WAITING) {
state = w->state;
if (state == IW_WAITING) {
AN(buddy->waiting);
/* _INSERT_HEAD? _INSERT_TAIL?
*
......@@ -1844,8 +1848,15 @@ buddy_reqs_wait_prio_adjust(struct buddy_reqs *reqs)
}
AZ(pthread_mutex_unlock(&w->wait_mtx));
if (buddy->waiting && buddy->wait_pri == w->pri)
buddy_wait_work(buddy);
if (state == IW_WAITING) {
if (reqs->pri >= buddy->wait_pri) {
buddy->wait_pri = reqs->pri;
buddy_wait_work(buddy);
}
else
buddy_new_wait_pri(buddy, opri);
}
AZ(pthread_mutex_unlock(&reqs->buddy->map_mtx));
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment