Whamcloud - gitweb
3a1a6e66fba09b69fbc1060855c54a7d2064d369
[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 ((exp->exp_connect_flags & OBD_CONNECT_FID) == 0) {
77                 CWARN("MGS requires FID support, but client not\n");
78                 rc = -EBADE;
79         }
80
81         if (rc) {
82                 class_disconnect(exp);
83         } else {
84                 class_export_put(exp);
85         }
86
87         RETURN(rc);
88 }
89
90 static int mgs_disconnect(struct obd_export *exp)
91 {
92         int rc;
93         ENTRY;
94
95         LASSERT(exp);
96         class_export_get(exp);
97
98         /* Disconnect early so that clients can't keep using export */
99         rc = class_disconnect(exp);
100         ldlm_cancel_locks_for_export(exp);
101
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;
109
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);
114         }
115         spin_unlock(&exp->exp_lock);
116
117         class_export_put(exp);
118         RETURN(rc);
119 }
120
121 static int mgs_cleanup(struct obd_device *obd);
122 static int mgs_handle(struct ptlrpc_request *req);
123
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)
127 {
128         struct obd_llog_group *olg = &obd->obd_olg;
129         int rc;
130         ENTRY;
131
132         LASSERT(group == OBD_LLOG_GROUP);
133         LASSERT(olg->olg_group == group);
134
135         rc = llog_setup(obd, olg, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
136                         &llog_lvfs_ops);
137         RETURN(rc);
138 }
139
140 static int mgs_llog_finish(struct obd_device *obd, int count)
141 {
142         struct llog_ctxt *ctxt;
143         int rc = 0;
144         ENTRY;
145
146         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
147         if (ctxt)
148                 rc = llog_cleanup(ctxt);
149
150         RETURN(rc);
151 }
152
153 /* Start the MGS obd */
154 static int mgs_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
155 {
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;
161         int rc = 0;
162         ENTRY;
163
164         CDEBUG(D_CONFIG, "Starting MGS\n");
165
166         /* Find our disk */
167         lmi = server_get_mount(obd->obd_name);
168         if (!lmi)
169                 RETURN(rc = -EINVAL);
170
171         mnt = lmi->lmi_mnt;
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));
176
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);
182
183         /* ldlm setup */
184         ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
185                            "mgs_ldlm_client", &obd->obd_ldlm_client);
186
187         LASSERT(!lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb)));
188
189         rc = mgs_fs_setup(obd, mnt);
190         if (rc) {
191                 CERROR("%s: MGS filesystem method init failed: rc = %d\n",
192                        obd->obd_name, rc);
193                 GOTO(err_ns, rc);
194         }
195
196         rc = obd_llog_init(obd, OBD_LLOG_GROUP, obd, 0, NULL, NULL);
197         if (rc)
198                 GOTO(err_fs, rc);
199
200         /* No recovery for MGC's */
201         obd->obd_replayable = 0;
202
203         /* Internal mgs setup */
204         mgs_init_fsdb_list(obd);
205         sema_init(&mgs->mgs_sem, 1);
206
207         /* Start the service threads */
208         mgs->mgs_service =
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);
216
217         if (!mgs->mgs_service) {
218                 CERROR("failed to start service\n");
219                 GOTO(err_llog, rc = -ENOMEM);
220         }
221
222         rc = ptlrpc_start_threads(obd, mgs->mgs_service);
223         if (rc)
224                 GOTO(err_thread, rc);
225
226         /* Setup proc */
227         lprocfs_mgs_init_vars(&lvars);
228         if (lprocfs_obd_setup(obd, lvars.obd_vars) == 0) {
229                 lproc_mgs_setup(obd);
230         }
231
232         ping_evictor_start();
233
234         LCONSOLE_INFO("MGS %s started\n", obd->obd_name);
235
236         RETURN(0);
237
238 err_thread:
239         ptlrpc_unregister_service(mgs->mgs_service);
240 err_llog:
241         obd_llog_finish(obd, 0);
242 err_fs:
243         /* No extra cleanup needed for llog_init_commit_thread() */
244         mgs_fs_cleanup(obd);
245 err_ns:
246         ldlm_namespace_free(obd->obd_namespace, 0);
247         obd->obd_namespace = NULL;
248 err_ops:
249         fsfilt_put_ops(obd->obd_fsops);
250 err_put:
251         server_put_mount(obd->obd_name, mnt);
252         mgs->mgs_sb = 0;
253         return rc;
254 }
255
256 static int mgs_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
257 {
258         int rc = 0;
259         ENTRY;
260
261         switch (stage) {
262         case OBD_CLEANUP_EARLY:
263         case OBD_CLEANUP_EXPORTS:
264                 break;
265         case OBD_CLEANUP_SELF_EXP:
266                 rc = obd_llog_finish(obd, 0);
267                 break;
268         case OBD_CLEANUP_OBD:
269                 break;
270         }
271         RETURN(rc);
272 }
273
274 static int mgs_ldlm_nsfree(void *data)
275 {
276         struct ldlm_namespace *ns = (struct ldlm_namespace *)data;
277         int rc;
278         ENTRY;
279
280         ptlrpc_daemonize("ll_mgs_nsfree");
281         rc = ldlm_namespace_free(ns, 1 /* obd_force should always be on */);
282         RETURN(rc);
283 }
284
285 static int mgs_cleanup(struct obd_device *obd)
286 {
287         struct mgs_obd *mgs = &obd->u.mgs;
288         ENTRY;
289
290         if (mgs->mgs_sb == NULL)
291                 RETURN(0);
292
293         ping_evictor_stop();
294
295         ptlrpc_unregister_service(mgs->mgs_service);
296
297         mgs_cleanup_fsdb_list(obd);
298
299         lprocfs_obd_cleanup(obd);
300         mgs->mgs_proc_live = NULL;
301
302         mgs_fs_cleanup(obd);
303
304         server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
305         mgs->mgs_sb = NULL;
306
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
309            deadlock here. */
310         cfs_kernel_thread(mgs_ldlm_nsfree, obd->obd_namespace,
311                           CLONE_VM | CLONE_FILES);
312
313
314         fsfilt_put_ops(obd->obd_fsops);
315
316         LCONSOLE_INFO("%s has stopped.\n", obd->obd_name);
317         RETURN(0);
318 }
319
320 /* similar to filter_prepare_destroy */
321 static int mgs_get_cfg_lock(struct obd_device *obd, char *fsname,
322                             struct lustre_handle *lockh)
323 {
324         struct ldlm_res_id res_id;
325         int rc, flags = 0;
326         ENTRY;
327
328         rc = mgc_fsname2resid(fsname, &res_id);
329         if (!rc)
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);
335         if (rc)
336                 CERROR("can't take cfg lock for %s (%d)\n", fsname, rc);
337
338         RETURN(rc);
339 }
340
341 static int mgs_put_cfg_lock(struct lustre_handle *lockh)
342 {
343         ENTRY;
344         ldlm_lock_decref(lockh, LCK_EX);
345         RETURN(0);
346 }
347
348 /* rc=0 means ok
349       1 means update
350      <0 means error */
351 static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti)
352 {
353         int rc;
354         ENTRY;
355
356         rc = mgs_check_index(obd, mti);
357         if (rc == 0) {
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;
362                 rc = 1;
363         } else if (rc == -1) {
364                 LCONSOLE_ERROR_MSG(0x13c, "Client log %s-client has "
365                                    "disappeared! Regenerating all logs.\n",
366                                    mti->mti_fsname);
367                 mti->mti_flags |= LDD_F_WRITECONF;
368                 rc = 1;
369         } else {
370                 /* Index is correctly marked as used */
371
372                 /* If the logs don't contain the mti_nids then add
373                    them as failover nids */
374                 rc = mgs_check_failnid(obd, mti);
375         }
376
377         RETURN(rc);
378 }
379
380 /* Called whenever a target starts up.  Flags indicate first connect, etc. */
381 static int mgs_handle_target_reg(struct ptlrpc_request *req)
382 {
383         struct obd_device *obd = req->rq_export->exp_obd;
384         struct lustre_handle lockh;
385         struct mgs_target_info *mti, *rep_mti;
386         int rc = 0, lockrc;
387         ENTRY;
388
389         mti = req_capsule_client_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
390         if (!(mti->mti_flags & (LDD_F_WRITECONF | LDD_F_UPGRADE14 |
391                                 LDD_F_UPDATE))) {
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 */
397                 if (rc <= 0)
398                         /* Nothing wrong, or fatal error */
399                         GOTO(out_nolock, rc);
400         }
401
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);
414         }
415
416         OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_SLOW_TARGET_REG, 10);
417
418         /* Log writing contention is handled by the fsdb_sem */
419
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 "
432                                       "request.\n",
433                                       obd->obd_name, mti->mti_svname);
434                 }
435                 mti->mti_flags |= LDD_F_UPDATE;
436                 /* Erased logs means start from scratch. */
437                 mti->mti_flags &= ~LDD_F_UPGRADE14; 
438         }
439
440         /* COMPAT_146 */
441         if (mti->mti_flags & LDD_F_UPGRADE14) {
442                 rc = mgs_upgrade_sv_14(obd, mti);
443                 if (rc) {
444                         CERROR("Can't upgrade from 1.4 (%d)\n", rc);
445                         GOTO(out, rc);
446                 }
447                 
448                 /* We're good to go */
449                 mti->mti_flags |= LDD_F_UPDATE;
450         }
451         /* end COMPAT_146 */
452
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);
456
457                 /* create or update the target log
458                    and update the client/mdt logs */
459                 rc = mgs_write_log_target(obd, mti);
460                 if (rc) {
461                         CERROR("Failed to write %s log (%d)\n",
462                                mti->mti_svname, rc);
463                         GOTO(out, rc);
464                 }
465
466                 mti->mti_flags &= ~(LDD_F_VIRGIN | LDD_F_UPDATE |
467                                     LDD_F_NEED_INDEX | LDD_F_WRITECONF |
468                                     LDD_F_UPGRADE14);
469                 mti->mti_flags |= LDD_F_REWRITE_LDD;
470         }
471
472 out:
473         /* done with log update */
474         if (lockrc == ELDLM_OK)
475                 mgs_put_cfg_lock(&lockh);
476 out_nolock:
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);
480         if (rc)
481                 RETURN(rc);
482
483         /* send back the whole mti in the reply */
484         rep_mti = req_capsule_server_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
485         *rep_mti = *mti;
486
487         /* Flush logs to disk */
488         fsfilt_sync(obd, obd->u.mgs.mgs_sb);
489         RETURN(rc);
490 }
491
492 static int mgs_set_info_rpc(struct ptlrpc_request *req)
493 {
494         struct obd_device *obd = req->rq_export->exp_obd;
495         struct mgs_send_param *msp, *rep_msp;
496         struct lustre_handle lockh;
497         int lockrc, rc;
498         struct lustre_cfg_bufs bufs;
499         struct lustre_cfg *lcfg;
500         char fsname[MTI_NAME_MAXLEN];
501         ENTRY;
502
503         msp = req_capsule_client_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
504         LASSERT(msp);
505
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);
511         if (rc) {
512                 CERROR("Error %d in setting the parameter %s for fs %s\n",
513                        rc, msp->mgs_param, fsname);
514                 RETURN(rc);
515         }
516
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
520          * writing.
521          */
522         if (fsname[0]) {
523                 lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
524                 if (lockrc != ELDLM_OK)
525                         CERROR("lock error %d for fs %s\n", lockrc,
526                                fsname);
527                 else
528                         mgs_put_cfg_lock(&lockh);
529         }
530         lustre_cfg_free(lcfg);
531
532         rc = req_capsule_server_pack(&req->rq_pill);
533         if (rc == 0) {
534                 rep_msp = req_capsule_server_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
535                 rep_msp = msp;
536         }
537         RETURN(rc);
538 }
539
540 /* TODO: handle requests in a similar way as MDT: see mdt_handle_common() */
541 int mgs_handle(struct ptlrpc_request *req)
542 {
543         int fail = OBD_FAIL_MGS_ALL_REPLY_NET;
544         int opc, rc = 0;
545         ENTRY;
546
547         req_capsule_init(&req->rq_pill, req, RCL_SERVER);
548         OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_SLOW_REQUEST_NET, 2);
549
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",
555                                opc);
556                         req->rq_status = -ENOTCONN;
557                         GOTO(out, rc = -ENOTCONN);
558                 }
559         }
560
561         switch (opc) {
562         case MGS_CONNECT:
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);
572                 break;
573         case MGS_DISCONNECT:
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? */
579                 break;
580         case MGS_TARGET_REG:
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);
584                 break;
585         case MGS_TARGET_DEL:
586                 DEBUG_REQ(D_MGS, req, "target del");
587                 //rc = mgs_handle_target_del(req);
588                 break;
589         case MGS_SET_INFO:
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);
593                 break;
594
595         case LDLM_ENQUEUE:
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);
600                 break;
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");
605                 LBUG();
606                 break;
607
608         case OBD_PING:
609                 DEBUG_REQ(D_INFO, req, "ping");
610                 req_capsule_set(&req->rq_pill, &RQF_OBD_PING);
611                 rc = target_handle_ping(req);
612                 break;
613         case OBD_LOG_CANCEL:
614                 DEBUG_REQ(D_MGS, req, "log cancel");
615                 rc = -ENOTSUPP; /* la la la */
616                 break;
617
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);
622                 break;
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);
628                 break;
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);
634                 break;
635         case LLOG_ORIGIN_HANDLE_CLOSE:
636                 DEBUG_REQ(D_MGS, req, "llog close");
637                 rc = llog_origin_handle_close(req);
638                 break;
639         case LLOG_CATINFO:
640                 DEBUG_REQ(D_MGS, req, "llog catinfo");
641                 req_capsule_set(&req->rq_pill, &RQF_LLOG_CATINFO);
642                 rc = llog_catinfo(req);
643                 break;
644         default:
645                 req->rq_status = -ENOTSUPP;
646                 rc = ptlrpc_error(req);
647                 RETURN(rc);
648         }
649
650         LASSERT(current->journal_info == NULL);
651
652         if (rc)
653                 CERROR("MGS handle cmd=%d rc=%d\n", opc, rc);
654
655 out:
656         target_send_reply(req, rc, fail);
657         RETURN(0);
658 }
659
660 static inline int mgs_destroy_export(struct obd_export *exp)
661 {
662         ENTRY;
663
664         target_destroy_export(exp);
665
666         RETURN(0);
667 }
668
669 /* from mdt_iocontrol */
670 int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
671                   void *karg, void *uarg)
672 {
673         struct obd_device *obd = exp->exp_obd;
674         struct obd_ioctl_data *data = karg;
675         struct lvfs_run_ctxt saved;
676         int rc = 0;
677
678         ENTRY;
679         CDEBUG(D_IOCTL, "handling ioctl cmd %#x\n", cmd);
680
681         switch (cmd) {
682
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];
688                 int lockrc;
689
690                 rec.lrh_len = llog_data_len(data->ioc_plen1);
691
692                 if (data->ioc_type == LUSTRE_CFG_TYPE) {
693                         rec.lrh_type = OBD_CFG_REC;
694                 } else {
695                         CERROR("unknown cfg record type:%d \n", data->ioc_type);
696                         RETURN(-EINVAL);
697                 }
698
699                 OBD_ALLOC(lcfg, data->ioc_plen1);
700                 if (lcfg == NULL)
701                         RETURN(-ENOMEM);
702                 rc = copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1);
703                 if (rc)
704                         GOTO(out_free, rc);
705
706                 if (lcfg->lcfg_bufcount < 1)
707                         GOTO(out_free, rc = -EINVAL);
708
709                 rc = mgs_setparam(obd, lcfg, fsname);
710                 if (rc) {
711                         CERROR("setparam err %d\n", rc);
712                         GOTO(out_free, rc);
713                 }
714
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
718                    writing (above). */
719                 if (fsname[0]) {
720                         lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
721                         if (lockrc != ELDLM_OK)
722                                 CERROR("lock error %d for fs %s\n", lockrc,
723                                        fsname);
724                         else
725                                 mgs_put_cfg_lock(&lockh);
726                 }
727
728 out_free:
729                 OBD_FREE(lcfg, data->ioc_plen1);
730                 RETURN(rc);
731         }
732
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);
739                 llog_ctxt_put(ctxt);
740
741                 RETURN(rc);
742         }
743
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);
749
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);
753                 llog_ctxt_put(ctxt);
754
755                 RETURN(rc);
756         }
757
758         default:
759                 CDEBUG(D_INFO, "unknown command %x\n", cmd);
760                 RETURN(-EINVAL);
761         }
762         RETURN(0);
763 }
764
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
777 };
778
779 static int __init mgs_init(void)
780 {
781         struct lprocfs_static_vars lvars;
782
783         lprocfs_mgs_init_vars(&lvars);
784         class_register_type(&mgs_obd_ops, NULL,
785                             lvars.module_vars, LUSTRE_MGS_NAME, NULL);
786
787         return 0;
788 }
789
790 static void /*__exit*/ mgs_exit(void)
791 {
792         class_unregister_type(LUSTRE_MGS_NAME);
793 }
794
795 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
796 MODULE_DESCRIPTION("Lustre  Management Server (MGS)");
797 MODULE_LICENSE("GPL");
798
799 module_init(mgs_init);
800 module_exit(mgs_exit);