pinger.c
来自「lustre 1.6.5 source code」· C语言 代码 · 共 703 行 · 第 1/2 页
C
703 行
struct obd_device *obd; struct obd_export *exp; struct l_wait_info lwi = { 0 }; time_t expire_time; ENTRY; ptlrpc_daemonize("ll_evictor"); CDEBUG(D_HA, "Starting Ping Evictor\n"); pet_exp = NULL; pet_state = PET_READY; while (1) { l_wait_event(pet_waitq, pet_exp || (pet_state == PET_TERMINATE), &lwi); if (pet_state == PET_TERMINATE) break; /* we only get here if pet_exp != NULL, and the end of this * loop is the only place which sets it NULL again, so lock * is not strictly necessary. */ spin_lock(&pet_lock); obd = pet_exp->exp_obd; spin_unlock(&pet_lock); expire_time = cfs_time_current_sec() - PING_EVICT_TIMEOUT; CDEBUG(D_HA, "evicting all exports of obd %s older than %ld\n", obd->obd_name, expire_time); /* Exports can't be deleted out of the list while we hold * the obd lock (class_unlink_export), which means we can't * lose the last ref on the export. If they've already been * removed from the list, we won't find them here. */ spin_lock(&obd->obd_dev_lock); while (!list_empty(&obd->obd_exports_timed)) { exp = list_entry(obd->obd_exports_timed.next, struct obd_export,exp_obd_chain_timed); if (expire_time > exp->exp_last_request_time) { class_export_get(exp); spin_unlock(&obd->obd_dev_lock); LCONSOLE_WARN("%s: haven't heard from client %s" " (at %s) in %ld seconds. I think" " it's dead, and I am evicting" " it.\n", obd->obd_name, obd_uuid2str(&exp->exp_client_uuid), obd_export_nid2str(exp), (long)(cfs_time_current_sec() - exp->exp_last_request_time)); CDEBUG(D_HA, "Last request was at %ld\n", exp->exp_last_request_time); class_fail_export(exp); class_export_put(exp); spin_lock(&obd->obd_dev_lock); } else { /* List is sorted, so everyone below is ok */ break; } } spin_unlock(&obd->obd_dev_lock); class_export_put(pet_exp); spin_lock(&pet_lock); pet_exp = NULL; spin_unlock(&pet_lock); } CDEBUG(D_HA, "Exiting Ping Evictor\n"); RETURN(0);}void ping_evictor_start(void){ int rc; if (++pet_refcount > 1) return; init_waitqueue_head(&pet_waitq); rc = cfs_kernel_thread(ping_evictor_main, NULL, CLONE_VM | CLONE_FILES); if (rc < 0) { pet_refcount--; CERROR("Cannot start ping evictor thread: %d\n", rc); }}EXPORT_SYMBOL(ping_evictor_start);void ping_evictor_stop(void){ if (--pet_refcount > 0) return; pet_state = PET_TERMINATE; wake_up(&pet_waitq);}EXPORT_SYMBOL(ping_evictor_stop);#else /* !__KERNEL__ *//* XXX * the current implementation of pinger in liblustre is not optimized */#ifdef ENABLE_PINGERstatic struct pinger_data { int pd_recursion; cfs_time_t pd_this_ping; /* jiffies */ cfs_time_t pd_next_ping; /* jiffies */ struct ptlrpc_request_set *pd_set;} pinger_args;static int pinger_check_rpcs(void *arg){ 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_prep_req(imp, LUSTRE_OBD_VERSION, OBD_PING, 1, NULL, NULL); if (!req) { CERROR("out of memory\n"); break; } req->rq_no_resend = 1; ptlrpc_req_set_repsize(req, 1, NULL); req->rq_send_state = LUSTRE_IMP_FULL; req->rq_phase = 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(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; req->rq_phase = 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); continue; } CDEBUG(D_RPCTRACE, "pinger initiate expire_one_request\n"); ptlrpc_expire_one_request(req); } 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;}static void *pinger_callback = NULL;#endif /* ENABLE_PINGER */int ptlrpc_start_pinger(void){#ifdef ENABLE_PINGER memset(&pinger_args, 0, sizeof(pinger_args)); pinger_callback = liblustre_register_wait_callback("pinger_check_rpcs", &pinger_check_rpcs, &pinger_args);#endif return 0;}int ptlrpc_stop_pinger(void){#ifdef ENABLE_PINGER if (pinger_callback) liblustre_deregister_wait_callback(pinger_callback);#endif return 0;}void ptlrpc_pinger_sending_on_import(struct obd_import *imp){#ifdef ENABLE_PINGER mutex_down(&pinger_sem); ptlrpc_update_next_ping(imp); if (pinger_args.pd_set == NULL && time_before(imp->imp_next_ping, pinger_args.pd_next_ping)) { CDEBUG(D_HA, "set next ping to "CFS_TIME_T"(cur "CFS_TIME_T")\n", imp->imp_next_ping, cfs_time_current()); pinger_args.pd_next_ping = imp->imp_next_ping; } mutex_up(&pinger_sem);#endif}int ptlrpc_pinger_add_import(struct obd_import *imp){ ENTRY; if (!list_empty(&imp->imp_pinger_chain)) RETURN(-EALREADY); CDEBUG(D_HA, "adding pingable import %s->%s\n", imp->imp_obd->obd_uuid.uuid, obd2cli_tgt(imp->imp_obd)); ptlrpc_pinger_sending_on_import(imp); mutex_down(&pinger_sem); list_add_tail(&imp->imp_pinger_chain, &pinger_imports); class_import_get(imp); mutex_up(&pinger_sem); RETURN(0);}int ptlrpc_pinger_del_import(struct obd_import *imp){ ENTRY; if (list_empty(&imp->imp_pinger_chain)) RETURN(-ENOENT); mutex_down(&pinger_sem); list_del_init(&imp->imp_pinger_chain); CDEBUG(D_HA, "removing pingable import %s->%s\n", imp->imp_obd->obd_uuid.uuid, obd2cli_tgt(imp->imp_obd)); class_import_put(imp); mutex_up(&pinger_sem); RETURN(0);}void ptlrpc_pinger_wake_up(){#ifdef ENABLE_PINGER ENTRY; /* XXX force pinger to run, if needed */ struct obd_import *imp; list_for_each_entry(imp, &pinger_imports, imp_pinger_chain) { CDEBUG(D_RPCTRACE, "checking import %s->%s\n", imp->imp_obd->obd_uuid.uuid, obd2cli_tgt(imp->imp_obd));#ifdef ENABLE_LIBLUSTRE_RECOVERY if (imp->imp_state == LUSTRE_IMP_DISCON && !imp->imp_deactive)#else /*XXX only recover for the initial connection */ if (!lustre_handle_is_used(&imp->imp_remote_handle) && imp->imp_state == LUSTRE_IMP_DISCON && !imp->imp_deactive)#endif ptlrpc_initiate_recovery(imp); else if (imp->imp_state != LUSTRE_IMP_FULL) CDEBUG(D_HA, "Refused to recover import %s->%s " "state %d, deactive %d\n", imp->imp_obd->obd_uuid.uuid, obd2cli_tgt(imp->imp_obd), imp->imp_state, imp->imp_deactive); }#endif EXIT;}#endif /* !__KERNEL__ */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?