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;
80 class_disconnect(exp);
82 class_export_put(exp);
88 static int mgs_disconnect(struct obd_export *exp)
95 class_export_get(exp);
96 mgs_counter_incr(exp, LPROC_MGS_DISCONNECT);
98 /* Disconnect early so that clients can't keep using export */
99 rc = class_disconnect(exp);
100 ldlm_cancel_locks_for_export(exp);
102 /* complete all outstanding replies */
103 spin_lock(&exp->exp_lock);
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;
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);
115 spin_unlock(&exp->exp_lock);
117 class_export_put(exp);
121 static int mgs_cleanup(struct obd_device *obd);
122 static int mgs_handle(struct ptlrpc_request *req);
124 static int mgs_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
125 struct obd_device *tgt, int count,
126 struct llog_catid *logid, struct obd_uuid *uuid)
131 LASSERT(olg == &obd->obd_olg);
132 rc = llog_setup(obd, olg, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
137 static int mgs_llog_finish(struct obd_device *obd, int count)
139 struct llog_ctxt *ctxt;
143 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
145 rc = llog_cleanup(ctxt);
150 /* Start the MGS obd */
151 static int mgs_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
153 struct lprocfs_static_vars lvars;
154 struct mgs_obd *mgs = &obd->u.mgs;
155 struct lustre_mount_info *lmi;
156 struct lustre_sb_info *lsi;
157 struct vfsmount *mnt;
161 CDEBUG(D_CONFIG, "Starting MGS\n");
164 lmi = server_get_mount(obd->obd_name);
166 RETURN(rc = -EINVAL);
169 lsi = s2lsi(lmi->lmi_sb);
170 obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd));
171 if (IS_ERR(obd->obd_fsops))
172 GOTO(err_put, rc = PTR_ERR(obd->obd_fsops));
174 /* namespace for mgs llog */
175 obd->obd_namespace = ldlm_namespace_new(obd ,"MGS", LDLM_NAMESPACE_SERVER,
176 LDLM_NAMESPACE_MODEST);
177 if (obd->obd_namespace == NULL)
178 GOTO(err_ops, rc = -ENOMEM);
181 ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
182 "mgs_ldlm_client", &obd->obd_ldlm_client);
184 LASSERT(!lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb)));
186 rc = mgs_fs_setup(obd, mnt);
188 CERROR("%s: MGS filesystem method init failed: rc = %d\n",
193 rc = obd_llog_init(obd, &obd->obd_olg, obd, 0, NULL, NULL);
197 /* No recovery for MGC's */
198 obd->obd_replayable = 0;
200 /* Internal mgs setup */
201 mgs_init_fsdb_list(obd);
202 sema_init(&mgs->mgs_sem, 1);
204 /* Start the service threads */
206 ptlrpc_init_svc(MGS_NBUFS, MGS_BUFSIZE, MGS_MAXREQSIZE,
207 MGS_MAXREPSIZE, MGS_REQUEST_PORTAL,
208 MGC_REPLY_PORTAL, MGS_SERVICE_WATCHDOG_TIMEOUT,
209 mgs_handle, LUSTRE_MGS_NAME,
210 obd->obd_proc_entry, NULL,
211 MGS_THREADS_AUTO_MIN, MGS_THREADS_AUTO_MAX,
212 "ll_mgs", LCT_MD_THREAD);
214 if (!mgs->mgs_service) {
215 CERROR("failed to start service\n");
216 GOTO(err_llog, rc = -ENOMEM);
219 rc = ptlrpc_start_threads(obd, mgs->mgs_service);
221 GOTO(err_thread, rc);
224 lprocfs_mgs_init_vars(&lvars);
225 if (lprocfs_obd_setup(obd, lvars.obd_vars) == 0) {
226 lproc_mgs_setup(obd);
229 ping_evictor_start();
231 LCONSOLE_INFO("MGS %s started\n", obd->obd_name);
236 ptlrpc_unregister_service(mgs->mgs_service);
238 obd_llog_finish(obd, 0);
240 /* No extra cleanup needed for llog_init_commit_thread() */
243 ldlm_namespace_free(obd->obd_namespace, NULL, 0);
244 obd->obd_namespace = NULL;
246 fsfilt_put_ops(obd->obd_fsops);
248 server_put_mount(obd->obd_name, mnt);
253 static int mgs_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
259 case OBD_CLEANUP_EARLY:
260 case OBD_CLEANUP_EXPORTS:
262 case OBD_CLEANUP_SELF_EXP:
263 rc = obd_llog_finish(obd, 0);
265 case OBD_CLEANUP_OBD:
272 * Performs cleanup procedures for passed \a obd given it is mgs obd.
274 static int mgs_cleanup(struct obd_device *obd)
276 struct mgs_obd *mgs = &obd->u.mgs;
279 if (mgs->mgs_sb == NULL)
284 ptlrpc_unregister_service(mgs->mgs_service);
286 mgs_cleanup_fsdb_list(obd);
287 lproc_mgs_cleanup(obd);
290 server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
293 ldlm_namespace_free(obd->obd_namespace, NULL, 1);
294 obd->obd_namespace = NULL;
296 fsfilt_put_ops(obd->obd_fsops);
298 LCONSOLE_INFO("%s has stopped.\n", obd->obd_name);
302 /* similar to filter_prepare_destroy */
303 static int mgs_get_cfg_lock(struct obd_device *obd, char *fsname,
304 struct lustre_handle *lockh)
306 struct ldlm_res_id res_id;
310 rc = mgc_fsname2resid(fsname, &res_id);
312 rc = ldlm_cli_enqueue_local(obd->obd_namespace, &res_id,
313 LDLM_PLAIN, NULL, LCK_EX,
314 &flags, ldlm_blocking_ast,
315 ldlm_completion_ast, NULL,
316 fsname, 0, NULL, lockh);
318 CERROR("can't take cfg lock for %s (%d)\n", fsname, rc);
323 static int mgs_put_cfg_lock(struct lustre_handle *lockh)
326 ldlm_lock_decref(lockh, LCK_EX);
333 static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti)
338 rc = mgs_check_index(obd, mti);
340 LCONSOLE_ERROR_MSG(0x13b, "%s claims to have registered, but "
341 "this MGS does not know about it. Assuming"
342 " writeconf.\n", mti->mti_svname);
343 mti->mti_flags |= LDD_F_WRITECONF;
345 } else if (rc == -1) {
346 LCONSOLE_ERROR_MSG(0x13c, "Client log %s-client has "
347 "disappeared! Regenerating all logs.\n",
349 mti->mti_flags |= LDD_F_WRITECONF;
352 /* Index is correctly marked as used */
354 /* If the logs don't contain the mti_nids then add
355 them as failover nids */
356 rc = mgs_check_failnid(obd, mti);
362 /* Called whenever a target starts up. Flags indicate first connect, etc. */
363 static int mgs_handle_target_reg(struct ptlrpc_request *req)
365 struct obd_device *obd = req->rq_export->exp_obd;
366 struct lustre_handle lockh;
367 struct mgs_target_info *mti, *rep_mti;
371 mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_REG);
373 mti = req_capsule_client_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
374 if (!(mti->mti_flags & (LDD_F_WRITECONF | LDD_F_UPGRADE14 |
376 /* We're just here as a startup ping. */
377 CDEBUG(D_MGS, "Server %s is running on %s\n",
378 mti->mti_svname, obd_export_nid2str(req->rq_export));
379 rc = mgs_check_target(obd, mti);
380 /* above will set appropriate mti flags */
382 /* Nothing wrong, or fatal error */
383 GOTO(out_nolock, rc);
386 /* Revoke the config lock to make sure nobody is reading. */
387 /* Although actually I think it should be alright if
388 someone was reading while we were updating the logs - if we
389 revoke at the end they will just update from where they left off. */
390 lockrc = mgs_get_cfg_lock(obd, mti->mti_fsname, &lockh);
391 if (lockrc != ELDLM_OK) {
392 LCONSOLE_ERROR_MSG(0x13d, "%s: Can't signal other nodes to "
393 "update their configuration (%d). Updating "
394 "local logs anyhow; you might have to "
395 "manually restart other nodes to get the "
396 "latest configuration.\n",
397 obd->obd_name, lockrc);
400 OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_SLOW_TARGET_REG, 10);
402 /* Log writing contention is handled by the fsdb_sem */
404 if (mti->mti_flags & LDD_F_WRITECONF) {
405 if (mti->mti_flags & LDD_F_SV_TYPE_MDT &&
406 mti->mti_stripe_index == 0) {
407 rc = mgs_erase_logs(obd, mti->mti_fsname);
408 LCONSOLE_WARN("%s: Logs for fs %s were removed by user "
409 "request. All servers must be restarted "
410 "in order to regenerate the logs."
411 "\n", obd->obd_name, mti->mti_fsname);
412 } else if (mti->mti_flags &
413 (LDD_F_SV_TYPE_OST | LDD_F_SV_TYPE_MDT)) {
414 rc = mgs_erase_log(obd, mti->mti_svname);
415 LCONSOLE_WARN("%s: Regenerating %s log by user "
417 obd->obd_name, mti->mti_svname);
419 mti->mti_flags |= LDD_F_UPDATE;
420 /* Erased logs means start from scratch. */
421 mti->mti_flags &= ~LDD_F_UPGRADE14;
425 if (mti->mti_flags & LDD_F_UPGRADE14) {
426 rc = mgs_upgrade_sv_14(obd, mti);
428 CERROR("Can't upgrade from 1.4 (%d)\n", rc);
432 /* We're good to go */
433 mti->mti_flags |= LDD_F_UPDATE;
437 if (mti->mti_flags & LDD_F_UPDATE) {
438 CDEBUG(D_MGS, "updating %s, index=%d\n", mti->mti_svname,
439 mti->mti_stripe_index);
441 /* create or update the target log
442 and update the client/mdt logs */
443 rc = mgs_write_log_target(obd, mti);
445 CERROR("Failed to write %s log (%d)\n",
446 mti->mti_svname, rc);
450 mti->mti_flags &= ~(LDD_F_VIRGIN | LDD_F_UPDATE |
451 LDD_F_NEED_INDEX | LDD_F_WRITECONF |
453 mti->mti_flags |= LDD_F_REWRITE_LDD;
457 /* done with log update */
458 if (lockrc == ELDLM_OK)
459 mgs_put_cfg_lock(&lockh);
461 CDEBUG(D_MGS, "replying with %s, index=%d, rc=%d\n", mti->mti_svname,
462 mti->mti_stripe_index, rc);
463 rc = req_capsule_server_pack(&req->rq_pill);
467 /* send back the whole mti in the reply */
468 rep_mti = req_capsule_server_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
471 /* Flush logs to disk */
472 fsfilt_sync(obd, obd->u.mgs.mgs_sb);
476 static int mgs_set_info_rpc(struct ptlrpc_request *req)
478 struct obd_device *obd = req->rq_export->exp_obd;
479 struct mgs_send_param *msp, *rep_msp;
480 struct lustre_handle lockh;
482 struct lustre_cfg_bufs bufs;
483 struct lustre_cfg *lcfg;
484 char fsname[MTI_NAME_MAXLEN];
487 msp = req_capsule_client_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
490 /* Construct lustre_cfg structure to pass to function mgs_setparam */
491 lustre_cfg_bufs_reset(&bufs, NULL);
492 lustre_cfg_bufs_set_string(&bufs, 1, msp->mgs_param);
493 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
494 rc = mgs_setparam(obd, lcfg, fsname);
496 CERROR("Error %d in setting the parameter %s for fs %s\n",
497 rc, msp->mgs_param, fsname);
501 /* Revoke lock so everyone updates. Should be alright if
502 * someone was already reading while we were updating the logs,
503 * so we don't really need to hold the lock while we're
507 lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
508 if (lockrc != ELDLM_OK)
509 CERROR("lock error %d for fs %s\n", lockrc,
512 mgs_put_cfg_lock(&lockh);
514 lustre_cfg_free(lcfg);
516 rc = req_capsule_server_pack(&req->rq_pill);
518 rep_msp = req_capsule_server_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
524 /* Called whenever a target cleans up. */
525 /* XXX - Currently unused */
526 static int mgs_handle_target_del(struct ptlrpc_request *req)
529 mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_DEL);
533 /* XXX - Currently unused */
534 static int mgs_handle_exception(struct ptlrpc_request *req)
537 mgs_counter_incr(req->rq_export, LPROC_MGS_EXCEPTION);
541 /* TODO: handle requests in a similar way as MDT: see mdt_handle_common() */
542 int mgs_handle(struct ptlrpc_request *req)
544 int fail = OBD_FAIL_MGS_ALL_REPLY_NET;
548 req_capsule_init(&req->rq_pill, req, RCL_SERVER);
549 OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_SLOW_REQUEST_NET, 2);
551 LASSERT(current->journal_info == NULL);
552 opc = lustre_msg_get_opc(req->rq_reqmsg);
553 if (opc != MGS_CONNECT) {
554 if (req->rq_export == NULL) {
555 CERROR("lustre_mgs: operation %d on unconnected MGS\n",
557 req->rq_status = -ENOTCONN;
558 GOTO(out, rc = -ENOTCONN);
564 DEBUG_REQ(D_MGS, req, "connect");
565 /* MGS and MDS have same request format for connect */
566 req_capsule_set(&req->rq_pill, &RQF_MDS_CONNECT);
567 rc = target_handle_connect(req);
568 if (!rc && (lustre_msg_get_conn_cnt(req->rq_reqmsg) > 1))
569 /* Make clients trying to reconnect after a MGS restart
570 happy; also requires obd_replayable */
571 lustre_msg_add_op_flags(req->rq_repmsg,
572 MSG_CONNECT_RECONNECT);
575 DEBUG_REQ(D_MGS, req, "disconnect");
576 /* MGS and MDS have same request format for disconnect */
577 req_capsule_set(&req->rq_pill, &RQF_MDS_DISCONNECT);
578 rc = target_handle_disconnect(req);
579 req->rq_status = rc; /* superfluous? */
582 DEBUG_REQ(D_MGS, req, "exception");
583 rc = mgs_handle_exception(req);
586 DEBUG_REQ(D_MGS, req, "target add");
587 req_capsule_set(&req->rq_pill, &RQF_MGS_TARGET_REG);
588 rc = mgs_handle_target_reg(req);
591 DEBUG_REQ(D_MGS, req, "target del");
592 rc = mgs_handle_target_del(req);
595 DEBUG_REQ(D_MGS, req, "set_info");
596 req_capsule_set(&req->rq_pill, &RQF_MGS_SET_INFO);
597 rc = mgs_set_info_rpc(req);
601 DEBUG_REQ(D_MGS, req, "enqueue");
602 req_capsule_set(&req->rq_pill, &RQF_LDLM_ENQUEUE);
603 rc = ldlm_handle_enqueue(req, ldlm_server_completion_ast,
604 ldlm_server_blocking_ast, NULL);
606 case LDLM_BL_CALLBACK:
607 case LDLM_CP_CALLBACK:
608 DEBUG_REQ(D_MGS, req, "callback");
609 CERROR("callbacks should not happen on MGS\n");
614 DEBUG_REQ(D_INFO, req, "ping");
615 req_capsule_set(&req->rq_pill, &RQF_OBD_PING);
616 rc = target_handle_ping(req);
619 DEBUG_REQ(D_MGS, req, "log cancel");
620 rc = -ENOTSUPP; /* la la la */
623 case LLOG_ORIGIN_HANDLE_CREATE:
624 DEBUG_REQ(D_MGS, req, "llog_init");
625 req_capsule_set(&req->rq_pill, &RQF_LLOG_ORIGIN_HANDLE_CREATE);
626 rc = llog_origin_handle_create(req);
628 case LLOG_ORIGIN_HANDLE_NEXT_BLOCK:
629 DEBUG_REQ(D_MGS, req, "llog next block");
630 req_capsule_set(&req->rq_pill,
631 &RQF_LLOG_ORIGIN_HANDLE_NEXT_BLOCK);
632 rc = llog_origin_handle_next_block(req);
634 case LLOG_ORIGIN_HANDLE_READ_HEADER:
635 DEBUG_REQ(D_MGS, req, "llog read header");
636 req_capsule_set(&req->rq_pill,
637 &RQF_LLOG_ORIGIN_HANDLE_READ_HEADER);
638 rc = llog_origin_handle_read_header(req);
640 case LLOG_ORIGIN_HANDLE_CLOSE:
641 DEBUG_REQ(D_MGS, req, "llog close");
642 rc = llog_origin_handle_close(req);
645 DEBUG_REQ(D_MGS, req, "llog catinfo");
646 req_capsule_set(&req->rq_pill, &RQF_LLOG_CATINFO);
647 rc = llog_catinfo(req);
650 req->rq_status = -ENOTSUPP;
651 rc = ptlrpc_error(req);
655 LASSERT(current->journal_info == NULL);
658 CERROR("MGS handle cmd=%d rc=%d\n", opc, rc);
661 target_send_reply(req, rc, fail);
665 static inline int mgs_destroy_export(struct obd_export *exp)
669 target_destroy_export(exp);
674 /* from mdt_iocontrol */
675 int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
676 void *karg, void *uarg)
678 struct obd_device *obd = exp->exp_obd;
679 struct obd_ioctl_data *data = karg;
680 struct lvfs_run_ctxt saved;
684 CDEBUG(D_IOCTL, "handling ioctl cmd %#x\n", cmd);
688 case OBD_IOC_PARAM: {
689 struct lustre_handle lockh;
690 struct lustre_cfg *lcfg;
691 struct llog_rec_hdr rec;
692 char fsname[MTI_NAME_MAXLEN];
695 rec.lrh_len = llog_data_len(data->ioc_plen1);
697 if (data->ioc_type == LUSTRE_CFG_TYPE) {
698 rec.lrh_type = OBD_CFG_REC;
700 CERROR("unknown cfg record type:%d \n", data->ioc_type);
704 OBD_ALLOC(lcfg, data->ioc_plen1);
707 rc = copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1);
711 if (lcfg->lcfg_bufcount < 1)
712 GOTO(out_free, rc = -EINVAL);
714 rc = mgs_setparam(obd, lcfg, fsname);
716 CERROR("setparam err %d\n", rc);
720 /* Revoke lock so everyone updates. Should be alright if
721 someone was already reading while we were updating the logs,
722 so we don't really need to hold the lock while we're
725 lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
726 if (lockrc != ELDLM_OK)
727 CERROR("lock error %d for fs %s\n", lockrc,
730 mgs_put_cfg_lock(&lockh);
734 OBD_FREE(lcfg, data->ioc_plen1);
738 case OBD_IOC_DUMP_LOG: {
739 struct llog_ctxt *ctxt;
740 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
741 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
742 rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL);
743 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
749 case OBD_IOC_LLOG_CHECK:
750 case OBD_IOC_LLOG_INFO:
751 case OBD_IOC_LLOG_PRINT: {
752 struct llog_ctxt *ctxt;
753 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
755 push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
756 rc = llog_ioctl(ctxt, cmd, data);
757 pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
764 CDEBUG(D_INFO, "unknown command %x\n", cmd);
770 /* use obd ops to offer management infrastructure */
771 static struct obd_ops mgs_obd_ops = {
772 .o_owner = THIS_MODULE,
773 .o_connect = mgs_connect,
774 .o_disconnect = mgs_disconnect,
775 .o_setup = mgs_setup,
776 .o_precleanup = mgs_precleanup,
777 .o_cleanup = mgs_cleanup,
778 .o_destroy_export = mgs_destroy_export,
779 .o_iocontrol = mgs_iocontrol,
780 .o_llog_init = mgs_llog_init,
781 .o_llog_finish = mgs_llog_finish
784 static int __init mgs_init(void)
786 struct lprocfs_static_vars lvars;
788 lprocfs_mgs_init_vars(&lvars);
789 class_register_type(&mgs_obd_ops, NULL,
790 lvars.module_vars, LUSTRE_MGS_NAME, NULL);
795 static void /*__exit*/ mgs_exit(void)
797 class_unregister_type(LUSTRE_MGS_NAME);
800 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
801 MODULE_DESCRIPTION("Lustre Management Server (MGS)");
802 MODULE_LICENSE("GPL");
804 module_init(mgs_init);
805 module_exit(mgs_exit);