Whamcloud - gitweb
land b_smallfix 20040407_1414:
[fs/lustre-release.git] / lustre / mgmt / mgmt_cli.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Implementation of the management/health monitoring client.
5  *
6  *  Copyright (c) 2003 Cluster File Systems, Inc.
7  *   Author: Mike Shaver <shaver@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 #ifndef EXPORT_SYMTAB
26 # define EXPORT_SYMTAB
27 #endif
28 #define DEBUG_SUBSYSTEM S_MGMT
29 #include <linux/module.h>
30 #include <linux/init.h>
31
32 #include <linux/obd.h>
33 #include <linux/obd_class.h>
34 #include <linux/obd_support.h>
35 #include <linux/lustre_idl.h>
36 #include <linux/lustre_net.h>
37 #include <linux/lustre_mgmt.h>
38
39 /*** Registration and service/thread management. ***/
40
41 /* An entry representing one obd which has registered for management events. */
42 struct mgmtcli_registrant {
43         struct list_head   chain;
44         struct obd_device *notify_obd;
45         struct obd_uuid   *relevant_uuid;
46 };
47  
48 static int mgmtcli_pinger_main(void *arg)
49 {
50         struct ptlrpc_svc_data *data = (struct ptlrpc_svc_data *)arg;
51         struct ptlrpc_thread *thread = data->thread;
52         unsigned long flags;
53         struct l_wait_info lwi = { 0 };
54         ENTRY;
55
56         lock_kernel();
57         /* vv ptlrpc_daemonize(); vv */
58         exit_mm(current);
59
60         current->session = 1;
61         current->pgrp = 1;
62         current->tty = NULL;
63
64         exit_files(current);
65         reparent_to_init();
66         /* ^^ ptlrpc_daemonize(); ^^ */
67
68         SIGNAL_MASK_LOCK(current, flags);
69         sigfillset(&current->blocked);
70         RECALC_SIGPENDING;
71         SIGNAL_MASK_UNLOCK(current, flags);
72
73 #if defined(__arch_um__) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20))
74         sprintf(current->comm, "%s|%d", data->name,current->thread.extern_pid);
75 #elif defined(__arch_um__) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
76         sprintf(current->comm, "%s|%d", data->name,
77                 current->thread.mode.tt.extern_pid);
78 #else
79         strcpy(current->comm, data->name);
80 #endif
81         unlock_kernel();
82
83         /* Record that the thread is running */
84         thread->t_flags = SVC_RUNNING;
85         wake_up(&thread->t_ctl_waitq);
86
87         /* And now, loop forever, pinging as needed. */
88         l_wait_event(thread->t_ctl_waitq, thread->t_flags & SVC_STOPPING, &lwi);
89         
90         thread->t_flags = SVC_STOPPED;
91         wake_up(&thread->t_ctl_waitq);
92
93         CDEBUG(D_NET, "pinger thread exiting");
94         return 0;
95 }
96
97 static int mgmtcli_connect_to_svc(struct obd_device *obd)
98 {
99         int rc;
100         struct mgmtcli_obd *mc = &obd->u.mgmtcli;
101         struct ptlrpc_svc_data svc_data;
102         struct ptlrpc_thread *thread;
103         struct l_wait_info lwi = { 0 };
104         struct lustre_handle conn = {0, };
105         ENTRY;
106
107         /* Connect to ourselves, and thusly to the mgmt service. */
108         rc = client_connect_import(&conn, obd, &obd->obd_uuid);
109         if (rc) {
110                 CERROR("failed to connect to mgmt svc: %d\n", rc);
111                 (void)client_obd_cleanup(obd, 0);
112                 RETURN(rc);
113         }
114         mc->mc_ping_exp = class_conn2export(&conn);
115         
116         LASSERT(mc->mc_ping_thread == NULL);
117         OBD_ALLOC(thread, sizeof (*thread));
118         if (thread == NULL)
119                 GOTO(out, rc = -ENOMEM);
120         mc->mc_ping_thread = thread;
121         init_waitqueue_head(&thread->t_ctl_waitq);
122
123         svc_data.name = "mgmtcli";
124         svc_data.thread = thread;
125
126         rc = kernel_thread(mgmtcli_pinger_main, &svc_data, CLONE_VM | CLONE_FILES);
127 out:
128         if (rc < 0) {
129                 CERROR("can't start thread to ping mgmt svc %s: %d\n",
130                        mc->mc_import->imp_target_uuid.uuid, rc);
131                 OBD_FREE(mc->mc_ping_thread, sizeof (*mc->mc_ping_thread));
132                 (void)client_disconnect_import(mc->mc_ping_exp, 0);
133                 RETURN(rc);
134         }
135         l_wait_event(thread->t_ctl_waitq, thread->t_flags & SVC_RUNNING, &lwi);
136         
137         RETURN(0);
138 }
139
140 static int mgmtcli_disconnect_from_svc(struct obd_device *obd)
141 {
142         struct mgmtcli_obd *mc = &obd->u.mgmtcli;
143         struct obd_import *imp = mc->mc_import;
144         struct ptlrpc_thread *thread = mc->mc_ping_thread;
145         struct l_wait_info lwi = { 0 };
146         int rc;
147
148         ENTRY;
149         rc = client_disconnect_import(mc->mc_ping_exp, 0);
150         if (rc) {
151                 CERROR("can't disconnect from %s: %d (%s)\n",
152                        imp->imp_target_uuid.uuid, rc,
153                        (thread ? 
154                         "stopping pinger thread anyway" :
155                         "pinger thread already stopped"));
156         }
157
158         if (thread) {
159                 thread->t_flags = SVC_STOPPING;
160                 wake_up(&thread->t_ctl_waitq);
161                 l_wait_event(thread->t_ctl_waitq, thread->t_flags & SVC_STOPPED, &lwi);
162                 
163                 OBD_FREE(mc->mc_ping_thread, sizeof (*mc->mc_ping_thread));
164         }
165
166         RETURN(rc);
167 }
168
169 static int mgmtcli_register_for_events(struct obd_device *mgmt_obd,
170                                        struct obd_device *notify_obd,
171                                        struct obd_uuid *relevant_uuid)
172 {
173         int start_thread;
174         struct mgmtcli_registrant *reg;
175         struct mgmtcli_obd *mcobd = &mgmt_obd->u.mgmtcli;
176
177         ENTRY;
178         if (strcmp(mgmt_obd->obd_type->typ_name, LUSTRE_MGMTCLI_NAME))
179                 RETURN(-EINVAL);
180
181         OBD_ALLOC(reg, sizeof(*reg));
182         if (reg == NULL)
183                 RETURN(-ENOMEM);
184
185         reg->notify_obd = notify_obd;
186         reg->relevant_uuid = relevant_uuid; /* XXX hash */
187
188         spin_lock(&mgmt_obd->obd_dev_lock);
189         start_thread = list_empty(&mcobd->mc_registered);
190         list_add(&reg->chain, &mcobd->mc_registered);
191         spin_unlock(&mgmt_obd->obd_dev_lock);
192
193         if (start_thread)
194                 RETURN(mgmtcli_connect_to_svc(mgmt_obd));
195
196         RETURN(0);
197 }
198
199 static int mgmtcli_deregister_for_events(struct obd_device *mgmt_obd,
200                                          struct obd_device *notify_obd)
201 {
202         int stop_thread, found = 0;
203         struct mgmtcli_registrant *reg = NULL;
204         struct list_head *tmp, *n;
205         struct mgmtcli_obd *mc = &mgmt_obd->u.mgmtcli;
206
207         ENTRY;
208         if (strcmp(mgmt_obd->obd_type->typ_name, LUSTRE_MGMTCLI_NAME))
209                 RETURN(-EINVAL);
210
211         spin_lock(&mgmt_obd->obd_dev_lock);
212         list_for_each_safe(tmp, n, &mc->mc_registered) {
213                 reg = list_entry(tmp, struct mgmtcli_registrant, chain);
214                 if (reg->notify_obd == notify_obd) {
215                         list_del(&reg->chain);
216                         found = 1;
217                         OBD_FREE(reg, sizeof(*reg));
218                         break;
219                 }
220         }
221         spin_unlock(&mgmt_obd->obd_dev_lock);
222
223         if (!found)
224                 RETURN(-ENOENT);
225         RETURN(0);
226 }
227
228 /*** OBD scaffolding and module paraphernalia. ***/
229
230 static int mgmtcli_setup(struct obd_device *obd, obd_count len, void *buf)
231 {
232         struct mgmtcli_obd *mc = &obd->u.mgmtcli;
233         INIT_LIST_HEAD(&mc->mc_registered);
234         
235         /* Initialize our nested client_obd structure. */
236         RETURN(client_obd_setup(obd, len, buf));
237 }
238
239 static int mgmtcli_cleanup(struct obd_device *obd, int flags)
240 {
241         struct mgmtcli_obd *mc = &obd->u.mgmtcli;
242         
243         if (!list_empty(&mc->mc_registered))
244                 RETURN(-EBUSY);
245
246         if (mc->mc_ping_thread) {
247                 rc = mgmtcli_disconnect_from_svc(obd);
248                 if (rc)
249                         RETURN(rc);
250         }
251
252         RETURN(client_obd_cleanup(obd, flags);
253 }
254
255 static struct obd_ops mgmtcli_obd_ops = {
256         o_owner:   THIS_MODULE,
257         o_setup:   mgmtcli_setup,
258         o_cleanup: client_obd_cleanup
259 };
260
261 static int __init mgmtcli_init(void)
262 {
263         inter_module_register("mgmtcli_register_for_events", THIS_MODULE,
264                               mgmtcli_register_for_events);
265         inter_module_register("mgmtcli_deregister_for_events", THIS_MODULE,
266                               mgmtcli_deregister_for_events);
267         return class_register_type(&mgmtcli_obd_ops, 0, LUSTRE_MGMTCLI_NAME);
268 }
269
270 static void __exit mgmtcli_exit(void)
271 {
272         class_unregister_type(LUSTRE_MGMTCLI_NAME);
273         inter_module_unregister("mgmtcli_register_for_events");
274         inter_module_unregister("mgmtcli_deregister_for_events");
275 }
276
277 #ifdef __KERNEL__
278 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
279 MODULE_DESCRIPTION("Lustre monitoring client v0.1");
280 MODULE_LICENSE("GPL");
281
282 module_init(mgmtcli_init);
283 module_exit(mgmtcli_exit);
284 #endif