Whamcloud - gitweb
cf1408eea05a076daef3bfd21017a2e7f038f5c5
[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 #ifndef EXPORT_SYMTAB
29 # define EXPORT_SYMTAB
30 #endif
31 #define DEBUG_SUBSYSTEM S_MGC
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/lustre_log.h>
45 #include <linux/lustre_fsfilt.h>
46 #include <linux/lustre_disk.h>
47 #include <linux/lustre_mgs.h>
48
49 #include "mgc_internal.h"
50
51
52 /* Get index and add to config llog, depending on flags */
53 int mgc_target_add(struct obd_export *exp, struct mgmt_ost_info *moi)
54 {
55         struct ptlrpc_request *req;
56         struct mgmt_ost_info *req_moi, *rep_moi;
57         int size = sizeof(*req_moi);
58         int rep_size = sizeof(*moi);
59         int rc;
60         ENTRY;
61
62         req = ptlrpc_prep_req(class_exp2cliimp(exp), MGMT_TARGET_ADD, 
63                               1, &size, NULL);
64         if (!req)
65                 RETURN(rc = -ENOMEM);
66
67         req_moi = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*req_moi));
68         memcpy(req_moi, moi, sizeof(*req_moi));
69
70         req->rq_replen = lustre_msg_size(1, &rep_size);
71
72         rc = ptlrpc_queue_wait(req);
73         if (!rc) {
74                 int index;
75                 rep_moi = lustre_swab_repbuf(req, 0, sizeof(*rep_moi),
76                                              lustre_swab_mgmt_ost_info);
77                 index = rep_moi->moi_stripe_index;
78                 if (index != moi->moi_stripe_index) {
79                         CERROR ("OST ADD failed. rc=%d\n", index);
80                         GOTO (out, rc = -EINVAL);
81                 }
82                 CERROR("OST ADD OK.(index = %d)\n", index);
83         }
84 out:
85         ptlrpc_req_finished(req);
86
87         RETURN(rc);
88 }
89 EXPORT_SYMBOL(mgc_target_add); 
90
91 /* Remove from config llog */
92 int mgc_target_del(struct obd_export *exp, struct mgmt_ost_info *moi)
93 {
94         struct ptlrpc_request *req;
95         struct mgmt_ost_info *req_moi, *rep_moi;
96         int size = sizeof(*req_moi);
97         int rc;
98         ENTRY;
99
100         req = ptlrpc_prep_req(class_exp2cliimp(exp), MGMT_TARGET_DEL,
101                               1, &size, NULL);
102         if (!req)
103                 RETURN(rc = -ENOMEM);
104
105         req_moi = lustre_msg_buf(req->rq_reqmsg, 0, sizeof(*req_moi));
106         memcpy(req_moi, moi, sizeof(*req_moi));
107
108         rc = ptlrpc_queue_wait(req);
109         if (!rc) {
110                 int index;
111                 rep_moi = lustre_swab_repbuf(req, 0, sizeof(*rep_moi),
112                                              lustre_swab_mgmt_ost_info);
113                 index = rep_moi->moi_stripe_index;
114                 if (index != moi->moi_stripe_index) {
115                         CERROR ("OST DEL failed. rc=%d\n", index);
116                         GOTO (out, rc = -EINVAL);
117                 }
118                 CERROR("OST DEL OK.(old index = %d)\n", index);
119         }
120 out:
121         ptlrpc_req_finished(req);
122
123         RETURN(rc);
124 }
125 EXPORT_SYMBOL(mgc_target_del);
126
127 static int mgc_fs_setup(struct obd_device *obd, struct super_block *sb, 
128                         struct vfsmount *mnt)
129 {
130         struct lvfs_run_ctxt saved;
131         struct lustre_sb_info *lsi = s2lsi(sb);
132         struct client_obd *cli = &obd->u.cli;
133         struct dentry *dentry;
134         int err = 0;
135
136         LASSERT(lsi);
137
138         obd->obd_fsops = fsfilt_get_ops(MT_STR(lsi->lsi_ldd));
139         if (IS_ERR(obd->obd_fsops)) {
140                CERROR("No fstype %s rc=%ld\n", MT_STR(lsi->lsi_ldd), 
141                       PTR_ERR(obd->obd_fsops));
142                return(PTR_ERR(obd->obd_fsops));
143         }
144
145         cli->cl_mgc_vfsmnt = mnt;
146         cli->cl_mgc_sb = mnt->mnt_root->d_inode->i_sb;
147         // FIXME which is the right SB? - filter_common_setup also 
148         CERROR("SB's: fill=%p mnt=%p root=%p\n", sb, mnt->mnt_sb, mnt->mnt_root->d_inode->i_sb);
149         fsfilt_setup(obd, cli->cl_mgc_sb);
150
151         OBD_SET_CTXT_MAGIC(&obd->obd_lvfs_ctxt);
152         obd->obd_lvfs_ctxt.pwdmnt = mnt;
153         obd->obd_lvfs_ctxt.pwd = mnt->mnt_root;
154         obd->obd_lvfs_ctxt.fs = get_ds();
155         //obd->obd_lvfs_ctxt.cb_ops = mds_lvfs_ops;
156
157         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
158         dentry = lookup_one_len(MOUNT_CONFIGS_DIR, current->fs->pwd,
159                                 strlen(MOUNT_CONFIGS_DIR));
160         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
161         if (IS_ERR(dentry)) {
162                 err = PTR_ERR(dentry);
163                 CERROR("cannot lookup %s directory: rc = %d\n", 
164                        MOUNT_CONFIGS_DIR, err);
165                 goto err_ops;
166         }
167         cli->cl_mgc_configs_dir = dentry;
168         return (0);
169
170 err_ops:        
171         fsfilt_put_ops(obd->obd_fsops);
172         obd->obd_fsops = NULL;
173         cli->cl_mgc_sb = NULL;
174         return(err);
175 }
176
177 static int mgc_fs_cleanup(struct obd_device *obd)
178 {
179         struct client_obd *cli = &obd->u.cli;
180         int rc;
181
182         if (cli->cl_mgc_configs_dir != NULL) {
183                 struct lvfs_run_ctxt saved;
184                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
185                 l_dput(cli->cl_mgc_configs_dir);
186                 cli->cl_mgc_configs_dir = NULL; 
187                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
188         }
189
190         rc = lustre_put_mount(obd->obd_name, cli->cl_mgc_vfsmnt);
191         if (rc)
192              CERROR("mount_put failed %d\n", rc);
193
194         cli->cl_mgc_vfsmnt = NULL;
195         cli->cl_mgc_sb = NULL;
196         
197         if (obd->obd_fsops) 
198                 fsfilt_put_ops(obd->obd_fsops);
199         return(rc);
200 }
201
202 static int mgc_cleanup(struct obd_device *obd)
203 {
204         struct client_obd *cli = &obd->u.cli;
205         int rc;
206
207         //lprocfs_obd_cleanup(obd);
208
209         if (cli->cl_mgc_vfsmnt) {
210                 /* if we're a server, eg. something's mounted */
211                 mgc_fs_cleanup(obd);
212         }
213
214         rc = obd_llog_finish(obd, 0);
215         if (rc != 0)
216                 CERROR("failed to cleanup llogging subsystems\n");
217
218         ptlrpcd_decref();
219         
220         OBD_FREE(cli->cl_mgc_rpc_lock, sizeof (*cli->cl_mgc_rpc_lock));
221
222         return client_obd_cleanup(obd);
223 }
224
225 /* the same as mdc_setup */
226 static int mgc_setup(struct obd_device *obd, obd_count len, void *buf)
227 {
228         struct client_obd *cli = &obd->u.cli;
229         int rc;
230         ENTRY;
231
232         OBD_ALLOC(cli->cl_mgc_rpc_lock, sizeof (*cli->cl_mgc_rpc_lock));
233         if (!cli->cl_mgc_rpc_lock)
234                 RETURN(-ENOMEM);
235         mgc_init_rpc_lock(cli->cl_mgc_rpc_lock);
236
237         ptlrpcd_addref();
238
239         rc = client_obd_setup(obd, len, buf);
240         if (rc)
241                 GOTO(err_rpc_lock, rc);
242
243         rc = obd_llog_init(obd, obd, 0, NULL);
244         if (rc) {
245                 CERROR("failed to setup llogging subsystems\n");
246                 GOTO(err_rpc_lock, rc);
247         }
248
249 #if 0
250         struct lustre_mount_info *lmi;
251         /* FIXME There's only one mgc for all local servers.  Must mgc_fs_setup 
252            on demand only when reading a local log file, then cleanup.
253            Make sure there's a lock so nobody else can mgc_fs_setup in the 
254            meantime */
255         lmi = lustre_get_mount(obd->obd_name);
256         if (lmi) {
257                 CERROR("mgc has local disk\n");
258                 /* there's a local disk, we must get access */
259                 rc = mgc_fs_setup(obd, lmi->lmi_sb, lmi->lmi_mnt);
260                 if (rc) {
261                         CERROR("fs setup failed %d\n", rc);
262                         mgc_cleanup(obd);
263                         RETURN(-ENOENT);
264                 }
265         }
266         else
267                 CERROR("mgc does not have local disk (client only)\n");
268 #endif
269
270         INIT_LIST_HEAD(&cli->cl_mgc_open_llogs);
271
272         RETURN(rc);
273
274 err_rpc_lock:
275         ptlrpcd_decref();
276         OBD_FREE(cli->cl_mgc_rpc_lock, sizeof (*cli->cl_mgc_rpc_lock));
277         RETURN(rc);
278 }
279
280 static int mgc_iocontrol(unsigned int cmd, struct obd_export *exp, int len,
281                          void *karg, void *uarg)
282 {
283         struct obd_device *obd = exp->exp_obd;
284         struct obd_ioctl_data *data = karg;
285         struct llog_ctxt *ctxt;
286         struct lvfs_run_ctxt saved;
287         int rc;
288         ENTRY;
289
290 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
291         MOD_INC_USE_COUNT;
292 #else
293         if (!try_module_get(THIS_MODULE)) {
294                 CERROR("Can't get module. Is it alive?");
295                 return -EINVAL;
296         }
297 #endif
298         switch (cmd) {
299         /* REPLicator context */
300         case OBD_IOC_PARSE: {
301                 CERROR("MGC parsing llog %s\n", data->ioc_inlbuf1);
302                 ctxt = llog_get_context(exp->exp_obd, LLOG_CONFIG_REPL_CTXT);
303                 rc = class_config_parse_llog(ctxt, data->ioc_inlbuf1, NULL);
304                 GOTO(out, rc);
305         }
306 #ifdef __KERNEL__
307         case OBD_IOC_LLOG_INFO:
308         case OBD_IOC_LLOG_PRINT: {
309                 ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT);
310                 rc = llog_ioctl(ctxt, cmd, data);
311
312                 GOTO(out, rc);
313         }
314 #endif
315         /* ORIGinator context */
316         case OBD_IOC_DUMP_LOG: {
317                 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
318                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
319                 rc = class_config_dump_llog(ctxt, data->ioc_inlbuf1, NULL);
320                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
321                 if (rc)
322                         RETURN(rc);
323
324                 GOTO(out, rc);
325         }
326         case OBD_IOC_START: {
327                 char *name = data->ioc_inlbuf1;
328                 CERROR("getting config log %s\n", name);
329                 /* FIXME Get llog from MGS */
330
331                 push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
332                 ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
333                 rc = class_config_parse_llog(ctxt, name, NULL);
334                 if (rc < 0)
335                         CERROR("Unable to process log: %s\n", name);
336                 pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
337
338                 GOTO(out, rc);
339         }
340         default:
341                 CERROR("mgc_ioctl(): unrecognised ioctl %#x\n", cmd);
342                 GOTO(out, rc = -ENOTTY);
343         }
344 out:
345 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
346         MOD_DEC_USE_COUNT;
347 #else
348         module_put(THIS_MODULE);
349 #endif
350
351         return rc;
352 }
353
354 #define INIT_RECOV_BACKUP "init_recov_bk"
355 int mgc_set_info(struct obd_export *exp, obd_count keylen,
356                  void *key, obd_count vallen, void *val)
357 {
358         struct obd_import *imp = class_exp2cliimp(exp);
359         int rc = -EINVAL;
360         ENTRY;
361
362         /* Try to "recover" the initial connection; i.e. retry */
363         if (keylen == strlen("initial_recov") &&
364             memcmp(key, "initial_recov", keylen) == 0) {
365                 if (vallen != sizeof(int))
366                         RETURN(-EINVAL);
367                 imp->imp_initial_recov = *(int *)val;
368                 CDEBUG(D_HA, "%s: set imp_initial_recov = %d\n",
369                        exp->exp_obd->obd_name, imp->imp_initial_recov);
370                 RETURN(0);
371         }
372         /* Turn off initial_recov after we try all backup servers once */
373         if (keylen == strlen(INIT_RECOV_BACKUP) &&
374             memcmp(key, INIT_RECOV_BACKUP, keylen) == 0) {
375                 if (vallen != sizeof(int))
376                         RETURN(-EINVAL);
377                 imp->imp_initial_recov_bk = *(int *)val;
378                 CDEBUG(D_HA, "%s: set imp_initial_recov_bk = %d\n",
379                        exp->exp_obd->obd_name, imp->imp_initial_recov_bk);
380                 RETURN(0);
381         }
382         /* Hack alert */
383         if (keylen == strlen("register") &&
384             memcmp(key, "register", keylen) == 0) {
385                 struct mgmt_ost_info *moi;
386                 if (vallen != sizeof(struct mgmt_ost_info))
387                         RETURN(-EINVAL);
388                 moi = (struct mgmt_ost_info *)val;
389                 CERROR("register %s %#x\n", moi->moi_ostname, moi->moi_flags);
390                 rc =  mgc_target_add(exp, moi);
391                 RETURN(rc);
392         }
393         RETURN(rc);
394 }               
395
396 static int mgc_import_event(struct obd_device *obd,
397                             struct obd_import *imp,
398                             enum obd_import_event event)
399 {
400         int rc = 0;
401
402         LASSERT(imp->imp_obd == obd);
403
404         switch (event) {
405         case IMP_EVENT_DISCON: {
406                 break;
407         }
408         case IMP_EVENT_INVALIDATE: {
409                 struct ldlm_namespace *ns = obd->obd_namespace;
410
411                 ldlm_namespace_cleanup(ns, LDLM_FL_LOCAL_ONLY);
412
413                 break;
414         }
415         case IMP_EVENT_INACTIVE: {
416                 break;
417         }
418         case IMP_EVENT_ACTIVE: {
419                 break;
420         }
421         default:
422                 CERROR("Unknown import event %d\n", event);
423                 LBUG();
424         }
425         RETURN(rc);
426 }
427
428 static int mgc_llog_init(struct obd_device *obd, struct obd_device *tgt,
429                          int count, struct llog_catid *logid)
430 {
431         struct llog_ctxt *ctxt;
432         int rc;
433         ENTRY;
434
435         rc = llog_setup(obd, LLOG_CONFIG_ORIG_CTXT, tgt, 0, NULL,
436                         &llog_lvfs_ops);
437         if (rc)
438                 RETURN(rc);
439
440         rc = llog_setup(obd, LLOG_CONFIG_REPL_CTXT, tgt, 0, NULL,
441                         &llog_client_ops);
442         if (rc == 0) {
443                 ctxt = llog_get_context(obd, LLOG_CONFIG_REPL_CTXT);
444                 ctxt->loc_imp = obd->u.cli.cl_import;
445         }
446
447         RETURN(rc);
448 }
449
450 static int mgc_llog_finish(struct obd_device *obd, int count)
451 {
452         int rc;
453         ENTRY;
454
455         rc = llog_cleanup(llog_get_context(obd, LLOG_CONFIG_REPL_CTXT));
456         rc = llog_cleanup(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT));
457
458         RETURN(rc);
459 }
460
461 /* reuse the client_import_[add/del]_conn*/
462 struct obd_ops mgc_obd_ops = {
463         .o_owner        = THIS_MODULE,
464         .o_setup        = mgc_setup,
465         .o_cleanup      = mgc_cleanup,
466         .o_add_conn     = client_import_add_conn,
467         .o_del_conn     = client_import_del_conn,
468         .o_connect      = client_connect_import,
469         .o_disconnect   = client_disconnect_export,
470         .o_iocontrol    = mgc_iocontrol,
471         .o_set_info     = mgc_set_info,
472         .o_import_event = mgc_import_event,
473         .o_llog_init    = mgc_llog_init,
474         .o_llog_finish  = mgc_llog_finish,
475 };
476
477 int __init mgc_init(void)
478 {
479         return class_register_type(&mgc_obd_ops, NULL, LUSTRE_MGC_NAME);
480 }
481
482 #ifdef __KERNEL__
483 static void /*__exit*/ mgc_exit(void)
484 {
485         class_unregister_type(LUSTRE_MGC_NAME);
486 }
487
488 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
489 MODULE_DESCRIPTION("Lustre Management Client");
490 MODULE_LICENSE("GPL");
491
492 module_init(mgc_init);
493 module_exit(mgc_exit);
494 #endif