kern: awake must not interrupt flushes in dev9p
While sending Tflush after a wakeup, we might call sleep. Since the awake was not yet consumed, the new sleep was interrupted causing a new Tflush, in an infinite loop that consumes all tags.
This commit is contained in:
parent
799f99a40f
commit
a3918b108d
|
@ -54,6 +54,10 @@ static AlarmPool awkpool;
|
||||||
static AwakeAlarm *registry;
|
static AwakeAlarm *registry;
|
||||||
static Lock rl;
|
static Lock rl;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
AwakeDisabled = 64, /* must be greater than all syscalls */
|
||||||
|
};
|
||||||
|
|
||||||
typedef enum ElapsedAlarmFate
|
typedef enum ElapsedAlarmFate
|
||||||
{
|
{
|
||||||
|
@ -146,6 +150,8 @@ awake_can_interrupt(Syscalls scall)
|
||||||
{
|
{
|
||||||
if(scall == 0)
|
if(scall == 0)
|
||||||
panic("awake_can_interrupts on page fault");
|
panic("awake_can_interrupts on page fault");
|
||||||
|
if(scall == (Syscalls)AwakeDisabled)
|
||||||
|
return 0;
|
||||||
if(scall >= nelem(awakeable_syscalls) - 1)
|
if(scall >= nelem(awakeable_syscalls) - 1)
|
||||||
panic("awake_can_interrupts: unknown syscall %d", scall);
|
panic("awake_can_interrupts: unknown syscall %d", scall);
|
||||||
return awakeable_syscalls[scall];
|
return awakeable_syscalls[scall];
|
||||||
|
@ -153,7 +159,7 @@ awake_can_interrupt(Syscalls scall)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# define awake_detect_loop(h)
|
# define awake_detect_loop(h)
|
||||||
# define awake_can_interrupt(scall) (awakeable_syscalls[scall])
|
# define awake_can_interrupt(scall) (scall != (Syscalls)AwakeDisabled && awakeable_syscalls[scall])
|
||||||
//# undef assert
|
//# undef assert
|
||||||
//# define assert(a)
|
//# define assert(a)
|
||||||
#endif
|
#endif
|
||||||
|
@ -230,6 +236,8 @@ void
|
||||||
awake_fell_asleep(Proc *p)
|
awake_fell_asleep(Proc *p)
|
||||||
{
|
{
|
||||||
Syscalls cs = p->cursyscall;
|
Syscalls cs = p->cursyscall;
|
||||||
|
if(p->wakeups[p->notified].blockingsc == (Syscalls)AwakeDisabled)
|
||||||
|
return;
|
||||||
if(cs != 0 && cs != SysAwake){
|
if(cs != 0 && cs != SysAwake){
|
||||||
/* awake_register might sleep() on alarm_new and we
|
/* awake_register might sleep() on alarm_new and we
|
||||||
* don't want this sleep to be interrupted.
|
* don't want this sleep to be interrupted.
|
||||||
|
@ -243,7 +251,7 @@ Syscalls
|
||||||
awake_disable(void)
|
awake_disable(void)
|
||||||
{
|
{
|
||||||
Syscalls blockingsc = up->wakeups[up->notified].blockingsc;
|
Syscalls blockingsc = up->wakeups[up->notified].blockingsc;
|
||||||
up->wakeups[up->notified].blockingsc = 0;
|
up->wakeups[up->notified].blockingsc = AwakeDisabled;
|
||||||
return blockingsc;
|
return blockingsc;
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
|
|
|
@ -1,3 +1,20 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Jehanne.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015-2017 Giacomo Tesio <giacomo@tesio.it>
|
||||||
|
*
|
||||||
|
* Jehanne is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, version 2 of the License.
|
||||||
|
*
|
||||||
|
* Jehanne is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Jehanne. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
#include "u.h"
|
#include "u.h"
|
||||||
#include "../port/lib.h"
|
#include "../port/lib.h"
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
|
@ -807,6 +824,7 @@ mountio(Mnt *mnt, Mntrpc *r)
|
||||||
int n;
|
int n;
|
||||||
Syscalls awksysc;
|
Syscalls awksysc;
|
||||||
|
|
||||||
|
awksysc = 0;
|
||||||
while(waserror()) {
|
while(waserror()) {
|
||||||
if(mnt->rip == up)
|
if(mnt->rip == up)
|
||||||
mntgate(mnt);
|
mntgate(mnt);
|
||||||
|
@ -847,6 +865,23 @@ mountio(Mnt *mnt, Mntrpc *r)
|
||||||
}
|
}
|
||||||
b->wp += n;
|
b->wp += n;
|
||||||
poperror();
|
poperror();
|
||||||
|
|
||||||
|
if(r->request.type == Tflush){
|
||||||
|
/* Tflush must not be interrupted by awake.
|
||||||
|
*
|
||||||
|
* The following code might call sleep() but it must
|
||||||
|
* since the syscall has already been interrupted
|
||||||
|
* (or we would not have to send a Tflush) awake must
|
||||||
|
* not interrupt such sleep.
|
||||||
|
*
|
||||||
|
* Thus we disable awake otherwise we will consume all
|
||||||
|
* tags trying to flush the flush.
|
||||||
|
*
|
||||||
|
* TODO: verify we do not have to do the same
|
||||||
|
* with notes
|
||||||
|
*/
|
||||||
|
awksysc = awake_disable();
|
||||||
|
}
|
||||||
mnt->c->dev->bwrite(mnt->c, b, 0);
|
mnt->c->dev->bwrite(mnt->c, b, 0);
|
||||||
|
|
||||||
/* Gate readers onto the mount point one at a time */
|
/* Gate readers onto the mount point one at a time */
|
||||||
|
@ -855,29 +890,10 @@ mountio(Mnt *mnt, Mntrpc *r)
|
||||||
if(mnt->rip == nil)
|
if(mnt->rip == nil)
|
||||||
break;
|
break;
|
||||||
unlock(&mnt->l);
|
unlock(&mnt->l);
|
||||||
if(r->request.type == Tflush){
|
|
||||||
/* Tflush must not be interrupted by awake
|
|
||||||
* or we will consume all tags trying: since
|
|
||||||
* awake cannot know that it's not worth to
|
|
||||||
* flush an interrupted flush it will interrupt
|
|
||||||
* them all and each interrupt will cause
|
|
||||||
* a new flush to be sent.
|
|
||||||
*
|
|
||||||
* TODO: verify we do not have to do the same
|
|
||||||
* with notes
|
|
||||||
*/
|
|
||||||
awksysc = awake_disable();
|
|
||||||
if(waserror()){
|
|
||||||
awake_enable(awksysc);
|
|
||||||
nexterror();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sleep(r->z, rpcattn, r);
|
sleep(r->z, rpcattn, r);
|
||||||
if(r->request.type == Tflush){
|
|
||||||
awake_enable(awksysc);
|
|
||||||
poperror();
|
|
||||||
}
|
|
||||||
if(r->done){
|
if(r->done){
|
||||||
|
if(r->request.type == Tflush)
|
||||||
|
awake_enable(awksysc);
|
||||||
poperror();
|
poperror();
|
||||||
mntflushfree(mnt, r);
|
mntflushfree(mnt, r);
|
||||||
return;
|
return;
|
||||||
|
@ -890,6 +906,9 @@ mountio(Mnt *mnt, Mntrpc *r)
|
||||||
error(Emountrpc);
|
error(Emountrpc);
|
||||||
mountmux(mnt, r);
|
mountmux(mnt, r);
|
||||||
}
|
}
|
||||||
|
if(r->request.type == Tflush)
|
||||||
|
awake_enable(awksysc);
|
||||||
|
|
||||||
mntgate(mnt);
|
mntgate(mnt);
|
||||||
poperror();
|
poperror();
|
||||||
mntflushfree(mnt, r);
|
mntflushfree(mnt, r);
|
||||||
|
|
Loading…
Reference in New Issue