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 + -
显示快捷键?