+/**
+ * Register a timeout callback to the pinger list, and the callback will
+ * be called when timeout happens.
+ */
+struct timeout_item* ptlrpc_new_timeout(int time, enum timeout_event event,
+ timeout_cb_t cb, void *data)
+{
+ struct timeout_item *ti;
+
+ OBD_ALLOC_PTR(ti);
+ if (!ti)
+ return(NULL);
+
+ CFS_INIT_LIST_HEAD(&ti->ti_obd_list);
+ CFS_INIT_LIST_HEAD(&ti->ti_chain);
+ ti->ti_timeout = time;
+ ti->ti_event = event;
+ ti->ti_cb = cb;
+ ti->ti_cb_data = data;
+
+ return ti;
+}
+
+/**
+ * Register timeout event on the the pinger thread.
+ * Note: the timeout list is an sorted list with increased timeout value.
+ */
+static struct timeout_item*
+ptlrpc_pinger_register_timeout(int time, enum timeout_event event,
+ timeout_cb_t cb, void *data)
+{
+ struct timeout_item *item;
+ struct timeout_item *ti = NULL;
+
+ LASSERT_SEM_LOCKED(&pinger_sem);
+ list_for_each_entry_reverse(item, &timeout_list, ti_chain) {
+ if (item->ti_event == event) {
+ ti = item;
+ break;
+ }
+ if (item->ti_timeout < ti->ti_timeout) {
+ ti = ptlrpc_new_timeout(time, event, cb, data);
+ if (!ti) {
+ ti = ERR_PTR(-ENOMEM);
+ break;
+ }
+ list_add(&ti->ti_chain, &item->ti_chain);
+ }
+ }
+ if (!ti) {
+ ti = ptlrpc_new_timeout(time, event, cb, data);
+ if (ti)
+ list_add(&ti->ti_chain, &timeout_list);
+ }
+
+ return ti;
+}
+/* Add a client_obd to the timeout event list, when timeout(@time)
+ * happens, the callback(@cb) will be called.
+ */
+int ptlrpc_add_timeout_client(int time, enum timeout_event event,
+ timeout_cb_t cb, void *data,
+ struct list_head *obd_list)
+{
+ struct timeout_item *ti;
+
+ mutex_down(&pinger_sem);
+ ti = ptlrpc_pinger_register_timeout(time, event, cb, data);
+ if (!ti) {
+ mutex_up(&pinger_sem);
+ return (-EINVAL);
+ }
+ list_add(obd_list, &ti->ti_obd_list);
+ mutex_up(&pinger_sem);
+ return 0;
+}
+
+int ptlrpc_del_timeout_client(struct list_head *obd_list)
+{
+ mutex_down(&pinger_sem);
+ list_del_init(obd_list);
+ mutex_up(&pinger_sem);
+ return 0;
+}
+
+int ptlrpc_pinger_remove_timeouts(void)
+{
+ struct timeout_item *item, *tmp;
+
+ mutex_down(&pinger_sem);
+ list_for_each_entry_safe(item, tmp, &timeout_list, ti_chain) {
+ LASSERT(list_empty(&item->ti_obd_list));
+ list_del(&item->ti_chain);
+ OBD_FREE_PTR(item);
+ }
+ mutex_up(&pinger_sem);
+ return 0;
+}
+