Whamcloud - gitweb
Branch b1_4_mountconf
[fs/lustre-release.git] / lustre / mgs / mgs_handler.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lustre/mgs/mgs_handler.c
5  *  Lustre Management Server (mgs) request handler
6  *
7  *  Copyright (C) 2001-2005 Cluster File Systems, Inc.
8  *   Author Nathan <nathan@clusterfs.com>
9  *   Author LinSongTao <lincent@clusterfs.com>
10  *
11  *   This file is part of Lustre, http://www.lustre.org.
12  *
13  *   Lustre is free software; you can redistribute it and/or
14  *   modify it under the terms of version 2 of the GNU General Public
15  *   License as published by the Free Software Foundation.
16  *
17  *   Lustre is distributed in the hope that it will be useful,
18  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *   GNU General Public License for more details.
21  *
22  *   You should have received a copy of the GNU General Public License
23  *   along with Lustre; if not, write to the Free Software
24  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  */
26
27 #ifndef EXPORT_SYMTAB
28 # define EXPORT_SYMTAB
29 #endif
30 #define DEBUG_SUBSYSTEM S_MGS
31 #define D_MGS D_INFO|D_ERROR
32
33 #ifdef __KERNEL__
34 # include <linux/module.h>
35 # include <linux/pagemap.h>
36 # include <linux/miscdevice.h>
37 # include <linux/init.h>
38 #else
39 # include <liblustre.h>
40 #endif
41
42 #include <linux/obd_class.h>
43 #include <linux/lustre_dlm.h>
44 #include <linux/lprocfs_status.h>
45 #include <linux/lustre_fsfilt.h>
46 #include <linux/lustre_commit_confd.h>
47 #include <linux/lustre_disk.h>
48 #include "mgs_internal.h"
49
50 static int mgs_cleanup(struct obd_device *obd);
51
52 /* Establish a connection to the MGS.*/
53 static int mgs_connect(struct lustre_handle *conn, struct obd_device *obd,
54                        struct obd_uuid *cluuid, struct obd_connect_data *data)
55 {
56         struct obd_export *exp;
57         int rc;
58         ENTRY;
59
60         if (!conn || !obd || !cluuid)
61                 RETURN(-EINVAL);
62
63         rc = class_connect(conn, obd, cluuid);
64         if (rc)
65                 RETURN(rc);
66         exp = class_conn2export(conn);
67         LASSERT(exp);
68
69         if (data != NULL) {
70                 data->ocd_connect_flags &= MGMT_CONNECT_SUPPORTED;
71                 exp->exp_connect_flags = data->ocd_connect_flags;
72         }
73
74         if (rc) {
75                 class_disconnect(exp);
76         } else {
77                 class_export_put(exp);
78         }
79
80         RETURN(rc);
81 }
82
83 static int mgs_disconnect(struct obd_export *exp)
84 {
85         unsigned long irqflags;
86         int rc;
87         ENTRY;
88
89         LASSERT(exp);
90         class_export_get(exp);
91
92         /* Disconnect early so that clients can't keep using export */
93         rc = class_disconnect(exp);
94         ldlm_cancel_locks_for_export(exp);
95
96         /* complete all outstanding replies */
97         spin_lock_irqsave(&exp->exp_lock, irqflags);
98         while (!list_empty(&exp->exp_outstanding_replies)) {
99                 struct ptlrpc_reply_state *rs =
100                         list_entry(exp->exp_outstanding_replies.next,
101                                    struct ptlrpc_reply_state, rs_exp_list);
102                 struct ptlrpc_service *svc = rs->rs_service;
103
104                 spin_lock(&svc->srv_lock);
105                 list_del_init(&rs->rs_exp_list);
106                 ptlrpc_schedule_difficult_reply(rs);
107                 spin_unlock(&svc->srv_lock);
108         }
109         spin_unlock_irqrestore(&exp->exp_lock, irqflags);
110
111         class_export_put(exp);
112         RETURN(rc);
113 }
114
115 /* Start the MGS obd */
116 static int mgs_setup(struct obd_device *obd, obd_count len, void *buf)
117 {
118         struct lprocfs_static_vars lvars;
119         char *ns_name = "MGS";
120         struct mgs_obd *mgs = &obd->u.mgs;
121         struct lustre_mount_info *lmi;
122         struct lustre_sb_info *lsi;
123         struct vfsmount *mnt;
124         int rc = 0;
125         ENTRY;
126
127         CDEBUG(D_CONFIG, "Starting MGS\n");
128
129         lmi = server_get_mount(obd->obd_name);
130         if (!lmi) 
131                 RETURN(rc = -EINVAL);
132
133         mnt = lmi->lmi_mnt;
134         lsi = s2lsi(lmi->lmi_sb);
135         obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd));
136         if (IS_ERR(obd->obd_fsops))
137                 GOTO(err_put, rc = PTR_ERR(obd->obd_fsops));
138
139         /* namespace for mgs llog */
140         obd->obd_namespace = ldlm_namespace_new(ns_name, LDLM_NAMESPACE_SERVER);
141         if (obd->obd_namespace == NULL) {
142                 mgs_cleanup(obd);
143                 GOTO(err_ops, rc = -ENOMEM);
144         }
145
146         LASSERT(!lvfs_check_rdonly(lvfs_sbdev(mnt->mnt_sb)));
147
148         rc = mgs_fs_setup(obd, mnt);
149         if (rc) {
150                 CERROR("%s: MGS filesystem method init failed: rc = %d\n",
151                        obd->obd_name, rc);
152                 GOTO(err_ns, rc);
153         }
154
155         rc = llog_start_commit_thread();
156         if (rc < 0)
157                 GOTO(err_fs, rc);
158
159         rc = llog_setup(obd, LLOG_CONFIG_ORIG_CTXT, obd, 0, NULL,
160                         &llog_lvfs_ops);
161         if (rc)
162                 GOTO(err_fs, rc);
163
164         mgs_init_db_list(obd);
165
166         lprocfs_init_vars(mgs, &lvars);
167         lprocfs_obd_setup(obd, lvars.obd_vars);
168
169         LCONSOLE_INFO("MGS %s started\n", obd->obd_name);
170
171         ldlm_timeout = 6;
172         ping_evictor_start();
173
174         RETURN(0);
175
176 err_fs:
177         /* No extra cleanup needed for llog_init_commit_thread() */
178         mgs_fs_cleanup(obd);
179 err_ns:
180         ldlm_namespace_free(obd->obd_namespace, 0);
181         obd->obd_namespace = NULL;
182 err_ops:
183         fsfilt_put_ops(obd->obd_fsops);
184 err_put:
185         server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
186         mgs->mgs_sb = 0;
187         return rc;
188 }
189
190 static int mgs_precleanup(struct obd_device *obd, int stage)
191 {
192         int rc = 0;
193         ENTRY;
194
195         CDEBUG(D_MGS, "precleanup %d\n", stage);
196
197         switch (stage) {
198         case OBD_CLEANUP_SELF_EXP:
199                 mgs_cleanup_db_list(obd);
200                 llog_cleanup(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT));
201                 rc = obd_llog_finish(obd, 0);
202         }
203         RETURN(rc);
204 }
205
206 static int mgs_cleanup(struct obd_device *obd)
207 {
208         struct mgs_obd *mgs = &obd->u.mgs;
209         lvfs_sbdev_type save_dev;
210         ENTRY;
211
212         ping_evictor_stop();
213
214         if (mgs->mgs_sb == NULL)
215                 RETURN(0);
216         save_dev = lvfs_sbdev(mgs->mgs_sb);
217
218 //       lprocfs_obd_cleanup(obd);
219
220  //       mgs_update_server_data(obd, 1);
221
222         mgs_fs_cleanup(obd);
223
224         server_put_mount(obd->obd_name, mgs->mgs_vfsmnt);
225         mgs->mgs_sb = NULL;
226
227         ldlm_namespace_free(obd->obd_namespace, obd->obd_force);
228
229         spin_lock_bh(&obd->obd_processing_task_lock);
230         if (obd->obd_recovering) {
231                 target_cancel_recovery_timer(obd);
232                 obd->obd_recovering = 0;
233         }
234         spin_unlock_bh(&obd->obd_processing_task_lock);
235
236         lvfs_clear_rdonly(save_dev);
237
238         fsfilt_put_ops(obd->obd_fsops);
239
240         LCONSOLE_INFO("MGS %s has stopped.\n", obd->obd_name);
241
242         RETURN(0);
243 }
244
245 static int mgs_handle_target_add(struct ptlrpc_request *req)
246 {    
247         struct obd_device *obd = req->rq_export->exp_obd;
248         struct mgmt_target_info *req_mti, *mti, *rep_mti;
249         int rep_size = sizeof(*mti);
250         int rc;
251         ENTRY;
252
253         OBD_ALLOC(mti, sizeof(*mti));
254         if (!mti)
255                 GOTO(out, rc = -ENOMEM);
256         req_mti = lustre_swab_reqbuf(req, 0, sizeof(*mti),
257                                      lustre_swab_mgmt_target_info);
258         memcpy(mti, req_mti, sizeof(*mti));
259         
260         CDEBUG(D_MGS, "adding %s, index=%d\n", mti->mti_svname, 
261                mti->mti_stripe_index);
262
263         /* set the new target index if needed */
264         if (mti->mti_flags & LDD_F_NEED_INDEX) {
265                 rc = mgs_set_next_index(obd, mti);
266                 if (rc) {
267                         CERROR("Can't get index (%d)\n", rc);
268                         GOTO(out, rc);
269                 }
270         }
271
272         /* create the log for the new target 
273            and update the client/mdt logs */
274         rc = mgs_write_log_target(obd, mti);
275         if (rc) {
276                 CERROR("Failed to write %s log (%d)\n", 
277                        mti->mti_svname, rc);
278                 GOTO(out, rc);
279         }
280
281 out:
282         lustre_pack_reply(req, 1, &rep_size, NULL); 
283         /* send back the whole mti in the reply */
284         rep_mti = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*rep_mti));
285         memcpy(rep_mti, mti, sizeof(*rep_mti));
286         rep_mti->mti_rc = rc;
287         RETURN(rc);
288 }
289
290 int mgs_handle(struct ptlrpc_request *req)
291 {
292         int fail = OBD_FAIL_MGMT_ALL_REPLY_NET;
293         int rc = 0;
294         ENTRY;
295         
296         CDEBUG(D_MGS, "MGS handle\n");
297
298         OBD_FAIL_RETURN(OBD_FAIL_MGMT_ALL_REQUEST_NET | OBD_FAIL_ONCE, 0);
299
300         LASSERT(current->journal_info == NULL);
301         if (req->rq_reqmsg->opc != MGMT_CONNECT) {
302                 if (req->rq_export == NULL) {
303                         CERROR("lustre_mgs: operation %d on unconnected MGS\n",
304                                req->rq_reqmsg->opc);
305                         req->rq_status = -ENOTCONN;
306                         GOTO(out, rc = -ENOTCONN);
307                 }
308         }
309
310         switch (req->rq_reqmsg->opc) {
311         case MGMT_CONNECT:
312                 DEBUG_REQ(D_MGS, req, "connect");
313                 OBD_FAIL_RETURN(OBD_FAIL_MGMT_CONNECT_NET, 0);
314                 rc = target_handle_connect(req, mgs_handle);
315                 break;
316         case MGMT_DISCONNECT:
317                 DEBUG_REQ(D_MGS, req, "disconnect");
318                 OBD_FAIL_RETURN(OBD_FAIL_MGMT_DISCONNECT_NET, 0);
319                 rc = target_handle_disconnect(req);
320                 req->rq_status = rc;            /* superfluous? */
321                 break;
322
323         case MGMT_TARGET_ADD:
324                 CDEBUG(D_MGS, "target add\n");
325                 rc = mgs_handle_target_add(req);
326                 break;
327         case MGMT_TARGET_DEL:
328                 CDEBUG(D_MGS, "target del\n");
329                 //rc = mgs_handle_target_del(req);
330                 break;
331
332         case LDLM_ENQUEUE:
333                 DEBUG_REQ(D_MGS, req, "enqueue");
334                 OBD_FAIL_RETURN(OBD_FAIL_LDLM_ENQUEUE, 0);
335                 rc = ldlm_handle_enqueue(req, ldlm_server_completion_ast,
336                                          ldlm_server_blocking_ast, NULL);
337                 fail = OBD_FAIL_LDLM_REPLY;
338                 break;
339         case LDLM_BL_CALLBACK:
340         case LDLM_CP_CALLBACK:
341                 DEBUG_REQ(D_MGS, req, "callback");
342                 CERROR("callbacks should not happen on MDS\n");
343                 LBUG();
344                 OBD_FAIL_RETURN(OBD_FAIL_LDLM_BL_CALLBACK, 0);
345                 break;
346
347         case OBD_PING:
348                 DEBUG_REQ(D_MGS, req, "ping");
349                 rc = target_handle_ping(req);
350                 break;
351
352         case OBD_LOG_CANCEL:
353                 CDEBUG(D_MGS, "log cancel\n");
354                 OBD_FAIL_RETURN(OBD_FAIL_OBD_LOG_CANCEL_NET, 0);
355                 rc = -ENOTSUPP; /* la la la */
356                 break;
357
358         case LLOG_ORIGIN_HANDLE_CREATE:
359                 DEBUG_REQ(D_MGS, req, "llog_init");
360                 OBD_FAIL_RETURN(OBD_FAIL_OBD_LOGD_NET, 0);
361                 rc = llog_origin_handle_create(req);
362                 break;
363         case LLOG_ORIGIN_HANDLE_NEXT_BLOCK:
364                 DEBUG_REQ(D_MGS, req, "llog next block");
365                 OBD_FAIL_RETURN(OBD_FAIL_OBD_LOGD_NET, 0);
366                 rc = llog_origin_handle_next_block(req);
367                 break;
368         case LLOG_ORIGIN_HANDLE_READ_HEADER:
369                 DEBUG_REQ(D_MGS, req, "llog read header");
370                 OBD_FAIL_RETURN(OBD_FAIL_OBD_LOGD_NET, 0);
371                 rc = llog_origin_handle_read_header(req);
372                 break;
373         case LLOG_ORIGIN_HANDLE_CLOSE:
374                 DEBUG_REQ(D_MGS, req, "llog close");
375                 OBD_FAIL_RETURN(OBD_FAIL_OBD_LOGD_NET, 0);
376                 rc = llog_origin_handle_close(req);
377                 break;
378         case LLOG_CATINFO:
379                 DEBUG_REQ(D_MGS, req, "llog catinfo");
380                 OBD_FAIL_RETURN(OBD_FAIL_OBD_LOGD_NET, 0);
381                 rc = llog_catinfo(req);
382                 break;
383         default:
384                 req->rq_status = -ENOTSUPP;
385                 rc = ptlrpc_error(req);
386                 RETURN(rc);
387         }
388
389         LASSERT(current->journal_info == NULL);
390
391  out:
392         target_send_reply(req, rc, fail);
393         RETURN(0);
394 }
395
396 static int mgt_setup(struct obd_device *obd, obd_count len, void *buf)
397 {
398         struct mgs_obd *mgs = &obd->u.mgs;
399         struct lprocfs_static_vars lvars;
400         int rc = 0;
401         ENTRY;
402
403        lprocfs_init_vars(mgt, &lvars);
404        lprocfs_obd_setup(obd, lvars.obd_vars);
405
406         mgs->mgs_service =
407                 ptlrpc_init_svc(MGS_NBUFS, MGS_BUFSIZE, MGS_MAXREQSIZE,
408                                 MGS_MAXREPSIZE, MGS_REQUEST_PORTAL, 
409                                 MGC_REPLY_PORTAL, MGS_SERVICE_WATCHDOG_TIMEOUT,
410                                 mgs_handle, "mgs", obd->obd_proc_entry, NULL,
411                                 MGT_NUM_THREADS);
412
413         if (!mgs->mgs_service) {
414                 CERROR("failed to start service\n");
415                 GOTO(err_lprocfs, rc = -ENOMEM);
416         }
417
418         rc = ptlrpc_start_threads(obd, mgs->mgs_service, "ll_mgt");
419         if (rc)
420                 GOTO(err_thread, rc);
421
422         RETURN(0);
423
424 err_thread:
425         ptlrpc_unregister_service(mgs->mgs_service);
426 err_lprocfs:
427         lprocfs_obd_cleanup(obd);
428         return rc;
429 }
430
431
432 static int mgt_cleanup(struct obd_device *obd)
433 {
434         struct mgs_obd *mgs = &obd->u.mgs;
435         ENTRY;
436
437         ptlrpc_unregister_service(mgs->mgs_service);
438
439         lprocfs_obd_cleanup(obd);
440
441         RETURN(0);
442 }
443
444 struct lvfs_callback_ops mgs_lvfs_ops = {
445      //     l_fid2dentry:     mgs_lvfs_fid2dentry,
446     //    l_open_llog:      mgs_lvfs_open_llog,
447 };
448
449 /* use obd ops to offer management infrastructure */
450 static struct obd_ops mgs_obd_ops = {
451         .o_owner           = THIS_MODULE,
452         .o_connect         = mgs_connect,
453         .o_disconnect      = mgs_disconnect,
454         .o_setup           = mgs_setup,
455         .o_precleanup      = mgs_precleanup,
456         .o_cleanup         = mgs_cleanup,
457         .o_iocontrol       = mgs_iocontrol,
458 };
459
460 static struct obd_ops mgt_obd_ops = {
461         .o_owner           = THIS_MODULE,
462         .o_setup           = mgt_setup,
463         .o_cleanup         = mgt_cleanup,
464 };
465
466 static int __init mgs_init(void)
467 {
468         struct lprocfs_static_vars lvars;
469
470         lprocfs_init_vars(mgs, &lvars);
471         class_register_type(&mgs_obd_ops, lvars.module_vars, LUSTRE_MGS_NAME);
472         lprocfs_init_vars(mgt, &lvars);
473         class_register_type(&mgt_obd_ops, lvars.module_vars, LUSTRE_MGT_NAME);
474
475         return 0;
476 }
477
478 static void /*__exit*/ mgs_exit(void)
479 {
480         class_unregister_type(LUSTRE_MGS_NAME);
481         class_unregister_type(LUSTRE_MGT_NAME);
482 }
483
484 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
485 MODULE_DESCRIPTION("Lustre  Management Server (MGS)");
486 MODULE_LICENSE("GPL");
487
488 module_init(mgs_init);
489 module_exit(mgs_exit);