Whamcloud - gitweb
- make HEAD from b_post_cmd3
[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) 2006 Cluster File Systems, Inc.
8  *   Author: Nathan Rutman <nathan@clusterfs.com>
9  *
10  *   This file is part of Lustre, http://www.lustre.org.
11  *
12  *   Lustre is free software; you can redistribute it and/or
13  *   modify it under the terms of version 2 of the GNU General Public
14  *   License as published by the Free Software Foundation.
15  *
16  *   Lustre is distributed in the hope that it will be useful,
17  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *   GNU General Public License for more details.
20  *
21  *   You should have received a copy of the GNU General Public License
22  *   along with Lustre; if not, write to the Free Software
23  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 #ifndef EXPORT_SYMTAB
27 # define EXPORT_SYMTAB
28 #endif
29 #define DEBUG_SUBSYSTEM S_MGS
30 #define D_MGS D_CONFIG/*|D_WARNING*/
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 <obd_class.h>
42 #include <lustre_dlm.h>
43 #include <lprocfs_status.h>
44 #include <lustre_fsfilt.h>
45 #include <lustre_commit_confd.h>
46 #include <lustre_disk.h>
47 #include "mgs_internal.h"
48
49
50 /* Establish a connection to the MGS.*/
51 static int mgs_connect(const struct lu_env *env,
52                        struct lustre_handle *conn, struct obd_device *obd,
53                        struct obd_uuid *cluuid, struct obd_connect_data *data)
54 {
55         struct obd_export *exp;
56         int rc;
57         ENTRY;
58
59         if (!conn || !obd || !cluuid)
60                 RETURN(-EINVAL);
61
62         rc = class_connect(conn, obd, cluuid);
63         if (rc)
64                 RETURN(rc);
65         exp = class_conn2export(conn);
66         LASSERT(exp);
67
68         if (data != NULL) {
69                 data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED;
70                 exp->exp_connect_flags = data->ocd_connect_flags;
71                 data->ocd_version = LUSTRE_VERSION_CODE;
72         }
73
74         if (rc) {
75                 class_disconnect(exp);
76         } else {
77                 class_export_put(exp);
78         }
79
80         RETURN(rc);
81 }
82
83 static int mgs_disconnect(struct obd_export *exp)
84 {
85         int rc;
86         ENTRY;
87
88         LASSERT(exp);
89         class_export_get(exp);
90
91         /* Disconnect early so that clients can't keep using export */
92         rc = class_disconnect(exp);
93         ldlm_cancel_locks_for_export(exp);
94
95         /* complete all outstanding replies */
96         spin_lock(&exp->exp_lock);
97         while (!list_empty(&exp->exp_outstanding_replies)) {
98                 struct ptlrpc_reply_state *rs =
99                         list_entry(exp->exp_outstanding_replies.next,
100                                    struct ptlrpc_reply_state, rs_exp_list);
101                 struct ptlrpc_service *svc = rs->rs_service;
102
103                 spin_lock(&svc->srv_lock);
104                 list_del_init(&rs->rs_exp_list);
105                 ptlrpc_schedule_difficult_reply(rs);
106                 spin_unlock(&svc->srv_lock);
107         }
108         spin_unlock(&exp->exp_lock);
109
110         class_export_put(exp);
111         RETURN(rc);
112 }
113
114 static int mgs_cleanup(struct obd_device *obd);
115 static int mgs_handle(struct ptlrpc_request *req);
116
117 /* Start the MGS obd */
118 static int mgs_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
119 {
120         struct lprocfs_static_vars lvars;
121         struct mgs_obd *mgs = &obd->u.mgs;
122         struct lustre_mount_info *lmi;
123         struct lustre_sb_info *lsi;
124         struct vfsmount *mnt;
125         int rc = 0;
126         ENTRY;
127
128         CDEBUG(D_CONFIG, "Starting MGS\n");
129
130         /* Find our disk */
131         lmi = server_get_mount(obd->obd_name);
132         if (!lmi)
133                 RETURN(rc = -EINVAL);
134
135         mnt = lmi->lmi_mnt;
136         lsi = s2lsi(lmi->lmi_sb);
137         obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd));
138         if (IS_ERR(obd->obd_fsops))
139                 GOTO(err_put, rc = PTR_ERR(obd->obd_fsops));
140
141         /* namespace for mgs llog */
142         obd->obd_namespace = ldlm_namespace_new("MGS", LDLM_NAMESPACE_SERVER);
143         if (obd->obd_namespace == NULL) {
144                 mgs_cleanup(obd);
145                 GOTO(err_ops, rc = -ENOMEM);
146         }
147
148         /* ldlm setup */
149         ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
150                            "mgs_ldlm_client", &obd->obd_ldlm_client);
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 = llog_setup(obd, NULL, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
166                         &llog_lvfs_ops);
167         if (rc)
168                 GOTO(err_fs, rc);
169
170         /* No recovery for MGC's */
171         obd->obd_replayable = 0;
172
173         /* Internal mgs setup */
174         mgs_init_fsdb_list(obd);
175         sema_init(&mgs->mgs_sem, 1);
176
177         /* Start the service threads */
178         mgs->mgs_service =
179                 ptlrpc_init_svc(MGS_NBUFS, MGS_BUFSIZE, MGS_MAXREQSIZE,
180                                 MGS_MAXREPSIZE, MGS_REQUEST_PORTAL,
181                                 MGC_REPLY_PORTAL, MGS_SERVICE_WATCHDOG_TIMEOUT,
182                                 mgs_handle, LUSTRE_MGS_NAME,
183                                 obd->obd_proc_entry, NULL,
184                                 MGS_THREADS_AUTO_MIN, MGS_THREADS_AUTO_MAX,
185                                 "ll_mgs", LCT_MD_THREAD);
186
187         if (!mgs->mgs_service) {
188                 CERROR("failed to start service\n");
189                 GOTO(err_fs, rc = -ENOMEM);
190         }
191
192         rc = ptlrpc_start_threads(obd, mgs->mgs_service);
193         if (rc)
194                 GOTO(err_thread, rc);
195
196         /* Setup proc */
197         lprocfs_init_vars(mgs, &lvars);
198         if (lprocfs_obd_setup(obd, lvars.obd_vars) == 0) {
199                 lproc_mgs_setup(obd);
200         }
201
202         ping_evictor_start();
203
204         LCONSOLE_INFO("MGS %s started\n", obd->obd_name);
205
206         RETURN(0);
207
208 err_thread:
209         ptlrpc_unregister_service(mgs->mgs_service);
210 err_fs:
211         /* No extra cleanup needed for llog_init_commit_thread() */
212         mgs_fs_cleanup(obd);
213 err_ns:
214         ldlm_namespace_free(obd->obd_namespace, 0);
215         obd->obd_namespace = NULL;
216 err_ops:
217         fsfilt_put_ops(obd->obd_fsops);
218 err_put:
219         server_put_mount(obd->obd_name, mnt);
220         mgs->mgs_sb = 0;
221         return rc;
222 }
223
224 static int mgs_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
225 {
226         int rc = 0;
227         ENTRY;
228
229         switch (stage) {
230         case OBD_CLEANUP_EARLY:
231         case OBD_CLEANUP_EXPORTS:
232                 break;
233         case OBD_CLEANUP_SELF_EXP:
234                 llog_cleanup(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT));
235                 rc = obd_llog_finish(obd, 0);
236                 break;
237         case OBD_CLEANUP_OBD:
238                 break;
239         }
240         RETURN(rc);
241 }
242
243 static int mgs_ldlm_nsfree(void *data)
244 {
245         struct ldlm_namespace *ns = (struct ldlm_namespace *)data;
246         int rc;
247         ENTRY;
248
249         ptlrpc_daemonize("ll_mgs_nsfree");
250         rc = ldlm_namespace_free(ns, 1 /* obd_force should always be on */);
251         RETURN(rc);
252 }
253
254 static int mgs_cleanup(struct obd_device *obd)
255 {
256         struct mgs_obd *mgs = &obd->u.mgs;
257         ENTRY;
258
259         ping_evictor_stop();
260
261         if (mgs->mgs_sb == NULL)
262                 RETURN(0);
263
264         ptlrpc_unregister_service(mgs->mgs_service);
265
266         mgs_cleanup_fsdb_list(obd);
267
268         lprocfs_obd_cleanup(obd);
269         mgs->mgs_proc_live = NULL;
270
271         mgs_fs_cleanup(obd);
272
273         server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
274         mgs->mgs_sb = NULL;
275
276         /* Free the namespace in it's own thread, so that if the
277            ldlm_cancel_handler put the last mgs obd ref, we won't
278            deadlock here. */
279         cfs_kernel_thread(mgs_ldlm_nsfree, obd->obd_namespace,
280                           CLONE_VM | CLONE_FILES);
281
282
283         fsfilt_put_ops(obd->obd_fsops);
284
285         LCONSOLE_INFO("%s has stopped.\n", obd->obd_name);
286         RETURN(0);
287 }
288
289 /* similar to filter_prepare_destroy */
290 static int mgs_get_cfg_lock(struct obd_device *obd, char *fsname,
291                             struct lustre_handle *lockh)
292 {
293         struct ldlm_res_id res_id;
294         int rc, flags = 0;
295         ENTRY;
296
297         rc = mgc_logname2resid(fsname, &res_id);
298         if (!rc)
299                 rc = ldlm_cli_enqueue_local(obd->obd_namespace, &res_id,
300                                             LDLM_PLAIN, NULL, LCK_EX,
301                                             &flags, ldlm_blocking_ast,
302                                             ldlm_completion_ast, NULL,
303                                             fsname, 0, NULL, lockh);
304         if (rc)
305                 CERROR("can't take cfg lock for %s (%d)\n", fsname, rc);
306
307         RETURN(rc);
308 }
309
310 static int mgs_put_cfg_lock(struct lustre_handle *lockh)
311 {
312         ENTRY;
313         ldlm_lock_decref(lockh, LCK_EX);
314         RETURN(0);
315 }
316
317 /* rc=0 means ok
318       1 means update
319      <0 means error */
320 static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti)
321 {
322         int rc;
323         ENTRY;
324
325         rc = mgs_check_index(obd, mti);
326         if (rc == 0) {
327                 LCONSOLE_ERROR_MSG(0x13b, "%s claims to have registered, but "
328                                    "this MGS does not know about it. Assuming"
329                                    " writeconf.\n", mti->mti_svname);
330                 mti->mti_flags |= LDD_F_WRITECONF;
331                 rc = 1;
332         } else if (rc == -1) {
333                 LCONSOLE_ERROR_MSG(0x13c, "Client log %s-client has "
334                                    "disappeared! Regenerating all logs.\n",
335                                    mti->mti_fsname);
336                 mti->mti_flags |= LDD_F_WRITECONF;
337                 rc = 1;
338         } else {
339                 /* Index is correctly marked as used */
340
341                 /* If the logs don't contain the mti_nids then add
342                    them as failover nids */
343                 rc = mgs_check_failnid(obd, mti);
344         }
345
346         RETURN(rc);
347 }
348
349 /* Called whenever a target starts up.  Flags indicate first connect, etc. */
350 static int mgs_handle_target_reg(struct ptlrpc_request *req)
351 {
352         struct obd_device *obd = req->rq_export->exp_obd;
353         struct lustre_handle lockh;
354         struct mgs_target_info *mti, *rep_mti;
355         int rep_size[] = { sizeof(struct ptlrpc_body), sizeof(*mti) };
356         int rc = 0, lockrc;
357         ENTRY;
358
359         mti = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*mti),
360                                  lustre_swab_mgs_target_info);
361
362         if (!(mti->mti_flags & (LDD_F_WRITECONF | LDD_F_UPGRADE14 |
363                                 LDD_F_UPDATE))) {
364                 /* We're just here as a startup ping. */
365                 CDEBUG(D_MGS, "Server %s is running on %s\n",
366                        mti->mti_svname, obd_export_nid2str(req->rq_export));
367                 rc = mgs_check_target(obd, mti);
368                 /* above will set appropriate mti flags */
369                 if (rc <= 0)
370                         /* Nothing wrong, or fatal error */
371                         GOTO(out_nolock, rc);
372         }
373
374         /* Revoke the config lock to make sure nobody is reading. */
375         /* Although actually I think it should be alright if
376            someone was reading while we were updating the logs - if we
377            revoke at the end they will just update from where they left off. */
378         lockrc = mgs_get_cfg_lock(obd, mti->mti_fsname, &lockh);
379         if (lockrc != ELDLM_OK) {
380                 LCONSOLE_ERROR_MSG(0x13d, "%s: Can't signal other nodes to "
381                                    "update their configuration (%d). Updating "
382                                    "local logs anyhow; you might have to "
383                                    "manually restart other nodes to get the "
384                                    "latest configuration.\n",
385                                    obd->obd_name, lockrc);
386         }
387
388         OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_SLOW_TARGET_REG, 10);
389
390         /* Log writing contention is handled by the fsdb_sem */
391
392         if (mti->mti_flags & LDD_F_WRITECONF) {
393                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
394                         rc = mgs_erase_logs(obd, mti->mti_fsname);
395                         LCONSOLE_WARN("%s: Logs for fs %s were removed by user "
396                                       "request.  All servers must be restarted "
397                                       "in order to regenerate the logs."
398                                       "\n", obd->obd_name, mti->mti_fsname);
399                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
400                         rc = mgs_erase_log(obd, mti->mti_svname);
401                         LCONSOLE_WARN("%s: Regenerating %s log by user "
402                                       "request.\n",
403                                       obd->obd_name, mti->mti_svname);
404                 }
405                 mti->mti_flags |= LDD_F_UPDATE;
406                 /* Erased logs means start from scratch. */
407                 mti->mti_flags &= ~LDD_F_UPGRADE14; 
408         }
409
410         /* COMPAT_146 */
411         if (mti->mti_flags & LDD_F_UPGRADE14) {
412                 rc = mgs_upgrade_sv_14(obd, mti);
413                 if (rc) {
414                         CERROR("Can't upgrade from 1.4 (%d)\n", rc);
415                         GOTO(out, rc);
416                 }
417                 
418                 /* We're good to go */
419                 mti->mti_flags |= LDD_F_UPDATE;
420         }
421         /* end COMPAT_146 */
422
423         if (mti->mti_flags & LDD_F_UPDATE) {
424                 CDEBUG(D_MGS, "updating %s, index=%d\n", mti->mti_svname,
425                        mti->mti_stripe_index);
426
427                 /* create or update the target log
428                    and update the client/mdt logs */
429                 rc = mgs_write_log_target(obd, mti);
430                 if (rc) {
431                         CERROR("Failed to write %s log (%d)\n",
432                                mti->mti_svname, rc);
433                         GOTO(out, rc);
434                 }
435
436                 mti->mti_flags &= ~(LDD_F_VIRGIN | LDD_F_UPDATE |
437                                     LDD_F_NEED_INDEX | LDD_F_WRITECONF |
438                                     LDD_F_UPGRADE14);
439                 mti->mti_flags |= LDD_F_REWRITE_LDD;
440         }
441
442 out:
443         /* done with log update */
444         if (lockrc == ELDLM_OK)
445                 mgs_put_cfg_lock(&lockh);
446 out_nolock:
447         CDEBUG(D_MGS, "replying with %s, index=%d, rc=%d\n", mti->mti_svname,
448                mti->mti_stripe_index, rc);
449         lustre_pack_reply(req, 2, rep_size, NULL);
450         /* send back the whole mti in the reply */
451         rep_mti = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
452                                  sizeof(*rep_mti));
453         memcpy(rep_mti, mti, sizeof(*rep_mti));
454
455         /* Flush logs to disk */
456         fsfilt_sync(obd, obd->u.mgs.mgs_sb);
457         RETURN(rc);
458 }
459
460 int mgs_handle(struct ptlrpc_request *req)
461 {
462         int fail = OBD_FAIL_MGS_ALL_REPLY_NET;
463         int opc, rc = 0;
464         ENTRY;
465
466         OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_SLOW_REQUEST_NET, 2);
467
468         LASSERT(current->journal_info == NULL);
469         opc = lustre_msg_get_opc(req->rq_reqmsg);
470         if (opc != MGS_CONNECT) {
471                 if (req->rq_export == NULL) {
472                         CERROR("lustre_mgs: operation %d on unconnected MGS\n",
473                                opc);
474                         req->rq_status = -ENOTCONN;
475                         GOTO(out, rc = -ENOTCONN);
476                 }
477         }
478
479         switch (opc) {
480         case MGS_CONNECT:
481                 DEBUG_REQ(D_MGS, req, "connect");
482                 rc = target_handle_connect(req);
483                 if (!rc && (lustre_msg_get_conn_cnt(req->rq_reqmsg) > 1))
484                         /* Make clients trying to reconnect after a MGS restart
485                            happy; also requires obd_replayable */
486                         lustre_msg_add_op_flags(req->rq_repmsg,
487                                                 MSG_CONNECT_RECONNECT);
488                 break;
489         case MGS_DISCONNECT:
490                 DEBUG_REQ(D_MGS, req, "disconnect");
491                 rc = target_handle_disconnect(req);
492                 req->rq_status = rc;            /* superfluous? */
493                 break;
494         case MGS_TARGET_REG:
495                 DEBUG_REQ(D_MGS, req, "target add");
496                 rc = mgs_handle_target_reg(req);
497                 break;
498         case MGS_TARGET_DEL:
499                 DEBUG_REQ(D_MGS, req, "target del");
500                 //rc = mgs_handle_target_del(req);
501                 break;
502
503         case LDLM_ENQUEUE:
504                 DEBUG_REQ(D_MGS, req, "enqueue");
505                 rc = ldlm_handle_enqueue(req, ldlm_server_completion_ast,
506                                          ldlm_server_blocking_ast, NULL);
507                 break;
508         case LDLM_BL_CALLBACK:
509         case LDLM_CP_CALLBACK:
510                 DEBUG_REQ(D_MGS, req, "callback");
511                 CERROR("callbacks should not happen on MGS\n");
512                 LBUG();
513                 break;
514
515         case OBD_PING:
516                 DEBUG_REQ(D_INFO, req, "ping");
517                 rc = target_handle_ping(req);
518                 break;
519         case OBD_LOG_CANCEL:
520                 DEBUG_REQ(D_MGS, req, "log cancel");
521                 rc = -ENOTSUPP; /* la la la */
522                 break;
523
524         case LLOG_ORIGIN_HANDLE_CREATE:
525                 DEBUG_REQ(D_MGS, req, "llog_init");
526                 rc = llog_origin_handle_create(req);
527                 break;
528         case LLOG_ORIGIN_HANDLE_NEXT_BLOCK:
529                 DEBUG_REQ(D_MGS, req, "llog next block");
530                 rc = llog_origin_handle_next_block(req);
531                 break;
532         case LLOG_ORIGIN_HANDLE_READ_HEADER:
533                 DEBUG_REQ(D_MGS, req, "llog read header");
534                 rc = llog_origin_handle_read_header(req);
535                 break;
536         case LLOG_ORIGIN_HANDLE_CLOSE:
537                 DEBUG_REQ(D_MGS, req, "llog close");
538                 rc = llog_origin_handle_close(req);
539                 break;
540         case LLOG_CATINFO:
541                 DEBUG_REQ(D_MGS, req, "llog catinfo");
542                 rc = llog_catinfo(req);
543                 break;
544         default:
545                 req->rq_status = -ENOTSUPP;
546                 rc = ptlrpc_error(req);
547                 RETURN(rc);
548         }
549
550         LASSERT(current->journal_info == NULL);
551
552         if (rc)
553                 CERROR("MGS handle cmd=%d rc=%d\n", opc, rc);
554
555 out:
556         target_send_reply(req, rc, fail);
557         RETURN(0);
558 }
559
560 static inline int mgs_destroy_export(struct obd_export *exp)
561 {
562         ENTRY;
563
564         target_destroy_export(exp);
565
566         RETURN(0);
567 }
568
569 /* from mdt_iocontrol */
570 int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
571                   void *karg, void *uarg)
572 {
573         struct obd_device *obd = exp->exp_obd;
574         struct obd_ioctl_data *data = karg;
575         struct lvfs_run_ctxt saved;
576         int rc = 0;
577
578         ENTRY;
579         CDEBUG(D_IOCTL, "handling ioctl cmd %#x\n", cmd);
580
581         switch (cmd) {
582
583         case OBD_IOC_PARAM: {
584                 struct lustre_handle lockh;
585                 struct lustre_cfg *lcfg;
586                 struct llog_rec_hdr rec;
587                 char fsname[MTI_NAME_MAXLEN];
588                 int lockrc;
589
590                 rec.lrh_len = llog_data_len(data->ioc_plen1);
591
592                 if (data->ioc_type == LUSTRE_CFG_TYPE) {
593                         rec.lrh_type = OBD_CFG_REC;
594                 } else {
595                         CERROR("unknown cfg record type:%d \n", data->ioc_type);
596                         RETURN(-EINVAL);
597                 }
598
599                 OBD_ALLOC(lcfg, data->ioc_plen1);
600                 if (lcfg == NULL)
601                         RETURN(-ENOMEM);
602                 rc = copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1);
603                 if (rc)
604                         GOTO(out_free, rc);
605
606                 if (lcfg->lcfg_bufcount < 1)
607                         GOTO(out_free, rc = -EINVAL);
608
609                 rc = mgs_setparam(obd, lcfg, fsname);
610                 if (rc) {
611                         CERROR("setparam err %d\n", rc);
612                         GOTO(out_free, rc);
613                 }
614
615                 /* Revoke lock so everyone updates.  Should be alright if
616                    someone was already reading while we were updating the logs,
617                    so we don't really need to hold the lock while we're
618                    writing (above). */
619                 if (fsname[0]) {
620                         lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
621                         if (lockrc != ELDLM_OK)
622                                 CERROR("lock error %d for fs %s\n", lockrc,
623                                        fsname);
624                         else
625                                 mgs_put_cfg_lock(&lockh);
626                 }
627
628 out_free:
629                 OBD_FREE(lcfg, data->ioc_plen1);
630                 RETURN(rc);
631         }
632
633         case OBD_IOC_DUMP_LOG: {
634                 struct llog_ctxt *ctxt =
635                         llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
636                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
637                 rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL);
638                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
639                 if (rc)
640                         RETURN(rc);
641
642                 RETURN(rc);
643         }
644
645         case OBD_IOC_LLOG_CHECK:
646         case OBD_IOC_LLOG_INFO:
647         case OBD_IOC_LLOG_PRINT: {
648                 struct llog_ctxt *ctxt =
649                         llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
650
651                 push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
652                 rc = llog_ioctl(ctxt, cmd, data);
653                 pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
654
655                 RETURN(rc);
656         }
657
658         default:
659                 CDEBUG(D_INFO, "unknown command %x\n", cmd);
660                 RETURN(-EINVAL);
661         }
662         RETURN(0);
663 }
664
665 /* use obd ops to offer management infrastructure */
666 static struct obd_ops mgs_obd_ops = {
667         .o_owner           = THIS_MODULE,
668         .o_connect         = mgs_connect,
669         .o_disconnect      = mgs_disconnect,
670         .o_setup           = mgs_setup,
671         .o_precleanup      = mgs_precleanup,
672         .o_cleanup         = mgs_cleanup,
673         .o_destroy_export  = mgs_destroy_export,
674         .o_iocontrol       = mgs_iocontrol,
675 };
676
677 static int __init mgs_init(void)
678 {
679         struct lprocfs_static_vars lvars;
680
681         lprocfs_init_vars(mgs, &lvars);
682         class_register_type(&mgs_obd_ops, NULL,
683                             lvars.module_vars, LUSTRE_MGS_NAME, NULL);
684
685         return 0;
686 }
687
688 static void /*__exit*/ mgs_exit(void)
689 {
690         class_unregister_type(LUSTRE_MGS_NAME);
691 }
692
693 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
694 MODULE_DESCRIPTION("Lustre  Management Server (MGS)");
695 MODULE_LICENSE("GPL");
696
697 module_init(mgs_init);
698 module_exit(mgs_exit);