Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+60 −21
Original line number Diff line number Diff line
@@ -638,42 +638,83 @@ int venus_statfs(struct dentry *dentry, struct kstatfs *sfs)

/*
 * 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);
	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 (;;) {
		if ( !coda_hard && vmp->uc_opcode != CODA_CLOSE ) 
		if (CODA_INTERRUPTIBLE(req))
			set_current_state(TASK_INTERRUPTIBLE);
		else
			set_current_state(TASK_UNINTERRUPTIBLE);

		/* got a reply */
		if ( vmp->uc_flags & ( REQ_WRITE | REQ_ABORT ) )
		if (req->uc_flags & (REQ_WRITE | REQ_ABORT))
			break;

		if ( !coda_hard && vmp->uc_opcode != CODA_CLOSE && signal_pending(current) ) {
			/* if this process really wants to die, let it go */
			if ( sigismember(&(current->pending.signal), SIGKILL) ||
			     sigismember(&(current->pending.signal), SIGINT) )
				break;
			/* signal is present: after timeout always return 
			   really smart idea, probably useless ... */
			if ( jiffies - vmp->uc_posttime > coda_timeout * HZ )
		if (blocked && time_after(jiffies, timeout) &&
		    CODA_INTERRUPTIBLE(req))
		{
			unblock_signals(&old);
			blocked = 0;
		}

		if (signal_pending(current)) {
			list_del(&req->uc_chain);
			break;
		}

		if (blocked)
			schedule_timeout(HZ);
		else
			schedule();
	}
	remove_wait_queue(&vmp->uc_sleep, &wait);
	set_current_state(TASK_RUNNING);
	if (blocked)
		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,
		goto exit;
	}

	list_del(&(req->uc_chain));

	/* Interrupted before venus read it. */
	if (!(req->uc_flags & REQ_READ))
		goto exit;
+0 −1
Original line number Diff line number Diff line
@@ -85,7 +85,6 @@ struct upc_req {
	u_short	            uc_opcode;  /* copied from data to save lookup */
	int		    uc_unique;
	wait_queue_head_t   uc_sleep;   /* process' wait queue */
	unsigned long       uc_posttime;
};

#define REQ_ASYNC  0x1