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_reconnect(const struct lu_env *env,
103 struct obd_export *exp, struct obd_device *obd,
104 struct obd_uuid *cluuid, struct obd_connect_data *data)
108 if (exp == NULL || obd == NULL || cluuid == NULL)
112 data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED;
113 exp->exp_connect_flags = data->ocd_connect_flags;
114 data->ocd_version = LUSTRE_VERSION_CODE;
120 static int mgs_disconnect(struct obd_export *exp)
127 class_export_get(exp);
128 mgs_counter_incr(exp, LPROC_MGS_DISCONNECT);
130 /* Disconnect early so that clients can't keep using export */
131 rc = class_disconnect(exp);
132 ldlm_cancel_locks_for_export(exp);
134 lprocfs_exp_cleanup(exp);
136 /* complete all outstanding replies */
137 spin_lock(&exp->exp_lock);
138 while (!list_empty(&exp->exp_outstanding_replies)) {
139 struct ptlrpc_reply_state *rs =
140 list_entry(exp->exp_outstanding_replies.next,
141 struct ptlrpc_reply_state, rs_exp_list);
142 struct ptlrpc_service *svc = rs->rs_service;
144 spin_lock(&svc->srv_lock);
145 list_del_init(&rs->rs_exp_list);
146 ptlrpc_schedule_difficult_reply(rs);
147 spin_unlock(&svc->srv_lock);
149 spin_unlock(&exp->exp_lock);
151 class_export_put(exp);
155 static int mgs_cleanup(struct obd_device *obd);
156 static int mgs_handle(struct ptlrpc_request *req);
158 static int mgs_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
159 struct obd_device *tgt, int count,
160 struct llog_catid *logid, struct obd_uuid *uuid)
165 LASSERT(olg == &obd->obd_olg);
166 rc = llog_setup(obd, olg, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
171 static int mgs_llog_finish(struct obd_device *obd, int count)
173 struct llog_ctxt *ctxt;
177 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
179 rc = llog_cleanup(ctxt);
184 /* Start the MGS obd */
185 static int mgs_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
187 struct lprocfs_static_vars lvars;
188 struct mgs_obd *mgs = &obd->u.mgs;
189 struct lustre_mount_info *lmi;
190 struct lustre_sb_info *lsi;
191 struct vfsmount *mnt;
195 CDEBUG(D_CONFIG, "Starting MGS\n");
198 lmi = server_get_mount(obd->obd_name);
200 RETURN(rc = -EINVAL);
203 lsi = s2lsi(lmi->lmi_sb);
204 obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd));
205 if (IS_ERR(obd->obd_fsops))
206 GOTO(err_put, rc = PTR_ERR(obd->obd_fsops));
208 /* namespace for mgs llog */
209 obd->obd_namespace = ldlm_namespace_new(obd ,"MGS", LDLM_NAMESPACE_SERVER,
210 LDLM_NAMESPACE_MODEST);
211 if (obd->obd_namespace == NULL)
212 GOTO(err_ops, rc = -ENOMEM);
215 ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
216 "mgs_ldlm_client", &obd->obd_ldlm_client);
218 LASSERT(!lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb)));
220 rc = mgs_fs_setup(obd, mnt);
222 CERROR("%s: MGS filesystem method init failed: rc = %d\n",
227 rc = obd_llog_init(obd, &obd->obd_olg, obd, 0, NULL, NULL);
231 /* No recovery for MGC's */
232 obd->obd_replayable = 0;
234 /* Internal mgs setup */
235 mgs_init_fsdb_list(obd);
236 sema_init(&mgs->mgs_sem, 1);
238 /* Start the service threads */
240 ptlrpc_init_svc(MGS_NBUFS, MGS_BUFSIZE, MGS_MAXREQSIZE,
241 MGS_MAXREPSIZE, MGS_REQUEST_PORTAL,
242 MGC_REPLY_PORTAL, 2000,
243 mgs_handle, LUSTRE_MGS_NAME,
244 obd->obd_proc_entry, target_print_req,
245 MGS_THREADS_AUTO_MIN, MGS_THREADS_AUTO_MAX,
246 "ll_mgs", LCT_MD_THREAD);
248 if (!mgs->mgs_service) {
249 CERROR("failed to start service\n");
250 GOTO(err_llog, rc = -ENOMEM);
253 rc = ptlrpc_start_threads(obd, mgs->mgs_service);
255 GOTO(err_thread, rc);
258 lprocfs_mgs_init_vars(&lvars);
259 if (lprocfs_obd_setup(obd, lvars.obd_vars) == 0) {
260 lproc_mgs_setup(obd);
263 ping_evictor_start();
265 LCONSOLE_INFO("MGS %s started\n", obd->obd_name);
270 ptlrpc_unregister_service(mgs->mgs_service);
272 obd_llog_finish(obd, 0);
274 /* No extra cleanup needed for llog_init_commit_thread() */
277 ldlm_namespace_free(obd->obd_namespace, NULL, 0);
278 obd->obd_namespace = NULL;
280 fsfilt_put_ops(obd->obd_fsops);
282 server_put_mount(obd->obd_name, mnt);
287 static int mgs_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
293 case OBD_CLEANUP_EARLY:
294 case OBD_CLEANUP_EXPORTS:
295 rc = obd_llog_finish(obd, 0);
302 * Performs cleanup procedures for passed \a obd given it is mgs obd.
304 static int mgs_cleanup(struct obd_device *obd)
306 struct mgs_obd *mgs = &obd->u.mgs;
309 if (mgs->mgs_sb == NULL)
314 ptlrpc_unregister_service(mgs->mgs_service);
316 mgs_cleanup_fsdb_list(obd);
317 lproc_mgs_cleanup(obd);
320 server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
323 ldlm_namespace_free(obd->obd_namespace, NULL, 1);
324 obd->obd_namespace = NULL;
326 fsfilt_put_ops(obd->obd_fsops);
328 LCONSOLE_INFO("%s has stopped.\n", obd->obd_name);
332 /* similar to filter_prepare_destroy */
333 static int mgs_get_cfg_lock(struct obd_device *obd, char *fsname,
334 struct lustre_handle *lockh)
336 struct ldlm_res_id res_id;
340 rc = mgc_fsname2resid(fsname, &res_id);
342 rc = ldlm_cli_enqueue_local(obd->obd_namespace, &res_id,
343 LDLM_PLAIN, NULL, LCK_EX,
344 &flags, ldlm_blocking_ast,
345 ldlm_completion_ast, NULL,
346 fsname, 0, NULL, lockh);
348 CERROR("can't take cfg lock for %s (%d)\n", fsname, rc);
353 static int mgs_put_cfg_lock(struct lustre_handle *lockh)
356 ldlm_lock_decref(lockh, LCK_EX);
363 static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti)
368 rc = mgs_check_index(obd, mti);
370 LCONSOLE_ERROR_MSG(0x13b, "%s claims to have registered, but "
371 "this MGS does not know about it. Assuming"
372 " writeconf.\n", mti->mti_svname);
373 mti->mti_flags |= LDD_F_WRITECONF;
375 } else if (rc == -1) {
376 LCONSOLE_ERROR_MSG(0x13c, "Client log %s-client has "
377 "disappeared! Regenerating all logs.\n",
379 mti->mti_flags |= LDD_F_WRITECONF;
382 /* Index is correctly marked as used */
384 /* If the logs don't contain the mti_nids then add
385 them as failover nids */
386 rc = mgs_check_failnid(obd, mti);
392 /* Called whenever a target starts up. Flags indicate first connect, etc. */
393 static int mgs_handle_target_reg(struct ptlrpc_request *req)
395 struct obd_device *obd = req->rq_export->exp_obd;
396 struct lustre_handle lockh;
397 struct mgs_target_info *mti, *rep_mti;
401 mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_REG);
403 mti = req_capsule_client_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
404 if (!(mti->mti_flags & (LDD_F_WRITECONF | LDD_F_UPGRADE14 |
406 /* We're just here as a startup ping. */
407 CDEBUG(D_MGS, "Server %s is running on %s\n",
408 mti->mti_svname, obd_export_nid2str(req->rq_export));
409 rc = mgs_check_target(obd, mti);
410 /* above will set appropriate mti flags */
412 /* Nothing wrong, or fatal error */
413 GOTO(out_nolock, rc);
416 /* Revoke the config lock to make sure nobody is reading. */
417 /* Although actually I think it should be alright if
418 someone was reading while we were updating the logs - if we
419 revoke at the end they will just update from where they left off. */
420 lockrc = mgs_get_cfg_lock(obd, mti->mti_fsname, &lockh);
421 if (lockrc != ELDLM_OK) {
422 LCONSOLE_ERROR_MSG(0x13d, "%s: Can't signal other nodes to "
423 "update their configuration (%d). Updating "
424 "local logs anyhow; you might have to "
425 "manually restart other nodes to get the "
426 "latest configuration.\n",
427 obd->obd_name, lockrc);
430 OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_PAUSE_TARGET_REG, 10);
432 /* Log writing contention is handled by the fsdb_sem */
434 if (mti->mti_flags & LDD_F_WRITECONF) {
435 if (mti->mti_flags & LDD_F_SV_TYPE_MDT &&
436 mti->mti_stripe_index == 0) {
437 rc = mgs_erase_logs(obd, mti->mti_fsname);
438 LCONSOLE_WARN("%s: Logs for fs %s were removed by user "
439 "request. All servers must be restarted "
440 "in order to regenerate the logs."
441 "\n", obd->obd_name, mti->mti_fsname);
442 } else if (mti->mti_flags &
443 (LDD_F_SV_TYPE_OST | LDD_F_SV_TYPE_MDT)) {
444 rc = mgs_erase_log(obd, mti->mti_svname);
445 LCONSOLE_WARN("%s: Regenerating %s log by user "
447 obd->obd_name, mti->mti_svname);
449 mti->mti_flags |= LDD_F_UPDATE;
450 /* Erased logs means start from scratch. */
451 mti->mti_flags &= ~LDD_F_UPGRADE14;
455 if (mti->mti_flags & LDD_F_UPGRADE14) {
456 rc = mgs_upgrade_sv_14(obd, mti);
458 CERROR("Can't upgrade from 1.4 (%d)\n", rc);
462 /* We're good to go */
463 mti->mti_flags |= LDD_F_UPDATE;
467 if (mti->mti_flags & LDD_F_UPDATE) {
468 CDEBUG(D_MGS, "updating %s, index=%d\n", mti->mti_svname,
469 mti->mti_stripe_index);
471 /* create or update the target log
472 and update the client/mdt logs */
473 rc = mgs_write_log_target(obd, mti);
475 CERROR("Failed to write %s log (%d)\n",
476 mti->mti_svname, rc);
480 mti->mti_flags &= ~(LDD_F_VIRGIN | LDD_F_UPDATE |
481 LDD_F_NEED_INDEX | LDD_F_WRITECONF |
483 mti->mti_flags |= LDD_F_REWRITE_LDD;
487 /* done with log update */
488 if (lockrc == ELDLM_OK)
489 mgs_put_cfg_lock(&lockh);
491 CDEBUG(D_MGS, "replying with %s, index=%d, rc=%d\n", mti->mti_svname,
492 mti->mti_stripe_index, rc);
493 rc = req_capsule_server_pack(&req->rq_pill);
497 /* send back the whole mti in the reply */
498 rep_mti = req_capsule_server_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
501 /* Flush logs to disk */
502 fsfilt_sync(obd, obd->u.mgs.mgs_sb);
506 static int mgs_set_info_rpc(struct ptlrpc_request *req)
508 struct obd_device *obd = req->rq_export->exp_obd;
509 struct mgs_send_param *msp, *rep_msp;
510 struct lustre_handle lockh;
512 struct lustre_cfg_bufs bufs;
513 struct lustre_cfg *lcfg;
514 char fsname[MTI_NAME_MAXLEN];
517 msp = req_capsule_client_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
520 /* Construct lustre_cfg structure to pass to function mgs_setparam */
521 lustre_cfg_bufs_reset(&bufs, NULL);
522 lustre_cfg_bufs_set_string(&bufs, 1, msp->mgs_param);
523 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
524 rc = mgs_setparam(obd, lcfg, fsname);
526 CERROR("Error %d in setting the parameter %s for fs %s\n",
527 rc, msp->mgs_param, fsname);
531 /* Revoke lock so everyone updates. Should be alright if
532 * someone was already reading while we were updating the logs,
533 * so we don't really need to hold the lock while we're
537 lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
538 if (lockrc != ELDLM_OK)
539 CERROR("lock error %d for fs %s\n", lockrc,
542 mgs_put_cfg_lock(&lockh);
544 lustre_cfg_free(lcfg);
546 rc = req_capsule_server_pack(&req->rq_pill);
548 rep_msp = req_capsule_server_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
554 /* Called whenever a target cleans up. */
555 /* XXX - Currently unused */
556 static int mgs_handle_target_del(struct ptlrpc_request *req)
559 mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_DEL);
563 /* XXX - Currently unused */
564 static int mgs_handle_exception(struct ptlrpc_request *req)
567 mgs_counter_incr(req->rq_export, LPROC_MGS_EXCEPTION);
571 /* TODO: handle requests in a similar way as MDT: see mdt_handle_common() */
572 int mgs_handle(struct ptlrpc_request *req)
574 int fail = OBD_FAIL_MGS_ALL_REPLY_NET;
578 req_capsule_init(&req->rq_pill, req, RCL_SERVER);
579 OBD_FAIL_TIMEOUT_MS(OBD_FAIL_MGS_PAUSE_REQ, obd_fail_val);
580 if (OBD_FAIL_CHECK(OBD_FAIL_MGS_ALL_REQUEST_NET))
583 LASSERT(current->journal_info == NULL);
584 opc = lustre_msg_get_opc(req->rq_reqmsg);
585 if (opc != MGS_CONNECT) {
586 if (req->rq_export == NULL) {
587 CERROR("lustre_mgs: operation %d on unconnected MGS\n",
589 req->rq_status = -ENOTCONN;
590 GOTO(out, rc = -ENOTCONN);
596 DEBUG_REQ(D_MGS, req, "connect");
597 /* MGS and MDS have same request format for connect */
598 req_capsule_set(&req->rq_pill, &RQF_MDS_CONNECT);
599 rc = target_handle_connect(req);
600 if (!rc && (lustre_msg_get_conn_cnt(req->rq_reqmsg) > 1))
601 /* Make clients trying to reconnect after a MGS restart
602 happy; also requires obd_replayable */
603 lustre_msg_add_op_flags(req->rq_repmsg,
604 MSG_CONNECT_RECONNECT);
607 DEBUG_REQ(D_MGS, req, "disconnect");
608 /* MGS and MDS have same request format for disconnect */
609 req_capsule_set(&req->rq_pill, &RQF_MDS_DISCONNECT);
610 rc = target_handle_disconnect(req);
611 req->rq_status = rc; /* superfluous? */
614 DEBUG_REQ(D_MGS, req, "exception");
615 rc = mgs_handle_exception(req);
618 DEBUG_REQ(D_MGS, req, "target add");
619 req_capsule_set(&req->rq_pill, &RQF_MGS_TARGET_REG);
620 rc = mgs_handle_target_reg(req);
623 DEBUG_REQ(D_MGS, req, "target del");
624 rc = mgs_handle_target_del(req);
627 DEBUG_REQ(D_MGS, req, "set_info");
628 req_capsule_set(&req->rq_pill, &RQF_MGS_SET_INFO);
629 rc = mgs_set_info_rpc(req);
633 DEBUG_REQ(D_MGS, req, "enqueue");
634 req_capsule_set(&req->rq_pill, &RQF_LDLM_ENQUEUE);
635 rc = ldlm_handle_enqueue(req, ldlm_server_completion_ast,
636 ldlm_server_blocking_ast, NULL);
638 case LDLM_BL_CALLBACK:
639 case LDLM_CP_CALLBACK:
640 DEBUG_REQ(D_MGS, req, "callback");
641 CERROR("callbacks should not happen on MGS\n");
646 DEBUG_REQ(D_INFO, req, "ping");
647 req_capsule_set(&req->rq_pill, &RQF_OBD_PING);
648 rc = target_handle_ping(req);
651 DEBUG_REQ(D_MGS, req, "log cancel");
652 rc = -ENOTSUPP; /* la la la */
655 case LLOG_ORIGIN_HANDLE_CREATE:
656 DEBUG_REQ(D_MGS, req, "llog_init");
657 req_capsule_set(&req->rq_pill, &RQF_LLOG_ORIGIN_HANDLE_CREATE);
658 rc = llog_origin_handle_create(req);
660 case LLOG_ORIGIN_HANDLE_NEXT_BLOCK:
661 DEBUG_REQ(D_MGS, req, "llog next block");
662 req_capsule_set(&req->rq_pill,
663 &RQF_LLOG_ORIGIN_HANDLE_NEXT_BLOCK);
664 rc = llog_origin_handle_next_block(req);
666 case LLOG_ORIGIN_HANDLE_READ_HEADER:
667 DEBUG_REQ(D_MGS, req, "llog read header");
668 req_capsule_set(&req->rq_pill,
669 &RQF_LLOG_ORIGIN_HANDLE_READ_HEADER);
670 rc = llog_origin_handle_read_header(req);
672 case LLOG_ORIGIN_HANDLE_CLOSE:
673 DEBUG_REQ(D_MGS, req, "llog close");
674 rc = llog_origin_handle_close(req);
677 DEBUG_REQ(D_MGS, req, "llog catinfo");
678 req_capsule_set(&req->rq_pill, &RQF_LLOG_CATINFO);
679 rc = llog_catinfo(req);
682 req->rq_status = -ENOTSUPP;
683 rc = ptlrpc_error(req);
687 LASSERT(current->journal_info == NULL);
690 CERROR("MGS handle cmd=%d rc=%d\n", opc, rc);
693 target_send_reply(req, rc, fail);
697 static inline int mgs_destroy_export(struct obd_export *exp)
701 target_destroy_export(exp);
706 /* from mdt_iocontrol */
707 int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
708 void *karg, void *uarg)
710 struct obd_device *obd = exp->exp_obd;
711 struct obd_ioctl_data *data = karg;
712 struct lvfs_run_ctxt saved;
716 CDEBUG(D_IOCTL, "handling ioctl cmd %#x\n", cmd);
720 case OBD_IOC_PARAM: {
721 struct lustre_handle lockh;
722 struct lustre_cfg *lcfg;
723 struct llog_rec_hdr rec;
724 char fsname[MTI_NAME_MAXLEN];
727 rec.lrh_len = llog_data_len(data->ioc_plen1);
729 if (data->ioc_type == LUSTRE_CFG_TYPE) {
730 rec.lrh_type = OBD_CFG_REC;
732 CERROR("unknown cfg record type:%d \n", data->ioc_type);
736 OBD_ALLOC(lcfg, data->ioc_plen1);
739 rc = copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1);
743 if (lcfg->lcfg_bufcount < 1)
744 GOTO(out_free, rc = -EINVAL);
746 rc = mgs_setparam(obd, lcfg, fsname);
748 CERROR("setparam err %d\n", rc);
752 /* Revoke lock so everyone updates. Should be alright if
753 someone was already reading while we were updating the logs,
754 so we don't really need to hold the lock while we're
757 lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
758 if (lockrc != ELDLM_OK)
759 CERROR("lock error %d for fs %s\n", lockrc,
762 mgs_put_cfg_lock(&lockh);
766 OBD_FREE(lcfg, data->ioc_plen1);
770 case OBD_IOC_DUMP_LOG: {
771 struct llog_ctxt *ctxt;
772 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
773 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
774 rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL);
775 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
781 case OBD_IOC_LLOG_CHECK:
782 case OBD_IOC_LLOG_INFO:
783 case OBD_IOC_LLOG_PRINT: {
784 struct llog_ctxt *ctxt;
785 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
787 push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
788 rc = llog_ioctl(ctxt, cmd, data);
789 pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
796 CDEBUG(D_INFO, "unknown command %x\n", cmd);
802 /* use obd ops to offer management infrastructure */
803 static struct obd_ops mgs_obd_ops = {
804 .o_owner = THIS_MODULE,
805 .o_connect = mgs_connect,
806 .o_reconnect = mgs_reconnect,
807 .o_disconnect = mgs_disconnect,
808 .o_setup = mgs_setup,
809 .o_precleanup = mgs_precleanup,
810 .o_cleanup = mgs_cleanup,
811 .o_destroy_export = mgs_destroy_export,
812 .o_iocontrol = mgs_iocontrol,
813 .o_llog_init = mgs_llog_init,
814 .o_llog_finish = mgs_llog_finish
817 static int __init mgs_init(void)
819 struct lprocfs_static_vars lvars;
821 lprocfs_mgs_init_vars(&lvars);
822 class_register_type(&mgs_obd_ops, NULL,
823 lvars.module_vars, LUSTRE_MGS_NAME, NULL);
828 static void /*__exit*/ mgs_exit(void)
830 class_unregister_type(LUSTRE_MGS_NAME);
833 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
834 MODULE_DESCRIPTION("Lustre Management Server (MGS)");
835 MODULE_LICENSE("GPL");
837 module_init(mgs_init);
838 module_exit(mgs_exit);