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)
55 struct obd_export *exp;
59 if (!conn || !obd || !cluuid)
62 rc = class_connect(conn, obd, cluuid);
65 exp = class_conn2export(conn);
68 exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_NULL;
71 data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED;
72 exp->exp_connect_flags = data->ocd_connect_flags;
73 data->ocd_version = LUSTRE_VERSION_CODE;
76 if ((exp->exp_connect_flags & OBD_CONNECT_FID) == 0) {
77 CWARN("MGS requires FID support, but client not\n");
82 class_disconnect(exp);
84 class_export_put(exp);
90 static int mgs_disconnect(struct obd_export *exp)
96 class_export_get(exp);
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, int group,
125 struct obd_device *tgt, int count,
126 struct llog_catid *logid, struct obd_uuid *uuid)
128 struct obd_llog_group *olg = &obd->obd_olg;
132 LASSERT(group == OBD_LLOG_GROUP);
133 LASSERT(olg->olg_group == group);
135 rc = llog_setup(obd, olg, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
140 static int mgs_llog_finish(struct obd_device *obd, int count)
142 struct llog_ctxt *ctxt;
146 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
148 rc = llog_cleanup(ctxt);
153 /* Start the MGS obd */
154 static int mgs_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
156 struct lprocfs_static_vars lvars;
157 struct mgs_obd *mgs = &obd->u.mgs;
158 struct lustre_mount_info *lmi;
159 struct lustre_sb_info *lsi;
160 struct vfsmount *mnt;
164 CDEBUG(D_CONFIG, "Starting MGS\n");
167 lmi = server_get_mount(obd->obd_name);
169 RETURN(rc = -EINVAL);
172 lsi = s2lsi(lmi->lmi_sb);
173 obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd));
174 if (IS_ERR(obd->obd_fsops))
175 GOTO(err_put, rc = PTR_ERR(obd->obd_fsops));
177 /* namespace for mgs llog */
178 obd->obd_namespace = ldlm_namespace_new("MGS", LDLM_NAMESPACE_SERVER,
179 LDLM_NAMESPACE_MODEST);
180 if (obd->obd_namespace == NULL)
181 GOTO(err_ops, rc = -ENOMEM);
184 ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
185 "mgs_ldlm_client", &obd->obd_ldlm_client);
187 LASSERT(!lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb)));
189 rc = mgs_fs_setup(obd, mnt);
191 CERROR("%s: MGS filesystem method init failed: rc = %d\n",
196 rc = obd_llog_init(obd, OBD_LLOG_GROUP, obd, 0, NULL, NULL);
200 /* No recovery for MGC's */
201 obd->obd_replayable = 0;
203 /* Internal mgs setup */
204 mgs_init_fsdb_list(obd);
205 sema_init(&mgs->mgs_sem, 1);
207 /* Start the service threads */
209 ptlrpc_init_svc(MGS_NBUFS, MGS_BUFSIZE, MGS_MAXREQSIZE,
210 MGS_MAXREPSIZE, MGS_REQUEST_PORTAL,
211 MGC_REPLY_PORTAL, MGS_SERVICE_WATCHDOG_TIMEOUT,
212 mgs_handle, LUSTRE_MGS_NAME,
213 obd->obd_proc_entry, NULL,
214 MGS_THREADS_AUTO_MIN, MGS_THREADS_AUTO_MAX,
215 "ll_mgs", LCT_MD_THREAD);
217 if (!mgs->mgs_service) {
218 CERROR("failed to start service\n");
219 GOTO(err_llog, rc = -ENOMEM);
222 rc = ptlrpc_start_threads(obd, mgs->mgs_service);
224 GOTO(err_thread, rc);
227 lprocfs_mgs_init_vars(&lvars);
228 if (lprocfs_obd_setup(obd, lvars.obd_vars) == 0) {
229 lproc_mgs_setup(obd);
232 ping_evictor_start();
234 LCONSOLE_INFO("MGS %s started\n", obd->obd_name);
239 ptlrpc_unregister_service(mgs->mgs_service);
241 obd_llog_finish(obd, 0);
243 /* No extra cleanup needed for llog_init_commit_thread() */
246 ldlm_namespace_free(obd->obd_namespace, 0);
247 obd->obd_namespace = NULL;
249 fsfilt_put_ops(obd->obd_fsops);
251 server_put_mount(obd->obd_name, mnt);
256 static int mgs_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
262 case OBD_CLEANUP_EARLY:
263 case OBD_CLEANUP_EXPORTS:
265 case OBD_CLEANUP_SELF_EXP:
266 rc = obd_llog_finish(obd, 0);
268 case OBD_CLEANUP_OBD:
274 static int mgs_ldlm_nsfree(void *data)
276 struct ldlm_namespace *ns = (struct ldlm_namespace *)data;
280 ptlrpc_daemonize("ll_mgs_nsfree");
281 rc = ldlm_namespace_free(ns, 1 /* obd_force should always be on */);
285 static int mgs_cleanup(struct obd_device *obd)
287 struct mgs_obd *mgs = &obd->u.mgs;
290 if (mgs->mgs_sb == NULL)
295 ptlrpc_unregister_service(mgs->mgs_service);
297 mgs_cleanup_fsdb_list(obd);
299 lprocfs_obd_cleanup(obd);
300 mgs->mgs_proc_live = NULL;
304 server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
307 /* Free the namespace in it's own thread, so that if the
308 ldlm_cancel_handler put the last mgs obd ref, we won't
310 cfs_kernel_thread(mgs_ldlm_nsfree, obd->obd_namespace,
311 CLONE_VM | CLONE_FILES);
314 fsfilt_put_ops(obd->obd_fsops);
316 LCONSOLE_INFO("%s has stopped.\n", obd->obd_name);
320 /* similar to filter_prepare_destroy */
321 static int mgs_get_cfg_lock(struct obd_device *obd, char *fsname,
322 struct lustre_handle *lockh)
324 struct ldlm_res_id res_id;
328 rc = mgc_fsname2resid(fsname, &res_id);
330 rc = ldlm_cli_enqueue_local(obd->obd_namespace, &res_id,
331 LDLM_PLAIN, NULL, LCK_EX,
332 &flags, ldlm_blocking_ast,
333 ldlm_completion_ast, NULL,
334 fsname, 0, NULL, lockh);
336 CERROR("can't take cfg lock for %s (%d)\n", fsname, rc);
341 static int mgs_put_cfg_lock(struct lustre_handle *lockh)
344 ldlm_lock_decref(lockh, LCK_EX);
351 static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti)
356 rc = mgs_check_index(obd, mti);
358 LCONSOLE_ERROR_MSG(0x13b, "%s claims to have registered, but "
359 "this MGS does not know about it. Assuming"
360 " writeconf.\n", mti->mti_svname);
361 mti->mti_flags |= LDD_F_WRITECONF;
363 } else if (rc == -1) {
364 LCONSOLE_ERROR_MSG(0x13c, "Client log %s-client has "
365 "disappeared! Regenerating all logs.\n",
367 mti->mti_flags |= LDD_F_WRITECONF;
370 /* Index is correctly marked as used */
372 /* If the logs don't contain the mti_nids then add
373 them as failover nids */
374 rc = mgs_check_failnid(obd, mti);
380 /* Called whenever a target starts up. Flags indicate first connect, etc. */
381 static int mgs_handle_target_reg(struct ptlrpc_request *req)
383 struct obd_device *obd = req->rq_export->exp_obd;
384 struct lustre_handle lockh;
385 struct mgs_target_info *mti, *rep_mti;
389 mti = req_capsule_client_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
390 if (!(mti->mti_flags & (LDD_F_WRITECONF | LDD_F_UPGRADE14 |
392 /* We're just here as a startup ping. */
393 CDEBUG(D_MGS, "Server %s is running on %s\n",
394 mti->mti_svname, obd_export_nid2str(req->rq_export));
395 rc = mgs_check_target(obd, mti);
396 /* above will set appropriate mti flags */
398 /* Nothing wrong, or fatal error */
399 GOTO(out_nolock, rc);
402 /* Revoke the config lock to make sure nobody is reading. */
403 /* Although actually I think it should be alright if
404 someone was reading while we were updating the logs - if we
405 revoke at the end they will just update from where they left off. */
406 lockrc = mgs_get_cfg_lock(obd, mti->mti_fsname, &lockh);
407 if (lockrc != ELDLM_OK) {
408 LCONSOLE_ERROR_MSG(0x13d, "%s: Can't signal other nodes to "
409 "update their configuration (%d). Updating "
410 "local logs anyhow; you might have to "
411 "manually restart other nodes to get the "
412 "latest configuration.\n",
413 obd->obd_name, lockrc);
416 OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_SLOW_TARGET_REG, 10);
418 /* Log writing contention is handled by the fsdb_sem */
420 if (mti->mti_flags & LDD_F_WRITECONF) {
421 if (mti->mti_flags & LDD_F_SV_TYPE_MDT &&
422 mti->mti_stripe_index == 0) {
423 rc = mgs_erase_logs(obd, mti->mti_fsname);
424 LCONSOLE_WARN("%s: Logs for fs %s were removed by user "
425 "request. All servers must be restarted "
426 "in order to regenerate the logs."
427 "\n", obd->obd_name, mti->mti_fsname);
428 } else if (mti->mti_flags &
429 (LDD_F_SV_TYPE_OST | LDD_F_SV_TYPE_MDT)) {
430 rc = mgs_erase_log(obd, mti->mti_svname);
431 LCONSOLE_WARN("%s: Regenerating %s log by user "
433 obd->obd_name, mti->mti_svname);
435 mti->mti_flags |= LDD_F_UPDATE;
436 /* Erased logs means start from scratch. */
437 mti->mti_flags &= ~LDD_F_UPGRADE14;
441 if (mti->mti_flags & LDD_F_UPGRADE14) {
442 rc = mgs_upgrade_sv_14(obd, mti);
444 CERROR("Can't upgrade from 1.4 (%d)\n", rc);
448 /* We're good to go */
449 mti->mti_flags |= LDD_F_UPDATE;
453 if (mti->mti_flags & LDD_F_UPDATE) {
454 CDEBUG(D_MGS, "updating %s, index=%d\n", mti->mti_svname,
455 mti->mti_stripe_index);
457 /* create or update the target log
458 and update the client/mdt logs */
459 rc = mgs_write_log_target(obd, mti);
461 CERROR("Failed to write %s log (%d)\n",
462 mti->mti_svname, rc);
466 mti->mti_flags &= ~(LDD_F_VIRGIN | LDD_F_UPDATE |
467 LDD_F_NEED_INDEX | LDD_F_WRITECONF |
469 mti->mti_flags |= LDD_F_REWRITE_LDD;
473 /* done with log update */
474 if (lockrc == ELDLM_OK)
475 mgs_put_cfg_lock(&lockh);
477 CDEBUG(D_MGS, "replying with %s, index=%d, rc=%d\n", mti->mti_svname,
478 mti->mti_stripe_index, rc);
479 rc = req_capsule_server_pack(&req->rq_pill);
483 /* send back the whole mti in the reply */
484 rep_mti = req_capsule_server_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
487 /* Flush logs to disk */
488 fsfilt_sync(obd, obd->u.mgs.mgs_sb);
492 static int mgs_set_info_rpc(struct ptlrpc_request *req)
494 struct obd_device *obd = req->rq_export->exp_obd;
495 struct mgs_send_param *msp, *rep_msp;
496 struct lustre_handle lockh;
498 struct lustre_cfg_bufs bufs;
499 struct lustre_cfg *lcfg;
500 char fsname[MTI_NAME_MAXLEN];
503 msp = req_capsule_client_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
506 /* Construct lustre_cfg structure to pass to function mgs_setparam */
507 lustre_cfg_bufs_reset(&bufs, NULL);
508 lustre_cfg_bufs_set_string(&bufs, 1, msp->mgs_param);
509 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
510 rc = mgs_setparam(obd, lcfg, fsname);
512 CERROR("Error %d in setting the parameter %s for fs %s\n",
513 rc, msp->mgs_param, fsname);
517 /* Revoke lock so everyone updates. Should be alright if
518 * someone was already reading while we were updating the logs,
519 * so we don't really need to hold the lock while we're
523 lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
524 if (lockrc != ELDLM_OK)
525 CERROR("lock error %d for fs %s\n", lockrc,
528 mgs_put_cfg_lock(&lockh);
530 lustre_cfg_free(lcfg);
532 rc = req_capsule_server_pack(&req->rq_pill);
534 rep_msp = req_capsule_server_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
540 /* TODO: handle requests in a similar way as MDT: see mdt_handle_common() */
541 int mgs_handle(struct ptlrpc_request *req)
543 int fail = OBD_FAIL_MGS_ALL_REPLY_NET;
547 req_capsule_init(&req->rq_pill, req, RCL_SERVER);
548 OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_SLOW_REQUEST_NET, 2);
550 LASSERT(current->journal_info == NULL);
551 opc = lustre_msg_get_opc(req->rq_reqmsg);
552 if (opc != MGS_CONNECT) {
553 if (req->rq_export == NULL) {
554 CERROR("lustre_mgs: operation %d on unconnected MGS\n",
556 req->rq_status = -ENOTCONN;
557 GOTO(out, rc = -ENOTCONN);
563 DEBUG_REQ(D_MGS, req, "connect");
564 /* MGS and MDS have same request format for connect */
565 req_capsule_set(&req->rq_pill, &RQF_MDS_CONNECT);
566 rc = target_handle_connect(req);
567 if (!rc && (lustre_msg_get_conn_cnt(req->rq_reqmsg) > 1))
568 /* Make clients trying to reconnect after a MGS restart
569 happy; also requires obd_replayable */
570 lustre_msg_add_op_flags(req->rq_repmsg,
571 MSG_CONNECT_RECONNECT);
574 DEBUG_REQ(D_MGS, req, "disconnect");
575 /* MGS and MDS have same request format for disconnect */
576 req_capsule_set(&req->rq_pill, &RQF_MDS_DISCONNECT);
577 rc = target_handle_disconnect(req);
578 req->rq_status = rc; /* superfluous? */
581 DEBUG_REQ(D_MGS, req, "target add");
582 req_capsule_set(&req->rq_pill, &RQF_MGS_TARGET_REG);
583 rc = mgs_handle_target_reg(req);
586 DEBUG_REQ(D_MGS, req, "target del");
587 //rc = mgs_handle_target_del(req);
590 DEBUG_REQ(D_MGS, req, "set_info");
591 req_capsule_set(&req->rq_pill, &RQF_MGS_SET_INFO);
592 rc = mgs_set_info_rpc(req);
596 DEBUG_REQ(D_MGS, req, "enqueue");
597 req_capsule_set(&req->rq_pill, &RQF_LDLM_ENQUEUE);
598 rc = ldlm_handle_enqueue(req, ldlm_server_completion_ast,
599 ldlm_server_blocking_ast, NULL);
601 case LDLM_BL_CALLBACK:
602 case LDLM_CP_CALLBACK:
603 DEBUG_REQ(D_MGS, req, "callback");
604 CERROR("callbacks should not happen on MGS\n");
609 DEBUG_REQ(D_INFO, req, "ping");
610 req_capsule_set(&req->rq_pill, &RQF_OBD_PING);
611 rc = target_handle_ping(req);
614 DEBUG_REQ(D_MGS, req, "log cancel");
615 rc = -ENOTSUPP; /* la la la */
618 case LLOG_ORIGIN_HANDLE_CREATE:
619 DEBUG_REQ(D_MGS, req, "llog_init");
620 req_capsule_set(&req->rq_pill, &RQF_LLOG_ORIGIN_HANDLE_CREATE);
621 rc = llog_origin_handle_create(req);
623 case LLOG_ORIGIN_HANDLE_NEXT_BLOCK:
624 DEBUG_REQ(D_MGS, req, "llog next block");
625 req_capsule_set(&req->rq_pill,
626 &RQF_LLOG_ORIGIN_HANDLE_NEXT_BLOCK);
627 rc = llog_origin_handle_next_block(req);
629 case LLOG_ORIGIN_HANDLE_READ_HEADER:
630 DEBUG_REQ(D_MGS, req, "llog read header");
631 req_capsule_set(&req->rq_pill,
632 &RQF_LLOG_ORIGIN_HANDLE_READ_HEADER);
633 rc = llog_origin_handle_read_header(req);
635 case LLOG_ORIGIN_HANDLE_CLOSE:
636 DEBUG_REQ(D_MGS, req, "llog close");
637 rc = llog_origin_handle_close(req);
640 DEBUG_REQ(D_MGS, req, "llog catinfo");
641 req_capsule_set(&req->rq_pill, &RQF_LLOG_CATINFO);
642 rc = llog_catinfo(req);
645 req->rq_status = -ENOTSUPP;
646 rc = ptlrpc_error(req);
650 LASSERT(current->journal_info == NULL);
653 CERROR("MGS handle cmd=%d rc=%d\n", opc, rc);
656 target_send_reply(req, rc, fail);
660 static inline int mgs_destroy_export(struct obd_export *exp)
664 target_destroy_export(exp);
669 /* from mdt_iocontrol */
670 int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
671 void *karg, void *uarg)
673 struct obd_device *obd = exp->exp_obd;
674 struct obd_ioctl_data *data = karg;
675 struct lvfs_run_ctxt saved;
679 CDEBUG(D_IOCTL, "handling ioctl cmd %#x\n", cmd);
683 case OBD_IOC_PARAM: {
684 struct lustre_handle lockh;
685 struct lustre_cfg *lcfg;
686 struct llog_rec_hdr rec;
687 char fsname[MTI_NAME_MAXLEN];
690 rec.lrh_len = llog_data_len(data->ioc_plen1);
692 if (data->ioc_type == LUSTRE_CFG_TYPE) {
693 rec.lrh_type = OBD_CFG_REC;
695 CERROR("unknown cfg record type:%d \n", data->ioc_type);
699 OBD_ALLOC(lcfg, data->ioc_plen1);
702 rc = copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1);
706 if (lcfg->lcfg_bufcount < 1)
707 GOTO(out_free, rc = -EINVAL);
709 rc = mgs_setparam(obd, lcfg, fsname);
711 CERROR("setparam err %d\n", rc);
715 /* Revoke lock so everyone updates. Should be alright if
716 someone was already reading while we were updating the logs,
717 so we don't really need to hold the lock while we're
720 lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
721 if (lockrc != ELDLM_OK)
722 CERROR("lock error %d for fs %s\n", lockrc,
725 mgs_put_cfg_lock(&lockh);
729 OBD_FREE(lcfg, data->ioc_plen1);
733 case OBD_IOC_DUMP_LOG: {
734 struct llog_ctxt *ctxt;
735 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
736 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
737 rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL);
738 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
744 case OBD_IOC_LLOG_CHECK:
745 case OBD_IOC_LLOG_INFO:
746 case OBD_IOC_LLOG_PRINT: {
747 struct llog_ctxt *ctxt;
748 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
750 push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
751 rc = llog_ioctl(ctxt, cmd, data);
752 pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
759 CDEBUG(D_INFO, "unknown command %x\n", cmd);
765 /* use obd ops to offer management infrastructure */
766 static struct obd_ops mgs_obd_ops = {
767 .o_owner = THIS_MODULE,
768 .o_connect = mgs_connect,
769 .o_disconnect = mgs_disconnect,
770 .o_setup = mgs_setup,
771 .o_precleanup = mgs_precleanup,
772 .o_cleanup = mgs_cleanup,
773 .o_destroy_export = mgs_destroy_export,
774 .o_iocontrol = mgs_iocontrol,
775 .o_llog_init = mgs_llog_init,
776 .o_llog_finish = mgs_llog_finish
779 static int __init mgs_init(void)
781 struct lprocfs_static_vars lvars;
783 lprocfs_mgs_init_vars(&lvars);
784 class_register_type(&mgs_obd_ops, NULL,
785 lvars.module_vars, LUSTRE_MGS_NAME, NULL);
790 static void /*__exit*/ mgs_exit(void)
792 class_unregister_type(LUSTRE_MGS_NAME);
795 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
796 MODULE_DESCRIPTION("Lustre Management Server (MGS)");
797 MODULE_LICENSE("GPL");
799 module_init(mgs_init);
800 module_exit(mgs_exit);