Whamcloud - gitweb
7d17a0a95e67ed16736673979d82cfb0780e21eb
[fs/lustre-release.git] / lustre / mgs / mgs_handler.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lustre/mgs/mgs_handler.c
5  *  Lustre Management Server (mgs) request handler
6  *
7  *  Copyright (C) 2001-2005 Cluster File Systems, Inc.
8  *   Author Nathan <nathan@clusterfs.com>
9  *   Author LinSongTao <lincent@clusterfs.com>
10  *
11  *   This file is part of Lustre, http://www.lustre.org.
12  *
13  *   Lustre is free software; you can redistribute it and/or
14  *   modify it under the terms of version 2 of the GNU General Public
15  *   License as published by the Free Software Foundation.
16  *
17  *   Lustre is distributed in the hope that it will be useful,
18  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *   GNU General Public License for more details.
21  *
22  *   You should have received a copy of the GNU General Public License
23  *   along with Lustre; if not, write to the Free Software
24  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  */
26
27 #ifndef EXPORT_SYMTAB
28 # define EXPORT_SYMTAB
29 #endif
30 #define DEBUG_SUBSYSTEM S_MGS
31
32 #ifdef __KERNEL__
33 # include <linux/module.h>
34 # include <linux/pagemap.h>
35 # include <linux/miscdevice.h>
36 # include <linux/init.h>
37 #else
38 # include <liblustre.h>
39 #endif
40
41 #include <linux/obd_class.h>
42 #include <linux/lustre_dlm.h>
43 #include <linux/lprocfs_status.h>
44 #include <linux/lustre_fsfilt.h>
45 #include <linux/lustre_commit_confd.h>
46 #include <linux/lustre_disk.h>
47 #include "mgs_internal.h"
48
49 static int mgs_postsetup(struct obd_device *obd);
50 static int mgs_cleanup(struct obd_device *obd);
51
52 /* Establish a connection to the MGS.*/
53 static int mgs_connect(struct lustre_handle *conn, struct obd_device *obd,
54                        struct obd_uuid *cluuid, struct obd_connect_data *data)
55 {
56         struct obd_export *exp;
57         int rc, abort_recovery;
58         ENTRY;
59
60         if (!conn || !obd || !cluuid)
61                 RETURN(-EINVAL);
62
63         rc = class_connect(conn, obd, cluuid);
64         if (rc)
65                 RETURN(rc);
66         exp = class_conn2export(conn);
67         LASSERT(exp);
68
69         if (data != NULL) {
70                 data->ocd_connect_flags &= MGMT_CONNECT_SUPPORTED;
71                 exp->exp_connect_flags = data->ocd_connect_flags;
72         }
73
74 #if 0
75         /* FIXME: recovery of connection*/
76         rc = mgs_client_add(obd, &obd->u.mgs, med, -1);
77         GOTO(out, rc);
78 #endif 
79 out:
80         if (rc) {
81                 class_disconnect(exp);
82         } else {
83                 class_export_put(exp);
84         }
85
86         RETURN(rc);
87 }
88
89 static int mgs_disconnect(struct obd_export *exp)
90 {
91         unsigned long irqflags;
92         int rc;
93         ENTRY;
94
95         LASSERT(exp);
96         class_export_get(exp);
97
98         /* Disconnect early so that clients can't keep using export */
99         rc = class_disconnect(exp);
100         ldlm_cancel_locks_for_export(exp);
101
102         /* complete all outstanding replies */
103         spin_lock_irqsave(&exp->exp_lock, irqflags);
104         while (!list_empty(&exp->exp_outstanding_replies)) {
105                 struct ptlrpc_reply_state *rs =
106                         list_entry(exp->exp_outstanding_replies.next,
107                                    struct ptlrpc_reply_state, rs_exp_list);
108                 struct ptlrpc_service *svc = rs->rs_service;
109
110                 spin_lock(&svc->srv_lock);
111                 list_del_init(&rs->rs_exp_list);
112                 ptlrpc_schedule_difficult_reply(rs);
113                 spin_unlock(&svc->srv_lock);
114         }
115         spin_unlock_irqrestore(&exp->exp_lock, irqflags);
116
117         class_export_put(exp);
118         RETURN(rc);
119 }
120
121 /* Start the MGS obd */
122 static int mgs_setup(struct obd_device *obd, obd_count len, void *buf)
123 {
124         struct lprocfs_static_vars lvars;
125         char *ns_name = "MGS";
126         struct mgs_obd *mgs = &obd->u.mgs;
127         struct lustre_mount_info *lmi;
128         struct lustre_sb_info *lsi;
129         struct vfsmount *mnt;
130         int rc = 0;
131         ENTRY;
132
133         CDEBUG(D_CONFIG, "Starting MGS\n");
134
135         lmi = server_get_mount(obd->obd_name);
136         if (!lmi) 
137                 RETURN(rc = -EINVAL);
138
139         mnt = lmi->lmi_mnt;
140         lsi = s2lsi(lmi->lmi_sb);
141         obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd));
142         if (IS_ERR(obd->obd_fsops))
143                 GOTO(err_put, rc = PTR_ERR(obd->obd_fsops));
144
145         /* namespace for mgs llog */
146         obd->obd_namespace = ldlm_namespace_new(ns_name, LDLM_NAMESPACE_SERVER);
147         if (obd->obd_namespace == NULL) {
148                 mgs_cleanup(obd);
149                 GOTO(err_ops, rc = -ENOMEM);
150         }
151
152         LASSERT(!lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb)));
153
154         rc = mgs_fs_setup(obd, mnt);
155         if (rc) {
156                 CERROR("%s: MGS filesystem method init failed: rc = %d\n",
157                        obd->obd_name, rc);
158                 GOTO(err_ns, rc);
159         }
160
161         rc = llog_start_commit_thread();
162         if (rc < 0)
163                 GOTO(err_fs, rc);
164
165         rc = mgs_postsetup(obd);
166         if (rc)
167                 GOTO(err_fs, rc);
168
169         lprocfs_init_vars(mgs, &lvars);
170         lprocfs_obd_setup(obd, lvars.obd_vars);
171
172         LCONSOLE_INFO("MGS %s started\n", obd->obd_name);
173
174         ldlm_timeout = 6;
175         ping_evictor_start();
176
177         RETURN(0);
178
179 err_fs:
180         /* No extra cleanup needed for llog_init_commit_thread() */
181         mgs_fs_cleanup(obd);
182 err_ns:
183         ldlm_namespace_free(obd->obd_namespace, 0);
184         obd->obd_namespace = NULL;
185 err_ops:
186         fsfilt_put_ops(obd->obd_fsops);
187 err_put:
188         server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
189         mgs->mgs_sb = 0;
190         return rc;
191 }
192
193 static int mgs_postsetup(struct obd_device *obd)
194 {
195         int rc = 0;
196         ENTRY;
197
198         rc = llog_setup(obd, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
199                         &llog_lvfs_ops);
200         RETURN(rc);
201 }
202
203 static int mgs_precleanup(struct obd_device *obd, int stage)
204 {
205         int rc = 0;
206         ENTRY;
207
208         llog_cleanup(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT));
209         rc = obd_llog_finish(obd, 0);
210         RETURN(rc);
211 }
212
213 static int mgs_cleanup(struct obd_device *obd)
214 {
215         struct mgs_obd *mgs = &obd->u.mgs;
216         lvfs_sbdev_type save_dev;
217         ENTRY;
218
219         ping_evictor_stop();
220
221         if (mgs->mgs_sb == NULL)
222                 RETURN(0);
223         save_dev = lvfs_sbdev(mgs->mgs_sb);
224
225 //       lprocfs_obd_cleanup(obd);
226
227  //       mgs_update_server_data(obd, 1);
228
229         //mgs_fs_cleanup(obd);
230
231         server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
232         mgs->mgs_sb = NULL;
233
234         ldlm_namespace_free(obd->obd_namespace, obd->obd_force);
235
236         spin_lock_bh(&obd->obd_processing_task_lock);
237         if (obd->obd_recovering) {
238                 target_cancel_recovery_timer(obd);
239                 obd->obd_recovering = 0;
240         }
241         spin_unlock_bh(&obd->obd_processing_task_lock);
242
243         lvfs_clear_rdonly(save_dev);
244
245         fsfilt_put_ops(obd->obd_fsops);
246
247         LCONSOLE_INFO("MGS %s has stopped.\n", obd->obd_name);
248
249         RETURN(0);
250 }
251
252 static int mgs_handle_target_add(struct ptlrpc_request *req)
253 {    
254         struct obd_device *obd = &req->rq_export->exp_obd;
255         struct mgs_obd *mgs = &obd->u.mgs;
256         struct mgmt_target_info *req_mti, *mti, *rep_mti;
257         int rep_size = sizeof(*mti);
258         int index, rc;
259
260         OBD_ALLOC(mti, sizeof(*mti));
261         if (!mti)
262                 GOTO(out, rc = -ENOMEM);
263         req_mti = lustre_swab_reqbuf(req, 0, sizeof(*mti),
264                                      lustre_swab_mgmt_target_info);
265         memcpy(mti, req_mti, sizeof(*mti));
266         
267         /* NEED_INDEX implies NEED_REGISTER, but not vice-versa */
268         if (mti->mti_flags & LDD_F_NEED_INDEX) {
269                 rc = mgs_get_index(mti);
270                // rc = mgmt_handle_first_connect(req);
271         }
272
273         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
274                 rc = llog_add_mds(obd, mti);
275         }
276
277 out:
278         lustre_pack_reply(req, 1, &rep_size, NULL); 
279         rep_mti = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*rep_mti));
280         memcpy(rep_mti, mti, sizeof(*rep_mti));
281         if (rc)
282                 rep_mti->mti_stripe_index = rc;
283         return rc;
284 }
285
286 int mgs_handle(struct ptlrpc_request *req)
287 {
288         int fail = OBD_FAIL_MGMT_ALL_REPLY_NET;
289         int rc = 0;
290         ENTRY;
291
292         OBD_FAIL_RETURN(OBD_FAIL_MGMT_ALL_REQUEST_NET | OBD_FAIL_ONCE, 0);
293
294         LASSERT(current->journal_info == NULL);
295         if (req->rq_reqmsg->opc != MGMT_CONNECT) {
296                 if (req->rq_export == NULL) {
297                         CERROR("lustre_mgs: operation %d on unconnected MGS\n",
298                                req->rq_reqmsg->opc);
299                         req->rq_status = -ENOTCONN;
300                         GOTO(out, rc = -ENOTCONN);
301                 }
302         }
303
304         switch (req->rq_reqmsg->opc) {
305         case MGMT_CONNECT:
306                 DEBUG_REQ(D_INODE, req, "connect");
307                 OBD_FAIL_RETURN(OBD_FAIL_MGMT_CONNECT_NET, 0);
308                 rc = target_handle_connect(req, mgs_handle);
309                 break;
310         case MGMT_DISCONNECT:
311                 DEBUG_REQ(D_INODE, req, "disconnect");
312                 OBD_FAIL_RETURN(OBD_FAIL_MGMT_DISCONNECT_NET, 0);
313                 rc = target_handle_disconnect(req);
314                 req->rq_status = rc;            /* superfluous? */
315                 break;
316
317         case MGMT_TARGET_ADD:
318                 CDEBUG(D_INODE, "target add\n");
319                 rc = mgs_handle_target_add(req);
320                 break;
321         case MGMT_TARGET_DEL:
322                 CDEBUG(D_INODE, "target del\n");
323                 //rc = mgs_handle_target_del(req);
324                 break;
325
326         case LDLM_ENQUEUE:
327                 DEBUG_REQ(D_INODE, req, "enqueue");
328                 OBD_FAIL_RETURN(OBD_FAIL_LDLM_ENQUEUE, 0);
329                 rc = ldlm_handle_enqueue(req, ldlm_server_completion_ast,
330                                          ldlm_server_blocking_ast, NULL);
331                 fail = OBD_FAIL_LDLM_REPLY;
332                 break;
333         case LDLM_BL_CALLBACK:
334         case LDLM_CP_CALLBACK:
335                 DEBUG_REQ(D_INODE, req, "callback");
336                 CERROR("callbacks should not happen on MDS\n");
337                 LBUG();
338                 OBD_FAIL_RETURN(OBD_FAIL_LDLM_BL_CALLBACK, 0);
339                 break;
340
341         case OBD_PING:
342                 DEBUG_REQ(D_INODE, req, "ping");
343                 rc = target_handle_ping(req);
344                 break;
345
346         case OBD_LOG_CANCEL:
347                 CDEBUG(D_INODE, "log cancel\n");
348                 OBD_FAIL_RETURN(OBD_FAIL_OBD_LOG_CANCEL_NET, 0);
349                 rc = -ENOTSUPP; /* la la la */
350                 break;
351
352         case LLOG_ORIGIN_HANDLE_CREATE:
353                 DEBUG_REQ(D_INODE, req, "llog_init");
354                 OBD_FAIL_RETURN(OBD_FAIL_OBD_LOGD_NET, 0);
355                 rc = llog_origin_handle_create(req);
356                 break;
357         case LLOG_ORIGIN_HANDLE_NEXT_BLOCK:
358                 DEBUG_REQ(D_INODE, req, "llog next block");
359                 OBD_FAIL_RETURN(OBD_FAIL_OBD_LOGD_NET, 0);
360                 rc = llog_origin_handle_next_block(req);
361                 break;
362         case LLOG_ORIGIN_HANDLE_READ_HEADER:
363                 DEBUG_REQ(D_INODE, req, "llog read header");
364                 OBD_FAIL_RETURN(OBD_FAIL_OBD_LOGD_NET, 0);
365                 rc = llog_origin_handle_read_header(req);
366                 break;
367         case LLOG_ORIGIN_HANDLE_CLOSE:
368                 DEBUG_REQ(D_INODE, req, "llog close");
369                 OBD_FAIL_RETURN(OBD_FAIL_OBD_LOGD_NET, 0);
370                 rc = llog_origin_handle_close(req);
371                 break;
372         case LLOG_CATINFO:
373                 DEBUG_REQ(D_INODE, req, "llog catinfo");
374                 OBD_FAIL_RETURN(OBD_FAIL_OBD_LOGD_NET, 0);
375                 rc = llog_catinfo(req);
376                 break;
377         default:
378                 req->rq_status = -ENOTSUPP;
379                 rc = ptlrpc_error(req);
380                 RETURN(rc);
381         }
382
383         LASSERT(current->journal_info == NULL);
384
385  out:
386         target_send_reply(req, rc, fail);
387         RETURN(0);
388 }
389
390 static int mgt_setup(struct obd_device *obd, obd_count len, void *buf)
391 {
392         struct mgs_obd *mgs = &obd->u.mgs;
393         struct lprocfs_static_vars lvars;
394         int rc = 0;
395         ENTRY;
396
397        lprocfs_init_vars(mgt, &lvars);
398        lprocfs_obd_setup(obd, lvars.obd_vars);
399
400         mgs->mgs_service =
401                 ptlrpc_init_svc(MGS_NBUFS, MGS_BUFSIZE, MGS_MAXREQSIZE,
402                                 MGS_MAXREPSIZE, MGS_REQUEST_PORTAL, 
403                                 MGC_REPLY_PORTAL, MGS_SERVICE_WATCHDOG_TIMEOUT,
404                                 mgs_handle, "mgs", obd->obd_proc_entry, NULL,
405                                 MGT_NUM_THREADS);
406
407         if (!mgs->mgs_service) {
408                 CERROR("failed to start service\n");
409                 GOTO(err_lprocfs, rc = -ENOMEM);
410         }
411
412         rc = ptlrpc_start_threads(obd, mgs->mgs_service, "ll_mgt");
413         if (rc)
414                 GOTO(err_thread, rc);
415
416         RETURN(0);
417
418 err_thread:
419         ptlrpc_unregister_service(mgs->mgs_service);
420 err_lprocfs:
421         lprocfs_obd_cleanup(obd);
422         return rc;
423 }
424
425
426 static int mgt_cleanup(struct obd_device *obd)
427 {
428         struct mgs_obd *mgs = &obd->u.mgs;
429         ENTRY;
430
431         ptlrpc_unregister_service(mgs->mgs_service);
432
433         lprocfs_obd_cleanup(obd);
434
435         RETURN(0);
436 }
437
438 struct lvfs_callback_ops mgs_lvfs_ops = {
439      //     l_fid2dentry:     mgs_lvfs_fid2dentry,
440     //    l_open_llog:      mgs_lvfs_open_llog,
441 };
442
443 /* use obd ops to offer management infrastructure */
444 static struct obd_ops mgs_obd_ops = {
445         .o_owner           = THIS_MODULE,
446         .o_connect         = mgs_connect,
447         .o_disconnect      = mgs_disconnect,
448         .o_setup           = mgs_setup,
449         .o_precleanup      = mgs_precleanup,
450         .o_cleanup         = mgs_cleanup,
451         .o_iocontrol       = mgs_iocontrol,
452 };
453
454 static struct obd_ops mgt_obd_ops = {
455         .o_owner           = THIS_MODULE,
456         .o_setup           = mgt_setup,
457         .o_cleanup         = mgt_cleanup,
458 };
459
460 static int __init mgs_init(void)
461 {
462         struct lprocfs_static_vars lvars;
463
464         lprocfs_init_vars(mgs, &lvars);
465         class_register_type(&mgs_obd_ops, lvars.module_vars, LUSTRE_MGS_NAME);
466         lprocfs_init_vars(mgt, &lvars);
467         class_register_type(&mgt_obd_ops, lvars.module_vars, LUSTRE_MGT_NAME);
468
469         return 0;
470 }
471
472 static void /*__exit*/ mgs_exit(void)
473 {
474         class_unregister_type(LUSTRE_MGS_NAME);
475         class_unregister_type(LUSTRE_MGT_NAME);
476 }
477
478 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
479 MODULE_DESCRIPTION("Lustre  Management Server (MGS)");
480 MODULE_LICENSE("GPL");
481
482 module_init(mgs_init);
483 module_exit(mgs_exit);