-/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
+/*
* GPL HEADER START
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* GPL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright (c) 2011, 2012, Whamcloud, Inc.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
#include <obd_class.h>
#include "ptlrpc_internal.h"
-cfs_semaphore_t pinger_sem;
+cfs_mutex_t pinger_mutex;
static CFS_LIST_HEAD(pinger_imports);
static cfs_list_t timeout_list = CFS_LIST_HEAD_INIT(timeout_list);
struct ptlrpc_request *
DEBUG_REQ(D_INFO, req, "pinging %s->%s",
imp->imp_obd->obd_uuid.uuid, obd2cli_tgt(imp->imp_obd));
- ptlrpcd_add_req(req, PSCOPE_OTHER);
+ ptlrpcd_add_req(req, PDL_POLICY_ROUND, -1);
RETURN(0);
}
-void ptlrpc_update_next_ping(struct obd_import *imp)
+void ptlrpc_update_next_ping(struct obd_import *imp, int soon)
{
#ifdef ENABLE_PINGER
- int time = PING_INTERVAL;
+ int time = soon ? PING_INTERVAL_SHORT : PING_INTERVAL;
if (imp->imp_state == LUSTRE_IMP_DISCON) {
int dtime = max_t(int, CONNECTION_SWITCH_MIN,
AT_OFF ? 0 :
cfs_time_t timeout = PING_INTERVAL;
/* The timeout list is a increase order sorted list */
- cfs_mutex_down(&pinger_sem);
+ cfs_mutex_lock(&pinger_mutex);
cfs_list_for_each_entry(item, &timeout_list, ti_chain) {
int ti_timeout = item->ti_timeout;
if (timeout > ti_timeout)
timeout = ti_timeout;
break;
}
- cfs_mutex_up(&pinger_sem);
+ cfs_mutex_unlock(&pinger_mutex);
return cfs_time_sub(cfs_time_add(time, cfs_time_seconds(timeout)),
cfs_time_current());
}
-#ifdef __KERNEL__
static cfs_waitq_t suspend_timeouts_waitq;
-#endif
cfs_time_t ptlrpc_suspend_wakeup_time(void)
{
return;
if (level == LUSTRE_IMP_DISCON && !imp_is_deactive(imp)) {
- /* wait at least a timeout before trying recovery again */
+ /* wait for a while before trying recovery again */
imp->imp_next_ping = ptlrpc_next_reconnect(imp);
- ptlrpc_initiate_recovery(imp);
+ if (!imp->imp_no_pinger_recover)
+ ptlrpc_initiate_recovery(imp);
} else if (level != LUSTRE_IMP_FULL ||
imp->imp_obd->obd_no_recov ||
imp_is_deactive(imp)) {
static int ptlrpc_pinger_main(void *arg)
{
- struct ptlrpc_svc_data *data = (struct ptlrpc_svc_data *)arg;
- struct ptlrpc_thread *thread = data->thread;
- ENTRY;
+ struct ptlrpc_thread *thread = (struct ptlrpc_thread *)arg;
+ ENTRY;
- cfs_daemonize(data->name);
+ cfs_daemonize(thread->t_name);
/* Record that the thread is running */
- thread->t_flags = SVC_RUNNING;
+ thread_set_flags(thread, SVC_RUNNING);
cfs_waitq_signal(&thread->t_ctl_waitq);
/* And now, loop forever, pinging as needed. */
struct timeout_item *item;
cfs_list_t *iter;
- cfs_mutex_down(&pinger_sem);
+ cfs_mutex_lock(&pinger_mutex);
cfs_list_for_each_entry(item, &timeout_list, ti_chain) {
item->ti_cb(item, item->ti_cb_data);
}
cfs_time_after(imp->imp_next_ping,
cfs_time_add(this_ping,
cfs_time_seconds(PING_INTERVAL))))
- ptlrpc_update_next_ping(imp);
+ ptlrpc_update_next_ping(imp, 0);
}
- cfs_mutex_up(&pinger_sem);
+ cfs_mutex_unlock(&pinger_mutex);
/* update memory usage info */
obd_update_maxusage();
next ping time to next_ping + .01 sec, which means
we will SKIP the next ping at next_ping, and the
ping will get sent 2 timeouts from now! Beware. */
- CDEBUG(D_INFO, "next wakeup in "CFS_DURATION_T" ("CFS_TIME_T")\n",
- time_to_next_wake,
- cfs_time_add(this_ping, cfs_time_seconds(PING_INTERVAL)));
+ CDEBUG(D_INFO, "next wakeup in "CFS_DURATION_T" ("
+ CFS_TIME_T")\n", time_to_next_wake,
+ cfs_time_add(this_ping,cfs_time_seconds(PING_INTERVAL)));
if (time_to_next_wake > 0) {
- lwi = LWI_TIMEOUT(max_t(cfs_duration_t, time_to_next_wake, cfs_time_seconds(1)),
- NULL, NULL);
+ lwi = LWI_TIMEOUT(max_t(cfs_duration_t,
+ time_to_next_wake,
+ cfs_time_seconds(1)),
+ NULL, NULL);
l_wait_event(thread->t_ctl_waitq,
- thread->t_flags & (SVC_STOPPING|SVC_EVENT),
+ thread_is_stopping(thread) ||
+ thread_is_event(thread),
&lwi);
- if (thread->t_flags & SVC_STOPPING) {
- thread->t_flags &= ~SVC_STOPPING;
+ if (thread_test_and_clear_flags(thread, SVC_STOPPING)) {
EXIT;
break;
- } else if (thread->t_flags & SVC_EVENT) {
+ } else {
/* woken after adding import to reset timer */
- thread->t_flags &= ~SVC_EVENT;
+ thread_test_and_clear_flags(thread, SVC_EVENT);
}
}
}
- thread->t_flags = SVC_STOPPED;
+ thread_set_flags(thread, SVC_STOPPED);
cfs_waitq_signal(&thread->t_ctl_waitq);
CDEBUG(D_NET, "pinger thread exiting, process %d\n", cfs_curproc_pid());
int ptlrpc_start_pinger(void)
{
struct l_wait_info lwi = { 0 };
- struct ptlrpc_svc_data d;
int rc;
#ifndef ENABLE_PINGER
return 0;
cfs_waitq_init(&pinger_thread->t_ctl_waitq);
cfs_waitq_init(&suspend_timeouts_waitq);
- d.name = "ll_ping";
- d.thread = pinger_thread;
+ strcpy(pinger_thread->t_name, "ll_ping");
- /* CLONE_VM and CLONE_FILES just avoid a needless copy, because we
- * just drop the VM and FILES in cfs_daemonize_ctxt() right away. */
- rc = cfs_kernel_thread(ptlrpc_pinger_main, &d, CLONE_VM | CLONE_FILES);
+ /* CLONE_VM and CLONE_FILES just avoid a needless copy, because we
+ * just drop the VM and FILES in cfs_daemonize_ctxt() right away. */
+ rc = cfs_create_thread(ptlrpc_pinger_main,
+ pinger_thread, CFS_DAEMON_FLAGS);
if (rc < 0) {
CERROR("cannot start thread: %d\n", rc);
OBD_FREE(pinger_thread, sizeof(*pinger_thread));
RETURN(rc);
}
l_wait_event(pinger_thread->t_ctl_waitq,
- pinger_thread->t_flags & SVC_RUNNING, &lwi);
+ thread_is_running(pinger_thread), &lwi);
RETURN(0);
}
RETURN(-EALREADY);
ptlrpc_pinger_remove_timeouts();
- cfs_mutex_down(&pinger_sem);
- pinger_thread->t_flags = SVC_STOPPING;
+ cfs_mutex_lock(&pinger_mutex);
+ thread_set_flags(pinger_thread, SVC_STOPPING);
cfs_waitq_signal(&pinger_thread->t_ctl_waitq);
- cfs_mutex_up(&pinger_sem);
+ cfs_mutex_unlock(&pinger_mutex);
l_wait_event(pinger_thread->t_ctl_waitq,
- (pinger_thread->t_flags & SVC_STOPPED), &lwi);
+ thread_is_stopped(pinger_thread), &lwi);
OBD_FREE_PTR(pinger_thread);
pinger_thread = NULL;
void ptlrpc_pinger_sending_on_import(struct obd_import *imp)
{
- ptlrpc_update_next_ping(imp);
+ ptlrpc_update_next_ping(imp, 0);
+}
+
+void ptlrpc_pinger_commit_expected(struct obd_import *imp)
+{
+ ptlrpc_update_next_ping(imp, 1);
}
int ptlrpc_pinger_add_import(struct obd_import *imp)
if (!cfs_list_empty(&imp->imp_pinger_chain))
RETURN(-EALREADY);
- cfs_mutex_down(&pinger_sem);
+ cfs_mutex_lock(&pinger_mutex);
CDEBUG(D_HA, "adding pingable import %s->%s\n",
imp->imp_obd->obd_uuid.uuid, obd2cli_tgt(imp->imp_obd));
/* if we add to pinger we want recovery on this import */
imp->imp_obd->obd_no_recov = 0;
- ptlrpc_update_next_ping(imp);
+ ptlrpc_update_next_ping(imp, 0);
/* XXX sort, blah blah */
cfs_list_add_tail(&imp->imp_pinger_chain, &pinger_imports);
class_import_get(imp);
ptlrpc_pinger_wake_up();
- cfs_mutex_up(&pinger_sem);
+ cfs_mutex_unlock(&pinger_mutex);
RETURN(0);
}
if (cfs_list_empty(&imp->imp_pinger_chain))
RETURN(-ENOENT);
- cfs_mutex_down(&pinger_sem);
+ cfs_mutex_lock(&pinger_mutex);
cfs_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));
/* if we remove from pinger we don't want recovery on this import */
imp->imp_obd->obd_no_recov = 1;
class_import_put(imp);
- cfs_mutex_up(&pinger_sem);
+ cfs_mutex_unlock(&pinger_mutex);
RETURN(0);
}
{
struct timeout_item *item, *tmp;
- LASSERT_SEM_LOCKED(&pinger_sem);
+ LASSERT_MUTEX_LOCKED(&pinger_mutex);
cfs_list_for_each_entry(item, &timeout_list, ti_chain)
if (item->ti_event == event)
{
struct timeout_item *ti;
- cfs_mutex_down(&pinger_sem);
+ cfs_mutex_lock(&pinger_mutex);
ti = ptlrpc_pinger_register_timeout(time, event, cb, data);
if (!ti) {
- cfs_mutex_up(&pinger_sem);
+ cfs_mutex_unlock(&pinger_mutex);
return (-EINVAL);
}
cfs_list_add(obd_list, &ti->ti_obd_list);
- cfs_mutex_up(&pinger_sem);
+ cfs_mutex_unlock(&pinger_mutex);
return 0;
}
if (cfs_list_empty(obd_list))
return 0;
- cfs_mutex_down(&pinger_sem);
+ cfs_mutex_lock(&pinger_mutex);
cfs_list_del_init(obd_list);
/**
* If there are no obd attached to the timeout event
cfs_list_del(&ti->ti_chain);
OBD_FREE_PTR(ti);
}
- cfs_mutex_up(&pinger_sem);
+ cfs_mutex_unlock(&pinger_mutex);
return 0;
}
{
struct timeout_item *item, *tmp;
- cfs_mutex_down(&pinger_sem);
+ cfs_mutex_lock(&pinger_mutex);
cfs_list_for_each_entry_safe(item, tmp, &timeout_list, ti_chain) {
LASSERT(cfs_list_empty(&item->ti_obd_list));
cfs_list_del(&item->ti_chain);
OBD_FREE_PTR(item);
}
- cfs_mutex_up(&pinger_sem);
+ cfs_mutex_unlock(&pinger_mutex);
return 0;
}
void ptlrpc_pinger_wake_up()
{
#ifdef ENABLE_PINGER
- pinger_thread->t_flags |= SVC_EVENT;
+ thread_add_flags(pinger_thread, SVC_EVENT);
cfs_waitq_signal(&pinger_thread->t_ctl_waitq);
#endif
}
obd = class_exp2obd(exp);
if (cfs_list_empty(&obd->obd_evict_list)) {
- class_incref(obd, __FUNCTION__, cfs_current());
+ class_incref(obd, "evictor", obd);
cfs_list_add(&obd->obd_evict_list, &pet_list);
}
cfs_spin_unlock(&pet_lock);
cfs_list_del_init(&obd->obd_evict_list);
cfs_spin_unlock(&pet_lock);
- class_decref(obd, __FUNCTION__, cfs_current());
+ class_decref(obd, "evictor", obd);
}
CDEBUG(D_HA, "Exiting Ping Evictor\n");
cfs_waitq_init(&pet_waitq);
- rc = cfs_kernel_thread(ping_evictor_main, NULL, CLONE_VM | CLONE_FILES);
+ rc = cfs_create_thread(ping_evictor_main, NULL, CFS_DAEMON_FLAGS);
if (rc < 0) {
pet_refcount--;
CERROR("Cannot start ping evictor thread: %d\n", rc);
set = pd->pd_set;
/* add rpcs into set */
- cfs_mutex_down(&pinger_sem);
+ cfs_mutex_lock(&pinger_mutex);
cfs_list_for_each(iter, &pinger_imports) {
struct obd_import *imp = cfs_list_entry(iter, struct obd_import,
imp_pinger_chain);
}
}
pd->pd_this_ping = curtime;
- cfs_mutex_up(&pinger_sem);
+ cfs_mutex_unlock(&pinger_mutex);
/* Might be empty, that's OK. */
if (cfs_atomic_read(&set->set_remaining) == 0)
}
/* Expire all the requests that didn't come back. */
- cfs_mutex_down(&pinger_sem);
+ cfs_mutex_lock(&pinger_mutex);
cfs_list_for_each(iter, &set->set_requests) {
req = cfs_list_entry(iter, struct ptlrpc_request,
rq_set_chain);
cfs_spin_unlock(&imp->imp_lock);
cfs_atomic_dec(&set->set_remaining);
}
- cfs_mutex_up(&pinger_sem);
+ cfs_mutex_unlock(&pinger_mutex);
ptlrpc_set_destroy(set);
pd->pd_set = NULL;
void ptlrpc_pinger_sending_on_import(struct obd_import *imp)
{
#ifdef ENABLE_PINGER
- cfs_mutex_down(&pinger_sem);
- ptlrpc_update_next_ping(imp);
+ cfs_mutex_lock(&pinger_mutex);
+ ptlrpc_update_next_ping(imp, 0);
if (pinger_args.pd_set == NULL &&
cfs_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;
}
- cfs_mutex_up(&pinger_sem);
+ cfs_mutex_unlock(&pinger_mutex);
+#endif
+}
+
+void ptlrpc_pinger_commit_expected(struct obd_import *imp)
+{
+#ifdef ENABLE_PINGER
+ cfs_mutex_lock(&pinger_mutex);
+ ptlrpc_update_next_ping(imp, 1);
+ if (pinger_args.pd_set == NULL &&
+ cfs_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;
+ }
+ cfs_mutex_unlock(&pinger_mutex);
#endif
}
imp->imp_obd->obd_uuid.uuid, obd2cli_tgt(imp->imp_obd));
ptlrpc_pinger_sending_on_import(imp);
- cfs_mutex_down(&pinger_sem);
+ cfs_mutex_lock(&pinger_mutex);
cfs_list_add_tail(&imp->imp_pinger_chain, &pinger_imports);
class_import_get(imp);
- cfs_mutex_up(&pinger_sem);
+ cfs_mutex_unlock(&pinger_mutex);
RETURN(0);
}
if (cfs_list_empty(&imp->imp_pinger_chain))
RETURN(-ENOENT);
- cfs_mutex_down(&pinger_sem);
+ cfs_mutex_lock(&pinger_mutex);
cfs_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);
- cfs_mutex_up(&pinger_sem);
+ cfs_mutex_unlock(&pinger_mutex);
RETURN(0);
}