From fb2c0993db42bf3fd9fa5d6a08537751b3baeb89 Mon Sep 17 00:00:00 2001 From: shaver Date: Thu, 25 Jul 2002 23:34:18 +0000 Subject: [PATCH 1/1] Only interrupt after timeout in ptlrpc_queue_wait. Fixed bug 583214. --- lustre/include/linux/lustre_lib.h | 29 +++++++++++++++++++++++++ lustre/ptlrpc/client.c | 45 ++++++++++++++++++++++++--------------- 2 files changed, 57 insertions(+), 17 deletions(-) diff --git a/lustre/include/linux/lustre_lib.h b/lustre/include/linux/lustre_lib.h index 08ce7f4..60dd8b9 100644 --- a/lustre/include/linux/lustre_lib.h +++ b/lustre/include/linux/lustre_lib.h @@ -404,6 +404,8 @@ static inline int obd_ioctl_getdata(char **buf, int *len, void *arg) /* * Like wait_event_interruptible, but we're only interruptible by KILL, INT, or * TERM. + * + * XXXshaver These are going away soon, I hope. */ #define __l_wait_event_killable(wq, condition, ret) \ do { \ @@ -435,4 +437,31 @@ do { \ __ret; \ }) +#define __l_wait_event_timeout(wq, condition, timeout, ret) \ +do { \ + wait_queue_t __wait; \ + init_waitqueue_entry(&__wait, current); \ + \ + add_wait_queue(&wq, &__wait); \ + for (;;) { \ + set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (timeout) \ + schedule_timeout(timeout); \ + else \ + schedule(); \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&wq, &__wait); \ +} while(0) + +#define l_wait_event_timeout(wq, condition, timeout) \ +({ \ + int __ret = 0; \ + if (!(condition)) \ + __l_wait_event_timeout(wq, condition, timeout, __ret); \ + __ret; \ +}) + #endif /* _LUSTRE_LIB_H */ diff --git a/lustre/ptlrpc/client.c b/lustre/ptlrpc/client.c index 35ef237..b135afe 100644 --- a/lustre/ptlrpc/client.c +++ b/lustre/ptlrpc/client.c @@ -261,6 +261,11 @@ static int ptlrpc_check_reply(struct ptlrpc_request *req) } if (req->rq_flags & PTL_RPC_FL_RESEND) { + if (l_killable_pending(current)) { + CERROR("-- INTR --\n"); + req->rq_flags |= PTL_RPC_FL_INTR; + GOTO(out, rc = 1); + } CERROR("-- RESEND --\n"); GOTO(out, rc = 1); } @@ -270,8 +275,13 @@ static int ptlrpc_check_reply(struct ptlrpc_request *req) GOTO(out, rc = 1); } + if (req->rq_flags & PTL_RPC_FL_TIMEOUT && l_killable_pending(current)) { + req->rq_flags |= PTL_RPC_FL_INTR; + GOTO(out, rc = 1); + } - if (CURRENT_TIME - req->rq_time >= req->rq_timeout) { + if (req->rq_timeout && + (CURRENT_TIME - req->rq_time >= req->rq_timeout)) { CERROR("-- REQ TIMEOUT ON CONNID %d XID %Ld --\n", req->rq_connid, (unsigned long long)req->rq_xid); /* clear the timeout */ @@ -280,22 +290,17 @@ static int ptlrpc_check_reply(struct ptlrpc_request *req) req->rq_flags |= PTL_RPC_FL_TIMEOUT; if (req->rq_client && req->rq_client->cli_recovd) recovd_cli_fail(req->rq_client); - if (req->rq_level < LUSTRE_CONN_FULL) + if (req->rq_level < LUSTRE_CONN_FULL) { rc = 1; - else + } else if (l_killable_pending(current)) { + req->rq_flags |= PTL_RPC_FL_INTR; + rc = 1; + } else { rc = 0; + } GOTO(out, rc); } - if (req->rq_timeout) { - schedule_timeout(req->rq_timeout * HZ); - } - - if (l_killable_pending(current)) { - req->rq_flags |= PTL_RPC_FL_INTR; - GOTO(out, rc = 1); - } - out: CDEBUG(D_NET, "req = %p, rc = %d\n", req, rc); return rc; @@ -459,7 +464,7 @@ void ptlrpc_restart_req(struct ptlrpc_request *req) int ptlrpc_queue_wait(struct ptlrpc_request *req) { - int rc = 0; + int rc = 0, timeout; struct ptlrpc_client *cli = req->rq_client; ENTRY; @@ -503,7 +508,13 @@ int ptlrpc_queue_wait(struct ptlrpc_request *req) spin_unlock(&cli->cli_lock); CDEBUG(D_OTHER, "-- sleeping\n"); - l_wait_event_killable(req->rq_wait_for_rep, ptlrpc_check_reply(req)); + /* + * req->rq_timeout gets reset in the timeout case, and + * l_wait_event_timeout is a macro, so save the timeout value here. + */ + timeout = req->rq_timeout * HZ; + l_wait_event_timeout(req->rq_wait_for_rep, ptlrpc_check_reply(req), + timeout); CDEBUG(D_OTHER, "-- done\n"); if (req->rq_flags & PTL_RPC_FL_RESEND) { @@ -512,15 +523,15 @@ int ptlrpc_queue_wait(struct ptlrpc_request *req) } up(&cli->cli_rpc_sem); - if (req->rq_flags & PTL_RPC_FL_TIMEOUT) - GOTO(out, rc = -ETIMEDOUT); - if (req->rq_flags & PTL_RPC_FL_INTR) { /* Clean up the dangling reply buffers */ ptlrpc_abort(req); GOTO(out, rc = -EINTR); } + if (req->rq_flags & PTL_RPC_FL_TIMEOUT) + GOTO(out, rc = -ETIMEDOUT); + if (!(req->rq_flags & PTL_RPC_FL_REPLIED)) GOTO(out, rc = req->rq_status); -- 1.8.3.1