orangefs: lift handling of timeouts and attempts count to service_operation()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Mike Marshall <hubcap@omnibond.com>
diff --git a/fs/orangefs/waitqueue.c b/fs/orangefs/waitqueue.c
index 86b4b1f..378cdcf 100644
--- a/fs/orangefs/waitqueue.c
+++ b/fs/orangefs/waitqueue.c
@@ -16,7 +16,7 @@
 #include "orangefs-kernel.h"
 #include "orangefs-bufmap.h"
 
-static int wait_for_matching_downcall(struct orangefs_kernel_op_s *, bool);
+static int wait_for_matching_downcall(struct orangefs_kernel_op_s *, long, bool);
 static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s *);
 
 /*
@@ -55,6 +55,7 @@
 		      const char *op_name,
 		      int flags)
 {
+	long timeout = MAX_SCHEDULE_TIMEOUT;
 	/* flags to modify behavior */
 	int ret = 0;
 
@@ -102,15 +103,10 @@
 	spin_unlock(&op->lock);
 	wake_up_interruptible(&orangefs_request_list_waitq);
 	if (!__is_daemon_in_service()) {
-		/*
-		 * By incrementing the per-operation attempt counter, we
-		 * directly go into the timeout logic while waiting for
-		 * the matching downcall to be read
-		 */
 		gossip_debug(GOSSIP_WAIT_DEBUG,
 			     "%s:client core is NOT in service.\n",
 			     __func__);
-		op->attempts++;
+		timeout = op_timeout_secs * HZ;
 	}
 	spin_unlock(&orangefs_request_list_lock);
 
@@ -124,33 +120,34 @@
 	if (flags & ORANGEFS_OP_ASYNC)
 		return 0;
 
-	ret = wait_for_matching_downcall(op, flags & ORANGEFS_OP_INTERRUPTIBLE);
-
-	if (ret < 0) {
-		/* failed to get matching downcall */
-		if (ret == -ETIMEDOUT) {
-			gossip_err("orangefs: %s -- wait timed out; aborting attempt.\n",
-				   op_name);
-		}
-		orangefs_clean_up_interrupted_operation(op);
-		op->downcall.status = ret;
-	} else {
+	ret = wait_for_matching_downcall(op, timeout,
+					 flags & ORANGEFS_OP_INTERRUPTIBLE);
+	if (!ret) {
 		spin_unlock(&op->lock);
 		/* got matching downcall; make sure status is in errno format */
 		op->downcall.status =
 		    orangefs_normalize_to_errno(op->downcall.status);
 		ret = op->downcall.status;
+		goto out;
 	}
 
-	BUG_ON(ret != op->downcall.status);
+	/* failed to get matching downcall */
+	if (ret == -ETIMEDOUT) {
+		gossip_err("orangefs: %s -- wait timed out; aborting attempt.\n",
+			   op_name);
+	}
+	orangefs_clean_up_interrupted_operation(op);
+	op->downcall.status = ret;
 	/* retry if operation has not been serviced and if requested */
-	if (!op_state_serviced(op) && op->downcall.status == -EAGAIN) {
+	if (ret == -EAGAIN) {
+		op->attempts++;
+		timeout = op_timeout_secs * HZ;
 		gossip_debug(GOSSIP_WAIT_DEBUG,
 			     "orangefs: tag %llu (%s)"
 			     " -- operation to be retried (%d attempt)\n",
 			     llu(op->tag),
 			     op_name,
-			     op->attempts + 1);
+			     op->attempts);
 
 		if (!op->uses_shared_memory)
 			/*
@@ -221,6 +218,7 @@
 		}
 	}
 
+out:
 	gossip_debug(GOSSIP_WAIT_DEBUG,
 		     "orangefs: service_operation %s returning: %d for %p.\n",
 		     op_name,
@@ -328,11 +326,10 @@
  * Returns with op->lock taken.
  */
 static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op,
+				      long timeout,
 				      bool interruptible)
 {
-	long timeout, n;
-
-	timeout = op->attempts ? op_timeout_secs * HZ : MAX_SCHEDULE_TIMEOUT;
+	long n;
 
 	if (interruptible)
 		n = wait_for_completion_interruptible_timeout(&op->waitq, timeout);
@@ -354,7 +351,6 @@
 			     op);
 		return -EINTR;
 	}
-	op->attempts++;
 	if (op_state_purged(op)) {
 		gossip_debug(GOSSIP_WAIT_DEBUG,
 			     "*** %s:"