Whamcloud - gitweb
LU-11128 ptlrpc: new request vs disconnect race
[fs/lustre-release.git] / lustre / ptlrpc / client.c
index 95fd6ec..a167146 100644 (file)
@@ -865,10 +865,37 @@ ptlrpc_request_alloc_internal(struct obd_import *imp,
                               const struct req_format *format)
 {
         struct ptlrpc_request *request;
+       int connect = 0;
 
-        request = __ptlrpc_request_alloc(imp, pool);
-        if (request == NULL)
-                return NULL;
+       request = __ptlrpc_request_alloc(imp, pool);
+       if (request == NULL)
+               return NULL;
+
+       /* initiate connection if needed when the import has been
+        * referenced by the new request to avoid races with disconnect */
+       if (unlikely(imp->imp_state == LUSTRE_IMP_IDLE)) {
+               int rc;
+               CDEBUG_LIMIT(imp->imp_idle_debug,
+                            "%s: reconnect after %llds idle\n",
+                            imp->imp_obd->obd_name, ktime_get_real_seconds() -
+                                                    imp->imp_last_reply_time);
+               spin_lock(&imp->imp_lock);
+               if (imp->imp_state == LUSTRE_IMP_IDLE) {
+                       imp->imp_generation++;
+                       imp->imp_initiated_at = imp->imp_generation;
+                       imp->imp_state =  LUSTRE_IMP_NEW;
+                       connect = 1;
+               }
+               spin_unlock(&imp->imp_lock);
+               if (connect) {
+                       rc = ptlrpc_connect_import(imp);
+                       if (rc < 0) {
+                               ptlrpc_request_free(request);
+                               return NULL;
+                       }
+                       ptlrpc_pinger_add_import(imp);
+               }
+       }
 
         req_capsule_init(&request->rq_pill, request, RCL_CLIENT);
         req_capsule_set(&request->rq_pill, format);
@@ -1058,6 +1085,7 @@ EXPORT_SYMBOL(ptlrpc_set_destroy);
 void ptlrpc_set_add_req(struct ptlrpc_request_set *set,
                         struct ptlrpc_request *req)
 {
+       LASSERT(req->rq_import->imp_state != LUSTRE_IMP_IDLE);
        LASSERT(list_empty(&req->rq_set_chain));
 
        if (req->rq_allow_intr)
@@ -1169,7 +1197,9 @@ static int ptlrpc_import_delay_req(struct obd_import *imp,
                if (atomic_read(&imp->imp_inval_count) != 0) {
                         DEBUG_REQ(D_ERROR, req, "invalidate in flight");
                         *status = -EIO;
-               } else if (req->rq_no_delay) {
+               } else if (req->rq_no_delay &&
+                          imp->imp_generation != imp->imp_initiated_at) {
+                       /* ignore nodelay for requests initiating connections */
                         *status = -EWOULDBLOCK;
                } else if (req->rq_allow_replay &&
                          (imp->imp_state == LUSTRE_IMP_REPLAY ||
@@ -1598,8 +1628,7 @@ static int ptlrpc_send_new_req(struct ptlrpc_request *req)
               " %s:%s:%d:%llu:%s:%d\n", current_comm(),
               imp->imp_obd->obd_uuid.uuid,
               lustre_msg_get_status(req->rq_reqmsg), req->rq_xid,
-              libcfs_nid2str(imp->imp_connection->c_peer.nid),
-              lustre_msg_get_opc(req->rq_reqmsg));
+              obd_import_nid2str(imp), lustre_msg_get_opc(req->rq_reqmsg));
 
         rc = ptl_send_rpc(req, 0);
        if (rc == -ENOMEM) {
@@ -1853,8 +1882,11 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
                                        spin_unlock(&imp->imp_lock);
                                        GOTO(interpret, req->rq_status);
                                }
+                               /* ignore on just initiated connections */
                                if (ptlrpc_no_resend(req) &&
-                                   !req->rq_wait_ctx) {
+                                   !req->rq_wait_ctx &&
+                                   imp->imp_generation !=
+                                   imp->imp_initiated_at) {
                                        req->rq_status = -ENOTCONN;
                                        ptlrpc_rqphase_move(req,
                                                            RQ_PHASE_INTERPRET);
@@ -2023,7 +2055,7 @@ int ptlrpc_check_set(const struct lu_env *env, struct ptlrpc_request_set *set)
                               imp->imp_obd->obd_uuid.uuid,
                               lustre_msg_get_status(req->rq_reqmsg),
                               req->rq_xid,
-                              libcfs_nid2str(imp->imp_connection->c_peer.nid),
+                              obd_import_nid2str(imp),
                               lustre_msg_get_opc(req->rq_reqmsg));
 
                spin_lock(&imp->imp_lock);
@@ -2318,7 +2350,7 @@ int ptlrpc_set_wait(struct ptlrpc_request_set *set)
                 /* wait until all complete, interrupted, or an in-flight
                  * req times out */
                CDEBUG(D_RPCTRACE, "set %p going to sleep for %lld seconds\n",
-                       set, timeout);
+                       set, timeout);
 
                if ((timeout == 0 && !signal_pending(current)) ||
                    set->set_allow_intr)
@@ -2646,8 +2678,11 @@ void ptlrpc_request_committed(struct ptlrpc_request *req, int force)
                return;
        }
 
-       if (force || req->rq_transno <= imp->imp_peer_committed_transno)
+       if (force || req->rq_transno <= imp->imp_peer_committed_transno) {
+               if (imp->imp_replay_cursor == &req->rq_replay_list)
+                       imp->imp_replay_cursor = req->rq_replay_list.next;
                ptlrpc_free_request(req);
+       }
 
        spin_unlock(&imp->imp_lock);
 }
@@ -2759,7 +2794,7 @@ void ptlrpc_cleanup_client(struct obd_import *imp)
  */
 void ptlrpc_resend_req(struct ptlrpc_request *req)
 {
-        DEBUG_REQ(D_HA, req, "going to resend");
+       DEBUG_REQ(D_HA, req, "going to resend");
        spin_lock(&req->rq_lock);
 
        /* Request got reply but linked to the import list still.
@@ -2770,14 +2805,13 @@ void ptlrpc_resend_req(struct ptlrpc_request *req)
                return;
        }
 
-        lustre_msg_set_handle(req->rq_reqmsg, &(struct lustre_handle){ 0 });
-        req->rq_status = -EAGAIN;
+       req->rq_status = -EAGAIN;
 
-        req->rq_resend = 1;
-        req->rq_net_err = 0;
-        req->rq_timedout = 0;
+       req->rq_resend = 1;
+       req->rq_net_err = 0;
+       req->rq_timedout = 0;
 
-        ptlrpc_client_wake_req(req);
+       ptlrpc_client_wake_req(req);
        spin_unlock(&req->rq_lock);
 }