Whamcloud - gitweb
Branch b1_4_mountconf
[fs/lustre-release.git] / lustre / obdclass / obd_config.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (c) 2001-2003 Cluster File Systems, Inc.
5  *
6  *   This file is part of the Lustre file system, http://www.lustre.org
7  *   Lustre is a trademark of Cluster File Systems, Inc.
8  *
9  *   You may have signed or agreed to another license before downloading
10  *   this software.  If so, you are bound by the terms and conditions
11  *   of that agreement, and the following does not apply to you.  See the
12  *   LICENSE file included with this distribution for more information.
13  *
14  *   If you did not agree to a different license, then this copy of Lustre
15  *   is open source software; you can redistribute it and/or modify it
16  *   under the terms of version 2 of the GNU General Public License as
17  *   published by the Free Software Foundation.
18  *
19  *   In either case, Lustre is distributed in the hope that it will be
20  *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
21  *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *   license text for more details.
23  *
24  * Config API
25  *
26  */
27
28 #define DEBUG_SUBSYSTEM S_CLASS
29 #ifdef __KERNEL__
30 #include <linux/kmod.h>   /* for request_module() */
31 #include <linux/module.h>
32 #include <linux/obd_class.h>
33 #include <linux/random.h>
34 #include <linux/slab.h>
35 #include <linux/pagemap.h>
36 #else
37 #include <liblustre.h>
38 #include <linux/obd_class.h>
39 #include <linux/obd.h>
40 #endif
41 #include <linux/lustre_log.h>
42 #include <linux/lprocfs_status.h>
43 #include <libcfs/list.h>
44
45
46 /* Create a new device and set the type, name and uuid.  If
47  * successful, the new device can be accessed by either name or uuid.
48  */
49 int class_attach(struct lustre_cfg *lcfg)
50 {
51         struct obd_type *type;
52         struct obd_device *obd = NULL;
53         char *typename, *name, *namecopy, *uuid;
54         int rc, len, cleanup_phase = 0;
55
56         if (!LUSTRE_CFG_BUFLEN(lcfg, 1)) {
57                 CERROR("No type passed!\n");
58                 RETURN(-EINVAL);
59         }
60         typename = lustre_cfg_string(lcfg, 1);
61
62         if (!LUSTRE_CFG_BUFLEN(lcfg, 0)) {
63                 CERROR("No name passed!\n");
64                 RETURN(-EINVAL);
65         }
66         name = lustre_cfg_string(lcfg, 0);
67
68         if (!LUSTRE_CFG_BUFLEN(lcfg, 2)) {
69                 CERROR("No UUID passed!\n");
70                 RETURN(-EINVAL);
71         }
72         uuid = lustre_cfg_string(lcfg, 2);
73
74         CDEBUG(D_IOCTL, "attach type %s name: %s uuid: %s\n",
75                MKSTR(typename), MKSTR(name), MKSTR(uuid));
76         
77         /* Mountconf transitional hack, should go away after 1.6.
78            1.4.7 uses the old names, so translate back if the 
79            mountconf flag is set. 
80            1.6 should set this flag, and translate the other way here
81            if not set. */
82         if (lcfg->lcfg_flags & LCFG_FLG_MOUNTCONF){
83                 char *tmp = NULL;
84                 if (strcmp(typename, "mds") == 0)
85                         tmp = "mdt";
86                 if (strcmp(typename, "mdt") == 0)
87                         tmp = "mds";
88                 if (strcmp(typename, "osd") == 0)
89                         tmp = "obdfilter";
90                 if (tmp) {
91                         LCONSOLE_WARN("Using type %s for %s %s\n", tmp,
92                                       MKSTR(typename), MKSTR(name));
93                         typename = tmp;
94                 }
95         }
96
97         /* find the type */
98         type = class_get_type(typename);
99         if (!type) {
100                 CERROR("OBD: unknown type: %s\n", typename);
101                 RETURN(-ENODEV);
102         }
103         cleanup_phase = 1;  /* class_put_type */
104
105         len = strlen(name) + 1;
106         OBD_ALLOC(namecopy, len);
107         if (!namecopy)
108                 GOTO(out, rc = -ENOMEM);
109         memcpy(namecopy, name, len);
110         cleanup_phase = 2; /* free obd_name */
111
112         obd = class_newdev(type, namecopy);
113         if (obd == NULL) {
114                 /* Already exists or out of obds */
115                 CERROR("Can't create device %s\n", name);
116                 GOTO(out, rc = -EEXIST);
117         }
118         cleanup_phase = 3;  /* class_release_dev */
119
120         INIT_LIST_HEAD(&obd->obd_exports);
121         INIT_LIST_HEAD(&obd->obd_exports_timed);
122         obd->obd_num_exports = 0;
123         spin_lock_init(&obd->obd_dev_lock);
124         spin_lock_init(&obd->obd_osfs_lock);
125         obd->obd_osfs_age = jiffies - 1000 * HZ;
126
127         /* XXX belongs in setup not attach  */
128         /* recovery data */
129         init_timer(&obd->obd_recovery_timer);
130         spin_lock_init(&obd->obd_processing_task_lock);
131         init_waitqueue_head(&obd->obd_next_transno_waitq);
132         INIT_LIST_HEAD(&obd->obd_recovery_queue);
133         INIT_LIST_HEAD(&obd->obd_delayed_reply_queue);
134
135         spin_lock_init(&obd->obd_uncommitted_replies_lock);
136         INIT_LIST_HEAD(&obd->obd_uncommitted_replies);
137
138         len = strlen(uuid);
139         if (len >= sizeof(obd->obd_uuid)) {
140                 CERROR("uuid must be < "LPSZ" bytes long\n",
141                        sizeof(obd->obd_uuid));
142                 GOTO(out, rc = -EINVAL);
143         }
144         memcpy(obd->obd_uuid.uuid, uuid, len);
145
146         /* do the attach */
147         if (OBP(obd, attach)) {
148                 rc = OBP(obd,attach)(obd, sizeof *lcfg, lcfg);
149                 if (rc)
150                         GOTO(out, rc = -EINVAL);
151         }
152
153         /* Detach drops this */
154         atomic_set(&obd->obd_refcount, 1);
155
156         obd->obd_attached = 1;
157         type->typ_refcnt++;
158         CDEBUG(D_IOCTL, "OBD: dev %d attached type %s\n",
159                obd->obd_minor, typename);
160         RETURN(0);
161  out:
162         switch (cleanup_phase) {
163         case 3:
164                 class_release_dev(obd);
165         case 2:
166                 OBD_FREE(namecopy, strlen(namecopy) + 1);
167         case 1:
168                 class_put_type(type);
169         }
170         return rc;
171 }
172
173 int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
174 {
175         int err = 0;
176         struct obd_export *exp;
177         ENTRY;
178
179         LASSERT(obd == (obd_dev + obd->obd_minor));
180
181         /* have we attached a type to this device? */
182         if (!obd->obd_attached) {
183                 CERROR("Device %d not attached\n", obd->obd_minor);
184                 RETURN(-ENODEV);
185         }
186
187         if (obd->obd_set_up) {
188                 CERROR("Device %d already setup (type %s)\n",
189                        obd->obd_minor, obd->obd_type->typ_name);
190                 RETURN(-EEXIST);
191         }
192
193         /* is someone else setting us up right now? (attach inits spinlock) */
194         spin_lock(&obd->obd_dev_lock);
195         if (obd->obd_starting) {
196                 spin_unlock(&obd->obd_dev_lock);
197                 CERROR("Device %d setup in progress (type %s)\n",
198                        obd->obd_minor, obd->obd_type->typ_name);
199                 RETURN(-EEXIST);
200         }
201         /* just leave this on forever.  I can't use obd_set_up here because
202            other fns check that status, and we're not actually set up yet. */
203         obd->obd_starting = 1;
204         spin_unlock(&obd->obd_dev_lock);
205
206         exp = class_new_export(obd);
207         if (!exp){
208                 CERROR("Fail to build export.\n");
209                 RETURN(-ENOMEM);
210         }
211         memcpy(&exp->exp_client_uuid, &obd->obd_uuid,
212                sizeof(exp->exp_client_uuid));
213         obd->obd_self_export = exp;
214         list_del_init(&exp->exp_obd_chain_timed);
215         class_export_put(exp);
216
217         err = obd_setup(obd, sizeof(*lcfg), lcfg);
218         if (err)
219                 GOTO(err_exp, err);
220
221         obd->obd_type->typ_refcnt++;
222         obd->obd_set_up = 1;
223         spin_lock(&obd->obd_dev_lock);
224         /* cleanup drops this */
225         atomic_inc(&obd->obd_refcount);
226         spin_unlock(&obd->obd_dev_lock);
227
228         CDEBUG(D_IOCTL, "finished setup of obd %s (uuid %s)\n",
229                obd->obd_name, obd->obd_uuid.uuid);
230
231         RETURN(0);
232
233 err_exp:
234         class_unlink_export(obd->obd_self_export);
235         obd->obd_self_export = NULL;
236         obd->obd_starting = 0;
237         RETURN(err);
238 }
239
240 static int __class_detach(struct obd_device *obd)
241 {
242         int err = 0;
243         ENTRY;
244
245         CDEBUG(D_CONFIG, "destroying obd %d (%s)\n",
246                obd->obd_minor, obd->obd_name);
247
248         if (OBP(obd, detach))
249                 err = OBP(obd,detach)(obd);
250
251         if (obd->obd_name) {
252                 OBD_FREE(obd->obd_name, strlen(obd->obd_name)+1);
253                 obd->obd_name = NULL;
254         } else {
255                 CERROR("device %d: no name at detach\n", obd->obd_minor);
256         }
257
258         LASSERT(OBT(obd));
259         /* Attach took type refcount */
260         obd->obd_type->typ_refcnt--;
261         class_put_type(obd->obd_type);
262         class_release_dev(obd);
263         RETURN(err);
264 }
265
266 int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg)
267 {
268         ENTRY;
269
270         if (obd->obd_set_up) {
271                 CERROR("OBD device %d still set up\n", obd->obd_minor);
272                 RETURN(-EBUSY);
273         }
274
275         spin_lock(&obd->obd_dev_lock);
276         if (!obd->obd_attached) {
277                 spin_unlock(&obd->obd_dev_lock);
278                 CERROR("OBD device %d not attached\n", obd->obd_minor);
279                 RETURN(-ENODEV);
280         }
281         obd->obd_attached = 0;
282         spin_unlock(&obd->obd_dev_lock);
283
284         CDEBUG(D_IOCTL, "detach on obd %s (uuid %s)\n",
285                obd->obd_name, obd->obd_uuid.uuid);
286
287         class_decref(obd);
288         RETURN(0);
289 }
290
291 static void dump_exports(struct obd_device *obd)
292 {
293         struct obd_export *exp, *n;
294
295         list_for_each_entry_safe(exp, n, &obd->obd_exports, exp_obd_chain) {
296                 struct ptlrpc_reply_state *rs;
297                 struct ptlrpc_reply_state *first_reply = NULL;
298                 int                        nreplies = 0;
299
300                 list_for_each_entry (rs, &exp->exp_outstanding_replies,
301                                      rs_exp_list) {
302                         if (nreplies == 0)
303                                 first_reply = rs;
304                         nreplies++;
305                 }
306
307                 CDEBUG(D_IOCTL, "%s: %p %s %s %d %d %d: %p %s\n",
308                        obd->obd_name, exp, exp->exp_client_uuid.uuid,
309                        obd_export_nid2str(exp),
310                        atomic_read(&exp->exp_refcount),
311                        exp->exp_failed, nreplies, first_reply,
312                        nreplies > 3 ? "..." : "");
313         }
314 }
315
316 int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
317 {
318         int err = 0;
319         char *flag;
320         ENTRY;
321
322         OBD_RACE(OBD_FAIL_LDLM_RECOV_CLIENTS);
323
324         if (!obd->obd_set_up) {
325                 CERROR("Device %d not setup\n", obd->obd_minor);
326                 RETURN(-ENODEV);
327         }
328
329         spin_lock(&obd->obd_dev_lock);
330         if (obd->obd_stopping) {
331                 spin_unlock(&obd->obd_dev_lock);
332                 CERROR("OBD %d already stopping\n", obd->obd_minor);
333                 RETURN(-ENODEV);
334         }
335         /* Leave this on forever */
336         obd->obd_stopping = 1;
337         spin_unlock(&obd->obd_dev_lock);
338
339         if (lcfg->lcfg_bufcount >= 2 && LUSTRE_CFG_BUFLEN(lcfg, 1) > 0) {
340                 for (flag = lustre_cfg_string(lcfg, 1); *flag != 0; flag++)
341                         switch (*flag) {
342                         case 'F':
343                                 obd->obd_force = 1;
344                                 break;
345                         case 'A':
346                                 LCONSOLE_WARN("Failing %s by user command\n",
347                                        obd->obd_name);
348                                 obd->obd_fail = 1;
349                                 obd->obd_no_transno = 1;
350                                 obd->obd_no_recov = 1;
351                                 /* Set the obd readonly if we can */
352                                 if (OBP(obd, iocontrol))
353                                         obd_iocontrol(OBD_IOC_SET_READONLY,
354                                                       obd->obd_self_export,
355                                                       0, NULL, NULL);
356                                 break;
357                         default:
358                                 CERROR("unrecognised flag '%c'\n",
359                                        *flag);
360                         }
361         }
362
363         /* The three references that should be remaining are the
364          * obd_self_export and the attach and setup references. */
365         if (atomic_read(&obd->obd_refcount) > 3) {
366                 if (!(obd->obd_fail || obd->obd_force)) {
367                         CERROR("OBD %s is still busy with %d references\n"
368                                "You should stop active file system users,"
369                                " or use the --force option to cleanup.\n",
370                                obd->obd_name, atomic_read(&obd->obd_refcount));
371                         dump_exports(obd);
372                         GOTO(out, err = -EBUSY);
373                 }
374                 CDEBUG(D_IOCTL, "%s: forcing exports to disconnect: %d\n",
375                        obd->obd_name, atomic_read(&obd->obd_refcount) - 1);
376                 dump_exports(obd);
377                 class_disconnect_exports(obd);
378         }
379
380         LASSERT(obd->obd_self_export);
381
382         /* Precleanup stage 1, we must make sure all exports (other than the
383            self-export) get destroyed. */
384         err = obd_precleanup(obd, OBD_CLEANUP_EXPORTS);
385         if (err)
386                 CERROR("Precleanup %s returned %d\n",
387                        obd->obd_name, err);
388
389         class_decref(obd);
390         obd->obd_set_up = 0;
391         obd->obd_type->typ_refcnt--;
392
393         RETURN(0);
394 out:
395         /* Allow a failed cleanup to try again. */
396         obd->obd_stopping = 0;
397         RETURN(err);
398 }
399
400 void class_decref(struct obd_device *obd)
401 {
402         int err;
403         int refs;
404
405         spin_lock(&obd->obd_dev_lock);
406         atomic_dec(&obd->obd_refcount);
407         refs = atomic_read(&obd->obd_refcount);
408         spin_unlock(&obd->obd_dev_lock);
409
410         CDEBUG(D_INFO, "Decref %s now %d\n", obd->obd_name, refs);
411
412         if ((refs == 1) && obd->obd_stopping) {
413                 /* All exports (other than the self-export) have been
414                    destroyed; there should be no more in-progress ops
415                    by this point.*/
416                 /* if we're not stopping, we didn't finish setup */
417                 /* Precleanup stage 2,  do other type-specific
418                    cleanup requiring the self-export. */
419                 err = obd_precleanup(obd, OBD_CLEANUP_SELF_EXP);
420                 if (err)
421                         CERROR("Precleanup %s returned %d\n",
422                                obd->obd_name, err);
423                 obd->obd_self_export->exp_flags |=
424                         (obd->obd_fail ? OBD_OPT_FAILOVER : 0) |
425                         (obd->obd_force ? OBD_OPT_FORCE : 0);
426                 /* note that we'll recurse into class_decref again */
427                 class_unlink_export(obd->obd_self_export);
428                 return;
429         }
430
431         if (refs == 0) {
432                 CDEBUG(D_CONFIG, "finishing cleanup of obd %s (%s)\n",
433                        obd->obd_name, obd->obd_uuid.uuid);
434                 LASSERT(!obd->obd_attached);
435                 if (obd->obd_stopping) {
436                         /* If we're not stopping, we were never set up */
437                         err = obd_cleanup(obd);
438                         if (err)
439                                 CERROR("Cleanup %s returned %d\n",
440                                        obd->obd_name, err);
441                 }
442                 err = __class_detach(obd);
443                 if (err)
444                         CERROR("Detach returned %d\n", err);
445         }
446 }
447
448 int class_add_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
449 {
450         struct obd_import *imp;
451         struct obd_uuid uuid;
452         int rc;
453         ENTRY;
454
455         if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 ||
456             LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(struct obd_uuid)) {
457                 CERROR("invalid conn_uuid\n");
458                 RETURN(-EINVAL);
459         }
460         if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
461             strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME) && 
462             strcmp(obd->obd_type->typ_name, LUSTRE_MGC_NAME)) {
463                 CERROR("can't add connection on non-client dev\n");
464                 RETURN(-EINVAL);
465         }
466
467         imp = obd->u.cli.cl_import;
468         if (!imp) {
469                 CERROR("try to add conn on immature client dev\n");
470                 RETURN(-EINVAL);
471         }
472
473         obd_str2uuid(&uuid, lustre_cfg_string(lcfg, 1));
474         rc = obd_add_conn(imp, &uuid, lcfg->lcfg_num);
475
476         RETURN(rc);
477 }
478
479 int class_del_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
480 {
481         struct obd_import *imp;
482         struct obd_uuid uuid;
483         int rc;
484         ENTRY;
485
486         if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 ||
487             LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(struct obd_uuid)) {
488                 CERROR("invalid conn_uuid\n");
489                 RETURN(-EINVAL);
490         }
491         if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
492             strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME)) {
493                 CERROR("can't del connection on non-client dev\n");
494                 RETURN(-EINVAL);
495         }
496
497         imp = obd->u.cli.cl_import;
498         if (!imp) {
499                 CERROR("try to del conn on immature client dev\n");
500                 RETURN(-EINVAL);
501         }
502
503         obd_str2uuid(&uuid, lustre_cfg_string(lcfg, 1));
504         rc = obd_del_conn(imp, &uuid);
505
506         RETURN(rc);
507 }
508
509 LIST_HEAD(lustre_profile_list);
510
511 struct lustre_profile *class_get_profile(char * prof)
512 {
513         struct lustre_profile *lprof;
514
515         list_for_each_entry(lprof, &lustre_profile_list, lp_list) {
516                 if (!strcmp(lprof->lp_profile, prof)) {
517                         RETURN(lprof);
518                 }
519         }
520         RETURN(NULL);
521 }
522
523 int class_add_profile(int proflen, char *prof, int osclen, char *osc,
524                       int mdclen, char *mdc)
525 {
526         struct lustre_profile *lprof;
527         int err = 0;
528
529         OBD_ALLOC(lprof, sizeof(*lprof));
530         if (lprof == NULL)
531                 RETURN(-ENOMEM);
532         INIT_LIST_HEAD(&lprof->lp_list);
533
534         LASSERT(proflen == (strlen(prof) + 1));
535         OBD_ALLOC(lprof->lp_profile, proflen);
536         if (lprof->lp_profile == NULL)
537                 GOTO(out, err = -ENOMEM);
538         memcpy(lprof->lp_profile, prof, proflen);
539
540         LASSERT(osclen == (strlen(osc) + 1));
541         OBD_ALLOC(lprof->lp_osc, osclen);
542         if (lprof->lp_osc == NULL)
543                 GOTO(out, err = -ENOMEM);
544         memcpy(lprof->lp_osc, osc, osclen);
545
546         if (mdclen > 0) {
547                 LASSERT(mdclen == (strlen(mdc) + 1));
548                 OBD_ALLOC(lprof->lp_mdc, mdclen);
549                 if (lprof->lp_mdc == NULL)
550                         GOTO(out, err = -ENOMEM);
551                 memcpy(lprof->lp_mdc, mdc, mdclen);
552         }
553
554         list_add(&lprof->lp_list, &lustre_profile_list);
555         RETURN(err);
556
557 out:
558         if (lprof->lp_mdc)
559                 OBD_FREE(lprof->lp_mdc, mdclen);
560         if (lprof->lp_osc)
561                 OBD_FREE(lprof->lp_osc, osclen);
562         if (lprof->lp_profile)
563                 OBD_FREE(lprof->lp_profile, proflen);
564         OBD_FREE(lprof, sizeof(*lprof));        
565         RETURN(err);                             
566 }
567
568 void class_del_profile(char *prof)
569 {
570         struct lustre_profile *lprof;
571
572         lprof = class_get_profile(prof);
573         if (lprof) {
574                 list_del(&lprof->lp_list);
575                 OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
576                 OBD_FREE(lprof->lp_osc, strlen(lprof->lp_osc) + 1);
577                 if (lprof->lp_mdc)
578                         OBD_FREE(lprof->lp_mdc, strlen(lprof->lp_mdc) + 1);
579                 OBD_FREE(lprof, sizeof *lprof);
580         }
581 }
582
583 int class_process_config(struct lustre_cfg *lcfg)
584 {
585         struct obd_device *obd;
586         int err;
587
588         LASSERT(lcfg && !IS_ERR(lcfg));
589         CDEBUG(D_IOCTL, "processing cmd: %x\n", lcfg->lcfg_command);
590
591         /* Commands that don't need a device */
592         switch(lcfg->lcfg_command) {
593         case LCFG_ATTACH: {
594                 err = class_attach(lcfg);
595                 GOTO(out, err);
596         }
597         case LCFG_ADD_UUID: {
598                 CDEBUG(D_IOCTL, "adding mapping from uuid %s to nid "LPX64
599                        " (%s)\n", lustre_cfg_string(lcfg, 1),
600                        lcfg->lcfg_nid, libcfs_nid2str(lcfg->lcfg_nid));
601
602                 err = class_add_uuid(lustre_cfg_string(lcfg, 1), lcfg->lcfg_nid);
603                 GOTO(out, err);
604         }
605         case LCFG_DEL_UUID: {
606                 CDEBUG(D_IOCTL, "removing mappings for uuid %s\n",
607                        (lcfg->lcfg_bufcount < 2 || LUSTRE_CFG_BUFLEN(lcfg, 1) == 0)
608                        ? "<all uuids>" : lustre_cfg_string(lcfg, 1));
609
610                 err = class_del_uuid(lustre_cfg_string(lcfg, 1));
611                 GOTO(out, err);
612         }
613         case LCFG_MOUNTOPT: {
614                 CDEBUG(D_IOCTL, "mountopt: profile %s osc %s mdc %s\n",
615                        lustre_cfg_string(lcfg, 1),
616                        lustre_cfg_string(lcfg, 2),
617                        lustre_cfg_string(lcfg, 3));
618                 /* set these mount options somewhere, so ll_fill_super
619                  * can find them. */
620                 err = class_add_profile(LUSTRE_CFG_BUFLEN(lcfg, 1),
621                                         lustre_cfg_string(lcfg, 1),
622                                         LUSTRE_CFG_BUFLEN(lcfg, 2),
623                                         lustre_cfg_string(lcfg, 2),
624                                         LUSTRE_CFG_BUFLEN(lcfg, 3),
625                                         lustre_cfg_string(lcfg, 3));
626                 GOTO(out, err);
627         }
628         case LCFG_DEL_MOUNTOPT: {
629                 CDEBUG(D_IOCTL, "mountopt: profile %s\n",
630                        lustre_cfg_string(lcfg, 1));
631                 /* set these mount options somewhere, so ll_fill_super
632                  * can find them. */
633                 class_del_profile(lustre_cfg_string(lcfg, 1));
634                 GOTO(out, err = 0);
635         }
636         case LCFG_SET_TIMEOUT: {
637                 CDEBUG(D_IOCTL, "changing lustre timeout from %d to %d\n",
638                        obd_timeout, lcfg->lcfg_num);
639                 obd_timeout = max(lcfg->lcfg_num, 1U);
640                 if (ldlm_timeout >= obd_timeout)
641                         ldlm_timeout = max(obd_timeout / 3, 1U);
642                 GOTO(out, err = 0);
643         }
644         case LCFG_SET_UPCALL: {
645                 CDEBUG(D_IOCTL, "setting lustre ucpall to: %s\n",
646                        lustre_cfg_string(lcfg, 1));
647                 if (LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof obd_lustre_upcall)
648                         GOTO(out, err = -EINVAL);
649                 strncpy(obd_lustre_upcall, lustre_cfg_string(lcfg, 1),
650                         sizeof (obd_lustre_upcall));
651                 GOTO(out, err = 0);
652         }
653         case LCFG_MARKER: {
654                 struct cfg_marker *marker;
655                 LCONSOLE_WARN("LCFG_MARKER not yet implemented.\n");
656                 marker = lustre_cfg_buf(lcfg, 1);
657                 CDEBUG(D_WARNING, "%d (%x) %s\n", marker->cm_step,
658                        marker->cm_flags, marker->cm_comment);
659                 GOTO(out, err = 0);
660         }
661         }
662
663         /* Commands that require a device */
664         obd = class_name2obd(lustre_cfg_string(lcfg, 0));
665         if (obd == NULL) {
666                 if (!LUSTRE_CFG_BUFLEN(lcfg, 0))
667                         CERROR("this lcfg command requires a device name\n");
668                 else
669                         CERROR("no device for: %s\n",
670                                lustre_cfg_string(lcfg, 0));
671
672                 GOTO(out, err = -EINVAL);
673         }
674
675         switch(lcfg->lcfg_command) {
676         case LCFG_SETUP: {
677                 err = class_setup(obd, lcfg);
678                 GOTO(out, err);
679         }
680         case LCFG_DETACH: {
681                 err = class_detach(obd, lcfg);
682                 GOTO(out, err = 0);
683         }
684         case LCFG_CLEANUP: {
685                 err = class_cleanup(obd, lcfg);
686                 GOTO(out, err = 0);
687         }
688         case LCFG_ADD_CONN: {
689                 err = class_add_conn(obd, lcfg);
690                 GOTO(out, err = 0);
691         }
692         case LCFG_DEL_CONN: {
693                 err = class_del_conn(obd, lcfg);
694                 GOTO(out, err = 0);
695         }
696         default: {
697                 err = obd_process_config(obd, sizeof(*lcfg), lcfg);
698                 GOTO(out, err);
699
700         }
701         }
702 out:
703         return err;
704 }
705
706 int class_config_dump_handler(struct llog_handle * handle,
707                               struct llog_rec_hdr *rec, void *data);
708
709 static int class_config_llog_handler(struct llog_handle * handle,
710                                      struct llog_rec_hdr *rec, void *data)
711 {
712         struct config_llog_instance *cfg = data;
713         int cfg_len = rec->lrh_len;
714         char *cfg_buf = (char*) (rec + 1);
715         int rc = 0;
716         ENTRY;
717         
718         // FIXME remove
719         class_config_dump_handler(handle, rec, data);
720
721         switch (rec->lrh_type) {
722         case OBD_CFG_REC: {
723                 struct lustre_cfg *lcfg, *lcfg_new;
724                 struct lustre_cfg_bufs bufs;
725                 char *inst_name = NULL;
726                 int inst_len = 0;
727                 int inst = 0;
728
729                 lcfg = (struct lustre_cfg *)cfg_buf;
730                 if (lcfg->lcfg_magic == __swab32(LUSTRE_CFG_MAGIC))
731                         lustre_swab_lustre_cfg(lcfg);
732
733                 rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
734                 if (rc)
735                         GOTO(out, rc);
736
737                 lustre_cfg_bufs_init(&bufs, lcfg);
738
739                 if (cfg && cfg->cfg_instance && LUSTRE_CFG_BUFLEN(lcfg, 0) > 0) {
740                         inst = 1;
741                         inst_len = LUSTRE_CFG_BUFLEN(lcfg, 0) +
742                                 strlen(cfg->cfg_instance) + 1;
743                         OBD_ALLOC(inst_name, inst_len);
744                         if (inst_name == NULL)
745                                 GOTO(out, rc = -ENOMEM);
746                         sprintf(inst_name, "%s-%s",
747                                 lustre_cfg_string(lcfg, 0),
748                                 cfg->cfg_instance);
749                         lustre_cfg_bufs_set_string(&bufs, 0, inst_name);
750                         CERROR("cmd %x, instance name: %s\n", 
751                                lcfg->lcfg_command, inst_name);
752                 }
753
754                 /* we override the llog's uuid for clients, to insure they
755                 are unique */
756                 if (cfg && cfg->cfg_instance && 
757                     lcfg->lcfg_command == LCFG_ATTACH) {
758                         lustre_cfg_bufs_set_string(&bufs, 2, cfg->cfg_uuid.uuid);
759                 }
760
761                 lcfg_new = lustre_cfg_new(lcfg->lcfg_command, &bufs);
762
763                 lcfg_new->lcfg_num   = lcfg->lcfg_num;
764                 lcfg_new->lcfg_flags = lcfg->lcfg_flags;
765
766                 /* XXX Hack to try to remain binary compatible with
767                  * pre-newconfig logs */
768                 if (lcfg->lcfg_nal != 0 &&      /* pre-newconfig log? */
769                     (lcfg->lcfg_nid >> 32) == 0) {
770                         __u32 addr = (__u32)(lcfg->lcfg_nid & 0xffffffff);
771
772                         lcfg_new->lcfg_nid =
773                                 LNET_MKNID(LNET_MKNET(lcfg->lcfg_nal, 0), addr);
774                         CWARN("Converted pre-newconfig NAL %d NID %x to %s\n",
775                               lcfg->lcfg_nal, addr,
776                               libcfs_nid2str(lcfg_new->lcfg_nid));
777                 } else {
778                         lcfg_new->lcfg_nid = lcfg->lcfg_nid;
779                 }
780
781                 lcfg_new->lcfg_nal = 0; /* illegal value for obsolete field */
782
783                 rc = class_process_config(lcfg_new);
784                 lustre_cfg_free(lcfg_new);
785
786                 if (inst)
787                         OBD_FREE(inst_name, inst_len);
788                 break;
789         }
790         case PTL_CFG_REC: {
791                 CWARN("Ignoring obsolete portals config\n");
792                 break;
793         }
794         default:
795                 CERROR("Unknown llog record type %#x encountered\n",
796                        rec->lrh_type);
797                 break;
798         }
799 out:
800         RETURN(rc);
801 }
802
803 int class_config_parse_llog(struct llog_ctxt *ctxt, char *name,
804                             struct config_llog_instance *cfg)
805 {
806         struct llog_handle *llh;
807         int rc, rc2;
808         ENTRY;
809
810         CDEBUG(D_INFO, "looking up llog %s\n", name);
811         rc = llog_create(ctxt, &llh, NULL, name);
812         if (rc)
813                 RETURN(rc);
814
815         rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
816         if (rc)
817                 GOTO(parse_out, rc);
818
819         rc = llog_process(llh, class_config_llog_handler, cfg, NULL);
820 parse_out:
821         rc2 = llog_close(llh);
822         if (rc == 0)
823                 rc = rc2;
824
825         RETURN(rc);
826 }
827
828 #define D_DUMP D_INFO|D_WARNING
829 int class_config_dump_handler(struct llog_handle * handle,
830                               struct llog_rec_hdr *rec, void *data)
831 {
832         int cfg_len = rec->lrh_len;
833         char *cfg_buf = (char*) (rec + 1);
834         char *outstr, *ptr, *end;
835         int rc = 0;
836         ENTRY;
837
838         OBD_ALLOC(outstr, 256);
839         end = outstr + 256;
840         ptr = outstr;
841         if (!outstr) {
842                 RETURN(-ENOMEM);
843         }
844         if (rec->lrh_type == OBD_CFG_REC) {
845                 struct lustre_cfg *lcfg;
846                 int i;
847
848                 rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
849                 if (rc)
850                         GOTO(out, rc);
851                 lcfg = (struct lustre_cfg *)cfg_buf;
852
853                 ptr += snprintf(ptr, end-ptr, "\n   cmd=%05x ",
854                                 lcfg->lcfg_command);
855                 if (lcfg->lcfg_flags) {
856                         ptr += snprintf(ptr, end-ptr, "flags=%#08x ",
857                                         lcfg->lcfg_flags);
858                 }
859                 if (lcfg->lcfg_num) {
860                         ptr += snprintf(ptr, end-ptr, "num=%#08x ",
861                                         lcfg->lcfg_num);
862                 }
863                 if (lcfg->lcfg_nid) {
864                         ptr += snprintf(ptr, end-ptr, "nid=%s("LPX64")\n",
865                                         libcfs_nid2str(lcfg->lcfg_nid),
866                                         lcfg->lcfg_nid);
867                 }
868                 for (i = 0; i <  lcfg->lcfg_bufcount; i++) {
869                         ptr += snprintf(ptr, end-ptr, "%d:%s  ", i,
870                                         lustre_cfg_string(lcfg, i));
871                 }
872                 CDEBUG(D_DUMP, "%s\n", outstr);
873         } else if (rec->lrh_type == PTL_CFG_REC) {
874                 CDEBUG(D_DUMP, "Obsolete pcfg command\n");
875         } else {
876                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
877                 rc = -EINVAL;
878         }
879 out:
880         OBD_FREE(outstr, end - outstr);
881         RETURN(rc);
882 }
883
884 int class_config_dump_llog(struct llog_ctxt *ctxt, char *name,
885                            struct config_llog_instance *cfg)
886 {
887         struct llog_handle *llh;
888         int rc, rc2;
889         ENTRY;
890
891         CDEBUG(D_DUMP, "Dumping config log %s\n", name);
892
893         rc = llog_create(ctxt, &llh, NULL, name);
894         if (rc)
895                 RETURN(rc);
896
897         rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
898         if (rc)
899                 GOTO(parse_out, rc);
900
901         rc = llog_process(llh, class_config_dump_handler, cfg, NULL);
902 parse_out:
903         rc2 = llog_close(llh);
904         if (rc == 0)
905                 rc = rc2;
906
907         CDEBUG(D_DUMP, "End config log %s\n", name);
908         RETURN(rc);
909
910 }
911
912 /* Cleanup and detach */
913 int class_manual_cleanup(struct obd_device *obd)
914 {
915         struct lustre_cfg *lcfg;
916         struct lustre_cfg_bufs bufs;
917         int rc;
918         char flags[3]="";
919         ENTRY;
920
921         if (!obd) {
922                 CERROR("empty cleanup\n");
923                 RETURN(-EALREADY);
924         }
925
926         if (obd->obd_force)
927                 strcat(flags, "F");
928         if (obd->obd_fail)
929                 strcat(flags, "A");
930
931         CDEBUG(D_CONFIG, "Manual cleanup of %s (flags='%s')\n",
932                obd->obd_name, flags);
933
934         lustre_cfg_bufs_reset(&bufs, obd->obd_name);
935         lustre_cfg_bufs_set_string(&bufs, 1, flags);
936         lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
937
938         rc = class_process_config(lcfg);
939         if (rc) {
940                 CERROR("cleanup failed %d: %s\n", rc, obd->obd_name);
941                 GOTO(out, rc);
942         }
943
944         /* the lcfg is almost the same for both ops */
945         lcfg->lcfg_command = LCFG_DETACH;
946         rc = class_process_config(lcfg);
947         if (rc)
948                 CERROR("detach failed %d: %s\n", rc, obd->obd_name);
949 out:
950         lustre_cfg_free(lcfg);
951         RETURN(rc);
952 }
953