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 mgs_counter_incr(exp, LPROC_MGS_CONNECT);
86 data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED;
87 exp->exp_connect_flags = data->ocd_connect_flags;
88 data->ocd_version = LUSTRE_VERSION_CODE;
91 rc = mgs_client_add(obd, exp, localdata);
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,
109 if (exp == NULL || obd == NULL || cluuid == NULL)
112 mgs_counter_incr(exp, LPROC_MGS_CONNECT);
115 data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED;
116 exp->exp_connect_flags = data->ocd_connect_flags;
117 data->ocd_version = LUSTRE_VERSION_CODE;
123 static int mgs_disconnect(struct obd_export *exp)
130 class_export_get(exp);
131 mgs_counter_incr(exp, LPROC_MGS_DISCONNECT);
133 /* Disconnect early so that clients can't keep using export */
134 rc = class_disconnect(exp);
135 ldlm_cancel_locks_for_export(exp);
137 lprocfs_exp_cleanup(exp);
139 /* complete all outstanding replies */
140 spin_lock(&exp->exp_lock);
141 while (!list_empty(&exp->exp_outstanding_replies)) {
142 struct ptlrpc_reply_state *rs =
143 list_entry(exp->exp_outstanding_replies.next,
144 struct ptlrpc_reply_state, rs_exp_list);
145 struct ptlrpc_service *svc = rs->rs_service;
147 spin_lock(&svc->srv_lock);
148 list_del_init(&rs->rs_exp_list);
149 ptlrpc_schedule_difficult_reply(rs);
150 spin_unlock(&svc->srv_lock);
152 spin_unlock(&exp->exp_lock);
154 class_export_put(exp);
158 static int mgs_cleanup(struct obd_device *obd);
159 static int mgs_handle(struct ptlrpc_request *req);
161 static int mgs_llog_init(struct obd_device *obd, struct obd_llog_group *olg,
162 struct obd_device *tgt, int count,
163 struct llog_catid *logid, struct obd_uuid *uuid)
168 LASSERT(olg == &obd->obd_olg);
169 rc = llog_setup(obd, olg, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
174 static int mgs_llog_finish(struct obd_device *obd, int count)
176 struct llog_ctxt *ctxt;
180 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
182 rc = llog_cleanup(ctxt);
187 /* Start the MGS obd */
188 static int mgs_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
190 struct lprocfs_static_vars lvars;
191 struct mgs_obd *mgs = &obd->u.mgs;
192 struct lustre_mount_info *lmi;
193 struct lustre_sb_info *lsi;
194 struct vfsmount *mnt;
198 CDEBUG(D_CONFIG, "Starting MGS\n");
201 lmi = server_get_mount(obd->obd_name);
203 RETURN(rc = -EINVAL);
206 lsi = s2lsi(lmi->lmi_sb);
207 obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd));
208 if (IS_ERR(obd->obd_fsops))
209 GOTO(err_put, rc = PTR_ERR(obd->obd_fsops));
211 /* namespace for mgs llog */
212 obd->obd_namespace = ldlm_namespace_new(obd ,"MGS", LDLM_NAMESPACE_SERVER,
213 LDLM_NAMESPACE_MODEST);
214 if (obd->obd_namespace == NULL)
215 GOTO(err_ops, rc = -ENOMEM);
218 ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
219 "mgs_ldlm_client", &obd->obd_ldlm_client);
221 LASSERT(!lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb)));
223 rc = mgs_fs_setup(obd, mnt);
225 CERROR("%s: MGS filesystem method init failed: rc = %d\n",
230 rc = obd_llog_init(obd, &obd->obd_olg, obd, 0, NULL, NULL);
234 /* No recovery for MGC's */
235 obd->obd_replayable = 0;
237 /* Internal mgs setup */
238 mgs_init_fsdb_list(obd);
239 sema_init(&mgs->mgs_sem, 1);
241 /* Start the service threads */
243 ptlrpc_init_svc(MGS_NBUFS, MGS_BUFSIZE, MGS_MAXREQSIZE,
244 MGS_MAXREPSIZE, MGS_REQUEST_PORTAL,
245 MGC_REPLY_PORTAL, 2000,
246 mgs_handle, LUSTRE_MGS_NAME,
247 obd->obd_proc_entry, target_print_req,
248 MGS_THREADS_AUTO_MIN, MGS_THREADS_AUTO_MAX,
249 "ll_mgs", LCT_MD_THREAD, NULL);
251 if (!mgs->mgs_service) {
252 CERROR("failed to start service\n");
253 GOTO(err_llog, rc = -ENOMEM);
256 rc = ptlrpc_start_threads(obd, mgs->mgs_service);
258 GOTO(err_thread, rc);
261 lprocfs_mgs_init_vars(&lvars);
262 if (lprocfs_obd_setup(obd, lvars.obd_vars) == 0) {
263 lproc_mgs_setup(obd);
266 ping_evictor_start();
268 LCONSOLE_INFO("MGS %s started\n", obd->obd_name);
273 ptlrpc_unregister_service(mgs->mgs_service);
275 obd_llog_finish(obd, 0);
277 /* No extra cleanup needed for llog_init_commit_thread() */
280 ldlm_namespace_free(obd->obd_namespace, NULL, 0);
281 obd->obd_namespace = NULL;
283 fsfilt_put_ops(obd->obd_fsops);
285 server_put_mount(obd->obd_name, mnt);
290 static int mgs_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
296 case OBD_CLEANUP_EARLY:
297 case OBD_CLEANUP_EXPORTS:
298 rc = obd_llog_finish(obd, 0);
305 * Performs cleanup procedures for passed \a obd given it is mgs obd.
307 static int mgs_cleanup(struct obd_device *obd)
309 struct mgs_obd *mgs = &obd->u.mgs;
312 if (mgs->mgs_sb == NULL)
317 ptlrpc_unregister_service(mgs->mgs_service);
319 mgs_cleanup_fsdb_list(obd);
320 lproc_mgs_cleanup(obd);
323 server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
326 ldlm_namespace_free(obd->obd_namespace, NULL, 1);
327 obd->obd_namespace = NULL;
329 fsfilt_put_ops(obd->obd_fsops);
331 LCONSOLE_INFO("%s has stopped.\n", obd->obd_name);
335 /* similar to filter_prepare_destroy */
336 static int mgs_get_cfg_lock(struct obd_device *obd, char *fsname,
337 struct lustre_handle *lockh)
339 struct ldlm_res_id res_id;
343 rc = mgc_fsname2resid(fsname, &res_id);
345 rc = ldlm_cli_enqueue_local(obd->obd_namespace, &res_id,
346 LDLM_PLAIN, NULL, LCK_EX,
347 &flags, ldlm_blocking_ast,
348 ldlm_completion_ast, NULL,
349 fsname, 0, NULL, NULL, lockh);
351 CERROR("can't take cfg lock for %s (%d)\n", fsname, rc);
356 static int mgs_put_cfg_lock(struct lustre_handle *lockh)
359 ldlm_lock_decref(lockh, LCK_EX);
363 static void mgs_revoke_lock(struct obd_device *obd, char *fsname,
364 struct lustre_handle *lockh)
369 lockrc = mgs_get_cfg_lock(obd, fsname, lockh);
370 if (lockrc != ELDLM_OK)
371 CERROR("lock error %d for fs %s\n", lockrc,
374 mgs_put_cfg_lock(lockh);
381 static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti)
386 rc = mgs_check_index(obd, mti);
388 LCONSOLE_ERROR_MSG(0x13b, "%s claims to have registered, but "
389 "this MGS does not know about it, preventing "
390 "registration.\n", mti->mti_svname);
392 } else if (rc == -1) {
393 LCONSOLE_ERROR_MSG(0x13c, "Client log %s-client has "
394 "disappeared! Regenerating all logs.\n",
396 mti->mti_flags |= LDD_F_WRITECONF;
399 /* Index is correctly marked as used */
401 /* If the logs don't contain the mti_nids then add
402 them as failover nids */
403 rc = mgs_check_failnid(obd, mti);
409 /* Called whenever a target starts up. Flags indicate first connect, etc. */
410 static int mgs_handle_target_reg(struct ptlrpc_request *req)
412 struct obd_device *obd = req->rq_export->exp_obd;
413 struct lustre_handle lockh;
414 struct mgs_target_info *mti, *rep_mti;
418 mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_REG);
420 mti = req_capsule_client_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
421 if (!(mti->mti_flags & (LDD_F_WRITECONF | LDD_F_UPGRADE14 |
423 /* We're just here as a startup ping. */
424 CDEBUG(D_MGS, "Server %s is running on %s\n",
425 mti->mti_svname, obd_export_nid2str(req->rq_export));
426 rc = mgs_check_target(obd, mti);
427 /* above will set appropriate mti flags */
429 /* Nothing wrong, or fatal error */
430 GOTO(out_nolock, rc);
433 /* Revoke the config lock to make sure nobody is reading. */
434 /* Although actually I think it should be alright if
435 someone was reading while we were updating the logs - if we
436 revoke at the end they will just update from where they left off. */
437 lockrc = mgs_get_cfg_lock(obd, mti->mti_fsname, &lockh);
438 if (lockrc != ELDLM_OK) {
439 LCONSOLE_ERROR_MSG(0x13d, "%s: Can't signal other nodes to "
440 "update their configuration (%d). Updating "
441 "local logs anyhow; you might have to "
442 "manually restart other nodes to get the "
443 "latest configuration.\n",
444 obd->obd_name, lockrc);
447 OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_PAUSE_TARGET_REG, 10);
449 /* Log writing contention is handled by the fsdb_sem */
451 if (mti->mti_flags & LDD_F_WRITECONF) {
452 if (mti->mti_flags & LDD_F_SV_TYPE_MDT &&
453 mti->mti_stripe_index == 0) {
454 rc = mgs_erase_logs(obd, mti->mti_fsname);
455 LCONSOLE_WARN("%s: Logs for fs %s were removed by user "
456 "request. All servers must be restarted "
457 "in order to regenerate the logs."
458 "\n", obd->obd_name, mti->mti_fsname);
459 } else if (mti->mti_flags &
460 (LDD_F_SV_TYPE_OST | LDD_F_SV_TYPE_MDT)) {
461 rc = mgs_erase_log(obd, mti->mti_svname);
462 LCONSOLE_WARN("%s: Regenerating %s log by user "
464 obd->obd_name, mti->mti_svname);
466 mti->mti_flags |= LDD_F_UPDATE;
467 /* Erased logs means start from scratch. */
468 mti->mti_flags &= ~LDD_F_UPGRADE14;
472 if (mti->mti_flags & LDD_F_UPGRADE14) {
473 rc = mgs_upgrade_sv_14(obd, mti);
475 CERROR("Can't upgrade from 1.4 (%d)\n", rc);
479 /* We're good to go */
480 mti->mti_flags |= LDD_F_UPDATE;
484 if (mti->mti_flags & LDD_F_UPDATE) {
485 CDEBUG(D_MGS, "updating %s, index=%d\n", mti->mti_svname,
486 mti->mti_stripe_index);
488 /* create or update the target log
489 and update the client/mdt logs */
490 rc = mgs_write_log_target(obd, mti);
492 CERROR("Failed to write %s log (%d)\n",
493 mti->mti_svname, rc);
497 mti->mti_flags &= ~(LDD_F_VIRGIN | LDD_F_UPDATE |
498 LDD_F_NEED_INDEX | LDD_F_WRITECONF |
500 mti->mti_flags |= LDD_F_REWRITE_LDD;
504 /* done with log update */
505 if (lockrc == ELDLM_OK)
506 mgs_put_cfg_lock(&lockh);
508 CDEBUG(D_MGS, "replying with %s, index=%d, rc=%d\n", mti->mti_svname,
509 mti->mti_stripe_index, rc);
510 rc = req_capsule_server_pack(&req->rq_pill);
514 /* send back the whole mti in the reply */
515 rep_mti = req_capsule_server_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
518 /* Flush logs to disk */
519 fsfilt_sync(obd, obd->u.mgs.mgs_sb);
523 static int mgs_set_info_rpc(struct ptlrpc_request *req)
525 struct obd_device *obd = req->rq_export->exp_obd;
526 struct mgs_send_param *msp, *rep_msp;
527 struct lustre_handle lockh;
529 struct lustre_cfg_bufs bufs;
530 struct lustre_cfg *lcfg;
531 char fsname[MTI_NAME_MAXLEN];
534 msp = req_capsule_client_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
537 /* Construct lustre_cfg structure to pass to function mgs_setparam */
538 lustre_cfg_bufs_reset(&bufs, NULL);
539 lustre_cfg_bufs_set_string(&bufs, 1, msp->mgs_param);
540 lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
541 rc = mgs_setparam(obd, lcfg, fsname);
543 CERROR("Error %d in setting the parameter %s for fs %s\n",
544 rc, msp->mgs_param, fsname);
548 /* request for update */
549 mgs_revoke_lock(obd, fsname, &lockh);
551 lustre_cfg_free(lcfg);
553 rc = req_capsule_server_pack(&req->rq_pill);
555 rep_msp = req_capsule_server_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
562 * similar as in ost_connect_check_sptlrpc()
564 static int mgs_connect_check_sptlrpc(struct ptlrpc_request *req)
566 struct obd_export *exp = req->rq_export;
567 struct obd_device *obd = exp->exp_obd;
569 struct sptlrpc_flavor flvr;
572 if (exp->exp_flvr.sf_rpc == SPTLRPC_FLVR_INVALID) {
573 rc = mgs_find_or_make_fsdb(obd, MGSSELF_NAME, &fsdb);
577 down(&fsdb->fsdb_sem);
578 if (sptlrpc_rule_set_choose(&fsdb->fsdb_srpc_gen,
579 LUSTRE_SP_MGC, LUSTRE_SP_MGS,
582 /* by defualt allow any flavors */
583 flvr.sf_rpc = SPTLRPC_FLVR_ANY;
587 spin_lock(&exp->exp_lock);
589 exp->exp_sp_peer = req->rq_sp_from;
590 exp->exp_flvr = flvr;
592 if (exp->exp_flvr.sf_rpc != SPTLRPC_FLVR_ANY &&
593 exp->exp_flvr.sf_rpc != req->rq_flvr.sf_rpc) {
594 CERROR("invalid rpc flavor %x, expect %x, from %s\n",
595 req->rq_flvr.sf_rpc, exp->exp_flvr.sf_rpc,
596 libcfs_nid2str(req->rq_peer.nid));
600 spin_unlock(&exp->exp_lock);
602 if (exp->exp_sp_peer != req->rq_sp_from) {
603 CERROR("RPC source %s doesn't match %s\n",
604 sptlrpc_part2name(req->rq_sp_from),
605 sptlrpc_part2name(exp->exp_sp_peer));
608 rc = sptlrpc_target_export_check(exp, req);
615 /* Called whenever a target cleans up. */
616 /* XXX - Currently unused */
617 static int mgs_handle_target_del(struct ptlrpc_request *req)
620 mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_DEL);
624 /* XXX - Currently unused */
625 static int mgs_handle_exception(struct ptlrpc_request *req)
628 mgs_counter_incr(req->rq_export, LPROC_MGS_EXCEPTION);
632 /* TODO: handle requests in a similar way as MDT: see mdt_handle_common() */
633 int mgs_handle(struct ptlrpc_request *req)
635 int fail = OBD_FAIL_MGS_ALL_REPLY_NET;
639 req_capsule_init(&req->rq_pill, req, RCL_SERVER);
640 OBD_FAIL_TIMEOUT_MS(OBD_FAIL_MGS_PAUSE_REQ, obd_fail_val);
641 if (OBD_FAIL_CHECK(OBD_FAIL_MGS_ALL_REQUEST_NET))
644 LASSERT(current->journal_info == NULL);
645 opc = lustre_msg_get_opc(req->rq_reqmsg);
647 if (opc == SEC_CTX_INIT ||
648 opc == SEC_CTX_INIT_CONT ||
652 if (opc != MGS_CONNECT) {
653 if (req->rq_export == NULL) {
654 CERROR("lustre_mgs: operation %d on unconnected MGS\n",
656 req->rq_status = -ENOTCONN;
657 GOTO(out, rc = -ENOTCONN);
663 DEBUG_REQ(D_MGS, req, "connect");
664 /* MGS and MDS have same request format for connect */
665 req_capsule_set(&req->rq_pill, &RQF_MDS_CONNECT);
666 rc = target_handle_connect(req);
668 rc = mgs_connect_check_sptlrpc(req);
670 if (!rc && (lustre_msg_get_conn_cnt(req->rq_reqmsg) > 1))
671 /* Make clients trying to reconnect after a MGS restart
672 happy; also requires obd_replayable */
673 lustre_msg_add_op_flags(req->rq_repmsg,
674 MSG_CONNECT_RECONNECT);
677 DEBUG_REQ(D_MGS, req, "disconnect");
678 /* MGS and MDS have same request format for disconnect */
679 req_capsule_set(&req->rq_pill, &RQF_MDS_DISCONNECT);
680 rc = target_handle_disconnect(req);
681 req->rq_status = rc; /* superfluous? */
684 DEBUG_REQ(D_MGS, req, "exception");
685 rc = mgs_handle_exception(req);
688 DEBUG_REQ(D_MGS, req, "target add");
689 req_capsule_set(&req->rq_pill, &RQF_MGS_TARGET_REG);
690 rc = mgs_handle_target_reg(req);
693 DEBUG_REQ(D_MGS, req, "target del");
694 rc = mgs_handle_target_del(req);
697 DEBUG_REQ(D_MGS, req, "set_info");
698 req_capsule_set(&req->rq_pill, &RQF_MGS_SET_INFO);
699 rc = mgs_set_info_rpc(req);
703 DEBUG_REQ(D_MGS, req, "enqueue");
704 req_capsule_set(&req->rq_pill, &RQF_LDLM_ENQUEUE);
705 rc = ldlm_handle_enqueue(req, ldlm_server_completion_ast,
706 ldlm_server_blocking_ast, NULL);
708 case LDLM_BL_CALLBACK:
709 case LDLM_CP_CALLBACK:
710 DEBUG_REQ(D_MGS, req, "callback");
711 CERROR("callbacks should not happen on MGS\n");
716 DEBUG_REQ(D_INFO, req, "ping");
717 req_capsule_set(&req->rq_pill, &RQF_OBD_PING);
718 rc = target_handle_ping(req);
721 DEBUG_REQ(D_MGS, req, "log cancel");
722 rc = -ENOTSUPP; /* la la la */
725 case LLOG_ORIGIN_HANDLE_CREATE:
726 DEBUG_REQ(D_MGS, req, "llog_init");
727 req_capsule_set(&req->rq_pill, &RQF_LLOG_ORIGIN_HANDLE_CREATE);
728 rc = llog_origin_handle_create(req);
730 case LLOG_ORIGIN_HANDLE_NEXT_BLOCK:
731 DEBUG_REQ(D_MGS, req, "llog next block");
732 req_capsule_set(&req->rq_pill,
733 &RQF_LLOG_ORIGIN_HANDLE_NEXT_BLOCK);
734 rc = llog_origin_handle_next_block(req);
736 case LLOG_ORIGIN_HANDLE_READ_HEADER:
737 DEBUG_REQ(D_MGS, req, "llog read header");
738 req_capsule_set(&req->rq_pill,
739 &RQF_LLOG_ORIGIN_HANDLE_READ_HEADER);
740 rc = llog_origin_handle_read_header(req);
742 case LLOG_ORIGIN_HANDLE_CLOSE:
743 DEBUG_REQ(D_MGS, req, "llog close");
744 rc = llog_origin_handle_close(req);
747 DEBUG_REQ(D_MGS, req, "llog catinfo");
748 req_capsule_set(&req->rq_pill, &RQF_LLOG_CATINFO);
749 rc = llog_catinfo(req);
752 req->rq_status = -ENOTSUPP;
753 rc = ptlrpc_error(req);
757 LASSERT(current->journal_info == NULL);
760 CERROR("MGS handle cmd=%d rc=%d\n", opc, rc);
763 target_send_reply(req, rc, fail);
767 static inline int mgs_init_export(struct obd_export *exp)
769 return ldlm_init_export(exp);
772 static inline int mgs_destroy_export(struct obd_export *exp)
776 target_destroy_export(exp);
777 mgs_client_free(exp);
778 ldlm_destroy_export(exp);
783 static int mgs_extract_fs_pool(char * arg, char *fsname, char *poolname)
788 for (ptr = arg; (*ptr != '\0') && (*ptr != '.'); ptr++ ) {
796 strcpy(poolname, ptr);
801 static int mgs_iocontrol_pool(struct obd_device *obd,
802 struct obd_ioctl_data *data)
805 struct lustre_handle lockh;
806 struct lustre_cfg *lcfg = NULL;
807 struct llog_rec_hdr rec;
809 char *poolname = NULL;
812 OBD_ALLOC(fsname, MTI_NAME_MAXLEN);
816 OBD_ALLOC(poolname, LOV_MAXPOOLNAME + 1);
817 if (poolname == NULL) {
821 rec.lrh_len = llog_data_len(data->ioc_plen1);
823 if (data->ioc_type == LUSTRE_CFG_TYPE) {
824 rec.lrh_type = OBD_CFG_REC;
826 CERROR("unknown cfg record type:%d \n", data->ioc_type);
831 if (data->ioc_plen1 > CFS_PAGE_SIZE) {
836 OBD_ALLOC(lcfg, data->ioc_plen1);
838 GOTO(out_pool, rc = -ENOMEM);
840 if (copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1))
841 GOTO(out_pool, rc = -EFAULT);
843 if (lcfg->lcfg_bufcount < 2) {
844 GOTO(out_pool, rc = -EFAULT);
847 /* first arg is always <fsname>.<poolname> */
848 mgs_extract_fs_pool(lustre_cfg_string(lcfg, 1), fsname,
851 switch (lcfg->lcfg_command) {
852 case LCFG_POOL_NEW: {
853 if (lcfg->lcfg_bufcount != 2)
855 rc = mgs_pool_cmd(obd, LCFG_POOL_NEW, fsname,
859 case LCFG_POOL_ADD: {
860 if (lcfg->lcfg_bufcount != 3)
862 rc = mgs_pool_cmd(obd, LCFG_POOL_ADD, fsname, poolname,
863 lustre_cfg_string(lcfg, 2));
866 case LCFG_POOL_REM: {
867 if (lcfg->lcfg_bufcount != 3)
869 rc = mgs_pool_cmd(obd, LCFG_POOL_REM, fsname, poolname,
870 lustre_cfg_string(lcfg, 2));
873 case LCFG_POOL_DEL: {
874 if (lcfg->lcfg_bufcount != 2)
876 rc = mgs_pool_cmd(obd, LCFG_POOL_DEL, fsname,
887 CERROR("OBD_IOC_POOL err %d, cmd %X for pool %s.%s\n",
888 rc, lcfg->lcfg_command, fsname, poolname);
892 /* request for update */
893 mgs_revoke_lock(obd, fsname, &lockh);
897 OBD_FREE(lcfg, data->ioc_plen1);
900 OBD_FREE(fsname, MTI_NAME_MAXLEN);
902 if (poolname != NULL)
903 OBD_FREE(poolname, LOV_MAXPOOLNAME + 1);
908 /* from mdt_iocontrol */
909 int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
910 void *karg, void *uarg)
912 struct obd_device *obd = exp->exp_obd;
913 struct obd_ioctl_data *data = karg;
914 struct lvfs_run_ctxt saved;
918 CDEBUG(D_IOCTL, "handling ioctl cmd %#x\n", cmd);
922 case OBD_IOC_PARAM: {
923 struct lustre_handle lockh;
924 struct lustre_cfg *lcfg;
925 struct llog_rec_hdr rec;
926 char fsname[MTI_NAME_MAXLEN];
928 rec.lrh_len = llog_data_len(data->ioc_plen1);
930 if (data->ioc_type == LUSTRE_CFG_TYPE) {
931 rec.lrh_type = OBD_CFG_REC;
933 CERROR("unknown cfg record type:%d \n", data->ioc_type);
937 OBD_ALLOC(lcfg, data->ioc_plen1);
940 if (copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1))
941 GOTO(out_free, rc = -EFAULT);
943 if (lcfg->lcfg_bufcount < 1)
944 GOTO(out_free, rc = -EINVAL);
946 rc = mgs_setparam(obd, lcfg, fsname);
948 CERROR("setparam err %d\n", rc);
952 /* Revoke lock so everyone updates. Should be alright if
953 someone was already reading while we were updating the logs,
954 so we don't really need to hold the lock while we're
956 mgs_revoke_lock(obd, fsname, &lockh);
959 OBD_FREE(lcfg, data->ioc_plen1);
964 RETURN(mgs_iocontrol_pool(obd, data));
967 case OBD_IOC_DUMP_LOG: {
968 struct llog_ctxt *ctxt;
969 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
970 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
971 rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL);
972 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
978 case OBD_IOC_LLOG_CHECK:
979 case OBD_IOC_LLOG_INFO:
980 case OBD_IOC_LLOG_PRINT: {
981 struct llog_ctxt *ctxt;
982 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
984 push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
985 rc = llog_ioctl(ctxt, cmd, data);
986 pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
993 CDEBUG(D_INFO, "unknown command %x\n", cmd);
999 /* use obd ops to offer management infrastructure */
1000 static struct obd_ops mgs_obd_ops = {
1001 .o_owner = THIS_MODULE,
1002 .o_connect = mgs_connect,
1003 .o_reconnect = mgs_reconnect,
1004 .o_disconnect = mgs_disconnect,
1005 .o_setup = mgs_setup,
1006 .o_precleanup = mgs_precleanup,
1007 .o_cleanup = mgs_cleanup,
1008 .o_init_export = mgs_init_export,
1009 .o_destroy_export = mgs_destroy_export,
1010 .o_iocontrol = mgs_iocontrol,
1011 .o_llog_init = mgs_llog_init,
1012 .o_llog_finish = mgs_llog_finish
1015 static int __init mgs_init(void)
1017 struct lprocfs_static_vars lvars;
1019 lprocfs_mgs_init_vars(&lvars);
1020 class_register_type(&mgs_obd_ops, NULL,
1021 lvars.module_vars, LUSTRE_MGS_NAME, NULL);
1026 static void /*__exit*/ mgs_exit(void)
1028 class_unregister_type(LUSTRE_MGS_NAME);
1031 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
1032 MODULE_DESCRIPTION("Lustre Management Server (MGS)");
1033 MODULE_LICENSE("GPL");
1035 module_init(mgs_init);
1036 module_exit(mgs_exit);