Whamcloud - gitweb
b=16098
[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  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/mgs/mgs_handler.c
37  *
38  * Author: Nathan Rutman <nathan@clusterfs.com>
39  */
40
41 #ifndef EXPORT_SYMTAB
42 # define EXPORT_SYMTAB
43 #endif
44 #define DEBUG_SUBSYSTEM S_MGS
45 #define D_MGS D_CONFIG/*|D_WARNING*/
46
47 #ifdef __KERNEL__
48 # include <linux/module.h>
49 # include <linux/pagemap.h>
50 # include <linux/miscdevice.h>
51 # include <linux/init.h>
52 #else
53 # include <liblustre.h>
54 #endif
55
56 #include <obd_class.h>
57 #include <lustre_dlm.h>
58 #include <lprocfs_status.h>
59 #include <lustre_fsfilt.h>
60 #include <lustre_disk.h>
61 #include "mgs_internal.h"
62
63
64 /* Establish a connection to the MGS.*/
65 static int mgs_connect(const struct lu_env *env,
66                        struct lustre_handle *conn, struct obd_device *obd,
67                        struct obd_uuid *cluuid, struct obd_connect_data *data,
68                        void *localdata)
69 {
70         struct obd_export *exp;
71         int rc;
72         ENTRY;
73
74         if (!conn || !obd || !cluuid)
75                 RETURN(-EINVAL);
76
77         rc = class_connect(conn, obd, cluuid);
78         if (rc)
79                 RETURN(rc);
80         exp = class_conn2export(conn);
81         LASSERT(exp);
82
83         exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_NULL;
84
85         mgs_counter_incr(exp, LPROC_MGS_CONNECT);
86
87         if (data != NULL) {
88                 data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED;
89                 exp->exp_connect_flags = data->ocd_connect_flags;
90                 data->ocd_version = LUSTRE_VERSION_CODE;
91         }
92
93         if (rc) {
94                 class_disconnect(exp);
95         } else {
96                 class_export_put(exp);
97         }
98
99         RETURN(rc);
100 }
101
102 static int mgs_disconnect(struct obd_export *exp)
103 {
104         int rc;
105         ENTRY;
106
107         LASSERT(exp);
108
109         class_export_get(exp);
110         mgs_counter_incr(exp, LPROC_MGS_DISCONNECT);
111
112         /* Disconnect early so that clients can't keep using export */
113         rc = class_disconnect(exp);
114         ldlm_cancel_locks_for_export(exp);
115
116         /* complete all outstanding replies */
117         spin_lock(&exp->exp_lock);
118         while (!list_empty(&exp->exp_outstanding_replies)) {
119                 struct ptlrpc_reply_state *rs =
120                         list_entry(exp->exp_outstanding_replies.next,
121                                    struct ptlrpc_reply_state, rs_exp_list);
122                 struct ptlrpc_service *svc = rs->rs_service;
123
124                 spin_lock(&svc->srv_lock);
125                 list_del_init(&rs->rs_exp_list);
126                 ptlrpc_schedule_difficult_reply(rs);
127                 spin_unlock(&svc->srv_lock);
128         }
129         spin_unlock(&exp->exp_lock);
130
131         class_export_put(exp);
132         RETURN(rc);
133 }
134
135 static int mgs_cleanup(struct obd_device *obd);
136 static int mgs_handle(struct ptlrpc_request *req);
137
138 static int mgs_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
139                          struct obd_device *tgt, int count,
140                          struct llog_catid *logid, struct obd_uuid *uuid)
141 {
142         int rc;
143         ENTRY;
144
145         LASSERT(olg == &obd->obd_olg);
146         rc = llog_setup(obd, olg, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
147                         &llog_lvfs_ops);
148         RETURN(rc);
149 }
150
151 static int mgs_llog_finish(struct obd_device *obd, int count)
152 {
153         struct llog_ctxt *ctxt;
154         int rc = 0;
155         ENTRY;
156
157         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
158         if (ctxt)
159                 rc = llog_cleanup(ctxt);
160
161         RETURN(rc);
162 }
163
164 /* Start the MGS obd */
165 static int mgs_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
166 {
167         struct lprocfs_static_vars lvars;
168         struct mgs_obd *mgs = &obd->u.mgs;
169         struct lustre_mount_info *lmi;
170         struct lustre_sb_info *lsi;
171         struct vfsmount *mnt;
172         int rc = 0;
173         ENTRY;
174
175         CDEBUG(D_CONFIG, "Starting MGS\n");
176
177         /* Find our disk */
178         lmi = server_get_mount(obd->obd_name);
179         if (!lmi)
180                 RETURN(rc = -EINVAL);
181
182         mnt = lmi->lmi_mnt;
183         lsi = s2lsi(lmi->lmi_sb);
184         obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd));
185         if (IS_ERR(obd->obd_fsops))
186                 GOTO(err_put, rc = PTR_ERR(obd->obd_fsops));
187
188         /* namespace for mgs llog */
189         obd->obd_namespace = ldlm_namespace_new(obd ,"MGS", LDLM_NAMESPACE_SERVER,
190                                                 LDLM_NAMESPACE_MODEST);
191         if (obd->obd_namespace == NULL)
192                 GOTO(err_ops, rc = -ENOMEM);
193
194         /* ldlm setup */
195         ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
196                            "mgs_ldlm_client", &obd->obd_ldlm_client);
197
198         LASSERT(!lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb)));
199
200         rc = mgs_fs_setup(obd, mnt);
201         if (rc) {
202                 CERROR("%s: MGS filesystem method init failed: rc = %d\n",
203                        obd->obd_name, rc);
204                 GOTO(err_ns, rc);
205         }
206
207         rc = obd_llog_init(obd, &obd->obd_olg, obd, 0, NULL, NULL);
208         if (rc)
209                 GOTO(err_fs, rc);
210
211         /* No recovery for MGC's */
212         obd->obd_replayable = 0;
213
214         /* Internal mgs setup */
215         mgs_init_fsdb_list(obd);
216         sema_init(&mgs->mgs_sem, 1);
217
218         /* Start the service threads */
219         mgs->mgs_service =
220                 ptlrpc_init_svc(MGS_NBUFS, MGS_BUFSIZE, MGS_MAXREQSIZE,
221                                 MGS_MAXREPSIZE, MGS_REQUEST_PORTAL,
222                                 MGC_REPLY_PORTAL, 2000,
223                                 mgs_handle, LUSTRE_MGS_NAME,
224                                 obd->obd_proc_entry, target_print_req,
225                                 MGS_THREADS_AUTO_MIN, MGS_THREADS_AUTO_MAX,
226                                 "ll_mgs", LCT_MD_THREAD);
227
228         if (!mgs->mgs_service) {
229                 CERROR("failed to start service\n");
230                 GOTO(err_llog, rc = -ENOMEM);
231         }
232
233         rc = ptlrpc_start_threads(obd, mgs->mgs_service);
234         if (rc)
235                 GOTO(err_thread, rc);
236
237         /* Setup proc */
238         lprocfs_mgs_init_vars(&lvars);
239         if (lprocfs_obd_setup(obd, lvars.obd_vars) == 0) {
240                 lproc_mgs_setup(obd);
241         }
242
243         ping_evictor_start();
244
245         LCONSOLE_INFO("MGS %s started\n", obd->obd_name);
246
247         RETURN(0);
248
249 err_thread:
250         ptlrpc_unregister_service(mgs->mgs_service);
251 err_llog:
252         obd_llog_finish(obd, 0);
253 err_fs:
254         /* No extra cleanup needed for llog_init_commit_thread() */
255         mgs_fs_cleanup(obd);
256 err_ns:
257         ldlm_namespace_free(obd->obd_namespace, NULL, 0);
258         obd->obd_namespace = NULL;
259 err_ops:
260         fsfilt_put_ops(obd->obd_fsops);
261 err_put:
262         server_put_mount(obd->obd_name, mnt);
263         mgs->mgs_sb = 0;
264         return rc;
265 }
266
267 static int mgs_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
268 {
269         int rc = 0;
270         ENTRY;
271
272         switch (stage) {
273         case OBD_CLEANUP_EARLY:
274         case OBD_CLEANUP_EXPORTS:
275                 rc = obd_llog_finish(obd, 0);
276                 break;
277         }
278         RETURN(rc);
279 }
280
281 /**
282  * Performs cleanup procedures for passed \a obd given it is mgs obd.
283  */
284 static int mgs_cleanup(struct obd_device *obd)
285 {
286         struct mgs_obd *mgs = &obd->u.mgs;
287         ENTRY;
288
289         if (mgs->mgs_sb == NULL)
290                 RETURN(0);
291
292         ping_evictor_stop();
293
294         ptlrpc_unregister_service(mgs->mgs_service);
295
296         mgs_cleanup_fsdb_list(obd);
297         lproc_mgs_cleanup(obd);
298         mgs_fs_cleanup(obd);
299
300         server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
301         mgs->mgs_sb = NULL;
302
303         ldlm_namespace_free(obd->obd_namespace, NULL, 1);
304         obd->obd_namespace = NULL;
305
306         fsfilt_put_ops(obd->obd_fsops);
307
308         LCONSOLE_INFO("%s has stopped.\n", obd->obd_name);
309         RETURN(0);
310 }
311
312 /* similar to filter_prepare_destroy */
313 static int mgs_get_cfg_lock(struct obd_device *obd, char *fsname,
314                             struct lustre_handle *lockh)
315 {
316         struct ldlm_res_id res_id;
317         int rc, flags = 0;
318         ENTRY;
319
320         rc = mgc_fsname2resid(fsname, &res_id);
321         if (!rc)
322                 rc = ldlm_cli_enqueue_local(obd->obd_namespace, &res_id,
323                                             LDLM_PLAIN, NULL, LCK_EX,
324                                             &flags, ldlm_blocking_ast,
325                                             ldlm_completion_ast, NULL,
326                                             fsname, 0, NULL, lockh);
327         if (rc)
328                 CERROR("can't take cfg lock for %s (%d)\n", fsname, rc);
329
330         RETURN(rc);
331 }
332
333 static int mgs_put_cfg_lock(struct lustre_handle *lockh)
334 {
335         ENTRY;
336         ldlm_lock_decref(lockh, LCK_EX);
337         RETURN(0);
338 }
339
340 /* rc=0 means ok
341       1 means update
342      <0 means error */
343 static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti)
344 {
345         int rc;
346         ENTRY;
347
348         rc = mgs_check_index(obd, mti);
349         if (rc == 0) {
350                 LCONSOLE_ERROR_MSG(0x13b, "%s claims to have registered, but "
351                                    "this MGS does not know about it. Assuming"
352                                    " writeconf.\n", mti->mti_svname);
353                 mti->mti_flags |= LDD_F_WRITECONF;
354                 rc = 1;
355         } else if (rc == -1) {
356                 LCONSOLE_ERROR_MSG(0x13c, "Client log %s-client has "
357                                    "disappeared! Regenerating all logs.\n",
358                                    mti->mti_fsname);
359                 mti->mti_flags |= LDD_F_WRITECONF;
360                 rc = 1;
361         } else {
362                 /* Index is correctly marked as used */
363
364                 /* If the logs don't contain the mti_nids then add
365                    them as failover nids */
366                 rc = mgs_check_failnid(obd, mti);
367         }
368
369         RETURN(rc);
370 }
371
372 /* Called whenever a target starts up.  Flags indicate first connect, etc. */
373 static int mgs_handle_target_reg(struct ptlrpc_request *req)
374 {
375         struct obd_device *obd = req->rq_export->exp_obd;
376         struct lustre_handle lockh;
377         struct mgs_target_info *mti, *rep_mti;
378         int rc = 0, lockrc;
379         ENTRY;
380
381         mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_REG);
382
383         mti = req_capsule_client_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
384         if (!(mti->mti_flags & (LDD_F_WRITECONF | LDD_F_UPGRADE14 |
385                                 LDD_F_UPDATE))) {
386                 /* We're just here as a startup ping. */
387                 CDEBUG(D_MGS, "Server %s is running on %s\n",
388                        mti->mti_svname, obd_export_nid2str(req->rq_export));
389                 rc = mgs_check_target(obd, mti);
390                 /* above will set appropriate mti flags */
391                 if (rc <= 0)
392                         /* Nothing wrong, or fatal error */
393                         GOTO(out_nolock, rc);
394         }
395
396         /* Revoke the config lock to make sure nobody is reading. */
397         /* Although actually I think it should be alright if
398            someone was reading while we were updating the logs - if we
399            revoke at the end they will just update from where they left off. */
400         lockrc = mgs_get_cfg_lock(obd, mti->mti_fsname, &lockh);
401         if (lockrc != ELDLM_OK) {
402                 LCONSOLE_ERROR_MSG(0x13d, "%s: Can't signal other nodes to "
403                                    "update their configuration (%d). Updating "
404                                    "local logs anyhow; you might have to "
405                                    "manually restart other nodes to get the "
406                                    "latest configuration.\n",
407                                    obd->obd_name, lockrc);
408         }
409
410         OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_PAUSE_TARGET_REG, 10);
411
412         /* Log writing contention is handled by the fsdb_sem */
413
414         if (mti->mti_flags & LDD_F_WRITECONF) {
415                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT &&
416                     mti->mti_stripe_index == 0) {
417                         rc = mgs_erase_logs(obd, mti->mti_fsname);
418                         LCONSOLE_WARN("%s: Logs for fs %s were removed by user "
419                                       "request.  All servers must be restarted "
420                                       "in order to regenerate the logs."
421                                       "\n", obd->obd_name, mti->mti_fsname);
422                 } else if (mti->mti_flags &
423                            (LDD_F_SV_TYPE_OST | LDD_F_SV_TYPE_MDT)) {
424                         rc = mgs_erase_log(obd, mti->mti_svname);
425                         LCONSOLE_WARN("%s: Regenerating %s log by user "
426                                       "request.\n",
427                                       obd->obd_name, mti->mti_svname);
428                 }
429                 mti->mti_flags |= LDD_F_UPDATE;
430                 /* Erased logs means start from scratch. */
431                 mti->mti_flags &= ~LDD_F_UPGRADE14; 
432         }
433
434         /* COMPAT_146 */
435         if (mti->mti_flags & LDD_F_UPGRADE14) {
436                 rc = mgs_upgrade_sv_14(obd, mti);
437                 if (rc) {
438                         CERROR("Can't upgrade from 1.4 (%d)\n", rc);
439                         GOTO(out, rc);
440                 }
441                 
442                 /* We're good to go */
443                 mti->mti_flags |= LDD_F_UPDATE;
444         }
445         /* end COMPAT_146 */
446
447         if (mti->mti_flags & LDD_F_UPDATE) {
448                 CDEBUG(D_MGS, "updating %s, index=%d\n", mti->mti_svname,
449                        mti->mti_stripe_index);
450
451                 /* create or update the target log
452                    and update the client/mdt logs */
453                 rc = mgs_write_log_target(obd, mti);
454                 if (rc) {
455                         CERROR("Failed to write %s log (%d)\n",
456                                mti->mti_svname, rc);
457                         GOTO(out, rc);
458                 }
459
460                 mti->mti_flags &= ~(LDD_F_VIRGIN | LDD_F_UPDATE |
461                                     LDD_F_NEED_INDEX | LDD_F_WRITECONF |
462                                     LDD_F_UPGRADE14);
463                 mti->mti_flags |= LDD_F_REWRITE_LDD;
464         }
465
466 out:
467         /* done with log update */
468         if (lockrc == ELDLM_OK)
469                 mgs_put_cfg_lock(&lockh);
470 out_nolock:
471         CDEBUG(D_MGS, "replying with %s, index=%d, rc=%d\n", mti->mti_svname,
472                mti->mti_stripe_index, rc);
473         rc = req_capsule_server_pack(&req->rq_pill);
474         if (rc)
475                 RETURN(rc);
476
477         /* send back the whole mti in the reply */
478         rep_mti = req_capsule_server_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
479         *rep_mti = *mti;
480
481         /* Flush logs to disk */
482         fsfilt_sync(obd, obd->u.mgs.mgs_sb);
483         RETURN(rc);
484 }
485
486 static int mgs_set_info_rpc(struct ptlrpc_request *req)
487 {
488         struct obd_device *obd = req->rq_export->exp_obd;
489         struct mgs_send_param *msp, *rep_msp;
490         struct lustre_handle lockh;
491         int lockrc, rc;
492         struct lustre_cfg_bufs bufs;
493         struct lustre_cfg *lcfg;
494         char fsname[MTI_NAME_MAXLEN];
495         ENTRY;
496
497         msp = req_capsule_client_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
498         LASSERT(msp);
499
500         /* Construct lustre_cfg structure to pass to function mgs_setparam */
501         lustre_cfg_bufs_reset(&bufs, NULL);
502         lustre_cfg_bufs_set_string(&bufs, 1, msp->mgs_param);
503         lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
504         rc = mgs_setparam(obd, lcfg, fsname);
505         if (rc) {
506                 CERROR("Error %d in setting the parameter %s for fs %s\n",
507                        rc, msp->mgs_param, fsname);
508                 RETURN(rc);
509         }
510
511         /* Revoke lock so everyone updates.  Should be alright if
512          * someone was already reading while we were updating the logs,
513          * so we don't really need to hold the lock while we're
514          * writing.
515          */
516         if (fsname[0]) {
517                 lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
518                 if (lockrc != ELDLM_OK)
519                         CERROR("lock error %d for fs %s\n", lockrc,
520                                fsname);
521                 else
522                         mgs_put_cfg_lock(&lockh);
523         }
524         lustre_cfg_free(lcfg);
525
526         rc = req_capsule_server_pack(&req->rq_pill);
527         if (rc == 0) {
528                 rep_msp = req_capsule_server_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
529                 rep_msp = msp;
530         }
531         RETURN(rc);
532 }
533
534 /* Called whenever a target cleans up. */
535 /* XXX - Currently unused */
536 static int mgs_handle_target_del(struct ptlrpc_request *req)
537 {
538         ENTRY;
539         mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_DEL);
540         RETURN(0);
541 }
542
543 /* XXX - Currently unused */
544 static int mgs_handle_exception(struct ptlrpc_request *req)
545 {
546         ENTRY;
547         mgs_counter_incr(req->rq_export, LPROC_MGS_EXCEPTION);
548         RETURN(0);
549 }
550
551 /* TODO: handle requests in a similar way as MDT: see mdt_handle_common() */
552 int mgs_handle(struct ptlrpc_request *req)
553 {
554         int fail = OBD_FAIL_MGS_ALL_REPLY_NET;
555         int opc, rc = 0;
556         ENTRY;
557
558         req_capsule_init(&req->rq_pill, req, RCL_SERVER);
559         OBD_FAIL_TIMEOUT_MS(OBD_FAIL_MGS_PAUSE_REQ, obd_fail_val);
560         if (OBD_FAIL_CHECK(OBD_FAIL_MGS_ALL_REQUEST_NET))
561                 RETURN(0);
562
563         LASSERT(current->journal_info == NULL);
564         opc = lustre_msg_get_opc(req->rq_reqmsg);
565         if (opc != MGS_CONNECT) {
566                 if (req->rq_export == NULL) {
567                         CERROR("lustre_mgs: operation %d on unconnected MGS\n",
568                                opc);
569                         req->rq_status = -ENOTCONN;
570                         GOTO(out, rc = -ENOTCONN);
571                 }
572         }
573
574         switch (opc) {
575         case MGS_CONNECT:
576                 DEBUG_REQ(D_MGS, req, "connect");
577                 /* MGS and MDS have same request format for connect */
578                 req_capsule_set(&req->rq_pill, &RQF_MDS_CONNECT);
579                 rc = target_handle_connect(req);
580                 if (!rc && (lustre_msg_get_conn_cnt(req->rq_reqmsg) > 1))
581                         /* Make clients trying to reconnect after a MGS restart
582                            happy; also requires obd_replayable */
583                         lustre_msg_add_op_flags(req->rq_repmsg,
584                                                 MSG_CONNECT_RECONNECT);
585                 break;
586         case MGS_DISCONNECT:
587                 DEBUG_REQ(D_MGS, req, "disconnect");
588                 /* MGS and MDS have same request format for disconnect */
589                 req_capsule_set(&req->rq_pill, &RQF_MDS_DISCONNECT);
590                 rc = target_handle_disconnect(req);
591                 req->rq_status = rc;            /* superfluous? */
592                 break;
593         case MGS_EXCEPTION:
594                 DEBUG_REQ(D_MGS, req, "exception");
595                 rc = mgs_handle_exception(req);
596                 break;
597         case MGS_TARGET_REG:
598                 DEBUG_REQ(D_MGS, req, "target add");
599                 req_capsule_set(&req->rq_pill, &RQF_MGS_TARGET_REG);
600                 rc = mgs_handle_target_reg(req);
601                 break;
602         case MGS_TARGET_DEL:
603                 DEBUG_REQ(D_MGS, req, "target del");
604                 rc = mgs_handle_target_del(req);
605                 break;
606         case MGS_SET_INFO:
607                 DEBUG_REQ(D_MGS, req, "set_info");
608                 req_capsule_set(&req->rq_pill, &RQF_MGS_SET_INFO);
609                 rc = mgs_set_info_rpc(req);
610                 break;
611
612         case LDLM_ENQUEUE:
613                 DEBUG_REQ(D_MGS, req, "enqueue");
614                 req_capsule_set(&req->rq_pill, &RQF_LDLM_ENQUEUE);
615                 rc = ldlm_handle_enqueue(req, ldlm_server_completion_ast,
616                                          ldlm_server_blocking_ast, NULL);
617                 break;
618         case LDLM_BL_CALLBACK:
619         case LDLM_CP_CALLBACK:
620                 DEBUG_REQ(D_MGS, req, "callback");
621                 CERROR("callbacks should not happen on MGS\n");
622                 LBUG();
623                 break;
624
625         case OBD_PING:
626                 DEBUG_REQ(D_INFO, req, "ping");
627                 req_capsule_set(&req->rq_pill, &RQF_OBD_PING);
628                 rc = target_handle_ping(req);
629                 break;
630         case OBD_LOG_CANCEL:
631                 DEBUG_REQ(D_MGS, req, "log cancel");
632                 rc = -ENOTSUPP; /* la la la */
633                 break;
634
635         case LLOG_ORIGIN_HANDLE_CREATE:
636                 DEBUG_REQ(D_MGS, req, "llog_init");
637                 req_capsule_set(&req->rq_pill, &RQF_LLOG_ORIGIN_HANDLE_CREATE);
638                 rc = llog_origin_handle_create(req);
639                 break;
640         case LLOG_ORIGIN_HANDLE_NEXT_BLOCK:
641                 DEBUG_REQ(D_MGS, req, "llog next block");
642                 req_capsule_set(&req->rq_pill,
643                                 &RQF_LLOG_ORIGIN_HANDLE_NEXT_BLOCK);
644                 rc = llog_origin_handle_next_block(req);
645                 break;
646         case LLOG_ORIGIN_HANDLE_READ_HEADER:
647                 DEBUG_REQ(D_MGS, req, "llog read header");
648                 req_capsule_set(&req->rq_pill,
649                                 &RQF_LLOG_ORIGIN_HANDLE_READ_HEADER);
650                 rc = llog_origin_handle_read_header(req);
651                 break;
652         case LLOG_ORIGIN_HANDLE_CLOSE:
653                 DEBUG_REQ(D_MGS, req, "llog close");
654                 rc = llog_origin_handle_close(req);
655                 break;
656         case LLOG_CATINFO:
657                 DEBUG_REQ(D_MGS, req, "llog catinfo");
658                 req_capsule_set(&req->rq_pill, &RQF_LLOG_CATINFO);
659                 rc = llog_catinfo(req);
660                 break;
661         default:
662                 req->rq_status = -ENOTSUPP;
663                 rc = ptlrpc_error(req);
664                 RETURN(rc);
665         }
666
667         LASSERT(current->journal_info == NULL);
668
669         if (rc)
670                 CERROR("MGS handle cmd=%d rc=%d\n", opc, rc);
671
672 out:
673         target_send_reply(req, rc, fail);
674         RETURN(0);
675 }
676
677 static inline int mgs_destroy_export(struct obd_export *exp)
678 {
679         ENTRY;
680
681         target_destroy_export(exp);
682
683         RETURN(0);
684 }
685
686 /* from mdt_iocontrol */
687 int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
688                   void *karg, void *uarg)
689 {
690         struct obd_device *obd = exp->exp_obd;
691         struct obd_ioctl_data *data = karg;
692         struct lvfs_run_ctxt saved;
693         int rc = 0;
694
695         ENTRY;
696         CDEBUG(D_IOCTL, "handling ioctl cmd %#x\n", cmd);
697
698         switch (cmd) {
699
700         case OBD_IOC_PARAM: {
701                 struct lustre_handle lockh;
702                 struct lustre_cfg *lcfg;
703                 struct llog_rec_hdr rec;
704                 char fsname[MTI_NAME_MAXLEN];
705                 int lockrc;
706
707                 rec.lrh_len = llog_data_len(data->ioc_plen1);
708
709                 if (data->ioc_type == LUSTRE_CFG_TYPE) {
710                         rec.lrh_type = OBD_CFG_REC;
711                 } else {
712                         CERROR("unknown cfg record type:%d \n", data->ioc_type);
713                         RETURN(-EINVAL);
714                 }
715
716                 OBD_ALLOC(lcfg, data->ioc_plen1);
717                 if (lcfg == NULL)
718                         RETURN(-ENOMEM);
719                 rc = copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1);
720                 if (rc)
721                         GOTO(out_free, rc);
722
723                 if (lcfg->lcfg_bufcount < 1)
724                         GOTO(out_free, rc = -EINVAL);
725
726                 rc = mgs_setparam(obd, lcfg, fsname);
727                 if (rc) {
728                         CERROR("setparam err %d\n", rc);
729                         GOTO(out_free, rc);
730                 }
731
732                 /* Revoke lock so everyone updates.  Should be alright if
733                    someone was already reading while we were updating the logs,
734                    so we don't really need to hold the lock while we're
735                    writing (above). */
736                 if (fsname[0]) {
737                         lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
738                         if (lockrc != ELDLM_OK)
739                                 CERROR("lock error %d for fs %s\n", lockrc,
740                                        fsname);
741                         else
742                                 mgs_put_cfg_lock(&lockh);
743                 }
744
745 out_free:
746                 OBD_FREE(lcfg, data->ioc_plen1);
747                 RETURN(rc);
748         }
749
750         case OBD_IOC_DUMP_LOG: {
751                 struct llog_ctxt *ctxt;
752                 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
753                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
754                 rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL);
755                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
756                 llog_ctxt_put(ctxt);
757
758                 RETURN(rc);
759         }
760
761         case OBD_IOC_LLOG_CHECK:
762         case OBD_IOC_LLOG_INFO:
763         case OBD_IOC_LLOG_PRINT: {
764                 struct llog_ctxt *ctxt;
765                 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
766
767                 push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
768                 rc = llog_ioctl(ctxt, cmd, data);
769                 pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
770                 llog_ctxt_put(ctxt);
771
772                 RETURN(rc);
773         }
774
775         default:
776                 CDEBUG(D_INFO, "unknown command %x\n", cmd);
777                 RETURN(-EINVAL);
778         }
779         RETURN(0);
780 }
781
782 /* use obd ops to offer management infrastructure */
783 static struct obd_ops mgs_obd_ops = {
784         .o_owner           = THIS_MODULE,
785         .o_connect         = mgs_connect,
786         .o_disconnect      = mgs_disconnect,
787         .o_setup           = mgs_setup,
788         .o_precleanup      = mgs_precleanup,
789         .o_cleanup         = mgs_cleanup,
790         .o_destroy_export  = mgs_destroy_export,
791         .o_iocontrol       = mgs_iocontrol,
792         .o_llog_init       = mgs_llog_init,
793         .o_llog_finish     = mgs_llog_finish
794 };
795
796 static int __init mgs_init(void)
797 {
798         struct lprocfs_static_vars lvars;
799
800         lprocfs_mgs_init_vars(&lvars);
801         class_register_type(&mgs_obd_ops, NULL,
802                             lvars.module_vars, LUSTRE_MGS_NAME, NULL);
803
804         return 0;
805 }
806
807 static void /*__exit*/ mgs_exit(void)
808 {
809         class_unregister_type(LUSTRE_MGS_NAME);
810 }
811
812 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
813 MODULE_DESCRIPTION("Lustre  Management Server (MGS)");
814 MODULE_LICENSE("GPL");
815
816 module_init(mgs_init);
817 module_exit(mgs_exit);