Whamcloud - gitweb
update changelog section
[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(struct lustre_handle *conn, struct obd_device *obd,
66                        struct obd_uuid *cluuid, struct obd_connect_data *data,
67                        void *localdata)
68 {
69         struct obd_export *exp;
70         int rc;
71         ENTRY;
72
73         if (!conn || !obd || !cluuid)
74                 RETURN(-EINVAL);
75
76         rc = class_connect(conn, obd, cluuid);
77         if (rc)
78                 RETURN(rc);
79         exp = class_conn2export(conn);
80         LASSERT(exp);
81
82         mgs_counter_incr(exp, LPROC_MGS_CONNECT);
83
84         if (data != NULL) {
85                 data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED;
86                 exp->exp_connect_flags = data->ocd_connect_flags;
87                 data->ocd_version = LUSTRE_VERSION_CODE;
88         }
89
90         rc =  mgs_export_stats_init(obd, exp, 0, localdata);
91         if (rc) {
92                 class_disconnect(exp);
93                 lprocfs_exp_cleanup(exp);
94         } else {
95                 class_export_put(exp);
96         }
97
98         RETURN(rc);
99 }
100
101 static int mgs_reconnect(struct obd_export *exp, struct obd_device *obd,
102                          struct obd_uuid *cluuid, struct obd_connect_data *data,
103                          void *localdata)
104 {
105         ENTRY;
106
107         if (exp == NULL || obd == NULL || cluuid == NULL)
108                 RETURN(-EINVAL);
109
110         mgs_counter_incr(exp, LPROC_MGS_CONNECT);
111
112         if (data != NULL) {
113                 data->ocd_connect_flags &= MGS_CONNECT_SUPPORTED;
114                 exp->exp_connect_flags = data->ocd_connect_flags;
115                 data->ocd_version = LUSTRE_VERSION_CODE;
116         }
117
118         RETURN(mgs_export_stats_init(obd, exp, 1, localdata));
119 }
120
121 static int mgs_disconnect(struct obd_export *exp)
122 {
123         int rc;
124         ENTRY;
125
126         LASSERT(exp);
127
128         class_export_get(exp);
129         mgs_counter_incr(exp, LPROC_MGS_DISCONNECT);
130
131         rc = server_disconnect_export(exp);
132
133         class_export_put(exp);
134         RETURN(rc);
135 }
136
137 static int mgs_cleanup(struct obd_device *obd);
138 static int mgs_handle(struct ptlrpc_request *req);
139
140 /* Start the MGS obd */
141 static int mgs_setup(struct obd_device *obd, obd_count len, void *buf)
142 {
143         struct lprocfs_static_vars lvars;
144         struct mgs_obd *mgs = &obd->u.mgs;
145         struct lustre_mount_info *lmi;
146         struct lustre_sb_info *lsi;
147         struct llog_ctxt *ctxt;
148         struct vfsmount *mnt;
149         int rc = 0;
150         ENTRY;
151
152         CDEBUG(D_CONFIG, "Starting MGS\n");
153
154         /* Find our disk */
155         lmi = server_get_mount(obd->obd_name);
156         if (!lmi)
157                 RETURN(rc = -EINVAL);
158
159         mnt = lmi->lmi_mnt;
160         lsi = s2lsi(lmi->lmi_sb);
161         obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd));
162         if (IS_ERR(obd->obd_fsops))
163                 GOTO(err_put, rc = PTR_ERR(obd->obd_fsops));
164
165         if (lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb))) {
166                 CERROR("%s: Underlying device is marked as read-only. "
167                        "Setup failed\n", obd->obd_name);
168                 GOTO(err_ops, rc = -EROFS);
169         }
170
171         /* namespace for mgs llog */
172         obd->obd_namespace = ldlm_namespace_new(obd, "MGS", LDLM_NAMESPACE_SERVER,
173                                                 LDLM_NAMESPACE_MODEST);
174         if (obd->obd_namespace == NULL)
175                 GOTO(err_ops, rc = -ENOMEM);
176
177         /* ldlm setup */
178         ptlrpc_init_client(LDLM_CB_REQUEST_PORTAL, LDLM_CB_REPLY_PORTAL,
179                            "mgs_ldlm_client", &obd->obd_ldlm_client);
180
181         rc = mgs_fs_setup(obd, mnt);
182         if (rc) {
183                 CERROR("%s: MGS filesystem method init failed: rc = %d\n",
184                        obd->obd_name, rc);
185                 GOTO(err_ns, rc);
186         }
187
188         rc = llog_setup(obd, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
189                         &llog_lvfs_ops);
190         if (rc)
191                 GOTO(err_fs, rc);
192
193         /* No recovery for MGC's */
194         obd->obd_replayable = 0;
195
196         /* Internal mgs setup */
197         mgs_init_fsdb_list(obd);
198         sema_init(&mgs->mgs_sem, 1);
199
200         /* Setup proc */
201         lprocfs_mgs_init_vars(&lvars);
202         if (lprocfs_obd_setup(obd, lvars.obd_vars) == 0)
203                 lproc_mgs_setup(obd);
204
205         /* Start the service threads */
206         mgs->mgs_service =
207                 ptlrpc_init_svc(MGS_NBUFS, MGS_BUFSIZE, MGS_MAXREQSIZE,
208                                 MGS_MAXREPSIZE, MGS_REQUEST_PORTAL,
209                                 MGC_REPLY_PORTAL, 2,
210                                 mgs_handle, LUSTRE_MGS_NAME,
211                                 obd->obd_proc_entry, NULL,
212                                 MGS_THREADS_AUTO_MIN, MGS_THREADS_AUTO_MAX,
213                                 "ll_mgs", NULL);
214
215         if (!mgs->mgs_service) {
216                 CERROR("failed to start service\n");
217                 GOTO(err_llog, rc = -ENOMEM);
218         }
219
220         rc = ptlrpc_start_threads(obd, mgs->mgs_service);
221         if (rc)
222                 GOTO(err_thread, rc);
223
224         ping_evictor_start();
225
226         LCONSOLE_INFO("MGS %s started\n", obd->obd_name);
227
228         RETURN(0);
229
230 err_thread:
231         ptlrpc_unregister_service(mgs->mgs_service);
232 err_llog:
233         lproc_mgs_cleanup(obd);
234         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
235         if (ctxt)
236                 llog_cleanup(ctxt);
237 err_fs:
238         /* No extra cleanup needed for llog_init_commit_thread() */
239         mgs_fs_cleanup(obd);
240 err_ns:
241         ldlm_namespace_free(obd->obd_namespace, NULL, 0);
242         obd->obd_namespace = NULL;
243 err_ops:
244         fsfilt_put_ops(obd->obd_fsops);
245 err_put:
246         server_put_mount(obd->obd_name, mnt);
247         mgs->mgs_sb = 0;
248         return rc;
249 }
250
251 static int mgs_precleanup(struct obd_device *obd, enum obd_cleanup_stage stage)
252 {
253         int rc = 0;
254         ENTRY;
255
256         switch (stage) {
257         case OBD_CLEANUP_EARLY:
258         case OBD_CLEANUP_EXPORTS:
259                 break;
260         case OBD_CLEANUP_SELF_EXP:
261                 llog_cleanup(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT));
262                 rc = obd_llog_finish(obd, 0);
263                 break;
264         case OBD_CLEANUP_OBD:
265                 break;
266         }
267         RETURN(rc);
268 }
269
270 static int mgs_cleanup(struct obd_device *obd)
271 {
272         struct mgs_obd *mgs = &obd->u.mgs;
273         ENTRY;
274
275         if (mgs->mgs_sb == NULL)
276                 RETURN(0);
277
278         ping_evictor_stop();
279
280         ptlrpc_unregister_service(mgs->mgs_service);
281
282         mgs_cleanup_fsdb_list(obd);
283         lproc_mgs_cleanup(obd);
284         mgs_fs_cleanup(obd);
285
286         server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
287         mgs->mgs_sb = NULL;
288
289         ldlm_namespace_free(obd->obd_namespace, NULL, 1);
290         obd->obd_namespace = NULL;
291         fsfilt_put_ops(obd->obd_fsops);
292
293         LCONSOLE_INFO("%s has stopped.\n", obd->obd_name);
294         RETURN(0);
295 }
296
297 /* similar to filter_prepare_destroy */
298 static int mgs_get_cfg_lock(struct obd_device *obd, char *fsname,
299                             struct lustre_handle *lockh)
300 {
301         struct ldlm_res_id res_id;
302         int rc, flags = 0;
303         ENTRY;
304
305         rc = mgc_fsname2resid(fsname, &res_id);
306         if (!rc)
307                 rc = ldlm_cli_enqueue_local(obd->obd_namespace, &res_id,
308                                             LDLM_PLAIN, NULL, LCK_EX,
309                                             &flags, ldlm_blocking_ast,
310                                             ldlm_completion_ast, NULL,
311                                             fsname, 0, NULL, lockh);
312         if (rc)
313                 CERROR("can't take cfg lock for %s (%d)\n", fsname, rc);
314
315         RETURN(rc);
316 }
317
318 static int mgs_put_cfg_lock(struct lustre_handle *lockh)
319 {
320         ENTRY;
321         ldlm_lock_decref(lockh, LCK_EX);
322         RETURN(0);
323 }
324
325 static void mgs_revoke_lock(struct obd_device *obd, char *fsname,
326                             struct lustre_handle *lockh)
327 {
328         int lockrc;
329
330         if (fsname[0]) {
331                 lockrc = mgs_get_cfg_lock(obd, fsname, lockh);
332                 if (lockrc != ELDLM_OK)
333                         CERROR("lock error %d for fs %s\n", lockrc,
334                                fsname);
335                 else
336                         mgs_put_cfg_lock(lockh);
337         }
338 }
339
340 /* rc=0 means ok
341       1 means update
342      <0 means error */
343 static int mgs_check_target(struct obd_device *obd, struct mgs_target_info *mti)
344 {
345         int rc;
346         ENTRY;
347
348         rc = mgs_check_index(obd, mti);
349         if (rc == 0) {
350                 LCONSOLE_ERROR_MSG(0x13b, "%s claims to have registered, but "
351                                   "this MGS does not know about it, preventing "
352                                   "registration.\n", mti->mti_svname);
353                 rc = -ENOENT;
354         } else if (rc == -1) {
355                 LCONSOLE_ERROR_MSG(0x13c, "Client log %s-client has "
356                                    "disappeared! Regenerating all logs.\n",
357                                    mti->mti_fsname);
358                 mti->mti_flags |= LDD_F_WRITECONF;
359                 rc = 1;
360         } else {
361                 /* Index is correctly marked as used */
362
363                 /* If the logs don't contain the mti_nids then add
364                    them as failover nids */
365                 rc = mgs_check_failnid(obd, mti);
366         }
367
368         RETURN(rc);
369 }
370
371 /* Called whenever a target starts up.  Flags indicate first connect, etc. */
372 static int mgs_handle_target_reg(struct ptlrpc_request *req)
373 {
374         struct obd_device *obd = req->rq_export->exp_obd;
375         struct lustre_handle lockh;
376         struct mgs_target_info *mti, *rep_mti;
377         int rep_size[] = { sizeof(struct ptlrpc_body), sizeof(*mti) };
378         int rc = 0, lockrc;
379         ENTRY;
380
381         mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_REG);
382
383         mti = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*mti),
384                                  lustre_swab_mgs_target_info);
385         LASSERT(mti);
386
387         if (!(mti->mti_flags & (LDD_F_WRITECONF | LDD_F_UPGRADE14 |
388                                 LDD_F_UPDATE))) {
389                 /* We're just here as a startup ping. */
390                 CDEBUG(D_MGS, "Server %s is running on %s\n",
391                        mti->mti_svname, obd_export_nid2str(req->rq_export));
392                 rc = mgs_check_target(obd, mti);
393                 /* above will set appropriate mti flags */
394                 if (rc <= 0)
395                         /* Nothing wrong, or fatal error */
396                         GOTO(out_nolock, rc);
397         }
398
399         /* Revoke the config lock to make sure nobody is reading. */
400         /* Although actually I think it should be alright if
401            someone was reading while we were updating the logs - if we
402            revoke at the end they will just update from where they left off. */
403         lockrc = mgs_get_cfg_lock(obd, mti->mti_fsname, &lockh);
404         if (lockrc != ELDLM_OK) {
405                 LCONSOLE_ERROR_MSG(0x13d, "%s: Can't signal other nodes to "
406                                    "update their configuration (%d). Updating "
407                                    "local logs anyhow; you might have to "
408                                    "manually restart other nodes to get the "
409                                    "latest configuration.\n",
410                                    obd->obd_name, lockrc);
411         }
412
413         OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_PAUSE_TARGET_REG, 10);
414
415         /* Log writing contention is handled by the fsdb_sem */
416
417         if (mti->mti_flags & LDD_F_WRITECONF) {
418                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
419                         rc = mgs_erase_logs(obd, mti->mti_fsname);
420                         LCONSOLE_WARN("%s: Logs for fs %s were removed by user "
421                                       "request.  All servers must be restarted "
422                                       "in order to regenerate the logs."
423                                       "\n", obd->obd_name, mti->mti_fsname);
424                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
425                         rc = mgs_erase_log(obd, mti->mti_svname);
426                         LCONSOLE_WARN("%s: Regenerating %s log by user "
427                                       "request.\n",
428                                       obd->obd_name, mti->mti_svname);
429                 }
430                 mti->mti_flags |= LDD_F_UPDATE;
431                 /* Erased logs means start from scratch. */
432                 mti->mti_flags &= ~LDD_F_UPGRADE14;
433         }
434
435         /* COMPAT_146 */
436         if (mti->mti_flags & LDD_F_UPGRADE14) {
437                 rc = mgs_upgrade_sv_14(obd, mti);
438                 if (rc) {
439                         CERROR("Can't upgrade from 1.4 (%d)\n", rc);
440                         GOTO(out, rc);
441                 }
442
443                 /* We're good to go */
444                 mti->mti_flags |= LDD_F_UPDATE;
445         }
446         /* end COMPAT_146 */
447
448         if (mti->mti_flags & LDD_F_UPDATE) {
449                 CDEBUG(D_MGS, "updating %s, index=%d\n", mti->mti_svname,
450                        mti->mti_stripe_index);
451
452                 /* create or update the target log
453                    and update the client/mdt logs */
454                 rc = mgs_write_log_target(obd, mti);
455                 if (rc) {
456                         CERROR("Failed to write %s log (%d)\n",
457                                mti->mti_svname, rc);
458                         GOTO(out, rc);
459                 }
460
461                 mti->mti_flags &= ~(LDD_F_VIRGIN | LDD_F_UPDATE |
462                                     LDD_F_NEED_INDEX | LDD_F_WRITECONF |
463                                     LDD_F_UPGRADE14);
464                 mti->mti_flags |= LDD_F_REWRITE_LDD;
465         }
466
467 out:
468         /* done with log update */
469         if (lockrc == ELDLM_OK)
470                 mgs_put_cfg_lock(&lockh);
471 out_nolock:
472         CDEBUG(D_MGS, "replying with %s, index=%d, rc=%d\n", mti->mti_svname,
473                mti->mti_stripe_index, rc);
474         lustre_pack_reply(req, 2, rep_size, NULL);
475         /* send back the whole mti in the reply */
476         rep_mti = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
477                                  sizeof(*rep_mti));
478         memcpy(rep_mti, mti, sizeof(*rep_mti));
479
480         /* Flush logs to disk */
481         fsfilt_sync(obd, obd->u.mgs.mgs_sb);
482         RETURN(rc);
483 }
484
485 static int mgs_set_info_rpc(struct ptlrpc_request *req)
486 {
487         struct obd_device *obd = req->rq_export->exp_obd;
488         struct mgs_send_param *msp, *rep_msp;
489         struct lustre_handle lockh;
490         int rep_size[] = { sizeof(struct ptlrpc_body), sizeof(*msp) };
491         int rc;
492         struct lustre_cfg_bufs bufs;
493         struct lustre_cfg *lcfg;
494         char fsname[MTI_NAME_MAXLEN];
495         ENTRY;
496
497         msp = lustre_swab_reqbuf(req, REQ_REC_OFF, sizeof(*msp), NULL);
498
499         /* Construct lustre_cfg structure to pass to function mgs_setparam */
500         lustre_cfg_bufs_reset(&bufs, NULL);
501         lustre_cfg_bufs_set_string(&bufs, 1, msp->mgs_param);
502         lcfg = lustre_cfg_new(LCFG_PARAM, &bufs);
503         rc = mgs_setparam(obd, lcfg, fsname);
504         if (rc) {
505                 CERROR("Error %d in setting the parameter %s for fs %s\n",
506                        rc, msp->mgs_param, fsname);
507                 RETURN(rc);
508         }
509
510         /* request for update */
511         mgs_revoke_lock(obd, fsname, &lockh);
512
513         lustre_cfg_free(lcfg);
514
515         lustre_pack_reply(req, 2, rep_size, NULL);
516         rep_msp = lustre_msg_buf(req->rq_repmsg, REPLY_REC_OFF,
517                                  sizeof(*rep_msp));
518         memcpy(rep_msp, msp, sizeof(*rep_msp));
519
520         RETURN(rc);
521 }
522
523 /* Called whenever a target cleans up. */
524 /* XXX - Currently unused */
525 static int mgs_handle_target_del(struct ptlrpc_request *req)
526 {
527         ENTRY;
528         mgs_counter_incr(req->rq_export, LPROC_MGS_TARGET_DEL);
529         RETURN(0);
530 }
531
532 /* XXX - Currently unused */
533 static int mgs_handle_exception(struct ptlrpc_request *req)
534 {
535         ENTRY;
536         mgs_counter_incr(req->rq_export, LPROC_MGS_EXCEPTION);
537         RETURN(0);
538 }
539
540 int mgs_handle(struct ptlrpc_request *req)
541 {
542         int fail = OBD_FAIL_MGS_ALL_REPLY_NET;
543         int opc, rc = 0;
544         ENTRY;
545
546         OBD_FAIL_TIMEOUT_MS(OBD_FAIL_MGS_PAUSE_REQ, obd_fail_val);
547         OBD_FAIL_RETURN(OBD_FAIL_MGS_ALL_REQUEST_NET, 0);
548
549         LASSERT(current->journal_info == NULL);
550         opc = lustre_msg_get_opc(req->rq_reqmsg);
551         if (opc != MGS_CONNECT) {
552                 if (!class_connected_export(req->rq_export)) {
553                         CERROR("lustre_mgs: operation %d on unconnected MGS\n",
554                                opc);
555                         req->rq_status = -ENOTCONN;
556                         GOTO(out, rc = -ENOTCONN);
557                 }
558         }
559
560         switch (opc) {
561         case MGS_CONNECT:
562                 DEBUG_REQ(D_MGS, req, "connect");
563                 rc = target_handle_connect(req, mgs_handle);
564                 if (!rc && (lustre_msg_get_conn_cnt(req->rq_reqmsg) > 1))
565                         /* Make clients trying to reconnect after a MGS restart
566                            happy; also requires obd_replayable */
567                         lustre_msg_add_op_flags(req->rq_repmsg,
568                                                 MSG_CONNECT_RECONNECT);
569                 break;
570         case MGS_DISCONNECT:
571                 DEBUG_REQ(D_MGS, req, "disconnect");
572                 rc = target_handle_disconnect(req);
573                 req->rq_status = rc;            /* superfluous? */
574                 break;
575         case MGS_EXCEPTION:
576                 DEBUG_REQ(D_MGS, req, "exception");
577                 rc = mgs_handle_exception(req);
578                 break;
579         case MGS_TARGET_REG:
580                 DEBUG_REQ(D_MGS, req, "target add");
581                 rc = mgs_handle_target_reg(req);
582                 break;
583         case MGS_TARGET_DEL:
584                 DEBUG_REQ(D_MGS, req, "target del");
585                 rc = mgs_handle_target_del(req);
586                 break;
587         case MGS_SET_INFO:
588                 rc = mgs_set_info_rpc(req);
589                 break;
590
591         case LDLM_ENQUEUE:
592                 DEBUG_REQ(D_MGS, req, "enqueue");
593                 rc = ldlm_handle_enqueue(req, ldlm_server_completion_ast,
594                                          ldlm_server_blocking_ast, NULL);
595                 break;
596         case LDLM_BL_CALLBACK:
597         case LDLM_CP_CALLBACK:
598                 DEBUG_REQ(D_MGS, req, "callback");
599                 CERROR("callbacks should not happen on MGS\n");
600                 LBUG();
601                 break;
602
603         case OBD_PING:
604                 DEBUG_REQ(D_INFO, req, "ping");
605                 rc = target_handle_ping(req);
606                 break;
607         case OBD_LOG_CANCEL:
608                 DEBUG_REQ(D_MGS, req, "log cancel");
609                 rc = -ENOTSUPP; /* la la la */
610                 break;
611
612         case LLOG_ORIGIN_HANDLE_CREATE:
613                 DEBUG_REQ(D_MGS, req, "llog_init");
614                 rc = llog_origin_handle_create(req);
615                 break;
616         case LLOG_ORIGIN_HANDLE_NEXT_BLOCK:
617                 DEBUG_REQ(D_MGS, req, "llog next block");
618                 rc = llog_origin_handle_next_block(req);
619                 break;
620         case LLOG_ORIGIN_HANDLE_READ_HEADER:
621                 DEBUG_REQ(D_MGS, req, "llog read header");
622                 rc = llog_origin_handle_read_header(req);
623                 break;
624         case LLOG_ORIGIN_HANDLE_CLOSE:
625                 DEBUG_REQ(D_MGS, req, "llog close");
626                 rc = llog_origin_handle_close(req);
627                 break;
628         case LLOG_CATINFO:
629                 DEBUG_REQ(D_MGS, req, "llog catinfo");
630                 rc = llog_catinfo(req);
631                 break;
632         default:
633                 req->rq_status = -ENOTSUPP;
634                 rc = ptlrpc_error(req);
635                 RETURN(rc);
636         }
637
638         LASSERT(current->journal_info == NULL);
639
640         if (rc)
641                 CERROR("MGS handle cmd=%d rc=%d\n", opc, rc);
642
643  out:
644         target_send_reply(req, rc, fail);
645         RETURN(0);
646 }
647
648 static inline int mgs_init_export(struct obd_export *exp)
649 {
650         spin_lock(&exp->exp_lock);
651         exp->exp_connecting = 1;
652         spin_unlock(&exp->exp_lock);
653
654         return ldlm_init_export(exp);
655 }
656
657 static inline int mgs_destroy_export(struct obd_export *exp)
658 {
659         ENTRY;
660
661         target_destroy_export(exp);
662         ldlm_destroy_export(exp);
663         mgs_client_free(exp);
664
665         RETURN(0);
666 }
667
668 static int mgs_extract_fs_pool(char * arg, char *fsname, char *poolname)
669 {
670         char *ptr;
671
672         ENTRY;
673         for (ptr = arg;  (*ptr != '\0') && (*ptr != '.'); ptr++ ) {
674                 *fsname = *ptr;
675                 fsname++;
676         }
677         if (*ptr == '\0')
678                 return -EINVAL;
679         *fsname = '\0';
680         ptr++;
681         strcpy(poolname, ptr);
682
683         RETURN(0);
684 }
685
686 static int mgs_iocontrol_pool(struct obd_device *obd,
687                               struct obd_ioctl_data *data)
688 {
689         int rc;
690         struct lustre_handle lockh;
691         struct lustre_cfg *lcfg = NULL;
692         struct llog_rec_hdr rec;
693         char *fsname = NULL;
694         char *poolname = NULL;
695         ENTRY;
696
697         OBD_ALLOC(fsname, MTI_NAME_MAXLEN);
698         if (fsname == NULL)
699                 RETURN(-ENOMEM);
700
701         OBD_ALLOC(poolname, LOV_MAXPOOLNAME + 1);
702         if (poolname == NULL) {
703                 rc = -ENOMEM;
704                 GOTO(out_pool, rc);
705         }
706         rec.lrh_len = llog_data_len(data->ioc_plen1);
707
708         if (data->ioc_type == LUSTRE_CFG_TYPE) {
709                 rec.lrh_type = OBD_CFG_REC;
710         } else {
711                 CERROR("unknown cfg record type:%d \n", data->ioc_type);
712                 rc = -EINVAL;
713                 GOTO(out_pool, rc);
714         }
715
716         if (data->ioc_plen1 > CFS_PAGE_SIZE) {
717                 rc = -E2BIG;
718                 GOTO(out_pool, rc);
719         }
720
721         OBD_ALLOC(lcfg, data->ioc_plen1);
722         if (lcfg == NULL) {
723                 rc = -ENOMEM;
724                 GOTO(out_pool, rc);
725         }
726         rc = copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1);
727         if (rc)
728                 GOTO(out_pool, rc);
729
730         if (lcfg->lcfg_bufcount < 2) {
731                 rc = -EINVAL;
732                 GOTO(out_pool, rc);
733         }
734
735         /* first arg is always <fsname>.<poolname> */
736         mgs_extract_fs_pool(lustre_cfg_string(lcfg, 1), fsname,
737                             poolname);
738
739         switch (lcfg->lcfg_command) {
740         case LCFG_POOL_NEW: {
741                 if (lcfg->lcfg_bufcount != 2)
742                         RETURN(-EINVAL);
743                 rc = mgs_pool_cmd(obd, LCFG_POOL_NEW, fsname,
744                                   poolname, NULL);
745                 break;
746         }
747         case LCFG_POOL_ADD: {
748                 if (lcfg->lcfg_bufcount != 3)
749                         RETURN(-EINVAL);
750                 rc = mgs_pool_cmd(obd, LCFG_POOL_ADD, fsname, poolname,
751                                   lustre_cfg_string(lcfg, 2));
752                 break;
753         }
754         case LCFG_POOL_REM: {
755                 if (lcfg->lcfg_bufcount != 3)
756                         RETURN(-EINVAL);
757                 rc = mgs_pool_cmd(obd, LCFG_POOL_REM, fsname, poolname,
758                                   lustre_cfg_string(lcfg, 2));
759                 break;
760         }
761         case LCFG_POOL_DEL: {
762                 if (lcfg->lcfg_bufcount != 2)
763                         RETURN(-EINVAL);
764                 rc = mgs_pool_cmd(obd, LCFG_POOL_DEL, fsname,
765                                   poolname, NULL);
766                 break;
767         }
768         default: {
769                  rc = -EINVAL;
770                  GOTO(out_pool, rc);
771         }
772         }
773
774         if (rc) {
775                 CERROR("OBD_IOC_POOL err %d, cmd %X for pool %s.%s\n",
776                        rc, lcfg->lcfg_command, fsname, poolname);
777                 GOTO(out_pool, rc);
778         }
779
780         /* request for update */
781         mgs_revoke_lock(obd, fsname, &lockh);
782
783 out_pool:
784         if (lcfg != NULL)
785                 OBD_FREE(lcfg, data->ioc_plen1);
786
787         if (fsname != NULL)
788                 OBD_FREE(fsname, MTI_NAME_MAXLEN);
789
790         if (poolname != NULL)
791                 OBD_FREE(poolname, LOV_MAXPOOLNAME + 1);
792
793         RETURN(rc);
794 }
795
796 /* from mdt_iocontrol */
797 int mgs_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
798                   void *karg, void *uarg)
799 {
800         struct obd_device *obd = exp->exp_obd;
801         struct obd_ioctl_data *data = karg;
802         struct lvfs_run_ctxt saved;
803         int rc = 0;
804
805         ENTRY;
806         CDEBUG(D_IOCTL, "handling ioctl cmd %#x\n", cmd);
807
808         switch (cmd) {
809
810         case OBD_IOC_PARAM: {
811                 struct lustre_handle lockh;
812                 struct lustre_cfg *lcfg;
813                 struct llog_rec_hdr rec;
814                 char fsname[MTI_NAME_MAXLEN];
815
816                 rec.lrh_len = llog_data_len(data->ioc_plen1);
817
818                 if (data->ioc_type == LUSTRE_CFG_TYPE) {
819                         rec.lrh_type = OBD_CFG_REC;
820                 } else {
821                         CERROR("unknown cfg record type:%d \n", data->ioc_type);
822                         RETURN(-EINVAL);
823                 }
824
825                 OBD_ALLOC(lcfg, data->ioc_plen1);
826                 if (lcfg == NULL)
827                         RETURN(-ENOMEM);
828                 rc = copy_from_user(lcfg, data->ioc_pbuf1, data->ioc_plen1);
829                 if (rc)
830                         GOTO(out_free, rc);
831
832                 if (lcfg->lcfg_bufcount < 1)
833                         GOTO(out_free, rc = -EINVAL);
834
835                 rc = mgs_setparam(obd, lcfg, fsname);
836                 if (rc) {
837                         CERROR("setparam err %d\n", rc);
838                         GOTO(out_free, rc);
839                 }
840
841                 /* Revoke lock so everyone updates.  Should be alright if
842                    someone was already reading while we were updating the logs,
843                    so we don't really need to hold the lock while we're
844                    writing (above). */
845                 mgs_revoke_lock(obd, fsname, &lockh);
846
847 out_free:
848                 OBD_FREE(lcfg, data->ioc_plen1);
849                 RETURN(rc);
850         }
851
852         case OBD_IOC_POOL: {
853                 RETURN(mgs_iocontrol_pool(obd, data));
854         }
855
856         case OBD_IOC_DUMP_LOG: {
857                 struct llog_ctxt *ctxt =
858                         llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
859                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
860                 rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL);
861                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
862                 llog_ctxt_put(ctxt);
863                 if (rc)
864                         RETURN(rc);
865
866                 RETURN(rc);
867         }
868
869         case OBD_IOC_LLOG_CHECK:
870         case OBD_IOC_LLOG_INFO:
871         case OBD_IOC_LLOG_PRINT: {
872                 struct llog_ctxt *ctxt =
873                         llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
874
875                 push_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
876                 rc = llog_ioctl(ctxt, cmd, data);
877                 pop_ctxt(&saved, &ctxt->loc_exp->exp_obd->obd_lvfs_ctxt, NULL);
878                 llog_ctxt_put(ctxt);
879
880                 RETURN(rc);
881         }
882
883         default:
884                 CDEBUG(D_INFO, "unknown command %x\n", cmd);
885                 RETURN(-EINVAL);
886         }
887         RETURN(0);
888 }
889
890 /* use obd ops to offer management infrastructure */
891 static struct obd_ops mgs_obd_ops = {
892         .o_owner           = THIS_MODULE,
893         .o_connect         = mgs_connect,
894         .o_reconnect       = mgs_reconnect,
895         .o_disconnect      = mgs_disconnect,
896         .o_setup           = mgs_setup,
897         .o_precleanup      = mgs_precleanup,
898         .o_cleanup         = mgs_cleanup,
899         .o_init_export     = mgs_init_export,
900         .o_destroy_export  = mgs_destroy_export,
901         .o_iocontrol       = mgs_iocontrol,
902 };
903
904 static int __init mgs_init(void)
905 {
906         struct lprocfs_static_vars lvars;
907
908         lprocfs_mgs_init_vars(&lvars);
909         class_register_type(&mgs_obd_ops, lvars.module_vars, LUSTRE_MGS_NAME);
910
911         return 0;
912 }
913
914 static void /*__exit*/ mgs_exit(void)
915 {
916         class_unregister_type(LUSTRE_MGS_NAME);
917 }
918
919 MODULE_AUTHOR("Sun Microsystems, Inc. <http://www.lustre.org/>");
920 MODULE_DESCRIPTION("Lustre  Management Server (MGS)");
921 MODULE_LICENSE("GPL");
922
923 module_init(mgs_init);
924 module_exit(mgs_exit);