Commit d9664c95 authored by Jan Harkes's avatar Jan Harkes Committed by Linus Torvalds

coda: block signals during upcall processing

We ignore signals for about 30 seconds to give userspace a chance to see the
upcall.  As we did not block signals we ended up in a busy loop for the
remainder of the period when a signal is received.
Signed-off-by: default avatarJan Harkes <jaharkes@cs.cmu.edu>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent fe71b5f3
...@@ -638,42 +638,83 @@ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs) ...@@ -638,42 +638,83 @@ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs)
/* /*
* coda_upcall and coda_downcall routines. * coda_upcall and coda_downcall routines.
*
*/ */
static void block_signals(sigset_t *old)
{
spin_lock_irq(&current->sighand->siglock);
*old = current->blocked;
sigfillset(&current->blocked);
sigdelset(&current->blocked, SIGKILL);
sigdelset(&current->blocked, SIGSTOP);
sigdelset(&current->blocked, SIGINT);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
static void unblock_signals(sigset_t *old)
{
spin_lock_irq(&current->sighand->siglock);
current->blocked = *old;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
/* Don't allow signals to interrupt the following upcalls before venus
* has seen them,
* - CODA_CLOSE or CODA_RELEASE upcall (to avoid reference count problems)
* - CODA_STORE (to avoid data loss)
*/
#define CODA_INTERRUPTIBLE(r) (!coda_hard && \
(((r)->uc_opcode != CODA_CLOSE && \
(r)->uc_opcode != CODA_STORE && \
(r)->uc_opcode != CODA_RELEASE) || \
(r)->uc_flags & REQ_READ))
static inline void coda_waitfor_upcall(struct upc_req *vmp) static inline void coda_waitfor_upcall(struct upc_req *req)
{ {
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
unsigned long timeout = jiffies + coda_timeout * HZ;
sigset_t old;
int blocked;
vmp->uc_posttime = jiffies; block_signals(&old);
blocked = 1;
add_wait_queue(&vmp->uc_sleep, &wait); add_wait_queue(&req->uc_sleep, &wait);
for (;;) { for (;;) {
if ( !coda_hard && vmp->uc_opcode != CODA_CLOSE ) if (CODA_INTERRUPTIBLE(req))
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
else else
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
/* got a reply */ /* got a reply */
if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) ) if (req->uc_flags & (REQ_WRITE | REQ_ABORT))
break; break;
if ( !coda_hard && vmp->uc_opcode != CODA_CLOSE && signal_pending(current) ) { if (blocked && time_after(jiffies, timeout) &&
/* if this process really wants to die, let it go */ CODA_INTERRUPTIBLE(req))
if ( sigismember(&(current->pending.signal), SIGKILL) || {
sigismember(&(current->pending.signal), SIGINT) ) unblock_signals(&old);
break; blocked = 0;
/* signal is present: after timeout always return }
really smart idea, probably useless ... */
if ( jiffies - vmp->uc_posttime > coda_timeout * HZ ) if (signal_pending(current)) {
list_del(&req->uc_chain);
break; break;
} }
if (blocked)
schedule_timeout(HZ);
else
schedule(); schedule();
} }
remove_wait_queue(&vmp->uc_sleep, &wait); if (blocked)
set_current_state(TASK_RUNNING); unblock_signals(&old);
return; remove_wait_queue(&req->uc_sleep, &wait);
set_current_state(TASK_RUNNING);
} }
...@@ -750,8 +791,6 @@ static int coda_upcall(struct coda_sb_info *sbi, ...@@ -750,8 +791,6 @@ static int coda_upcall(struct coda_sb_info *sbi,
goto exit; goto exit;
} }
list_del(&(req->uc_chain));
/* Interrupted before venus read it. */ /* Interrupted before venus read it. */
if (!(req->uc_flags & REQ_READ)) if (!(req->uc_flags & REQ_READ))
goto exit; goto exit;
......
...@@ -85,7 +85,6 @@ struct upc_req { ...@@ -85,7 +85,6 @@ struct upc_req {
u_short uc_opcode; /* copied from data to save lookup */ u_short uc_opcode; /* copied from data to save lookup */
int uc_unique; int uc_unique;
wait_queue_head_t uc_sleep; /* process' wait queue */ wait_queue_head_t uc_sleep; /* process' wait queue */
unsigned long uc_posttime;
}; };
#define REQ_ASYNC 0x1 #define REQ_ASYNC 0x1
......
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