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