1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Implementation of the management/health monitoring client.
6 * Copyright (c) 2003 Cluster File Systems, Inc.
7 * Author: Mike Shaver <shaver@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.
26 # define EXPORT_SYMTAB
28 #define DEBUG_SUBSYSTEM S_MGMT
29 #include <linux/module.h>
30 #include <linux/init.h>
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>
39 /*** Registration and service/thread management. ***/
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;
48 static int mgmtcli_pinger_main(void *arg)
50 struct ptlrpc_svc_data *data = (struct ptlrpc_svc_data *)arg;
51 struct ptlrpc_thread *thread = data->thread;
53 struct l_wait_info lwi = { 0 };
57 /* vv ptlrpc_daemonize(); vv */
66 /* ^^ ptlrpc_daemonize(); ^^ */
68 SIGNAL_MASK_LOCK(current, flags);
69 sigfillset(¤t->blocked);
71 SIGNAL_MASK_UNLOCK(current, flags);
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);
79 strcpy(current->comm, data->name);
83 /* Record that the thread is running */
84 thread->t_flags = SVC_RUNNING;
85 wake_up(&thread->t_ctl_waitq);
87 /* And now, loop forever, pinging as needed. */
88 l_wait_event(thread->t_ctl_waitq, thread->t_flags & SVC_STOPPING, &lwi);
90 thread->t_flags = SVC_STOPPED;
91 wake_up(&thread->t_ctl_waitq);
93 CDEBUG(D_NET, "pinger thread exiting");
97 static int mgmtcli_connect_to_svc(struct obd_device *obd)
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, };
107 /* Connect to ourselves, and thusly to the mgmt service. */
108 rc = client_connect_import(&conn, obd, &obd->obd_uuid);
110 CERROR("failed to connect to mgmt svc: %d\n", rc);
111 (void)client_obd_cleanup(obd, 0);
114 mc->mc_ping_exp = class_conn2export(&conn);
116 LASSERT(mc->mc_ping_thread == NULL);
117 OBD_ALLOC(thread, sizeof (*thread));
119 GOTO(out, rc = -ENOMEM);
120 mc->mc_ping_thread = thread;
121 init_waitqueue_head(&thread->t_ctl_waitq);
123 svc_data.name = "mgmtcli";
124 svc_data.thread = thread;
126 rc = kernel_thread(mgmtcli_pinger_main, &svc_data, CLONE_VM | CLONE_FILES);
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);
135 l_wait_event(thread->t_ctl_waitq, thread->t_flags & SVC_RUNNING, &lwi);
140 static int mgmtcli_disconnect_from_svc(struct obd_device *obd)
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 };
149 rc = client_disconnect_import(mc->mc_ping_exp, 0);
151 CERROR("can't disconnect from %s: %d (%s)\n",
152 imp->imp_target_uuid.uuid, rc,
154 "stopping pinger thread anyway" :
155 "pinger thread already stopped"));
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);
163 OBD_FREE(mc->mc_ping_thread, sizeof (*mc->mc_ping_thread));
169 static int mgmtcli_register_for_events(struct obd_device *mgmt_obd,
170 struct obd_device *notify_obd,
171 struct obd_uuid *relevant_uuid)
174 struct mgmtcli_registrant *reg;
175 struct mgmtcli_obd *mcobd = &mgmt_obd->u.mgmtcli;
178 if (strcmp(mgmt_obd->obd_type->typ_name, LUSTRE_MGMTCLI_NAME))
181 OBD_ALLOC(reg, sizeof(*reg));
185 reg->notify_obd = notify_obd;
186 reg->relevant_uuid = relevant_uuid; /* XXX hash */
188 spin_lock(&mgmt_obd->obd_dev_lock);
189 start_thread = list_empty(&mcobd->mc_registered);
190 list_add(®->chain, &mcobd->mc_registered);
191 spin_unlock(&mgmt_obd->obd_dev_lock);
194 RETURN(mgmtcli_connect_to_svc(mgmt_obd));
199 static int mgmtcli_deregister_for_events(struct obd_device *mgmt_obd,
200 struct obd_device *notify_obd)
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;
208 if (strcmp(mgmt_obd->obd_type->typ_name, LUSTRE_MGMTCLI_NAME))
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(®->chain);
217 OBD_FREE(reg, sizeof(*reg));
221 spin_unlock(&mgmt_obd->obd_dev_lock);
228 /*** OBD scaffolding and module paraphernalia. ***/
230 static int mgmtcli_setup(struct obd_device *obd, obd_count len, void *buf)
232 struct mgmtcli_obd *mc = &obd->u.mgmtcli;
233 INIT_LIST_HEAD(&mc->mc_registered);
235 /* Initialize our nested client_obd structure. */
236 RETURN(client_obd_setup(obd, len, buf));
239 static int mgmtcli_cleanup(struct obd_device *obd, int flags)
241 struct mgmtcli_obd *mc = &obd->u.mgmtcli;
243 if (!list_empty(&mc->mc_registered))
246 if (mc->mc_ping_thread) {
247 rc = mgmtcli_disconnect_from_svc(obd);
252 RETURN(client_obd_cleanup(obd, flags);
255 static struct obd_ops mgmtcli_obd_ops = {
256 .o_owner = THIS_MODULE,
257 .o_setup = mgmtcli_setup,
258 .o_cleanup = client_obd_cleanup
261 static int __init mgmtcli_init(void)
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);
270 static void __exit mgmtcli_exit(void)
272 class_unregister_type(LUSTRE_MGMTCLI_NAME);
273 inter_module_unregister("mgmtcli_register_for_events");
274 inter_module_unregister("mgmtcli_deregister_for_events");
278 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
279 MODULE_DESCRIPTION("Lustre monitoring client v0.1");
280 MODULE_LICENSE("GPL");
282 module_init(mgmtcli_init);
283 module_exit(mgmtcli_exit);