- cfs_time_t curtime = cfs_time_current();
- struct ptlrpc_request *req;
- struct ptlrpc_request_set *set;
- struct list_head *iter;
- struct pinger_data *pd = &pinger_args;
- int rc;
-
- /* prevent recursion */
- if (pd->pd_recursion++) {
- CDEBUG(D_HA, "pinger: recursion! quit\n");
- LASSERT(pd->pd_set);
- pd->pd_recursion--;
- return 0;
- }
-
- /* have we reached ping point? */
- if (!pd->pd_set && time_before(curtime, pd->pd_next_ping)) {
- pd->pd_recursion--;
- return 0;
- }
-
- /* if we have rpc_set already, continue processing it */
- if (pd->pd_set) {
- LASSERT(pd->pd_this_ping);
- set = pd->pd_set;
- goto do_check_set;
- }
-
- pd->pd_this_ping = curtime;
- pd->pd_set = ptlrpc_prep_set();
- if (pd->pd_set == NULL)
- goto out;
- set = pd->pd_set;
-
- /* add rpcs into set */
- mutex_down(&pinger_sem);
- list_for_each(iter, &pinger_imports) {
- struct obd_import *imp =
- list_entry(iter, struct obd_import, imp_pinger_chain);
- int generation, level;
-
- if (cfs_time_aftereq(pd->pd_this_ping,
- imp->imp_next_ping - 5 * CFS_TICK)) {
- /* Add a ping. */
- spin_lock(&imp->imp_lock);
- generation = imp->imp_generation;
- level = imp->imp_state;
- spin_unlock(&imp->imp_lock);
-
- if (level != LUSTRE_IMP_FULL) {
- CDEBUG(D_HA,
- "not pinging %s (in recovery)\n",
- obd2cli_tgt(imp->imp_obd));
- continue;
- }
-
- req = ptlrpc_request_alloc_pack(imp, &RQF_OBD_PING,
- LUSTRE_OBD_VERSION,
- OBD_PING);
- if (req == NULL) {
- CERROR("OOM trying to ping %s->%s\n",
- imp->imp_obd->obd_uuid.uuid,
- obd2cli_tgt(imp->imp_obd));
- break;
- }
-
- req->rq_no_resend = 1;
- ptlrpc_request_set_replen(req);
- req->rq_send_state = LUSTRE_IMP_FULL;
- ptlrpc_rqphase_move(req, RQ_PHASE_RPC);
- req->rq_import_generation = generation;
- ptlrpc_set_add_req(set, req);
- } else {
- CDEBUG(D_INFO, "don't need to ping %s ("CFS_TIME_T
- " > "CFS_TIME_T")\n", obd2cli_tgt(imp->imp_obd),
- imp->imp_next_ping, pd->pd_this_ping);
- }
- }
- pd->pd_this_ping = curtime;
- mutex_up(&pinger_sem);
-
- /* Might be empty, that's OK. */
- if (set->set_remaining == 0)
- CDEBUG(D_RPCTRACE, "nothing to ping\n");
-
- list_for_each(iter, &set->set_requests) {
- struct ptlrpc_request *req =
- list_entry(iter, struct ptlrpc_request,
- rq_set_chain);
- DEBUG_REQ(D_RPCTRACE, req, "pinging %s->%s",
- req->rq_import->imp_obd->obd_uuid.uuid,
- obd2cli_tgt(req->rq_import->imp_obd));
- (void)ptl_send_rpc(req, 0);
- }
-
-do_check_set:
- rc = ptlrpc_check_set(NULL, set);
-
- /* not finished, and we are not expired, simply return */
- if (!rc && cfs_time_before(curtime, cfs_time_add(pd->pd_this_ping,
- cfs_time_seconds(PING_INTERVAL)))) {
- CDEBUG(D_RPCTRACE, "not finished, but also not expired\n");
- pd->pd_recursion--;
- return 0;
- }
-
- /* Expire all the requests that didn't come back. */
- mutex_down(&pinger_sem);
- list_for_each(iter, &set->set_requests) {
- req = list_entry(iter, struct ptlrpc_request,
- rq_set_chain);
-
- if (req->rq_phase == RQ_PHASE_COMPLETE)
- continue;
-
- ptlrpc_rqphase_move(req, RQ_PHASE_COMPLETE);
- atomic_dec(&req->rq_import->imp_inflight);
- set->set_remaining--;
- /* If it was disconnected, don't sweat it. */
- if (list_empty(&req->rq_import->imp_pinger_chain)) {
- ptlrpc_unregister_reply(req, 0);
- continue;
- }
-
- CDEBUG(D_RPCTRACE, "pinger initiate expire_one_request\n");
- ptlrpc_expire_one_request(req, 0);
- }
- mutex_up(&pinger_sem);
-
- ptlrpc_set_destroy(set);
- pd->pd_set = NULL;
-
-out:
- pd->pd_next_ping = cfs_time_add(pd->pd_this_ping,
- cfs_time_seconds(PING_INTERVAL));
- pd->pd_this_ping = 0; /* XXX for debug */
-
- CDEBUG(D_INFO, "finished a round ping\n");
- pd->pd_recursion--;
- return 0;