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

Commit d2d87a3b authored by Al Viro's avatar Al Viro Committed by Mike Marshall
Browse files

orangefs: get rid of loop in wait_for_matching_downcall()



turn op->waitq into struct completion...

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarMike Marshall <hubcap@omnibond.com>
parent cf22644a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -118,7 +118,7 @@ struct orangefs_kernel_op_s *op_alloc(__s32 type)
	if (new_op) {
		INIT_LIST_HEAD(&new_op->list);
		spin_lock_init(&new_op->lock);
		init_waitqueue_head(&new_op->waitq);
		init_completion(&new_op->waitq);

		atomic_set(&new_op->ref_count, 1);

+3 −3
Original line number Diff line number Diff line
@@ -202,7 +202,7 @@ struct orangefs_kernel_op_s {
	struct orangefs_upcall_s upcall;
	struct orangefs_downcall_s downcall;

	wait_queue_head_t waitq;
	struct completion waitq;
	spinlock_t lock;

	struct completion done;
@@ -222,7 +222,7 @@ struct orangefs_kernel_op_s {
static inline void set_op_state_serviced(struct orangefs_kernel_op_s *op)
{
	op->op_state = OP_VFS_STATE_SERVICED;
	wake_up_interruptible(&op->waitq);
	complete(&op->waitq);
}

#define op_state_waiting(op)     ((op)->op_state & OP_VFS_STATE_WAITING)
@@ -266,7 +266,7 @@ static inline void set_op_state_purged(struct orangefs_kernel_op_s *op)
		put_cancel(op);
	} else {
		op->op_state |= OP_VFS_STATE_PURGED;
		wake_up_interruptible(&op->waitq);
		complete(&op->waitq);
		spin_unlock(&op->lock);
	}
}
+45 −84
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include "orangefs-bufmap.h"

static int wait_for_matching_downcall(struct orangefs_kernel_op_s *);
static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s *);

/*
 * What we do in this function is to walk the list of operations that are
@@ -170,8 +171,10 @@ int service_operation(struct orangefs_kernel_op_s *op,
			gossip_err("orangefs: %s -- wait timed out; aborting attempt.\n",
				   op_name);
		}
		orangefs_clean_up_interrupted_operation(op);
		op->downcall.status = ret;
	} else {
		spin_unlock(&op->lock);
		/* got matching downcall; make sure status is in errno format */
		op->downcall.status =
		    orangefs_normalize_to_errno(op->downcall.status);
@@ -343,6 +346,7 @@ static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s
		gossip_err("%s: can't get here.\n", __func__);
		spin_unlock(&op->lock);
	}
	reinit_completion(&op->waitq);
}

/*
@@ -359,22 +363,21 @@ static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s
 * EINTR/EIO/ETIMEDOUT indicating we are done trying to service this
 * operation since client-core seems to be exiting too often
 * or if we were interrupted.
 *
 * Returns with op->lock taken.
 */
static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op)
{
	int ret = -EINVAL;
	DEFINE_WAIT(wait_entry);
	long timeout, n;

	while (1) {
	timeout = op->attempts ? op_timeout_secs * HZ : MAX_SCHEDULE_TIMEOUT;
	n = wait_for_completion_interruptible_timeout(&op->waitq, timeout);
	spin_lock(&op->lock);
		prepare_to_wait(&op->waitq, &wait_entry, TASK_INTERRUPTIBLE);
		if (op_state_serviced(op)) {
			spin_unlock(&op->lock);
			ret = 0;
			break;
		}

		if (unlikely(signal_pending(current))) {
	if (op_state_serviced(op))
		return 0;

	if (unlikely(n < 0)) {
		gossip_debug(GOSSIP_WAIT_DEBUG,
			     "*** %s:"
			     " operation interrupted by a signal (tag "
@@ -382,72 +385,30 @@ static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op)
			     __func__,
			     llu(op->tag),
			     op);
			orangefs_clean_up_interrupted_operation(op);
			ret = -EINTR;
			break;
		return -EINTR;
	}

		/*
		 * if this was our first attempt and client-core
		 * has not purged our operation, we are happy to
		 * simply wait
		 */
		if (op->attempts == 0 && !op_state_purged(op)) {
			spin_unlock(&op->lock);
			schedule();
		} else {
			spin_unlock(&op->lock);
			/*
			 * subsequent attempts, we retry exactly once
			 * with timeouts
			 */
			if (!schedule_timeout(op_timeout_secs * HZ)) {
	op->attempts++;
	if (op_state_purged(op)) {
		gossip_debug(GOSSIP_WAIT_DEBUG,
			     "*** %s:"
					     " operation timed out (tag"
			     " operation purged (tag "
			     "%llu, %p, att %d)\n",
			     __func__,
			     llu(op->tag),
			     op,
			     op->attempts);
				ret = -ETIMEDOUT;
				spin_lock(&op->lock);
				orangefs_clean_up_interrupted_operation(op);
				break;
			}
		}
		spin_lock(&op->lock);
		op->attempts++;
		/*
		 * if the operation was purged in the meantime, it
		 * is better to requeue it afresh but ensure that
		 * we have not been purged repeatedly. This could
		 * happen if client-core crashes when an op
		 * is being serviced, so we requeue the op, client
		 * core crashes again so we requeue the op, client
		 * core starts, and so on...
		 */
		if (op_state_purged(op)) {
			ret = (op->attempts < ORANGEFS_PURGE_RETRY_COUNT) ?
		return (op->attempts < ORANGEFS_PURGE_RETRY_COUNT) ?
			 -EAGAIN :
			 -EIO;
	}
	/* must have timed out, then... */
	gossip_debug(GOSSIP_WAIT_DEBUG,
		     "*** %s:"
				     " operation purged (tag "
		     " operation timed out (tag"
		     " %llu, %p, att %d)\n",
		     __func__,
		     llu(op->tag),
		     op,
		     op->attempts);
			orangefs_clean_up_interrupted_operation(op);
			break;
		}
		spin_unlock(&op->lock);
	}

	spin_lock(&op->lock);
	finish_wait(&op->waitq, &wait_entry);
	spin_unlock(&op->lock);

	return ret;
	return -ETIMEDOUT;
}