Whamcloud - gitweb
LU-1820 ptlrpc: fix req reference to export
[fs/lustre-release.git] / lustre / ptlrpc / service.c
index 25bb4c2..6d45c5c 100644 (file)
@@ -65,6 +65,7 @@ CFS_MODULE_PARM(at_extra, "i", int, 0644,
 /* forward ref */
 static int ptlrpc_server_post_idle_rqbds(struct ptlrpc_service_part *svcpt);
 static void ptlrpc_hpreq_fini(struct ptlrpc_request *req);
+static void ptlrpc_at_remove_timed(struct ptlrpc_request *req);
 
 static CFS_LIST_HEAD(ptlrpc_all_services);
 cfs_spinlock_t ptlrpc_all_services_lock;
@@ -728,6 +729,8 @@ ptlrpc_register_service(struct ptlrpc_service_conf *conf,
                        if (rc <= 0) {
                                CERROR("%s: failed to parse CPT array %s: %d\n",
                                       conf->psc_name, cconf->cc_pattern, rc);
+                               if (cpts != NULL)
+                                       OBD_FREE(cpts, sizeof(*cpts) * ncpts);
                                RETURN(ERR_PTR(rc < 0 ? rc : -EINVAL));
                        }
                        ncpts = rc;
@@ -863,24 +866,16 @@ void ptlrpc_server_drop_request(struct ptlrpc_request *req)
                 return;
 
        if (req->rq_at_linked) {
-               struct ptlrpc_at_array *array = &svcpt->scp_at_array;
-                __u32 index = req->rq_at_index;
-
                cfs_spin_lock(&svcpt->scp_at_lock);
-
-                LASSERT(!cfs_list_empty(&req->rq_timed_list));
-                cfs_list_del_init(&req->rq_timed_list);
-                cfs_spin_lock(&req->rq_lock);
-                req->rq_at_linked = 0;
-                cfs_spin_unlock(&req->rq_lock);
-                array->paa_reqs_count[index]--;
-                array->paa_count--;
-
+               /* recheck with lock, in case it's unlinked by
+                * ptlrpc_at_check_timed() */
+               if (likely(req->rq_at_linked))
+                       ptlrpc_at_remove_timed(req);
                cfs_spin_unlock(&svcpt->scp_at_lock);
-       } else {
-               LASSERT(cfs_list_empty(&req->rq_timed_list));
        }
 
+       LASSERT(cfs_list_empty(&req->rq_timed_list));
+
         /* finalize request */
         if (req->rq_export) {
                 class_export_put(req->rq_export);
@@ -950,6 +945,10 @@ void ptlrpc_server_drop_request(struct ptlrpc_request *req)
                cfs_list_del(&req->rq_list);
                cfs_list_del_init(&req->rq_history_list);
 
+               /* Track the highest culled req seq */
+               if (req->rq_history_seq > svcpt->scp_hist_seq_culled)
+                       svcpt->scp_hist_seq_culled = req->rq_history_seq;
+
                cfs_spin_unlock(&svcpt->scp_lock);
 
                ptlrpc_server_free_request(req);
@@ -1183,6 +1182,25 @@ static int ptlrpc_at_add_timed(struct ptlrpc_request *req)
        return 0;
 }
 
+static void
+ptlrpc_at_remove_timed(struct ptlrpc_request *req)
+{
+       struct ptlrpc_at_array *array;
+
+       array = &req->rq_rqbd->rqbd_svcpt->scp_at_array;
+
+       /* NB: must call with hold svcpt::scp_at_lock */
+       LASSERT(!cfs_list_empty(&req->rq_timed_list));
+       cfs_list_del_init(&req->rq_timed_list);
+
+       cfs_spin_lock(&req->rq_lock);
+       req->rq_at_linked = 0;
+       cfs_spin_unlock(&req->rq_lock);
+
+       array->paa_reqs_count[req->rq_at_index]--;
+       array->paa_count--;
+}
+
 static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req)
 {
        struct ptlrpc_service_part *svcpt = req->rq_rqbd->rqbd_svcpt;
@@ -1366,29 +1384,23 @@ static int ptlrpc_at_check_timed(struct ptlrpc_service_part *svcpt)
                 cfs_list_for_each_entry_safe(rq, n,
                                              &array->paa_reqs_array[index],
                                              rq_timed_list) {
-                        if (rq->rq_deadline <= now + at_early_margin) {
-                                cfs_list_del_init(&rq->rq_timed_list);
-                                /**
-                                 * ptlrpc_server_drop_request() may drop
-                                 * refcount to 0 already. Let's check this and
-                                 * don't add entry to work_list
-                                 */
-                                if (likely(cfs_atomic_inc_not_zero(&rq->rq_refcount)))
-                                        cfs_list_add(&rq->rq_timed_list, &work_list);
-                                counter++;
-                                array->paa_reqs_count[index]--;
-                                array->paa_count--;
-                                cfs_spin_lock(&rq->rq_lock);
-                                rq->rq_at_linked = 0;
-                                cfs_spin_unlock(&rq->rq_lock);
-                                continue;
-                        }
-
-                        /* update the earliest deadline */
-                        if (deadline == -1 || rq->rq_deadline < deadline)
-                                deadline = rq->rq_deadline;
+                       if (rq->rq_deadline > now + at_early_margin) {
+                               /* update the earliest deadline */
+                               if (deadline == -1 ||
+                                   rq->rq_deadline < deadline)
+                                       deadline = rq->rq_deadline;
+                               break;
+                       }
 
-                        break;
+                       ptlrpc_at_remove_timed(rq);
+                       /**
+                        * ptlrpc_server_drop_request() may drop
+                        * refcount to 0 already. Let's check this and
+                        * don't add entry to work_list
+                        */
+                       if (likely(cfs_atomic_inc_not_zero(&rq->rq_refcount)))
+                               cfs_list_add(&rq->rq_timed_list, &work_list);
+                       counter++;
                 }
 
                 if (++index >= array->paa_size)
@@ -1782,6 +1794,7 @@ ptlrpc_server_handle_req_in(struct ptlrpc_service_part *svcpt)
         req->rq_export = class_conn2export(
                 lustre_msg_get_handle(req->rq_reqmsg));
         if (req->rq_export) {
+               class_export_rpc_get(req->rq_export);
                 rc = ptlrpc_check_req(req);
                 if (rc == 0) {
                         rc = sptlrpc_target_export_check(req->rq_export, req);
@@ -1824,6 +1837,8 @@ ptlrpc_server_handle_req_in(struct ptlrpc_service_part *svcpt)
        RETURN(1);
 
 err_req:
+       if (req->rq_export)
+               class_export_rpc_put(req->rq_export);
        cfs_spin_lock(&svcpt->scp_req_lock);
        svcpt->scp_nreqs_active++;
        cfs_spin_unlock(&svcpt->scp_req_lock);
@@ -1909,6 +1924,7 @@ ptlrpc_server_handle_request(struct ptlrpc_service_part *svcpt,
                                    at_get(&svcpt->scp_at_estimate));
         }
 
+       export = request->rq_export;
        rc = lu_context_init(&request->rq_session, LCT_SESSION | LCT_NOREF);
         if (rc) {
                 CERROR("Failure to initialize session: %d\n", rc);
@@ -1925,10 +1941,9 @@ ptlrpc_server_handle_request(struct ptlrpc_service_part *svcpt,
                 request->rq_svc_thread->t_env->le_ses = &request->rq_session;
 
         if (likely(request->rq_export)) {
-                if (unlikely(ptlrpc_check_req(request)))
-                        goto put_conn;
+               if (unlikely(ptlrpc_check_req(request)))
+                       goto put_conn;
                 ptlrpc_update_export_timer(request->rq_export, timediff >> 19);
-                export = class_export_rpc_get(request->rq_export);
         }
 
         /* Discard requests queued for longer than the deadline.
@@ -1941,7 +1956,7 @@ ptlrpc_server_handle_request(struct ptlrpc_service_part *svcpt,
                           request->rq_arrival_time.tv_sec),
                           cfs_time_sub(cfs_time_current_sec(),
                           request->rq_deadline));
-                goto put_rpc_export;
+                goto put_conn;
         }
 
         CDEBUG(D_RPCTRACE, "Handling RPC pname:cluuid+ref:pid:xid:nid:opc "
@@ -1961,9 +1976,6 @@ ptlrpc_server_handle_request(struct ptlrpc_service_part *svcpt,
 
         ptlrpc_rqphase_move(request, RQ_PHASE_COMPLETE);
 
-put_rpc_export:
-        if (export != NULL)
-                class_export_rpc_put(export);
 put_conn:
         lu_context_exit(&request->rq_session);
         lu_context_fini(&request->rq_session);
@@ -2020,6 +2032,8 @@ put_conn:
         }
 
 out_req:
+       if (export != NULL)
+               class_export_rpc_put(export);
        ptlrpc_server_finish_request(svcpt, request);
 
        RETURN(1);
@@ -3031,6 +3045,9 @@ ptlrpc_service_purge_all(struct ptlrpc_service *svc)
                        cfs_list_del(&req->rq_list);
                        svcpt->scp_nreqs_active++;
                        ptlrpc_hpreq_fini(req);
+
+                       if (req->rq_export != NULL)
+                               class_export_rpc_put(req->rq_export);
                        ptlrpc_server_finish_request(svcpt, req);
                }