1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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
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
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/mgs/mgs_handler.c
38 * Author: Nathan Rutman <nathan@clusterfs.com>
42 # define EXPORT_SYMTAB
44 #define DEBUG_SUBSYSTEM S_MGS
45 #define D_MGS D_CONFIG/*|D_WARNING*/
48 # include <linux/module.h>
49 # include <linux/pagemap.h>
50 # include <linux/miscdevice.h>
51 # include <linux/init.h>
53 # include <liblustre.h>
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"
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,
70 struct obd_export *exp;
74 if (!conn || !obd || !cluuid)
77 rc = class_connect(conn, obd, cluuid);
80 exp = class_conn2export(conn);
83 exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_NULL;
85 mgs_counter_incr(exp, LPROC_MGS_CONNECT);
88 data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED;
89 exp->exp_connect_flags = data->ocd_connect_flags;
90 data->ocd_version = LUSTRE_VERSION_CODE;
94 class_disconnect(exp);
96 class_export_put(exp);
102 static int mgs_disconnect(struct obd_export *exp)
109 class_export_get(exp);
110 mgs_counter_incr(exp, LPROC_MGS_DISCONNECT);
112 /* Disconnect early so that clients can't keep using export */
113 rc = class_disconnect(exp);
114 ldlm_cancel_locks_for_export(exp);
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;
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);
129 spin_unlock(&exp->exp_lock);
131 class_export_put(exp);
135 static int mgs_cleanup(struct obd_device *obd);
136 static int mgs_handle(struct ptlrpc_request *req);
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)
145 LASSERT(olg == &obd->obd_olg);
146 rc = llog_setup(obd, olg, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
151 static int mgs_llog_finish(struct obd_device *obd, int count)
153 struct llog_ctxt *ctxt;
157 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
159 rc = llog_cleanup(ctxt);
164 /* Start the MGS obd */
165 static int mgs_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
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;
175 CDEBUG(D_CONFIG, "Starting MGS\n");
178 lmi = server_get_mount(obd->obd_name);
180 RETURN(rc = -EINVAL);
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));
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);
195 ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
196 "mgs_ldlm_client", &obd->obd_ldlm_client);
198 LASSERT(!lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb)));
200 rc = mgs_fs_setup(obd, mnt);
202 CERROR("%s: MGS filesystem method init failed: rc = %d\n",
207 rc = obd_llog_init(obd, &obd->obd_olg, obd, 0, NULL, NULL);
211 /* No recovery for MGC's */
212 obd->obd_replayable = 0;
214 /* Internal mgs setup */
215 mgs_init_fsdb_list(obd);
216 sema_init(&mgs->mgs_sem, 1);
218 /* Start the service threads */
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);
228 if (!mgs->mgs_service) {
229 CERROR("failed to start service\n");
230 GOTO(err_llog, rc = -ENOMEM);
233 rc = ptlrpc_start_threads(obd, mgs->mgs_service);
235 GOTO(err_thread, rc);
238 lprocfs_mgs_init_vars(&lvars);
239 if (lprocfs_obd_setup(obd, lvars.obd_vars) == 0) {
240 lproc_mgs_setup(obd);
243 ping_evictor_start();
245 LCONSOLE_INFO("MGS %s started\n", obd->obd_name);
250 ptlrpc_unregister_service(mgs->mgs_service);
252 obd_llog_finish(obd, 0);
254 /* No extra cleanup needed for llog_init_commit_thread() */
257 ldlm_namespace_free(obd->obd_namespace, NULL, 0);
258 obd->obd_namespace = NULL;
260 fsfilt_put_ops(obd->obd_fsops);
262 server_put_mount(obd->obd_name, mnt);
267 static int mgs_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
273 case OBD_CLEANUP_EARLY:
274 case OBD_CLEANUP_EXPORTS:
275 rc = obd_llog_finish(obd, 0);
282 * Performs cleanup procedures for passed \a obd given it is mgs obd.
284 static int mgs_cleanup(struct obd_device *obd)
286 struct mgs_obd *mgs = &obd->u.mgs;
289 if (mgs->mgs_sb == NULL)
294 ptlrpc_unregister_service(mgs->mgs_service);
296 mgs_cleanup_fsdb_list(obd);
297 lproc_mgs_cleanup(obd);
300 server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
303 ldlm_namespace_free(obd->obd_namespace, NULL, 1);
304 obd->obd_namespace = NULL;
306 fsfilt_put_ops(obd->obd_fsops);
308 LCONSOLE_INFO("%s has stopped.\n", obd->obd_name);
312 /* similar to filter_prepare_destroy */
313 static int mgs_get_cfg_lock(struct obd_device *obd, char *fsname,
314 struct lustre_handle *lockh)
316 struct ldlm_res_id res_id;
320 rc = mgc_fsname2resid(fsname, &res_id);
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);
328 CERROR("can't take cfg lock for %s (%d)\n", fsname, rc);
333 static int mgs_put_cfg_lock(struct lustre_handle *lockh)
336 ldlm_lock_decref(lockh, LCK_EX);
343 static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti)
348 rc = mgs_check_index(obd, mti);
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;
355 } else if (rc == -1) {
356 LCONSOLE_ERROR_MSG(0x13c, "Client log %s-client has "
357 "disappeared! Regenerating all logs.\n",
359 mti->mti_flags |= LDD_F_WRITECONF;
362 /* Index is correctly marked as used */
364 /* If the logs don't contain the mti_nids then add
365 them as failover nids */
366 rc = mgs_check_failnid(obd, mti);
372 /* Called whenever a target starts up. Flags indicate first connect, etc. */
373 static int mgs_handle_target_reg(struct ptlrpc_request *req)
375 struct obd_device *obd = req->rq_export->exp_obd;
376 struct lustre_handle lockh;
377 struct mgs_target_info *mti, *rep_mti;
381 mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_REG);
383 mti = req_capsule_client_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
384 if (!(mti->mti_flags & (LDD_F_WRITECONF | LDD_F_UPGRADE14 |
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 */
392 /* Nothing wrong, or fatal error */
393 GOTO(out_nolock, rc);
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);
410 OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_PAUSE_TARGET_REG, 10);
412 /* Log writing contention is handled by the fsdb_sem */
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 "
427 obd->obd_name, mti->mti_svname);
429 mti->mti_flags |= LDD_F_UPDATE;
430 /* Erased logs means start from scratch. */
431 mti->mti_flags &= ~LDD_F_UPGRADE14;
435 if (mti->mti_flags & LDD_F_UPGRADE14) {
436 rc = mgs_upgrade_sv_14(obd, mti);
438 CERROR("Can't upgrade from 1.4 (%d)\n", rc);
442 /* We're good to go */
443 mti->mti_flags |= LDD_F_UPDATE;
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);
451 /* create or update the target log
452 and update the client/mdt logs */
453 rc = mgs_write_log_target(obd, mti);
455 CERROR("Failed to write %s log (%d)\n",
456 mti->mti_svname, rc);
460 mti->mti_flags &= ~(LDD_F_VIRGIN | LDD_F_UPDATE |
461 LDD_F_NEED_INDEX | LDD_F_WRITECONF |
463 mti->mti_flags |= LDD_F_REWRITE_LDD;
467 /* done with log update */
468 if (lockrc == ELDLM_OK)
469 mgs_put_cfg_lock(&lockh);
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);
477 /* send back the whole mti in the reply */
478 rep_mti = req_capsule_server_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
481 /* Flush logs to disk */
482 fsfilt_sync(obd, obd->u.mgs.mgs_sb);
486 static int mgs_set_info_rpc(struct ptlrpc_request *req)
488 struct obd_device *obd = req->rq_export->exp_obd;
489 struct mgs_send_param *msp, *rep_msp;
490 struct lustre_handle lockh;
492 struct lustre_cfg_bufs bufs;
493 struct lustre_cfg *lcfg;
494 char fsname[MTI_NAME_MAXLEN];
497 msp = req_capsule_client_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
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);
506 CERROR("Error %d in setting the parameter %s for fs %s\n",
507 rc, msp->mgs_param, fsname);
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
517 lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
518 if (lockrc != ELDLM_OK)
519 CERROR("lock error %d for fs %s\n", lockrc,
522 mgs_put_cfg_lock(&lockh);
524 lustre_cfg_free(lcfg);
526 rc = req_capsule_server_pack(&req->rq_pill);
528 rep_msp = req_capsule_server_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
534 /* Called whenever a target cleans up. */
535 /* XXX - Currently unused */
536 static int mgs_handle_target_del(struct ptlrpc_request *req)
539 mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_DEL);
543 /* XXX - Currently unused */
544 static int mgs_handle_exception(struct ptlrpc_request *req)
547 mgs_counter_incr(req->rq_export, LPROC_MGS_EXCEPTION);
551 /* TODO: handle requests in a similar way as MDT: see mdt_handle_common() */
552 int mgs_handle(struct ptlrpc_request *req)
554 int fail = OBD_FAIL_MGS_ALL_REPLY_NET;
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))
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",
569 req->rq_status = -ENOTCONN;
570 GOTO(out, rc = -ENOTCONN);
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);
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? */
594 DEBUG_REQ(D_MGS, req, "exception");
595 rc = mgs_handle_exception(req);
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);
603 DEBUG_REQ(D_MGS, req, "target del");
604 rc = mgs_handle_target_del(req);
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);
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);
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");
626 DEBUG_REQ(D_INFO, req, "ping");
627 req_capsule_set(&req->rq_pill, &RQF_OBD_PING);
628 rc = target_handle_ping(req);
631 DEBUG_REQ(D_MGS, req, "log cancel");
632 rc = -ENOTSUPP; /* la la la */
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);
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);
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);
652 case LLOG_ORIGIN_HANDLE_CLOSE:
653 DEBUG_REQ(D_MGS, req, "llog close");
654 rc = llog_origin_handle_close(req);
657 DEBUG_REQ(D_MGS, req, "llog catinfo");
658 req_capsule_set(&req->rq_pill, &RQF_LLOG_CATINFO);
659 rc = llog_catinfo(req);
662 req->rq_status = -ENOTSUPP;
663 rc = ptlrpc_error(req);
667 LASSERT(current->journal_info == NULL);
670 CERROR("MGS handle cmd=%d rc=%d\n", opc, rc);
673 target_send_reply(req, rc, fail);
677 static inline int mgs_destroy_export(struct obd_export *exp)
681 target_destroy_export(exp);
686 /* from mdt_iocontrol */
687 int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
688 void *karg, void *uarg)
690 struct obd_device *obd = exp->exp_obd;
691 struct obd_ioctl_data *data = karg;
692 struct lvfs_run_ctxt saved;
696 CDEBUG(D_IOCTL, "handling ioctl cmd %#x\n", cmd);
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];
707 rec.lrh_len = llog_data_len(data->ioc_plen1);
709 if (data->ioc_type == LUSTRE_CFG_TYPE) {
710 rec.lrh_type = OBD_CFG_REC;
712 CERROR("unknown cfg record type:%d \n", data->ioc_type);
716 OBD_ALLOC(lcfg, data->ioc_plen1);
719 rc = copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1);
723 if (lcfg->lcfg_bufcount < 1)
724 GOTO(out_free, rc = -EINVAL);
726 rc = mgs_setparam(obd, lcfg, fsname);
728 CERROR("setparam err %d\n", rc);
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
737 lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
738 if (lockrc != ELDLM_OK)
739 CERROR("lock error %d for fs %s\n", lockrc,
742 mgs_put_cfg_lock(&lockh);
746 OBD_FREE(lcfg, data->ioc_plen1);
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);
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);
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);
776 CDEBUG(D_INFO, "unknown command %x\n", cmd);
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
796 static int __init mgs_init(void)
798 struct lprocfs_static_vars lvars;
800 lprocfs_mgs_init_vars(&lvars);
801 class_register_type(&mgs_obd_ops, NULL,
802 lvars.module_vars, LUSTRE_MGS_NAME, NULL);
807 static void /*__exit*/ mgs_exit(void)
809 class_unregister_type(LUSTRE_MGS_NAME);
812 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
813 MODULE_DESCRIPTION("Lustre Management Server (MGS)");
814 MODULE_LICENSE("GPL");
816 module_init(mgs_init);
817 module_exit(mgs_exit);