Whamcloud - gitweb
32085725980737faa5ba7c8ac7af6f6e1d9d853f
[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  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
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.
11  *
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).
17  *
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
21  *
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
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/mgs/mgs_handler.c
37  *
38  * Author: Nathan Rutman <nathan@clusterfs.com>
39  */
40
41 #ifndef EXPORT_SYMTAB
42 # define EXPORT_SYMTAB
43 #endif
44 #define DEBUG_SUBSYSTEM S_MGS
45 #define D_MGS D_CONFIG/*|D_WARNING*/
46
47 #ifdef __KERNEL__
48 # include <linux/module.h>
49 # include <linux/pagemap.h>
50 # include <linux/miscdevice.h>
51 # include <linux/init.h>
52 #else
53 # include <liblustre.h>
54 #endif
55
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"
62
63
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,
68                        void *localdata)
69 {
70         struct obd_export *exp;
71         int rc;
72         ENTRY;
73
74         if (!conn || !obd || !cluuid)
75                 RETURN(-EINVAL);
76
77         rc = class_connect(conn, obd, cluuid);
78         if (rc)
79                 RETURN(rc);
80         exp = class_conn2export(conn);
81         LASSERT(exp);
82
83         exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_NULL;
84
85         mgs_counter_incr(exp, LPROC_MGS_CONNECT);
86
87         if (data != NULL) {
88                 data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED;
89                 exp->exp_connect_flags = data->ocd_connect_flags;
90                 data->ocd_version = LUSTRE_VERSION_CODE;
91         }
92
93         if (rc) {
94                 class_disconnect(exp);
95         } else {
96                 class_export_put(exp);
97         }
98
99         RETURN(rc);
100 }
101
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)
105 {
106         ENTRY;
107
108         if (exp == NULL || obd == NULL || cluuid == NULL)
109                 RETURN(-EINVAL);
110
111         if (data != 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;
115         }
116
117         RETURN(0);
118 }
119
120 static int mgs_disconnect(struct obd_export *exp)
121 {
122         int rc;
123         ENTRY;
124
125         LASSERT(exp);
126
127         class_export_get(exp);
128         mgs_counter_incr(exp, LPROC_MGS_DISCONNECT);
129
130         /* Disconnect early so that clients can't keep using export */
131         rc = class_disconnect(exp);
132         ldlm_cancel_locks_for_export(exp);
133
134         lprocfs_exp_cleanup(exp);
135
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;
143
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);
148         }
149         spin_unlock(&exp->exp_lock);
150
151         class_export_put(exp);
152         RETURN(rc);
153 }
154
155 static int mgs_cleanup(struct obd_device *obd);
156 static int mgs_handle(struct ptlrpc_request *req);
157
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)
161 {
162         int rc;
163         ENTRY;
164
165         LASSERT(olg == &obd->obd_olg);
166         rc = llog_setup(obd, olg, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
167                         &llog_lvfs_ops);
168         RETURN(rc);
169 }
170
171 static int mgs_llog_finish(struct obd_device *obd, int count)
172 {
173         struct llog_ctxt *ctxt;
174         int rc = 0;
175         ENTRY;
176
177         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
178         if (ctxt)
179                 rc = llog_cleanup(ctxt);
180
181         RETURN(rc);
182 }
183
184 /* Start the MGS obd */
185 static int mgs_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
186 {
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;
192         int rc = 0;
193         ENTRY;
194
195         CDEBUG(D_CONFIG, "Starting MGS\n");
196
197         /* Find our disk */
198         lmi = server_get_mount(obd->obd_name);
199         if (!lmi)
200                 RETURN(rc = -EINVAL);
201
202         mnt = lmi->lmi_mnt;
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));
207
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);
213
214         /* ldlm setup */
215         ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
216                            "mgs_ldlm_client", &obd->obd_ldlm_client);
217
218         LASSERT(!lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb)));
219
220         rc = mgs_fs_setup(obd, mnt);
221         if (rc) {
222                 CERROR("%s: MGS filesystem method init failed: rc = %d\n",
223                        obd->obd_name, rc);
224                 GOTO(err_ns, rc);
225         }
226
227         rc = obd_llog_init(obd, &obd->obd_olg, obd, 0, NULL, NULL);
228         if (rc)
229                 GOTO(err_fs, rc);
230
231         /* No recovery for MGC's */
232         obd->obd_replayable = 0;
233
234         /* Internal mgs setup */
235         mgs_init_fsdb_list(obd);
236         sema_init(&mgs->mgs_sem, 1);
237
238         /* Start the service threads */
239         mgs->mgs_service =
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);
247
248         if (!mgs->mgs_service) {
249                 CERROR("failed to start service\n");
250                 GOTO(err_llog, rc = -ENOMEM);
251         }
252
253         rc = ptlrpc_start_threads(obd, mgs->mgs_service);
254         if (rc)
255                 GOTO(err_thread, rc);
256
257         /* Setup proc */
258         lprocfs_mgs_init_vars(&lvars);
259         if (lprocfs_obd_setup(obd, lvars.obd_vars) == 0) {
260                 lproc_mgs_setup(obd);
261         }
262
263         ping_evictor_start();
264
265         LCONSOLE_INFO("MGS %s started\n", obd->obd_name);
266
267         RETURN(0);
268
269 err_thread:
270         ptlrpc_unregister_service(mgs->mgs_service);
271 err_llog:
272         obd_llog_finish(obd, 0);
273 err_fs:
274         /* No extra cleanup needed for llog_init_commit_thread() */
275         mgs_fs_cleanup(obd);
276 err_ns:
277         ldlm_namespace_free(obd->obd_namespace, NULL, 0);
278         obd->obd_namespace = NULL;
279 err_ops:
280         fsfilt_put_ops(obd->obd_fsops);
281 err_put:
282         server_put_mount(obd->obd_name, mnt);
283         mgs->mgs_sb = 0;
284         return rc;
285 }
286
287 static int mgs_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
288 {
289         int rc = 0;
290         ENTRY;
291
292         switch (stage) {
293         case OBD_CLEANUP_EARLY:
294         case OBD_CLEANUP_EXPORTS:
295                 rc = obd_llog_finish(obd, 0);
296                 break;
297         }
298         RETURN(rc);
299 }
300
301 /**
302  * Performs cleanup procedures for passed \a obd given it is mgs obd.
303  */
304 static int mgs_cleanup(struct obd_device *obd)
305 {
306         struct mgs_obd *mgs = &obd->u.mgs;
307         ENTRY;
308
309         if (mgs->mgs_sb == NULL)
310                 RETURN(0);
311
312         ping_evictor_stop();
313
314         ptlrpc_unregister_service(mgs->mgs_service);
315
316         mgs_cleanup_fsdb_list(obd);
317         lproc_mgs_cleanup(obd);
318         mgs_fs_cleanup(obd);
319
320         server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
321         mgs->mgs_sb = NULL;
322
323         ldlm_namespace_free(obd->obd_namespace, NULL, 1);
324         obd->obd_namespace = NULL;
325
326         fsfilt_put_ops(obd->obd_fsops);
327
328         LCONSOLE_INFO("%s has stopped.\n", obd->obd_name);
329         RETURN(0);
330 }
331
332 /* similar to filter_prepare_destroy */
333 static int mgs_get_cfg_lock(struct obd_device *obd, char *fsname,
334                             struct lustre_handle *lockh)
335 {
336         struct ldlm_res_id res_id;
337         int rc, flags = 0;
338         ENTRY;
339
340         rc = mgc_fsname2resid(fsname, &res_id);
341         if (!rc)
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);
347         if (rc)
348                 CERROR("can't take cfg lock for %s (%d)\n", fsname, rc);
349
350         RETURN(rc);
351 }
352
353 static int mgs_put_cfg_lock(struct lustre_handle *lockh)
354 {
355         ENTRY;
356         ldlm_lock_decref(lockh, LCK_EX);
357         RETURN(0);
358 }
359
360 /* rc=0 means ok
361       1 means update
362      <0 means error */
363 static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti)
364 {
365         int rc;
366         ENTRY;
367
368         rc = mgs_check_index(obd, mti);
369         if (rc == 0) {
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;
374                 rc = 1;
375         } else if (rc == -1) {
376                 LCONSOLE_ERROR_MSG(0x13c, "Client log %s-client has "
377                                    "disappeared! Regenerating all logs.\n",
378                                    mti->mti_fsname);
379                 mti->mti_flags |= LDD_F_WRITECONF;
380                 rc = 1;
381         } else {
382                 /* Index is correctly marked as used */
383
384                 /* If the logs don't contain the mti_nids then add
385                    them as failover nids */
386                 rc = mgs_check_failnid(obd, mti);
387         }
388
389         RETURN(rc);
390 }
391
392 /* Called whenever a target starts up.  Flags indicate first connect, etc. */
393 static int mgs_handle_target_reg(struct ptlrpc_request *req)
394 {
395         struct obd_device *obd = req->rq_export->exp_obd;
396         struct lustre_handle lockh;
397         struct mgs_target_info *mti, *rep_mti;
398         int rc = 0, lockrc;
399         ENTRY;
400
401         mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_REG);
402
403         mti = req_capsule_client_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
404         if (!(mti->mti_flags & (LDD_F_WRITECONF | LDD_F_UPGRADE14 |
405                                 LDD_F_UPDATE))) {
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 */
411                 if (rc <= 0)
412                         /* Nothing wrong, or fatal error */
413                         GOTO(out_nolock, rc);
414         }
415
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);
428         }
429
430         OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_PAUSE_TARGET_REG, 10);
431
432         /* Log writing contention is handled by the fsdb_sem */
433
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 "
446                                       "request.\n",
447                                       obd->obd_name, mti->mti_svname);
448                 }
449                 mti->mti_flags |= LDD_F_UPDATE;
450                 /* Erased logs means start from scratch. */
451                 mti->mti_flags &= ~LDD_F_UPGRADE14; 
452         }
453
454         /* COMPAT_146 */
455         if (mti->mti_flags & LDD_F_UPGRADE14) {
456                 rc = mgs_upgrade_sv_14(obd, mti);
457                 if (rc) {
458                         CERROR("Can't upgrade from 1.4 (%d)\n", rc);
459                         GOTO(out, rc);
460                 }
461                 
462                 /* We're good to go */
463                 mti->mti_flags |= LDD_F_UPDATE;
464         }
465         /* end COMPAT_146 */
466
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);
470
471                 /* create or update the target log
472                    and update the client/mdt logs */
473                 rc = mgs_write_log_target(obd, mti);
474                 if (rc) {
475                         CERROR("Failed to write %s log (%d)\n",
476                                mti->mti_svname, rc);
477                         GOTO(out, rc);
478                 }
479
480                 mti->mti_flags &= ~(LDD_F_VIRGIN | LDD_F_UPDATE |
481                                     LDD_F_NEED_INDEX | LDD_F_WRITECONF |
482                                     LDD_F_UPGRADE14);
483                 mti->mti_flags |= LDD_F_REWRITE_LDD;
484         }
485
486 out:
487         /* done with log update */
488         if (lockrc == ELDLM_OK)
489                 mgs_put_cfg_lock(&lockh);
490 out_nolock:
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);
494         if (rc)
495                 RETURN(rc);
496
497         /* send back the whole mti in the reply */
498         rep_mti = req_capsule_server_get(&req->rq_pill, &RMF_MGS_TARGET_INFO);
499         *rep_mti = *mti;
500
501         /* Flush logs to disk */
502         fsfilt_sync(obd, obd->u.mgs.mgs_sb);
503         RETURN(rc);
504 }
505
506 static int mgs_set_info_rpc(struct ptlrpc_request *req)
507 {
508         struct obd_device *obd = req->rq_export->exp_obd;
509         struct mgs_send_param *msp, *rep_msp;
510         struct lustre_handle lockh;
511         int lockrc, rc;
512         struct lustre_cfg_bufs bufs;
513         struct lustre_cfg *lcfg;
514         char fsname[MTI_NAME_MAXLEN];
515         ENTRY;
516
517         msp = req_capsule_client_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
518         LASSERT(msp);
519
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);
525         if (rc) {
526                 CERROR("Error %d in setting the parameter %s for fs %s\n",
527                        rc, msp->mgs_param, fsname);
528                 RETURN(rc);
529         }
530
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
534          * writing.
535          */
536         if (fsname[0]) {
537                 lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
538                 if (lockrc != ELDLM_OK)
539                         CERROR("lock error %d for fs %s\n", lockrc,
540                                fsname);
541                 else
542                         mgs_put_cfg_lock(&lockh);
543         }
544         lustre_cfg_free(lcfg);
545
546         rc = req_capsule_server_pack(&req->rq_pill);
547         if (rc == 0) {
548                 rep_msp = req_capsule_server_get(&req->rq_pill, &RMF_MGS_SEND_PARAM);
549                 rep_msp = msp;
550         }
551         RETURN(rc);
552 }
553
554 /* Called whenever a target cleans up. */
555 /* XXX - Currently unused */
556 static int mgs_handle_target_del(struct ptlrpc_request *req)
557 {
558         ENTRY;
559         mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_DEL);
560         RETURN(0);
561 }
562
563 /* XXX - Currently unused */
564 static int mgs_handle_exception(struct ptlrpc_request *req)
565 {
566         ENTRY;
567         mgs_counter_incr(req->rq_export, LPROC_MGS_EXCEPTION);
568         RETURN(0);
569 }
570
571 /* TODO: handle requests in a similar way as MDT: see mdt_handle_common() */
572 int mgs_handle(struct ptlrpc_request *req)
573 {
574         int fail = OBD_FAIL_MGS_ALL_REPLY_NET;
575         int opc, rc = 0;
576         ENTRY;
577
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))
581                 RETURN(0);
582
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",
588                                opc);
589                         req->rq_status = -ENOTCONN;
590                         GOTO(out, rc = -ENOTCONN);
591                 }
592         }
593
594         switch (opc) {
595         case MGS_CONNECT:
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);
605                 break;
606         case MGS_DISCONNECT:
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? */
612                 break;
613         case MGS_EXCEPTION:
614                 DEBUG_REQ(D_MGS, req, "exception");
615                 rc = mgs_handle_exception(req);
616                 break;
617         case MGS_TARGET_REG:
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);
621                 break;
622         case MGS_TARGET_DEL:
623                 DEBUG_REQ(D_MGS, req, "target del");
624                 rc = mgs_handle_target_del(req);
625                 break;
626         case MGS_SET_INFO:
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);
630                 break;
631
632         case LDLM_ENQUEUE:
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);
637                 break;
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");
642                 LBUG();
643                 break;
644
645         case OBD_PING:
646                 DEBUG_REQ(D_INFO, req, "ping");
647                 req_capsule_set(&req->rq_pill, &RQF_OBD_PING);
648                 rc = target_handle_ping(req);
649                 break;
650         case OBD_LOG_CANCEL:
651                 DEBUG_REQ(D_MGS, req, "log cancel");
652                 rc = -ENOTSUPP; /* la la la */
653                 break;
654
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);
659                 break;
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);
665                 break;
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);
671                 break;
672         case LLOG_ORIGIN_HANDLE_CLOSE:
673                 DEBUG_REQ(D_MGS, req, "llog close");
674                 rc = llog_origin_handle_close(req);
675                 break;
676         case LLOG_CATINFO:
677                 DEBUG_REQ(D_MGS, req, "llog catinfo");
678                 req_capsule_set(&req->rq_pill, &RQF_LLOG_CATINFO);
679                 rc = llog_catinfo(req);
680                 break;
681         default:
682                 req->rq_status = -ENOTSUPP;
683                 rc = ptlrpc_error(req);
684                 RETURN(rc);
685         }
686
687         LASSERT(current->journal_info == NULL);
688
689         if (rc)
690                 CERROR("MGS handle cmd=%d rc=%d\n", opc, rc);
691
692 out:
693         target_send_reply(req, rc, fail);
694         RETURN(0);
695 }
696
697 static inline int mgs_init_export(struct obd_export *exp)
698 {
699         return ldlm_init_export(exp);
700 }
701
702 static inline int mgs_destroy_export(struct obd_export *exp)
703 {
704         ENTRY;
705
706         target_destroy_export(exp);
707         ldlm_destroy_export(exp);
708
709         RETURN(0);
710 }
711
712 /* from mdt_iocontrol */
713 int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
714                   void *karg, void *uarg)
715 {
716         struct obd_device *obd = exp->exp_obd;
717         struct obd_ioctl_data *data = karg;
718         struct lvfs_run_ctxt saved;
719         int rc = 0;
720
721         ENTRY;
722         CDEBUG(D_IOCTL, "handling ioctl cmd %#x\n", cmd);
723
724         switch (cmd) {
725
726         case OBD_IOC_PARAM: {
727                 struct lustre_handle lockh;
728                 struct lustre_cfg *lcfg;
729                 struct llog_rec_hdr rec;
730                 char fsname[MTI_NAME_MAXLEN];
731                 int lockrc;
732
733                 rec.lrh_len = llog_data_len(data->ioc_plen1);
734
735                 if (data->ioc_type == LUSTRE_CFG_TYPE) {
736                         rec.lrh_type = OBD_CFG_REC;
737                 } else {
738                         CERROR("unknown cfg record type:%d \n", data->ioc_type);
739                         RETURN(-EINVAL);
740                 }
741
742                 OBD_ALLOC(lcfg, data->ioc_plen1);
743                 if (lcfg == NULL)
744                         RETURN(-ENOMEM);
745                 rc = copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1);
746                 if (rc)
747                         GOTO(out_free, rc);
748
749                 if (lcfg->lcfg_bufcount < 1)
750                         GOTO(out_free, rc = -EINVAL);
751
752                 rc = mgs_setparam(obd, lcfg, fsname);
753                 if (rc) {
754                         CERROR("setparam err %d\n", rc);
755                         GOTO(out_free, rc);
756                 }
757
758                 /* Revoke lock so everyone updates.  Should be alright if
759                    someone was already reading while we were updating the logs,
760                    so we don't really need to hold the lock while we're
761                    writing (above). */
762                 if (fsname[0]) {
763                         lockrc = mgs_get_cfg_lock(obd, fsname, &lockh);
764                         if (lockrc != ELDLM_OK)
765                                 CERROR("lock error %d for fs %s\n", lockrc,
766                                        fsname);
767                         else
768                                 mgs_put_cfg_lock(&lockh);
769                 }
770
771 out_free:
772                 OBD_FREE(lcfg, data->ioc_plen1);
773                 RETURN(rc);
774         }
775
776         case OBD_IOC_DUMP_LOG: {
777                 struct llog_ctxt *ctxt;
778                 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
779                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
780                 rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL);
781                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
782                 llog_ctxt_put(ctxt);
783
784                 RETURN(rc);
785         }
786
787         case OBD_IOC_LLOG_CHECK:
788         case OBD_IOC_LLOG_INFO:
789         case OBD_IOC_LLOG_PRINT: {
790                 struct llog_ctxt *ctxt;
791                 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
792
793                 push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
794                 rc = llog_ioctl(ctxt, cmd, data);
795                 pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
796                 llog_ctxt_put(ctxt);
797
798                 RETURN(rc);
799         }
800
801         default:
802                 CDEBUG(D_INFO, "unknown command %x\n", cmd);
803                 RETURN(-EINVAL);
804         }
805         RETURN(0);
806 }
807
808 /* use obd ops to offer management infrastructure */
809 static struct obd_ops mgs_obd_ops = {
810         .o_owner           = THIS_MODULE,
811         .o_connect         = mgs_connect,
812         .o_reconnect       = mgs_reconnect,
813         .o_disconnect      = mgs_disconnect,
814         .o_setup           = mgs_setup,
815         .o_precleanup      = mgs_precleanup,
816         .o_cleanup         = mgs_cleanup,
817         .o_init_export     = mgs_init_export,
818         .o_destroy_export  = mgs_destroy_export,
819         .o_iocontrol       = mgs_iocontrol,
820         .o_llog_init       = mgs_llog_init,
821         .o_llog_finish     = mgs_llog_finish
822 };
823
824 static int __init mgs_init(void)
825 {
826         struct lprocfs_static_vars lvars;
827
828         lprocfs_mgs_init_vars(&lvars);
829         class_register_type(&mgs_obd_ops, NULL,
830                             lvars.module_vars, LUSTRE_MGS_NAME, NULL);
831
832         return 0;
833 }
834
835 static void /*__exit*/ mgs_exit(void)
836 {
837         class_unregister_type(LUSTRE_MGS_NAME);
838 }
839
840 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
841 MODULE_DESCRIPTION("Lustre  Management Server (MGS)");
842 MODULE_LICENSE("GPL");
843
844 module_init(mgs_init);
845 module_exit(mgs_exit);