1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Portal-RPC reconnection and replay operations, for use in recovery.
6 * Copyright (c) 2003 Cluster File Systems, Inc.
7 * Author: Phil Schwan <phil@clusterfs.com>
9 * This file is part of Lustre, http://www.lustre.org.
11 * Lustre is free software; you can redistribute it and/or
12 * modify it under the terms of version 2 of the GNU General Public
13 * License as published by the Free Software Foundation.
15 * Lustre is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with Lustre; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <linux/version.h>
27 #define DEBUG_SUBSYSTEM S_RPC
28 #include <linux/obd_support.h>
29 #include <linux/obd_class.h>
30 #include "ptlrpc_internal.h"
32 static struct ptlrpc_thread *pinger_thread = NULL;
33 static spinlock_t pinger_lock = SPIN_LOCK_UNLOCKED;
34 static struct list_head pinger_imports = LIST_HEAD_INIT(pinger_imports);
36 int ptlrpc_pinger_add_import(struct obd_import *imp)
39 if (!list_empty(&imp->imp_pinger_chain))
42 spin_lock(&pinger_lock);
43 list_add(&imp->imp_pinger_chain, &pinger_imports);
44 spin_unlock(&pinger_lock);
48 int ptlrpc_pinger_del_import(struct obd_import *imp)
51 if (list_empty(&imp->imp_pinger_chain))
54 spin_lock(&pinger_lock);
55 list_del_init(&imp->imp_pinger_chain);
56 spin_unlock(&pinger_lock);
60 static void ptlrpc_pinger_do_stuff(void)
67 static int ptlrpc_pinger_main(void *arg)
69 struct ptlrpc_svc_data *data = (struct ptlrpc_svc_data *)arg;
70 struct ptlrpc_thread *thread = data->thread;
78 SIGNAL_MASK_LOCK(current, flags);
79 sigfillset(¤t->blocked);
81 SIGNAL_MASK_UNLOCK(current, flags);
83 #if defined(__arch_um__) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20))
84 sprintf(current->comm, "%s|%d", data->name,current->thread.extern_pid);
85 #elif defined(__arch_um__) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
86 sprintf(current->comm, "%s|%d", data->name,
87 current->thread.mode.tt.extern_pid);
89 strcpy(current->comm, data->name);
93 /* Record that the thread is running */
94 thread->t_flags = SVC_RUNNING;
95 wake_up(&thread->t_ctl_waitq);
97 /* And now, loop forever on requests */
99 struct l_wait_info lwi = LWI_TIMEOUT(5 * HZ, NULL, NULL);
100 l_wait_event(thread->t_ctl_waitq,
101 thread->t_flags & SVC_STOPPING, &lwi);
103 if (thread->t_flags & SVC_STOPPING) {
104 thread->t_flags &= ~SVC_STOPPING;
108 ptlrpc_pinger_do_stuff();
111 thread->t_flags = SVC_STOPPED;
112 wake_up(&thread->t_ctl_waitq);
114 CDEBUG(D_NET, "pinger thread exiting, process %d: rc = %d\n",
119 int ptlrpc_pinger_start(void)
121 struct l_wait_info lwi = { 0 };
122 struct ptlrpc_svc_data d;
126 spin_lock(&pinger_lock);
127 if (pinger_thread != NULL)
128 GOTO(out, rc = -EALREADY);
130 OBD_ALLOC(pinger_thread, sizeof(*pinger_thread));
131 if (pinger_thread == NULL)
132 GOTO(out, rc = -ENOMEM);
133 init_waitqueue_head(&pinger_thread->t_ctl_waitq);
135 d.name = "Lustre pinger";
136 d.thread = pinger_thread;
138 /* CLONE_VM and CLONE_FILES just avoid a needless copy, because we
139 * just drop the VM and FILES in ptlrpc_daemonize() right away. */
140 rc = kernel_thread(ptlrpc_pinger_main, &d, CLONE_VM | CLONE_FILES);
142 CERROR("cannot start thread: %d\n", rc);
143 OBD_FREE(pinger_thread, sizeof(*pinger_thread));
146 l_wait_event(pinger_thread->t_ctl_waitq,
147 pinger_thread->t_flags & SVC_RUNNING, &lwi);
150 spin_unlock(&pinger_lock);
154 int ptlrpc_stop_pinger(void)
156 struct l_wait_info lwi = { 0 };
160 spin_lock(&pinger_lock);
161 if (pinger_thread == NULL)
162 GOTO(out, rc = -EALREADY);
164 pinger_thread->t_flags = SVC_STOPPING;
165 wake_up(&pinger_thread->t_ctl_waitq);
166 l_wait_event(pinger_thread->t_ctl_waitq,
167 (pinger_thread->t_flags & SVC_STOPPED), &lwi);
169 OBD_FREE(pinger_thread, sizeof(*pinger_thread));
172 spin_unlock(&pinger_lock);