Whamcloud - gitweb
51a0cadfe9f7979ad6d7f1fd3b445039f48f62e0
[fs/lustre-release.git] / lustre / ptlrpc / pinger.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Portal-RPC reconnection and replay operations, for use in recovery.
5  *
6  *  Copyright (c) 2003 Cluster File Systems, Inc.
7  *   Author: Phil Schwan <phil@clusterfs.com>
8  *
9  *   This file is part of Lustre, http://www.lustre.org.
10  *
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.
14  *
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.
19  *
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.
23  */
24
25 #include <linux/version.h>
26
27 #define DEBUG_SUBSYSTEM S_RPC
28 #include <linux/obd_support.h>
29 #include <linux/obd_class.h>
30 #include "ptlrpc_internal.h"
31
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);
35
36 int ptlrpc_pinger_add_import(struct obd_import *imp)
37 {
38         ENTRY;
39         if (!list_empty(&imp->imp_pinger_chain))
40                 RETURN(-EALREADY);
41
42         spin_lock(&pinger_lock);
43         list_add(&imp->imp_pinger_chain, &pinger_imports);
44         spin_unlock(&pinger_lock);
45         RETURN(0);
46 }
47
48 int ptlrpc_pinger_del_import(struct obd_import *imp)
49 {
50         ENTRY;
51         if (list_empty(&imp->imp_pinger_chain))
52                 RETURN(-EALREADY);
53
54         spin_lock(&pinger_lock);
55         list_del_init(&imp->imp_pinger_chain);
56         spin_unlock(&pinger_lock);
57         RETURN(0);
58 }
59
60 static void ptlrpc_pinger_do_stuff(void)
61 {
62
63
64
65 }
66
67 static int ptlrpc_pinger_main(void *arg)
68 {
69         struct ptlrpc_svc_data *data = (struct ptlrpc_svc_data *)arg;
70         struct ptlrpc_thread *thread = data->thread;
71         unsigned long flags;
72         int rc = 0;
73         ENTRY;
74
75         lock_kernel();
76         ptlrpc_daemonize();
77
78         SIGNAL_MASK_LOCK(current, flags);
79         sigfillset(&current->blocked);
80         RECALC_SIGPENDING;
81         SIGNAL_MASK_UNLOCK(current, flags);
82
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);
88 #else
89         strcpy(current->comm, data->name);
90 #endif
91         unlock_kernel();
92
93         /* Record that the thread is running */
94         thread->t_flags = SVC_RUNNING;
95         wake_up(&thread->t_ctl_waitq);
96
97         /* And now, loop forever on requests */
98         while (1) {
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);
102
103                 if (thread->t_flags & SVC_STOPPING) {
104                         thread->t_flags &= ~SVC_STOPPING;
105                         EXIT;
106                         break;
107                 }
108                 ptlrpc_pinger_do_stuff();
109         }
110
111         thread->t_flags = SVC_STOPPED;
112         wake_up(&thread->t_ctl_waitq);
113
114         CDEBUG(D_NET, "pinger thread exiting, process %d: rc = %d\n",
115                current->pid, rc);
116         return rc;
117 }
118
119 int ptlrpc_pinger_start(void)
120 {
121         struct l_wait_info lwi = { 0 };
122         struct ptlrpc_svc_data d;
123         int rc;
124         ENTRY;
125
126         spin_lock(&pinger_lock);
127         if (pinger_thread != NULL)
128                 GOTO(out, rc = -EALREADY);
129
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);
134
135         d.name = "Lustre pinger";
136         d.thread = pinger_thread;
137
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);
141         if (rc < 0) {
142                 CERROR("cannot start thread: %d\n", rc);
143                 OBD_FREE(pinger_thread, sizeof(*pinger_thread));
144                 GOTO(out, rc);
145         }
146         l_wait_event(pinger_thread->t_ctl_waitq,
147                      pinger_thread->t_flags & SVC_RUNNING, &lwi);
148
149  out:
150         spin_unlock(&pinger_lock);
151         RETURN(rc);
152 }
153
154 int ptlrpc_stop_pinger(void)
155 {
156         struct l_wait_info lwi = { 0 };
157         int rc = 0;
158         ENTRY;
159
160         spin_lock(&pinger_lock);
161         if (pinger_thread == NULL)
162                 GOTO(out, rc = -EALREADY);
163
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);
168
169         OBD_FREE(pinger_thread, sizeof(*pinger_thread));
170
171  out:
172         spin_unlock(&pinger_lock);
173         RETURN(rc);
174 }