Whamcloud - gitweb
MGS/MGC requests.
[fs/lustre-release.git] / lustre / mgc / mgc_request.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (C) 2001-2005 Cluster File Systems, Inc.
5  *   Author Nathan <nathan@clusterfs.com>
6  *   Author LinSongTao <lincent@clusterfs.com>
7  *
8  *   This file is part of Lustre, http://www.lustre.org
9  *
10  *   Lustre is free software; you can redistribute it and/or
11  *   modify it under the terms of version 2 of the GNU General Public
12  *   License as published by the Free Software Foundation.
13  *
14  *   Lustre is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with Lustre; if not, write to the Free Software
21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  *  For testing and management it is treated as an obd_device,
24  *  although * it does not export a full OBD method table (the
25  *  requests are coming * in over the wire, so object target modules
26  *  do not have a full * method table.)
27  */
28
29 #ifndef EXPORT_SYMTAB
30 # define EXPORT_SYMTAB
31 #endif
32 #define DEBUG_SUBSYSTEM S_CONFOBD
33
34 #ifdef __KERNEL__
35 # include <linux/module.h>
36 # include <linux/pagemap.h>
37 # include <linux/miscdevice.h>
38 # include <linux/init.h>
39 #else
40 # include <liblustre.h>
41 #endif
42
43 #include <linux/obd_class.h>
44 //#include <linux/lustre_mds.h>
45 #include <linux/lustre_dlm.h>
46 #include <linux/lustre_log.h>
47 #include <linux/lustre_fsfilt.h>
48 #include <linux/lustre_disk.h>
49
50 #include "mgc_internal.h"
51           
52 static int mgc_fs_setup(struct obd_device *obd, struct super_block *sb, 
53                         struct vfsmount *mnt)
54 {
55         struct lvfs_run_ctxt saved;
56         struct lustre_sb_info *sbi = s2sbi(sb);
57         struct mgc_obd *mgcobd = &obd->u.mgc;
58         struct dentry *dentry;
59         int err = 0;
60
61
62         LASSERT(sbi);
63
64         obd->obd_fsops = fsfilt_get_ops(MT_STR(sbi->lsi_ldd));
65         if (IS_ERR(obd->obd_fsops)) {
66                CERROR("No fstype %s rc=%ld\n", MT_STR(sbi->lsi_ldd), 
67                       PTR_ERR(obd->obd_fsops));
68                return(PTR_ERR(obd->obd_fsops));
69         }
70
71         mgcobd->mgc_vfsmnt = mnt;
72         mgcobd->mgc_sb = mnt->mnt_root->d_inode->i_sb;
73         // FIXME which one? - filter_common_setup also 
74         CERROR("SB's: fill=%p mnt=%p root=%p\n", sb, mnt->mnt_sb, mnt->mnt_root->d_inode->i_sb);
75         fsfilt_setup(obd, mgcobd->mgc_sb);
76
77         OBD_SET_CTXT_MAGIC(&obd->obd_lvfs_ctxt);
78         obd->obd_lvfs_ctxt.pwdmnt = mnt;
79         obd->obd_lvfs_ctxt.pwd = mnt->mnt_root;
80         obd->obd_lvfs_ctxt.fs = get_ds();
81         //obd->obd_lvfs_ctxt.cb_ops = mds_lvfs_ops;
82
83         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
84         dentry = lookup_one_len(MOUNT_CONFIGS_DIR, current->fs->pwd,
85                                 strlen(MOUNT_CONFIGS_DIR));
86         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
87         if (IS_ERR(dentry)) {
88                 err = PTR_ERR(dentry);
89                 CERROR("cannot lookup %s directory: rc = %d\n", 
90                        MOUNT_CONFIGS_DIR, err);
91                 goto err_ops;
92         }
93         mgcobd->mgc_configs_dir = dentry;
94         return (0);
95
96 err_ops:        
97         fsfilt_put_ops(obd->obd_fsops);
98         obd->obd_fsops = NULL;
99         mgcobd->mgc_sb = NULL;
100         return(err);
101 }
102
103 static int mgc_fs_cleanup(struct obd_device *obd)
104 {
105         struct mgc_obd *mgc = &obd->u.mgc;
106
107        // in mgc_cleanup: llog_cleanup(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT));
108         
109         if (mgc->mgc_configs_dir != NULL) {
110                 struct lvfs_run_ctxt saved;
111                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
112                 l_dput(mgc->mgc_configs_dir);
113                 mgc->mgc_configs_dir = NULL; 
114                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
115         }
116
117         mgc->mgc_vfsmnt = NULL;
118         mgc->mgc_sb = NULL;
119         
120         if (obd->obd_fsops) 
121                 fsfilt_put_ops(obd->obd_fsops);
122         return(0);
123 }
124
125 static int mgc_cleanup(struct obd_device *obd)
126 {
127         struct mgc_obd *mgc = &obd->u.mgc;
128         int rc;
129
130         rc = llog_cleanup(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT));
131
132         // FIXME REPL rc = obd_llog_finish(obd, 0);
133         if (rc != 0)
134                 CERROR("failed to cleanup llogging subsystems\n");
135
136         //lprocfs_obd_cleanup(obd);
137         
138         //rc = mgc_obd_cleanup(obd);
139
140         if (mgc->mgc_vfsmnt) {
141                 /* if we're a server, eg. something's mounted */
142                 mgc_fs_cleanup(obd);
143                 if ((rc = lustre_put_mount(obd->obd_name)))
144                      CERROR("mount_put failed %d\n", rc);
145         }
146
147         ptlrpcd_decref();
148         
149         OBD_FREE(mgc->mgc_rpc_lock, sizeof (*mgc->mgc_rpc_lock));
150
151         return(rc);
152 }
153
154 static int mgc_setup(struct obd_device *obd, obd_count len, void *buf)
155 {
156         struct lustre_mount_info *lmi;
157         struct mgc_obd *mgc = &obd->u.mgc;
158         //struct lprocfs_static_vars lvars;
159         int rc;
160         ENTRY;
161
162         OBD_ALLOC(mgc->mgc_rpc_lock, sizeof (*mgc->mgc_rpc_lock));
163         if (!mgc->mgc_rpc_lock)
164                 RETURN(-ENOMEM);
165         mgc_init_rpc_lock(mgc->mgc_rpc_lock);
166
167         ptlrpcd_addref();
168
169         rc = obd_llog_init(obd, obd, 0, NULL);
170         if (rc) {
171                 CERROR("failed to setup llogging subsystems\n");
172                 GOTO(err_rpc_lock, rc);
173         }
174
175         lmi = lustre_get_mount(obd->obd_name);
176         if (lmi) {
177                 CERROR("mgc has local disk\n");
178                 /* there's a local disk, we must get access */
179                 rc = mgc_fs_setup(obd, lmi->lmi_sb, lmi->lmi_mnt);
180                 if (rc) {
181                         CERROR("fs setup failed %d\n", rc);
182                         mgc_cleanup(obd);
183                         RETURN(-ENOENT);
184                         GOTO(err_rpc_lock, rc);
185                 }                                                                                                     
186         } else {
187                 CERROR("mgc does not have local disk (client only)\n");
188                 rc = mgc_obd_setup(obd, len, buf);
189                 if (rc)
190                         GOTO(err_rpc_lock, rc);
191         }
192
193         RETURN(rc);
194
195 err_rpc_lock:
196         ptlrpcd_decref();
197         OBD_FREE(mgc->mgc_rpc_lock, sizeof (*mgc->mgc_rpc_lock));
198         RETURN(rc);
199 }
200
201
202 static int mgc_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
203                          void *karg, void *uarg)
204 {
205         struct obd_device *obd = exp->exp_obd;
206         struct obd_ioctl_data *data = karg;
207         struct llog_ctxt *ctxt;
208         struct lvfs_run_ctxt saved;
209         int rc;
210         ENTRY;
211
212 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
213         MOD_INC_USE_COUNT;
214 #else
215         if (!try_module_get(THIS_MODULE)) {
216                 CERROR("Can't get module. Is it alive?");
217                 return -EINVAL;
218         }
219 #endif
220         switch (cmd) {
221         /* REPLicator context */
222         case OBD_IOC_PARSE: {
223                 CERROR("MGC parsing llog %s\n", data->ioc_inlbuf1);
224                 ctxt = llog_get_context(exp->exp_obd, LLOG_CONFIG_REPL_CTXT);
225                 rc = class_config_parse_llog(ctxt, data->ioc_inlbuf1, NULL);
226                 GOTO(out, rc);
227         }
228 #ifdef __KERNEL__
229         case OBD_IOC_LLOG_INFO:
230         case OBD_IOC_LLOG_PRINT: {
231                 ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT);
232                 rc = llog_ioctl(ctxt, cmd, data);
233
234                 GOTO(out, rc);
235         }
236 #endif
237         /* ORIGinator context */
238         case OBD_IOC_DUMP_LOG: {
239                 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
240                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
241                 rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL);
242                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
243                 if (rc)
244                         RETURN(rc);
245
246                 RETURN(rc);
247         }
248         case OBD_IOC_START: {
249                 char *conf_prof;
250                 char *name = data->ioc_inlbuf1;
251                 int len = strlen(name) + sizeof("-conf");
252
253                 OBD_ALLOC(conf_prof, len);
254                 if (!conf_prof) {
255                         CERROR("no memory\n");
256                         RETURN(-ENOMEM);
257                 }
258                 sprintf(conf_prof, "%s-conf", name);
259
260                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
261
262                 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
263                 rc = class_config_parse_llog(ctxt, conf_prof, NULL);
264                 if (rc < 0)
265                         CERROR("Unable to process log: %s\n", conf_prof);
266
267                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
268                 OBD_FREE(conf_prof, len);
269
270                 RETURN(rc);
271         }
272         default:
273                 CERROR("mgc_ioctl(): unrecognised ioctl %#x\n", cmd);
274                 GOTO(out, rc = -ENOTTY);
275         }
276 out:
277 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
278         MOD_DEC_USE_COUNT;
279 #else
280         module_put(THIS_MODULE);
281 #endif
282
283         return rc;
284 }
285
286 static int mgc_import_event(struct obd_device *obd,
287                             struct obd_import *imp,
288                             enum obd_import_event event)
289 {
290         int rc = 0;
291
292         LASSERT(imp->imp_obd == obd);
293
294         switch (event) {
295         case IMP_EVENT_DISCON: {
296                 break;
297         }
298         case IMP_EVENT_INACTIVE: {
299                 if (obd->obd_observer)
300                         rc = obd_notify(obd->obd_observer, obd, 0);
301                 break;
302         }
303         case IMP_EVENT_ACTIVE: {
304                 if (obd->obd_observer)
305                         rc = obd_notify(obd->obd_observer, obd, 1);
306                 break;
307         }
308         default:
309                 CERROR("Unknown import event %d\n", event);
310                 LBUG();
311         }
312         RETURN(rc);
313 }
314
315 static int mgc_llog_init(struct obd_device *obd, struct obd_device *tgt,
316                          int count, struct llog_catid *logid)
317 {
318         struct llog_ctxt *ctxt;
319         int rc;
320         ENTRY;
321
322         rc = llog_setup(obd, LLOG_CONFIG_ORIG_CTXT, tgt, 0, NULL,
323                         &llog_lvfs_ops);
324         if (rc)
325                 RETURN(rc);
326
327         rc = llog_setup(obd, LLOG_CONFIG_REPL_CTXT, tgt, 0, NULL,
328                         &llog_client_ops);
329         if (!rc) {
330                 ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT);
331                 ctxt->loc_imp = obd->u.mgc.mgc_import;
332         }
333
334         RETURN(rc);
335 }
336
337 static int mgc_llog_finish(struct obd_device *obd, int count)
338 {
339         int rc;
340         ENTRY;
341
342         rc = llog_cleanup(llog_get_context(obd, LLOG_CONFIG_REPL_CTXT));
343         RETURN(rc);
344 }
345
346 /*mgc_obd_setup for mount-conf*/
347 int mgc_obd_setup(struct obd_device *obddev, obd_count len, void *buf)
348 {
349         struct lustre_cfg* lcfg = buf;
350         struct mgc_obd *mgc = &obddev->u.mgc;
351         struct obd_import *imp;
352         struct obd_uuid server_uuid;
353         int rq_portal, rp_portal, connect_op;
354         char *name = obddev->obd_type->typ_name;
355         int rc;
356         ENTRY;
357
358         LASSERT(!strcmp(name, LUSTRE_MGC_NAME)); 
359                 
360         rq_portal = MGS_REQUEST_PORTAL;
361         rp_portal = MGC_REPLY_PORTAL;
362         connect_op = MGS_CONNECT;
363
364         if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1) {
365                 CERROR("requires a TARGET UUID\n");
366                 RETURN(-EINVAL);
367         }
368
369         if (LUSTRE_CFG_BUFLEN(lcfg, 1) > 37) {
370                 CERROR("client UUID must be less than 38 characters\n");
371                 RETURN(-EINVAL);
372         }
373
374         if (LUSTRE_CFG_BUFLEN(lcfg, 2) < 1) {
375                 CERROR("setup requires a SERVER UUID\n");
376                 RETURN(-EINVAL);
377         }
378
379         if (LUSTRE_CFG_BUFLEN(lcfg, 2) > 37) {
380                 CERROR("target UUID must be less than 38 characters\n");
381                 RETURN(-EINVAL);
382         }
383
384         sema_init(&mgc->mgc_sem, 1);
385         mgc->mgc_conn_count = 0;
386         memcpy(server_uuid.uuid, lustre_cfg_buf(lcfg, 2),
387                min_t(unsigned int, LUSTRE_CFG_BUFLEN(lcfg, 2),
388                      sizeof(server_uuid)));
389
390         rc = ldlm_get_ref();
391         if (rc) {
392                 CERROR("ldlm_get_ref failed: %d\n", rc);
393                 GOTO(err, rc);
394         }
395
396         ptlrpc_init_client(rq_portal, rp_portal, name,
397                            &obddev->obd_ldlm_client);
398
399         imp = class_new_import();
400         if (imp == NULL)
401                 GOTO(err_ldlm, rc = -ENOENT);
402         imp->imp_client = &obddev->obd_ldlm_client;
403         imp->imp_obd = obddev;
404         imp->imp_connect_op = connect_op;
405         imp->imp_generation = 0;
406         imp->imp_initial_recov = 1;
407         INIT_LIST_HEAD(&imp->imp_pinger_chain);
408         memcpy(imp->imp_target_uuid.uuid, lustre_cfg_buf(lcfg, 1),
409                LUSTRE_CFG_BUFLEN(lcfg, 1));
410         class_import_put(imp);
411
412         rc = client_import_add_conn(imp, &server_uuid, 1);
413         if (rc) {
414                 CERROR("can't add initial connection\n");
415                 GOTO(err_import, rc);
416         }
417
418         mgc->mgc_import = imp;
419
420         RETURN(rc);
421
422 err_import:
423         class_destroy_import(imp);
424 err_ldlm:
425         ldlm_put_ref(0);
426 err:
427         RETURN(rc);
428 }
429
430 /*mgc_obd_cleaup for mount-conf*/
431 int mgc_obd_cleanup(struct obd_device *obddev)
432 {
433         struct mgc_obd *mgc = &obddev->u.mgc;
434
435         if (!mgc->mgc_import)
436                 RETURN(-EINVAL);
437
438         class_destroy_import(mgc->mgc_import);
439         mgc->mgc_import = NULL;
440
441         ldlm_put_ref(obddev->obd_force);
442
443         RETURN(0);
444 }
445
446 /* mgc_connect_import for mount-conf*/
447 int mgc_connect_import(struct lustre_handle *dlm_handle,
448                        struct obd_device *obd, struct obd_uuid *cluuid,
449                        struct obd_connect_data *data)
450 {
451         struct mgc_obd *mgc = &obd->u.mgc;
452         struct obd_import *imp = mgc->mgc_import;
453         struct obd_export *exp;
454         int rc;
455         ENTRY;
456
457         down(&mgc->mgc_sem);
458         rc = class_connect(dlm_handle, obd, cluuid);
459         if (rc)
460                 GOTO(out_sem, rc);
461
462         mgc->mgc_conn_count++;
463         if (mgc->mgc_conn_count > 1)
464                 GOTO(out_sem, rc);
465         exp = class_conn2export(dlm_handle);
466
467         imp->imp_dlm_handle = *dlm_handle;
468         rc = ptlrpc_init_import(imp);
469         if (rc != 0) 
470                 GOTO(out_disco, rc);
471
472         if (data)
473                 memcpy(&imp->imp_connect_data, data, sizeof(*data));
474         rc = ptlrpc_connect_import(imp, NULL);
475         if (rc != 0) {
476                 LASSERT (imp->imp_state == LUSTRE_IMP_DISCON);
477                 GOTO(out_disco, rc);
478         }
479         LASSERT(exp->exp_connection);
480
481         ptlrpc_pinger_add_import(imp);
482         EXIT;
483
484         if (rc) {
485 out_disco:
486                 mgc->mgc_conn_count--;
487                 class_disconnect(exp);
488         } else {
489                 class_export_put(exp);
490         }
491 out_sem:
492         up(&mgc->mgc_sem);
493         return rc;
494 }
495
496 /* mgc_disconnect_export for mount-conf*/
497 int mgc_disconnect_export(struct obd_export *exp)
498 {
499         struct obd_device *obd = class_exp2obd(exp);
500         struct mgc_obd *mgc = &obd->u.mgc;
501         struct obd_import *imp = mgc->mgc_import;
502         int rc = 0, err;
503         ENTRY;
504
505         if (!obd) {
506                 CERROR("invalid export for disconnect: exp %p cookie "LPX64"\n",
507                        exp, exp ? exp->exp_handle.h_cookie : -1);
508                 RETURN(-EINVAL);
509         }
510
511         down(&mgc->mgc_sem);
512         if (!mgc->mgc_conn_count) {
513                 CERROR("disconnecting disconnected device (%s)\n",
514                        obd->obd_name);
515                 GOTO(out_sem, rc = -EINVAL);
516         }
517
518         mgc->mgc_conn_count--;
519         if (mgc->mgc_conn_count)
520                 GOTO(out_no_disconnect, rc = 0);
521
522         /* Some non-replayable imports (MDS's OSCs) are pinged, so just
523          * delete it regardless.  (It's safe to delete an import that was
524          * never added.) */
525         (void)ptlrpc_pinger_del_import(imp);
526
527         /* Yeah, obd_no_recov also (mainly) means "forced shutdown". */
528         if (obd->obd_no_recov)
529                 ptlrpc_invalidate_import(imp);
530         else
531                 rc = ptlrpc_disconnect_import(imp);
532
533         EXIT;
534  out_no_disconnect:
535         err = class_disconnect(exp);
536         if (!rc && err)
537                 rc = err;
538  out_sem:
539         up(&mgc->mgc_sem);
540         RETURN(rc);
541 }
542
543 /* reuse the client_import_[add/del]_conn*/
544 struct obd_ops mgc_obd_ops = {
545         .o_owner        = THIS_MODULE,
546         .o_setup        = mgc_setup,
547         .o_cleanup      = mgc_cleanup,
548         .o_add_conn     = client_import_add_conn,
549         .o_del_conn     = client_import_del_conn,
550         .o_connect      = mgc_connect_import,
551         .o_disconnect   = mgc_disconnect_export,
552         .o_iocontrol    = mgc_iocontrol,
553         .o_import_event = mgc_import_event,
554         .o_llog_init    = mgc_llog_init,
555         .o_llog_finish  = mgc_llog_finish,
556 };
557
558 int __init mgc_init(void)
559 {
560         return class_register_type(&mgc_obd_ops, NULL, LUSTRE_MGC_NAME);
561 }
562
563 #ifdef __KERNEL__
564 static void /*__exit*/ mgc_exit(void)
565 {
566         class_unregister_type(LUSTRE_MGC_NAME);
567 }
568
569 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
570 MODULE_DESCRIPTION("Lustre Management Client");
571 MODULE_LICENSE("GPL");
572
573 module_init(mgc_init);
574 module_exit(mgc_exit);
575 #endif