提交 d2d87a3b 编写于 作者: A Al Viro 提交者: Mike Marshall

orangefs: get rid of loop in wait_for_matching_downcall()

turn op->waitq into struct completion...
Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: NMike Marshall <hubcap@omnibond.com>
上级 cf22644a
...@@ -118,7 +118,7 @@ struct orangefs_kernel_op_s *op_alloc(__s32 type) ...@@ -118,7 +118,7 @@ struct orangefs_kernel_op_s *op_alloc(__s32 type)
if (new_op) { if (new_op) {
INIT_LIST_HEAD(&new_op->list); INIT_LIST_HEAD(&new_op->list);
spin_lock_init(&new_op->lock); spin_lock_init(&new_op->lock);
init_waitqueue_head(&new_op->waitq); init_completion(&new_op->waitq);
atomic_set(&new_op->ref_count, 1); atomic_set(&new_op->ref_count, 1);
......
...@@ -202,7 +202,7 @@ struct orangefs_kernel_op_s { ...@@ -202,7 +202,7 @@ struct orangefs_kernel_op_s {
struct orangefs_upcall_s upcall; struct orangefs_upcall_s upcall;
struct orangefs_downcall_s downcall; struct orangefs_downcall_s downcall;
wait_queue_head_t waitq; struct completion waitq;
spinlock_t lock; spinlock_t lock;
struct completion done; struct completion done;
...@@ -222,7 +222,7 @@ struct orangefs_kernel_op_s { ...@@ -222,7 +222,7 @@ struct orangefs_kernel_op_s {
static inline void set_op_state_serviced(struct orangefs_kernel_op_s *op) static inline void set_op_state_serviced(struct orangefs_kernel_op_s *op)
{ {
op->op_state = OP_VFS_STATE_SERVICED; 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) #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) ...@@ -266,7 +266,7 @@ static inline void set_op_state_purged(struct orangefs_kernel_op_s *op)
put_cancel(op); put_cancel(op);
} else { } else {
op->op_state |= OP_VFS_STATE_PURGED; op->op_state |= OP_VFS_STATE_PURGED;
wake_up_interruptible(&op->waitq); complete(&op->waitq);
spin_unlock(&op->lock); spin_unlock(&op->lock);
} }
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "orangefs-bufmap.h" #include "orangefs-bufmap.h"
static int wait_for_matching_downcall(struct orangefs_kernel_op_s *); 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 * 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, ...@@ -170,8 +171,10 @@ int service_operation(struct orangefs_kernel_op_s *op,
gossip_err("orangefs: %s -- wait timed out; aborting attempt.\n", gossip_err("orangefs: %s -- wait timed out; aborting attempt.\n",
op_name); op_name);
} }
orangefs_clean_up_interrupted_operation(op);
op->downcall.status = ret; op->downcall.status = ret;
} else { } else {
spin_unlock(&op->lock);
/* got matching downcall; make sure status is in errno format */ /* got matching downcall; make sure status is in errno format */
op->downcall.status = op->downcall.status =
orangefs_normalize_to_errno(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 ...@@ -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__); gossip_err("%s: can't get here.\n", __func__);
spin_unlock(&op->lock); spin_unlock(&op->lock);
} }
reinit_completion(&op->waitq);
} }
/* /*
...@@ -359,22 +363,21 @@ static void orangefs_clean_up_interrupted_operation(struct orangefs_kernel_op_s ...@@ -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 * EINTR/EIO/ETIMEDOUT indicating we are done trying to service this
* operation since client-core seems to be exiting too often * operation since client-core seems to be exiting too often
* or if we were interrupted. * or if we were interrupted.
*
* Returns with op->lock taken.
*/ */
static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op) static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op)
{ {
int ret = -EINVAL; long timeout, n;
DEFINE_WAIT(wait_entry);
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); 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, gossip_debug(GOSSIP_WAIT_DEBUG,
"*** %s:" "*** %s:"
" operation interrupted by a signal (tag " " operation interrupted by a signal (tag "
...@@ -382,72 +385,30 @@ static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op) ...@@ -382,72 +385,30 @@ static int wait_for_matching_downcall(struct orangefs_kernel_op_s *op)
__func__, __func__,
llu(op->tag), llu(op->tag),
op); op);
orangefs_clean_up_interrupted_operation(op); return -EINTR;
ret = -EINTR;
break;
} }
op->attempts++;
/* if (op_state_purged(op)) {
* 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)) {
gossip_debug(GOSSIP_WAIT_DEBUG, gossip_debug(GOSSIP_WAIT_DEBUG,
"*** %s:" "*** %s:"
" operation timed out (tag" " operation purged (tag "
" %llu, %p, att %d)\n", "%llu, %p, att %d)\n",
__func__, __func__,
llu(op->tag), llu(op->tag),
op, op,
op->attempts); op->attempts);
ret = -ETIMEDOUT; return (op->attempts < ORANGEFS_PURGE_RETRY_COUNT) ?
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) ?
-EAGAIN : -EAGAIN :
-EIO; -EIO;
}
/* must have timed out, then... */
gossip_debug(GOSSIP_WAIT_DEBUG, gossip_debug(GOSSIP_WAIT_DEBUG,
"*** %s:" "*** %s:"
" operation purged (tag " " operation timed out (tag"
"%llu, %p, att %d)\n", " %llu, %p, att %d)\n",
__func__, __func__,
llu(op->tag), llu(op->tag),
op, op,
op->attempts); op->attempts);
orangefs_clean_up_interrupted_operation(op); return -ETIMEDOUT;
break;
}
spin_unlock(&op->lock);
}
spin_lock(&op->lock);
finish_wait(&op->waitq, &wait_entry);
spin_unlock(&op->lock);
return ret;
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册