1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * lustre/mgs/mgs_handler.c
5 * Lustre Management Server (mgs) request handler
7 * Copyright (C) 2006 Cluster File Systems, Inc.
8 * Author: Nathan Rutman <nathan@clusterfs.com>
10 * This file is part of Lustre, http://www.lustre.org.
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.
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.
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.
27 # define EXPORT_SYMTAB
29 #define DEBUG_SUBSYSTEM S_MGS
30 #define D_MGS D_CONFIG/*|D_WARNING*/
33 # include <linux/module.h>
34 # include <linux/pagemap.h>
35 # include <linux/miscdevice.h>
36 # include <linux/init.h>
38 # include <liblustre.h>
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"
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,
56 struct obd_export *exp;
60 if (!conn || !obd || !cluuid)
63 rc = class_connect(conn, obd, cluuid);
66 exp = class_conn2export(conn);
69 exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_NULL;
71 mgs_counter_incr(exp, LPROC_MGS_CONNECT);
74 data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED;
75 exp->exp_connect_flags = data->ocd_connect_flags;
76 data->ocd_version = LUSTRE_VERSION_CODE;
79 if ((exp->exp_connect_flags & OBD_CONNECT_FID) == 0) {
80 CWARN("MGS requires FID support, but client not\n");
85 class_disconnect(exp);
87 class_export_put(exp);
93 static int mgs_disconnect(struct obd_export *exp)
100 class_export_get(exp);
101 mgs_counter_incr(exp, LPROC_MGS_DISCONNECT);
103 /* Disconnect early so that clients can't keep using export */
104 rc = class_disconnect(exp);
105 ldlm_cancel_locks_for_export(exp);
107 /* complete all outstanding replies */
108 spin_lock(&exp->exp_lock);
109 while (!list_empty(&exp->exp_outstanding_replies)) {
110 struct ptlrpc_reply_state *rs =
111 list_entry(exp->exp_outstanding_replies.next,
112 struct ptlrpc_reply_state, rs_exp_list);
113 struct ptlrpc_service *svc = rs->rs_service;
115 spin_lock(&svc->srv_lock);
116 list_del_init(&rs->rs_exp_list);
117 ptlrpc_schedule_difficult_reply(rs);
118 spin_unlock(&svc->srv_lock);
120 spin_unlock(&exp->exp_lock);
122 class_export_put(exp);
126 static int mgs_cleanup(struct obd_device *obd);
127 static int mgs_handle(struct ptlrpc_request *req);
129 static int mgs_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
130 struct obd_device *tgt, int count,
131 struct llog_catid *logid, struct obd_uuid *uuid)
136 LASSERT(olg == &obd->obd_olg);
137 rc = llog_setup(obd, olg, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
142 static int mgs_llog_finish(struct obd_device *obd, int count)
144 struct llog_ctxt *ctxt;
148 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
150 rc = llog_cleanup(ctxt);
155 /* Start the MGS obd */
156 static int mgs_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
158 struct lprocfs_static_vars lvars;
159 struct mgs_obd *mgs = &obd->u.mgs;
160 struct lustre_mount_info *lmi;
161 struct lustre_sb_info *lsi;
162 struct vfsmount *mnt;
166 CDEBUG(D_CONFIG, "Starting MGS\n");
169 lmi = server_get_mount(obd->obd_name);
171 RETURN(rc = -EINVAL);
174 lsi = s2lsi(lmi->lmi_sb);
175 obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd));
176 if (IS_ERR(obd->obd_fsops))
177 GOTO(err_put, rc = PTR_ERR(obd->obd_fsops));
179 /* namespace for mgs llog */
180 obd->obd_namespace = ldlm_namespace_new(obd ,"MGS", LDLM_NAMESPACE_SERVER,
181 LDLM_NAMESPACE_MODEST);
182 if (obd->obd_namespace == NULL)
183 GOTO(err_ops, rc = -ENOMEM);
186 ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
187 "mgs_ldlm_client", &obd->obd_ldlm_client);
189 LASSERT(!lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb)));
191 rc = mgs_fs_setup(obd, mnt);
193 CERROR("%s: MGS filesystem method init failed: rc = %d\n",
198 rc = obd_llog_init(obd, &obd->obd_olg, obd, 0, NULL, NULL);
202 /* No recovery for MGC's */
203 obd->obd_replayable = 0;
205 /* Internal mgs setup */
206 mgs_init_fsdb_list(obd);
207 sema_init(&mgs->mgs_sem, 1);
209 /* Start the service threads */
211 ptlrpc_init_svc(MGS_NBUFS, MGS_BUFSIZE, MGS_MAXREQSIZE,
212 MGS_MAXREPSIZE, MGS_REQUEST_PORTAL,
213 MGC_REPLY_PORTAL, MGS_SERVICE_WATCHDOG_TIMEOUT,
214 mgs_handle, LUSTRE_MGS_NAME,
215 obd->obd_proc_entry, NULL,
216 MGS_THREADS_AUTO_MIN, MGS_THREADS_AUTO_MAX,
217 "ll_mgs", LCT_MD_THREAD);
219 if (!mgs->mgs_service) {
220 CERROR("failed to start service\n");
221 GOTO(err_llog, rc = -ENOMEM);
224 rc = ptlrpc_start_threads(obd, mgs->mgs_service);
226 GOTO(err_thread, rc);
229 lprocfs_mgs_init_vars(&lvars);
230 if (lprocfs_obd_setup(obd, lvars.obd_vars) == 0) {
231 lproc_mgs_setup(obd);
234 ping_evictor_start();
236 LCONSOLE_INFO("MGS %s started\n", obd->obd_name);
241 ptlrpc_unregister_service(mgs->mgs_service);
243 obd_llog_finish(obd, 0);
245 /* No extra cleanup needed for llog_init_commit_thread() */
248 ldlm_namespace_free(obd->obd_namespace, NULL, 0);
249 obd->obd_namespace = NULL;
251 fsfilt_put_ops(obd->obd_fsops);
253 server_put_mount(obd->obd_name, mnt);
258 static int mgs_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
264 case OBD_CLEANUP_EARLY:
265 case OBD_CLEANUP_EXPORTS:
267 case OBD_CLEANUP_SELF_EXP:
268 rc = obd_llog_finish(obd, 0);
270 case OBD_CLEANUP_OBD:
277 * Performs cleanup procedures for passed \a obd given it is mgs obd.
279 static int mgs_cleanup(struct obd_device *obd)
281 struct mgs_obd *mgs = &obd->u.mgs;
284 if (mgs->mgs_sb == NULL)
289 ptlrpc_unregister_service(mgs->mgs_service);
291 mgs_cleanup_fsdb_list(obd);
292 lproc_mgs_cleanup(obd);
295 server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
298 ldlm_namespace_free(obd->obd_namespace, NULL, 1);
299 obd->obd_namespace = NULL;
301 fsfilt_put_ops(obd->obd_fsops);
303 LCONSOLE_INFO("%s has stopped.\n", obd->obd_name);
307 /* similar to filter_prepare_destroy */
308 static int mgs_get_cfg_lock(struct obd_device *obd, char *fsname,
309 struct lustre_handle *lockh)
311 struct ldlm_res_id res_id;
315 rc = mgc_fsname2resid(fsname, &res_id);
317 rc = ldlm_cli_enqueue_local(obd->obd_namespace, &res_id,
318 LDLM_PLAIN, NULL, LCK_EX,
319 &flags, ldlm_blocking_ast,
320 ldlm_completion_ast, NULL,
321 fsname, 0, NULL, lockh);
323 CERROR("can't take cfg lock for %s (%d)\n", fsname, rc);
328 static int mgs_put_cfg_lock(struct lustre_handle *lockh)
331 ldlm_lock_decref(lockh, LCK_EX);
338 static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti)
343 rc = mgs_check_index(obd, mti);
345 LCONSOLE_ERROR_MSG(0x13b, "%s claims to have registered, but "
346 "this MGS does not know about it. Assuming"
347 " writeconf.\n", mti->mti_svname);
348 mti->mti_flags |= LDD_F_WRITECONF;
350 } else if (rc == -1) {
351 LCONSOLE_ERROR_MSG(0x13c, "Client log %s-client has "
352 "disappeared! Regenerating all logs.\n",
354 mti->mti_flags |= LDD_F_WRITECONF;
357 /* Index is correctly marked as used */
359 /* If the logs don't contain the mti_nids then add
360 them as failover nids */
361 rc = mgs_check_failnid(obd, mti);
367 /* Called whenever a target starts up. Flags indicate first connect, etc. */
368 static int mgs_handle_target_reg(struct ptlrpc_request *req)
370 struct obd_device *obd = req->rq_export->exp_obd;
371 struct lustre_handle lockh;
372 struct mgs_target_info *mti, *rep_mti;
376 mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_REG);
378 mti = req_capsule_client_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
379 if (!(mti->mti_flags & (LDD_F_WRITECONF | LDD_F_UPGRADE14 |
381 /* We're just here as a startup ping. */
382 CDEBUG(D_MGS, "Server %s is running on %s\n",
383 mti->mti_svname, obd_export_nid2str(req->rq_export));
384 rc = mgs_check_target(obd, mti);
385 /* above will set appropriate mti flags */
387 /* Nothing wrong, or fatal error */
388 GOTO(out_nolock, rc);
391 /* Revoke the config lock to make sure nobody is reading. */
392 /* Although actually I think it should be alright if
393 someone was reading while we were updating the logs - if we
394 revoke at the end they will just update from where they left off. */
395 lockrc = mgs_get_cfg_lock(obd, mti->mti_fsname, &lockh);
396 if (lockrc != ELDLM_OK) {
397 LCONSOLE_ERROR_MSG(0x13d, "%s: Can't signal other nodes to "
398 "update their configuration (%d). Updating "
399 "local logs anyhow; you might have to "
400 "manually restart other nodes to get the "
401 "latest configuration.\n",
402 obd->obd_name, lockrc);
405 OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_SLOW_TARGET_REG, 10);
407 /* Log writing contention is handled by the fsdb_sem */
409 if (mti->mti_flags & LDD_F_WRITECONF) {
410 if (mti->mti_flags & LDD_F_SV_TYPE_MDT &&
411 mti->mti_stripe_index == 0) {
412 rc = mgs_erase_logs(obd, mti->mti_fsname);
413 LCONSOLE_WARN("%s: Logs for fs %s were removed by user "
414 "request. All servers must be restarted "
415 "in order to regenerate the logs."
416 "\n", obd->obd_name, mti->mti_fsname);
417 } else if (mti->mti_flags &
418 (LDD_F_SV_TYPE_OST | LDD_F_SV_TYPE_MDT)) {
419 rc = mgs_erase_log(obd, mti->mti_svname);
420 LCONSOLE_WARN("%s: Regenerating %s log by user "
422 obd->obd_name, mti->mti_svname);
424 mti->mti_flags |= LDD_F_UPDATE;
425 /* Erased logs means start from scratch. */
426 mti->mti_flags &= ~LDD_F_UPGRADE14;
430 if (mti->mti_flags & LDD_F_UPGRADE14) {
431 rc = mgs_upgrade_sv_14(obd, mti);
433 CERROR("Can't upgrade from 1.4 (%d)\n", rc);
437 /* We're good to go */
438 mti->mti_flags |= LDD_F_UPDATE;
442 if (mti->mti_flags & LDD_F_UPDATE) {
443 CDEBUG(D_MGS, "updating %s, index=%d\n", mti->mti_svname,
444 mti->mti_stripe_index);
446 /* create or update the target log
447 and update the client/mdt logs */
448 rc = mgs_write_log_target(obd, mti);
450 CERROR("Failed to write %s log (%d)\n",
451 mti->mti_svname, rc);
455 mti->mti_flags &= ~(LDD_F_VIRGIN | LDD_F_UPDATE |
456 LDD_F_NEED_INDEX | LDD_F_WRITECONF |
458 mti->mti_flags |= LDD_F_REWRITE_LDD;
462 /* done with log update */
463 if (lockrc == ELDLM_OK)
464 mgs_put_cfg_lock(&lockh);
466 CDEBUG(D_MGS, "replying with %s, index=%d, rc=%d\n", mti->mti_svname,
467 mti->mti_stripe_index, rc);
468 rc = req_capsule_server_pack(&req->rq_pill);
472 /* send back the whole mti in the reply */
473 rep_mti = req_capsule_server_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
476 /* Flush logs to disk */
477 fsfilt_sync(obd, obd->u.mgs.mgs_sb);
481 static int mgs_set_info_rpc(struct ptlrpc_request *req)
483 struct obd_device *obd = req->rq_export->exp_obd;
484 struct mgs_send_param *msp, *rep_msp;
485 struct lustre_handle lockh;
487 struct lustre_cfg_bufs bufs;
488 struct lustre_cfg *lcfg;
489 char fsname[MTI_NAME_MAXLEN];
492 msp = req_capsule_client_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
495 /* Construct lustre_cfg structure to pass to function mgs_setparam */
496 lustre_cfg_bufs_reset(&bufs, NULL);
497 lustre_cfg_bufs_set_string(&bufs, 1, msp->mgs_param);
498 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
499 rc = mgs_setparam(obd, lcfg, fsname);
501 CERROR("Error %d in setting the parameter %s for fs %s\n",
502 rc, msp->mgs_param, fsname);
506 /* Revoke lock so everyone updates. Should be alright if
507 * someone was already reading while we were updating the logs,
508 * so we don't really need to hold the lock while we're
512 lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
513 if (lockrc != ELDLM_OK)
514 CERROR("lock error %d for fs %s\n", lockrc,
517 mgs_put_cfg_lock(&lockh);
519 lustre_cfg_free(lcfg);
521 rc = req_capsule_server_pack(&req->rq_pill);
523 rep_msp = req_capsule_server_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
529 /* Called whenever a target cleans up. */
530 /* XXX - Currently unused */
531 static int mgs_handle_target_del(struct ptlrpc_request *req)
534 mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_DEL);
538 /* XXX - Currently unused */
539 static int mgs_handle_exception(struct ptlrpc_request *req)
542 mgs_counter_incr(req->rq_export, LPROC_MGS_EXCEPTION);
546 /* TODO: handle requests in a similar way as MDT: see mdt_handle_common() */
547 int mgs_handle(struct ptlrpc_request *req)
549 int fail = OBD_FAIL_MGS_ALL_REPLY_NET;
553 req_capsule_init(&req->rq_pill, req, RCL_SERVER);
554 OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_SLOW_REQUEST_NET, 2);
556 LASSERT(current->journal_info == NULL);
557 opc = lustre_msg_get_opc(req->rq_reqmsg);
558 if (opc != MGS_CONNECT) {
559 if (req->rq_export == NULL) {
560 CERROR("lustre_mgs: operation %d on unconnected MGS\n",
562 req->rq_status = -ENOTCONN;
563 GOTO(out, rc = -ENOTCONN);
569 DEBUG_REQ(D_MGS, req, "connect");
570 /* MGS and MDS have same request format for connect */
571 req_capsule_set(&req->rq_pill, &RQF_MDS_CONNECT);
572 rc = target_handle_connect(req);
573 if (!rc && (lustre_msg_get_conn_cnt(req->rq_reqmsg) > 1))
574 /* Make clients trying to reconnect after a MGS restart
575 happy; also requires obd_replayable */
576 lustre_msg_add_op_flags(req->rq_repmsg,
577 MSG_CONNECT_RECONNECT);
580 DEBUG_REQ(D_MGS, req, "disconnect");
581 /* MGS and MDS have same request format for disconnect */
582 req_capsule_set(&req->rq_pill, &RQF_MDS_DISCONNECT);
583 rc = target_handle_disconnect(req);
584 req->rq_status = rc; /* superfluous? */
587 DEBUG_REQ(D_MGS, req, "exception");
588 rc = mgs_handle_exception(req);
591 DEBUG_REQ(D_MGS, req, "target add");
592 req_capsule_set(&req->rq_pill, &RQF_MGS_TARGET_REG);
593 rc = mgs_handle_target_reg(req);
596 DEBUG_REQ(D_MGS, req, "target del");
597 rc = mgs_handle_target_del(req);
600 DEBUG_REQ(D_MGS, req, "set_info");
601 req_capsule_set(&req->rq_pill, &RQF_MGS_SET_INFO);
602 rc = mgs_set_info_rpc(req);
606 DEBUG_REQ(D_MGS, req, "enqueue");
607 req_capsule_set(&req->rq_pill, &RQF_LDLM_ENQUEUE);
608 rc = ldlm_handle_enqueue(req, ldlm_server_completion_ast,
609 ldlm_server_blocking_ast, NULL);
611 case LDLM_BL_CALLBACK:
612 case LDLM_CP_CALLBACK:
613 DEBUG_REQ(D_MGS, req, "callback");
614 CERROR("callbacks should not happen on MGS\n");
619 DEBUG_REQ(D_INFO, req, "ping");
620 req_capsule_set(&req->rq_pill, &RQF_OBD_PING);
621 rc = target_handle_ping(req);
624 DEBUG_REQ(D_MGS, req, "log cancel");
625 rc = -ENOTSUPP; /* la la la */
628 case LLOG_ORIGIN_HANDLE_CREATE:
629 DEBUG_REQ(D_MGS, req, "llog_init");
630 req_capsule_set(&req->rq_pill, &RQF_LLOG_ORIGIN_HANDLE_CREATE);
631 rc = llog_origin_handle_create(req);
633 case LLOG_ORIGIN_HANDLE_NEXT_BLOCK:
634 DEBUG_REQ(D_MGS, req, "llog next block");
635 req_capsule_set(&req->rq_pill,
636 &RQF_LLOG_ORIGIN_HANDLE_NEXT_BLOCK);
637 rc = llog_origin_handle_next_block(req);
639 case LLOG_ORIGIN_HANDLE_READ_HEADER:
640 DEBUG_REQ(D_MGS, req, "llog read header");
641 req_capsule_set(&req->rq_pill,
642 &RQF_LLOG_ORIGIN_HANDLE_READ_HEADER);
643 rc = llog_origin_handle_read_header(req);
645 case LLOG_ORIGIN_HANDLE_CLOSE:
646 DEBUG_REQ(D_MGS, req, "llog close");
647 rc = llog_origin_handle_close(req);
650 DEBUG_REQ(D_MGS, req, "llog catinfo");
651 req_capsule_set(&req->rq_pill, &RQF_LLOG_CATINFO);
652 rc = llog_catinfo(req);
655 req->rq_status = -ENOTSUPP;
656 rc = ptlrpc_error(req);
660 LASSERT(current->journal_info == NULL);
663 CERROR("MGS handle cmd=%d rc=%d\n", opc, rc);
666 target_send_reply(req, rc, fail);
670 static inline int mgs_destroy_export(struct obd_export *exp)
674 target_destroy_export(exp);
679 /* from mdt_iocontrol */
680 int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
681 void *karg, void *uarg)
683 struct obd_device *obd = exp->exp_obd;
684 struct obd_ioctl_data *data = karg;
685 struct lvfs_run_ctxt saved;
689 CDEBUG(D_IOCTL, "handling ioctl cmd %#x\n", cmd);
693 case OBD_IOC_PARAM: {
694 struct lustre_handle lockh;
695 struct lustre_cfg *lcfg;
696 struct llog_rec_hdr rec;
697 char fsname[MTI_NAME_MAXLEN];
700 rec.lrh_len = llog_data_len(data->ioc_plen1);
702 if (data->ioc_type == LUSTRE_CFG_TYPE) {
703 rec.lrh_type = OBD_CFG_REC;
705 CERROR("unknown cfg record type:%d \n", data->ioc_type);
709 OBD_ALLOC(lcfg, data->ioc_plen1);
712 rc = copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1);
716 if (lcfg->lcfg_bufcount < 1)
717 GOTO(out_free, rc = -EINVAL);
719 rc = mgs_setparam(obd, lcfg, fsname);
721 CERROR("setparam err %d\n", rc);
725 /* Revoke lock so everyone updates. Should be alright if
726 someone was already reading while we were updating the logs,
727 so we don't really need to hold the lock while we're
730 lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
731 if (lockrc != ELDLM_OK)
732 CERROR("lock error %d for fs %s\n", lockrc,
735 mgs_put_cfg_lock(&lockh);
739 OBD_FREE(lcfg, data->ioc_plen1);
743 case OBD_IOC_DUMP_LOG: {
744 struct llog_ctxt *ctxt;
745 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
746 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
747 rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL);
748 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
754 case OBD_IOC_LLOG_CHECK:
755 case OBD_IOC_LLOG_INFO:
756 case OBD_IOC_LLOG_PRINT: {
757 struct llog_ctxt *ctxt;
758 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
760 push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
761 rc = llog_ioctl(ctxt, cmd, data);
762 pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
769 CDEBUG(D_INFO, "unknown command %x\n", cmd);
775 /* use obd ops to offer management infrastructure */
776 static struct obd_ops mgs_obd_ops = {
777 .o_owner = THIS_MODULE,
778 .o_connect = mgs_connect,
779 .o_disconnect = mgs_disconnect,
780 .o_setup = mgs_setup,
781 .o_precleanup = mgs_precleanup,
782 .o_cleanup = mgs_cleanup,
783 .o_destroy_export = mgs_destroy_export,
784 .o_iocontrol = mgs_iocontrol,
785 .o_llog_init = mgs_llog_init,
786 .o_llog_finish = mgs_llog_finish
789 static int __init mgs_init(void)
791 struct lprocfs_static_vars lvars;
793 lprocfs_mgs_init_vars(&lvars);
794 class_register_type(&mgs_obd_ops, NULL,
795 lvars.module_vars, LUSTRE_MGS_NAME, NULL);
800 static void /*__exit*/ mgs_exit(void)
802 class_unregister_type(LUSTRE_MGS_NAME);
805 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
806 MODULE_DESCRIPTION("Lustre Management Server (MGS)");
807 MODULE_LICENSE("GPL");
809 module_init(mgs_init);
810 module_exit(mgs_exit);