Whamcloud - gitweb
1efe1ab90bed8abc0d45a9b1415fc1c976571e91
[fs/lustre-release.git] / lustre / mgs / mgs_handler.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lustre/mgs/mgs_handler.c
5  *  Lustre Management Server (mgs) request handler
6  *
7  *  Copyright (C) 2006 Cluster File Systems, Inc.
8  *   Author: Nathan Rutman <nathan@clusterfs.com>
9  *
10  *   This file is part of Lustre, http://www.lustre.org.
11  *
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.
15  *
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.
20  *
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.
24  */
25
26 #ifndef EXPORT_SYMTAB
27 # define EXPORT_SYMTAB
28 #endif
29 #define DEBUG_SUBSYSTEM S_MGS
30 #define D_MGS D_CONFIG/*|D_WARNING*/
31
32 #ifdef __KERNEL__
33 # include <linux/module.h>
34 # include <linux/pagemap.h>
35 # include <linux/miscdevice.h>
36 # include <linux/init.h>
37 #else
38 # include <liblustre.h>
39 #endif
40
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"
48
49
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)
54 {
55         struct obd_export *exp;
56         int rc;
57         ENTRY;
58
59         if (!conn || !obd || !cluuid)
60                 RETURN(-EINVAL);
61
62         rc = class_connect(conn, obd, cluuid);
63         if (rc)
64                 RETURN(rc);
65         exp = class_conn2export(conn);
66         LASSERT(exp);
67
68         exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_NULL;
69
70         if (data != 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;
74         }
75
76         if (rc) {
77                 class_disconnect(exp);
78         } else {
79                 class_export_put(exp);
80         }
81
82         RETURN(rc);
83 }
84
85 static int mgs_disconnect(struct obd_export *exp)
86 {
87         int rc;
88         ENTRY;
89
90         LASSERT(exp);
91         class_export_get(exp);
92
93         /* Disconnect early so that clients can't keep using export */
94         rc = class_disconnect(exp);
95         ldlm_cancel_locks_for_export(exp);
96
97         /* complete all outstanding replies */
98         spin_lock(&exp->exp_lock);
99         while (!list_empty(&exp->exp_outstanding_replies)) {
100                 struct ptlrpc_reply_state *rs =
101                         list_entry(exp->exp_outstanding_replies.next,
102                                    struct ptlrpc_reply_state, rs_exp_list);
103                 struct ptlrpc_service *svc = rs->rs_service;
104
105                 spin_lock(&svc->srv_lock);
106                 list_del_init(&rs->rs_exp_list);
107                 ptlrpc_schedule_difficult_reply(rs);
108                 spin_unlock(&svc->srv_lock);
109         }
110         spin_unlock(&exp->exp_lock);
111
112         class_export_put(exp);
113         RETURN(rc);
114 }
115
116 static int mgs_cleanup(struct obd_device *obd);
117 static int mgs_handle(struct ptlrpc_request *req);
118
119 /* Start the MGS obd */
120 static int mgs_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
121 {
122         struct lprocfs_static_vars lvars;
123         struct mgs_obd *mgs = &obd->u.mgs;
124         struct lustre_mount_info *lmi;
125         struct lustre_sb_info *lsi;
126         struct vfsmount *mnt;
127         int rc = 0;
128         ENTRY;
129
130         CDEBUG(D_CONFIG, "Starting MGS\n");
131
132         /* Find our disk */
133         lmi = server_get_mount(obd->obd_name);
134         if (!lmi)
135                 RETURN(rc = -EINVAL);
136
137         mnt = lmi->lmi_mnt;
138         lsi = s2lsi(lmi->lmi_sb);
139         obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd));
140         if (IS_ERR(obd->obd_fsops))
141                 GOTO(err_put, rc = PTR_ERR(obd->obd_fsops));
142
143         /* namespace for mgs llog */
144         obd->obd_namespace = ldlm_namespace_new("MGS", LDLM_NAMESPACE_SERVER,
145                                                 LDLM_NAMESPACE_MODEST);
146         if (obd->obd_namespace == NULL)
147                 GOTO(err_ops, rc = -ENOMEM);
148
149         /* ldlm setup */
150         ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
151                            "mgs_ldlm_client", &obd->obd_ldlm_client);
152
153         LASSERT(!lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb)));
154
155         rc = mgs_fs_setup(obd, mnt);
156         if (rc) {
157                 CERROR("%s: MGS filesystem method init failed: rc = %d\n",
158                        obd->obd_name, rc);
159                 GOTO(err_ns, rc);
160         }
161
162         rc = llog_start_commit_thread();
163         if (rc < 0)
164                 GOTO(err_fs, rc);
165
166         rc = llog_setup(obd, NULL, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
167                         &llog_lvfs_ops);
168         if (rc)
169                 GOTO(err_fs, rc);
170
171         /* No recovery for MGC's */
172         obd->obd_replayable = 0;
173
174         /* Internal mgs setup */
175         mgs_init_fsdb_list(obd);
176         sema_init(&mgs->mgs_sem, 1);
177
178         /* Start the service threads */
179         mgs->mgs_service =
180                 ptlrpc_init_svc(MGS_NBUFS, MGS_BUFSIZE, MGS_MAXREQSIZE,
181                                 MGS_MAXREPSIZE, MGS_REQUEST_PORTAL,
182                                 MGC_REPLY_PORTAL, MGS_SERVICE_WATCHDOG_TIMEOUT,
183                                 mgs_handle, LUSTRE_MGS_NAME,
184                                 obd->obd_proc_entry, NULL,
185                                 MGS_THREADS_AUTO_MIN, MGS_THREADS_AUTO_MAX,
186                                 "ll_mgs", LCT_MD_THREAD);
187
188         if (!mgs->mgs_service) {
189                 CERROR("failed to start service\n");
190                 GOTO(err_fs, rc = -ENOMEM);
191         }
192
193         rc = ptlrpc_start_threads(obd, mgs->mgs_service);
194         if (rc)
195                 GOTO(err_thread, rc);
196
197         /* Setup proc */
198         lprocfs_mgs_init_vars(&lvars);
199         if (lprocfs_obd_setup(obd, lvars.obd_vars) == 0) {
200                 lproc_mgs_setup(obd);
201         }
202
203         ping_evictor_start();
204
205         LCONSOLE_INFO("MGS %s started\n", obd->obd_name);
206
207         RETURN(0);
208
209 err_thread:
210         ptlrpc_unregister_service(mgs->mgs_service);
211 err_fs:
212         /* No extra cleanup needed for llog_init_commit_thread() */
213         mgs_fs_cleanup(obd);
214 err_ns:
215         ldlm_namespace_free(obd->obd_namespace, 0);
216         obd->obd_namespace = NULL;
217 err_ops:
218         fsfilt_put_ops(obd->obd_fsops);
219 err_put:
220         server_put_mount(obd->obd_name, mnt);
221         mgs->mgs_sb = 0;
222         return rc;
223 }
224
225 static int mgs_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
226 {
227         int rc = 0;
228         ENTRY;
229
230         switch (stage) {
231         case OBD_CLEANUP_EARLY:
232         case OBD_CLEANUP_EXPORTS:
233                 break;
234         case OBD_CLEANUP_SELF_EXP:
235                 llog_cleanup(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT));
236                 rc = obd_llog_finish(obd, 0);
237                 break;
238         case OBD_CLEANUP_OBD:
239                 break;
240         }
241         RETURN(rc);
242 }
243
244 static int mgs_ldlm_nsfree(void *data)
245 {
246         struct ldlm_namespace *ns = (struct ldlm_namespace *)data;
247         int rc;
248         ENTRY;
249
250         ptlrpc_daemonize("ll_mgs_nsfree");
251         rc = ldlm_namespace_free(ns, 1 /* obd_force should always be on */);
252         RETURN(rc);
253 }
254
255 static int mgs_cleanup(struct obd_device *obd)
256 {
257         struct mgs_obd *mgs = &obd->u.mgs;
258         ENTRY;
259
260         if (mgs->mgs_sb == NULL)
261                 RETURN(0);
262
263         ping_evictor_stop();
264
265         ptlrpc_unregister_service(mgs->mgs_service);
266
267         mgs_cleanup_fsdb_list(obd);
268
269         lprocfs_obd_cleanup(obd);
270         mgs->mgs_proc_live = NULL;
271
272         mgs_fs_cleanup(obd);
273
274         server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
275         mgs->mgs_sb = NULL;
276
277         /* Free the namespace in it's own thread, so that if the
278            ldlm_cancel_handler put the last mgs obd ref, we won't
279            deadlock here. */
280         cfs_kernel_thread(mgs_ldlm_nsfree, obd->obd_namespace,
281                           CLONE_VM | CLONE_FILES);
282
283
284         fsfilt_put_ops(obd->obd_fsops);
285
286         LCONSOLE_INFO("%s has stopped.\n", obd->obd_name);
287         RETURN(0);
288 }
289
290 /* similar to filter_prepare_destroy */
291 static int mgs_get_cfg_lock(struct obd_device *obd, char *fsname,
292                             struct lustre_handle *lockh)
293 {
294         struct ldlm_res_id res_id;
295         int rc, flags = 0;
296         ENTRY;
297
298         rc = mgc_fsname2resid(fsname, &res_id);
299         if (!rc)
300                 rc = ldlm_cli_enqueue_local(obd->obd_namespace, &res_id,
301                                             LDLM_PLAIN, NULL, LCK_EX,
302                                             &flags, ldlm_blocking_ast,
303                                             ldlm_completion_ast, NULL,
304                                             fsname, 0, NULL, lockh);
305         if (rc)
306                 CERROR("can't take cfg lock for %s (%d)\n", fsname, rc);
307
308         RETURN(rc);
309 }
310
311 static int mgs_put_cfg_lock(struct lustre_handle *lockh)
312 {
313         ENTRY;
314         ldlm_lock_decref(lockh, LCK_EX);
315         RETURN(0);
316 }
317
318 /* rc=0 means ok
319       1 means update
320      <0 means error */
321 static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti)
322 {
323         int rc;
324         ENTRY;
325
326         rc = mgs_check_index(obd, mti);
327         if (rc == 0) {
328                 LCONSOLE_ERROR_MSG(0x13b, "%s claims to have registered, but "
329                                    "this MGS does not know about it. Assuming"
330                                    " writeconf.\n", mti->mti_svname);
331                 mti->mti_flags |= LDD_F_WRITECONF;
332                 rc = 1;
333         } else if (rc == -1) {
334                 LCONSOLE_ERROR_MSG(0x13c, "Client log %s-client has "
335                                    "disappeared! Regenerating all logs.\n",
336                                    mti->mti_fsname);
337                 mti->mti_flags |= LDD_F_WRITECONF;
338                 rc = 1;
339         } else {
340                 /* Index is correctly marked as used */
341
342                 /* If the logs don't contain the mti_nids then add
343                    them as failover nids */
344                 rc = mgs_check_failnid(obd, mti);
345         }
346
347         RETURN(rc);
348 }
349
350 /* Called whenever a target starts up.  Flags indicate first connect, etc. */
351 static int mgs_handle_target_reg(struct ptlrpc_request *req)
352 {
353         struct obd_device *obd = req->rq_export->exp_obd;
354         struct lustre_handle lockh;
355         struct mgs_target_info *mti, *rep_mti;
356         int rep_size[] = { sizeof(struct ptlrpc_body), sizeof(*mti) };
357         int rc = 0, lockrc;
358         ENTRY;
359
360         mti = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*mti),
361                                  lustre_swab_mgs_target_info);
362
363         if (!(mti->mti_flags & (LDD_F_WRITECONF | LDD_F_UPGRADE14 |
364                                 LDD_F_UPDATE))) {
365                 /* We're just here as a startup ping. */
366                 CDEBUG(D_MGS, "Server %s is running on %s\n",
367                        mti->mti_svname, obd_export_nid2str(req->rq_export));
368                 rc = mgs_check_target(obd, mti);
369                 /* above will set appropriate mti flags */
370                 if (rc <= 0)
371                         /* Nothing wrong, or fatal error */
372                         GOTO(out_nolock, rc);
373         }
374
375         /* Revoke the config lock to make sure nobody is reading. */
376         /* Although actually I think it should be alright if
377            someone was reading while we were updating the logs - if we
378            revoke at the end they will just update from where they left off. */
379         lockrc = mgs_get_cfg_lock(obd, mti->mti_fsname, &lockh);
380         if (lockrc != ELDLM_OK) {
381                 LCONSOLE_ERROR_MSG(0x13d, "%s: Can't signal other nodes to "
382                                    "update their configuration (%d). Updating "
383                                    "local logs anyhow; you might have to "
384                                    "manually restart other nodes to get the "
385                                    "latest configuration.\n",
386                                    obd->obd_name, lockrc);
387         }
388
389         OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_SLOW_TARGET_REG, 10);
390
391         /* Log writing contention is handled by the fsdb_sem */
392
393         if (mti->mti_flags & LDD_F_WRITECONF) {
394                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT &&
395                     mti->mti_stripe_index == 0) {
396                         rc = mgs_erase_logs(obd, mti->mti_fsname);
397                         LCONSOLE_WARN("%s: Logs for fs %s were removed by user "
398                                       "request.  All servers must be restarted "
399                                       "in order to regenerate the logs."
400                                       "\n", obd->obd_name, mti->mti_fsname);
401                 } else if (mti->mti_flags &
402                            (LDD_F_SV_TYPE_OST | LDD_F_SV_TYPE_MDT)) {
403                         rc = mgs_erase_log(obd, mti->mti_svname);
404                         LCONSOLE_WARN("%s: Regenerating %s log by user "
405                                       "request.\n",
406                                       obd->obd_name, mti->mti_svname);
407                 }
408                 mti->mti_flags |= LDD_F_UPDATE;
409                 /* Erased logs means start from scratch. */
410                 mti->mti_flags &= ~LDD_F_UPGRADE14; 
411         }
412
413         /* COMPAT_146 */
414         if (mti->mti_flags & LDD_F_UPGRADE14) {
415                 rc = mgs_upgrade_sv_14(obd, mti);
416                 if (rc) {
417                         CERROR("Can't upgrade from 1.4 (%d)\n", rc);
418                         GOTO(out, rc);
419                 }
420                 
421                 /* We're good to go */
422                 mti->mti_flags |= LDD_F_UPDATE;
423         }
424         /* end COMPAT_146 */
425
426         if (mti->mti_flags & LDD_F_UPDATE) {
427                 CDEBUG(D_MGS, "updating %s, index=%d\n", mti->mti_svname,
428                        mti->mti_stripe_index);
429
430                 /* create or update the target log
431                    and update the client/mdt logs */
432                 rc = mgs_write_log_target(obd, mti);
433                 if (rc) {
434                         CERROR("Failed to write %s log (%d)\n",
435                                mti->mti_svname, rc);
436                         GOTO(out, rc);
437                 }
438
439                 mti->mti_flags &= ~(LDD_F_VIRGIN | LDD_F_UPDATE |
440                                     LDD_F_NEED_INDEX | LDD_F_WRITECONF |
441                                     LDD_F_UPGRADE14);
442                 mti->mti_flags |= LDD_F_REWRITE_LDD;
443         }
444
445 out:
446         /* done with log update */
447         if (lockrc == ELDLM_OK)
448                 mgs_put_cfg_lock(&lockh);
449 out_nolock:
450         CDEBUG(D_MGS, "replying with %s, index=%d, rc=%d\n", mti->mti_svname,
451                mti->mti_stripe_index, rc);
452         lustre_pack_reply(req, 2, rep_size, NULL);
453         /* send back the whole mti in the reply */
454         rep_mti = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
455                                  sizeof(*rep_mti));
456         memcpy(rep_mti, mti, sizeof(*rep_mti));
457
458         /* Flush logs to disk */
459         fsfilt_sync(obd, obd->u.mgs.mgs_sb);
460         RETURN(rc);
461 }
462
463 static int mgs_set_info_rpc(struct ptlrpc_request *req)
464 {
465         struct obd_device *obd = req->rq_export->exp_obd;
466         struct mgs_send_param *msp, *rep_msp;
467         struct lustre_handle lockh;
468         int rep_size[] = { sizeof(struct ptlrpc_body), sizeof(*msp) };
469         int lockrc, rc;
470         struct lustre_cfg_bufs bufs;
471         struct lustre_cfg *lcfg;
472         char fsname[MTI_NAME_MAXLEN];
473         ENTRY;
474
475         msp = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*msp), NULL);
476
477         /* Construct lustre_cfg structure to pass to function mgs_setparam */
478         lustre_cfg_bufs_reset(&bufs, NULL);
479         lustre_cfg_bufs_set_string(&bufs, 1, msp->mgs_param);
480         lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
481         rc = mgs_setparam(obd, lcfg, fsname);
482         if (rc) {
483                 CERROR("Error %d in setting the parameter %s for fs %s\n",
484                        rc, msp->mgs_param, fsname);
485                 RETURN(rc);
486         }
487
488         /* Revoke lock so everyone updates.  Should be alright if
489          * someone was already reading while we were updating the logs,
490          * so we don't really need to hold the lock while we're
491          * writing.
492          */
493         if (fsname[0]) {
494                 lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
495                 if (lockrc != ELDLM_OK)
496                         CERROR("lock error %d for fs %s\n", lockrc,
497                                fsname);
498                 else
499                         mgs_put_cfg_lock(&lockh);
500         }
501         lustre_cfg_free(lcfg);
502
503         lustre_pack_reply(req, 2, rep_size, NULL);
504         rep_msp = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
505                                  sizeof(*rep_msp));
506         memcpy(rep_msp, msp, sizeof(*rep_msp));
507
508         RETURN(rc);
509 }
510
511 int mgs_handle(struct ptlrpc_request *req)
512 {
513         int fail = OBD_FAIL_MGS_ALL_REPLY_NET;
514         int opc, rc = 0;
515         ENTRY;
516
517         OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_SLOW_REQUEST_NET, 2);
518
519         LASSERT(current->journal_info == NULL);
520         opc = lustre_msg_get_opc(req->rq_reqmsg);
521         if (opc != MGS_CONNECT) {
522                 if (req->rq_export == NULL) {
523                         CERROR("lustre_mgs: operation %d on unconnected MGS\n",
524                                opc);
525                         req->rq_status = -ENOTCONN;
526                         GOTO(out, rc = -ENOTCONN);
527                 }
528         }
529
530         switch (opc) {
531         case MGS_CONNECT:
532                 DEBUG_REQ(D_MGS, req, "connect");
533                 rc = target_handle_connect(req);
534                 if (!rc && (lustre_msg_get_conn_cnt(req->rq_reqmsg) > 1))
535                         /* Make clients trying to reconnect after a MGS restart
536                            happy; also requires obd_replayable */
537                         lustre_msg_add_op_flags(req->rq_repmsg,
538                                                 MSG_CONNECT_RECONNECT);
539                 break;
540         case MGS_DISCONNECT:
541                 DEBUG_REQ(D_MGS, req, "disconnect");
542                 rc = target_handle_disconnect(req);
543                 req->rq_status = rc;            /* superfluous? */
544                 break;
545         case MGS_TARGET_REG:
546                 DEBUG_REQ(D_MGS, req, "target add");
547                 rc = mgs_handle_target_reg(req);
548                 break;
549         case MGS_TARGET_DEL:
550                 DEBUG_REQ(D_MGS, req, "target del");
551                 //rc = mgs_handle_target_del(req);
552                 break;
553         case MGS_SET_INFO:
554                 rc = mgs_set_info_rpc(req);
555                 break;
556
557         case LDLM_ENQUEUE:
558                 DEBUG_REQ(D_MGS, req, "enqueue");
559                 rc = ldlm_handle_enqueue(req, ldlm_server_completion_ast,
560                                          ldlm_server_blocking_ast, NULL);
561                 break;
562         case LDLM_BL_CALLBACK:
563         case LDLM_CP_CALLBACK:
564                 DEBUG_REQ(D_MGS, req, "callback");
565                 CERROR("callbacks should not happen on MGS\n");
566                 LBUG();
567                 break;
568
569         case OBD_PING:
570                 DEBUG_REQ(D_INFO, req, "ping");
571                 rc = target_handle_ping(req);
572                 break;
573         case OBD_LOG_CANCEL:
574                 DEBUG_REQ(D_MGS, req, "log cancel");
575                 rc = -ENOTSUPP; /* la la la */
576                 break;
577
578         case LLOG_ORIGIN_HANDLE_CREATE:
579                 DEBUG_REQ(D_MGS, req, "llog_init");
580                 rc = llog_origin_handle_create(req);
581                 break;
582         case LLOG_ORIGIN_HANDLE_NEXT_BLOCK:
583                 DEBUG_REQ(D_MGS, req, "llog next block");
584                 rc = llog_origin_handle_next_block(req);
585                 break;
586         case LLOG_ORIGIN_HANDLE_READ_HEADER:
587                 DEBUG_REQ(D_MGS, req, "llog read header");
588                 rc = llog_origin_handle_read_header(req);
589                 break;
590         case LLOG_ORIGIN_HANDLE_CLOSE:
591                 DEBUG_REQ(D_MGS, req, "llog close");
592                 rc = llog_origin_handle_close(req);
593                 break;
594         case LLOG_CATINFO:
595                 DEBUG_REQ(D_MGS, req, "llog catinfo");
596                 rc = llog_catinfo(req);
597                 break;
598         default:
599                 req->rq_status = -ENOTSUPP;
600                 rc = ptlrpc_error(req);
601                 RETURN(rc);
602         }
603
604         LASSERT(current->journal_info == NULL);
605
606         if (rc)
607                 CERROR("MGS handle cmd=%d rc=%d\n", opc, rc);
608
609 out:
610         target_send_reply(req, rc, fail);
611         RETURN(0);
612 }
613
614 static inline int mgs_destroy_export(struct obd_export *exp)
615 {
616         ENTRY;
617
618         target_destroy_export(exp);
619
620         RETURN(0);
621 }
622
623 /* from mdt_iocontrol */
624 int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
625                   void *karg, void *uarg)
626 {
627         struct obd_device *obd = exp->exp_obd;
628         struct obd_ioctl_data *data = karg;
629         struct lvfs_run_ctxt saved;
630         int rc = 0;
631
632         ENTRY;
633         CDEBUG(D_IOCTL, "handling ioctl cmd %#x\n", cmd);
634
635         switch (cmd) {
636
637         case OBD_IOC_PARAM: {
638                 struct lustre_handle lockh;
639                 struct lustre_cfg *lcfg;
640                 struct llog_rec_hdr rec;
641                 char fsname[MTI_NAME_MAXLEN];
642                 int lockrc;
643
644                 rec.lrh_len = llog_data_len(data->ioc_plen1);
645
646                 if (data->ioc_type == LUSTRE_CFG_TYPE) {
647                         rec.lrh_type = OBD_CFG_REC;
648                 } else {
649                         CERROR("unknown cfg record type:%d \n", data->ioc_type);
650                         RETURN(-EINVAL);
651                 }
652
653                 OBD_ALLOC(lcfg, data->ioc_plen1);
654                 if (lcfg == NULL)
655                         RETURN(-ENOMEM);
656                 rc = copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1);
657                 if (rc)
658                         GOTO(out_free, rc);
659
660                 if (lcfg->lcfg_bufcount < 1)
661                         GOTO(out_free, rc = -EINVAL);
662
663                 rc = mgs_setparam(obd, lcfg, fsname);
664                 if (rc) {
665                         CERROR("setparam err %d\n", rc);
666                         GOTO(out_free, rc);
667                 }
668
669                 /* Revoke lock so everyone updates.  Should be alright if
670                    someone was already reading while we were updating the logs,
671                    so we don't really need to hold the lock while we're
672                    writing (above). */
673                 if (fsname[0]) {
674                         lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
675                         if (lockrc != ELDLM_OK)
676                                 CERROR("lock error %d for fs %s\n", lockrc,
677                                        fsname);
678                         else
679                                 mgs_put_cfg_lock(&lockh);
680                 }
681
682 out_free:
683                 OBD_FREE(lcfg, data->ioc_plen1);
684                 RETURN(rc);
685         }
686
687         case OBD_IOC_DUMP_LOG: {
688                 struct llog_ctxt *ctxt =
689                         llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
690                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
691                 rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL);
692                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
693                 if (rc)
694                         RETURN(rc);
695
696                 RETURN(rc);
697         }
698
699         case OBD_IOC_LLOG_CHECK:
700         case OBD_IOC_LLOG_INFO:
701         case OBD_IOC_LLOG_PRINT: {
702                 struct llog_ctxt *ctxt =
703                         llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
704
705                 push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
706                 rc = llog_ioctl(ctxt, cmd, data);
707                 pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
708
709                 RETURN(rc);
710         }
711
712         default:
713                 CDEBUG(D_INFO, "unknown command %x\n", cmd);
714                 RETURN(-EINVAL);
715         }
716         RETURN(0);
717 }
718
719 /* use obd ops to offer management infrastructure */
720 static struct obd_ops mgs_obd_ops = {
721         .o_owner           = THIS_MODULE,
722         .o_connect         = mgs_connect,
723         .o_disconnect      = mgs_disconnect,
724         .o_setup           = mgs_setup,
725         .o_precleanup      = mgs_precleanup,
726         .o_cleanup         = mgs_cleanup,
727         .o_destroy_export  = mgs_destroy_export,
728         .o_iocontrol       = mgs_iocontrol,
729 };
730
731 static int __init mgs_init(void)
732 {
733         struct lprocfs_static_vars lvars;
734
735         lprocfs_mgs_init_vars(&lvars);
736         class_register_type(&mgs_obd_ops, NULL,
737                             lvars.module_vars, LUSTRE_MGS_NAME, NULL);
738
739         return 0;
740 }
741
742 static void /*__exit*/ mgs_exit(void)
743 {
744         class_unregister_type(LUSTRE_MGS_NAME);
745 }
746
747 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
748 MODULE_DESCRIPTION("Lustre  Management Server (MGS)");
749 MODULE_LICENSE("GPL");
750
751 module_init(mgs_init);
752 module_exit(mgs_exit);