Whamcloud - gitweb
b=6063
[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 Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  *
21  * Config API
22  *
23  */
24
25 #define DEBUG_SUBSYSTEM S_CLASS
26 #ifdef __KERNEL__
27 #include <linux/kmod.h>   /* for request_module() */
28 #include <linux/module.h>
29 #include <linux/obd_class.h>
30 #include <linux/random.h>
31 #include <linux/slab.h>
32 #include <linux/pagemap.h>
33 #else
34 #include <liblustre.h>
35 #include <linux/obd_class.h>
36 #include <linux/obd.h>
37 #endif
38 #include <linux/lustre_log.h>
39 #include <linux/lprocfs_status.h>
40 #include <libcfs/list.h>
41
42
43 /* Create a new device and set the type, name and uuid.  If
44  * successful, the new device can be accessed by either name or uuid.
45  */
46 static int class_attach(struct lustre_cfg *lcfg)
47 {
48         struct obd_type *type;
49         struct obd_device *obd;
50         char *typename, *name, *uuid;
51         int rc, len, cleanup_phase = 0;
52
53         if (!lcfg->lcfg_inllen1 || !lcfg->lcfg_inlbuf1) {
54                 CERROR("No type passed!\n");
55                 RETURN(-EINVAL);
56         }
57         if (lcfg->lcfg_inlbuf1[lcfg->lcfg_inllen1 - 1] != 0) {
58                 CERROR("Type not nul terminated!\n");
59                 RETURN(-EINVAL);
60         }
61         typename = lcfg->lcfg_inlbuf1;
62
63         if (!lcfg->lcfg_dev_namelen || !lcfg->lcfg_dev_name) {
64                 CERROR("No name passed!\n");
65                 RETURN(-EINVAL);
66         }
67         if (lcfg->lcfg_dev_name[lcfg->lcfg_dev_namelen - 1] != 0) {
68                 CERROR("Name not nul terminated!\n");
69                 RETURN(-EINVAL);
70         }
71         name = lcfg->lcfg_dev_name;
72
73         if (!lcfg->lcfg_inllen2 || !lcfg->lcfg_inlbuf2) {
74                 CERROR("No UUID passed!\n");
75                 RETURN(-EINVAL);
76         }
77         if (lcfg->lcfg_inlbuf2[lcfg->lcfg_inllen2 - 1] != 0) {
78                 CERROR("UUID not nul terminated!\n");
79                 RETURN(-EINVAL);
80         }
81         uuid = lcfg->lcfg_inlbuf2;
82
83         CDEBUG(D_IOCTL, "attach type %s name: %s uuid: %s\n",
84                MKSTR(lcfg->lcfg_inlbuf1), MKSTR(lcfg->lcfg_dev_name),
85                MKSTR(lcfg->lcfg_inlbuf2));
86
87         /* find the type */
88         type = class_get_type(typename);
89         if (!type) {
90                 CERROR("OBD: unknown type: %s\n", typename);
91                 RETURN(-EINVAL);
92         }
93         cleanup_phase = 1;  /* class_put_type */
94
95         obd = class_name2obd(name);
96         if (obd != NULL) {
97                 CERROR("obd %s already attached\n", name);
98                 GOTO(out, rc = -EEXIST);
99         }
100
101         obd = class_newdev(type);
102         if (obd == NULL)
103                 GOTO(out, rc = -EINVAL);
104
105         cleanup_phase = 2;  /* class_release_dev */
106         
107         INIT_LIST_HEAD(&obd->obd_exports);
108         obd->obd_num_exports = 0;
109         spin_lock_init(&obd->obd_dev_lock);
110         spin_lock_init(&obd->obd_osfs_lock);
111         obd->obd_osfs_age = jiffies - 1000 * HZ;
112         init_waitqueue_head(&obd->obd_refcount_waitq);
113
114         /* XXX belongs in setup not attach  */
115         /* recovery data */
116         init_timer(&obd->obd_recovery_timer);
117         spin_lock_init(&obd->obd_processing_task_lock);
118         init_waitqueue_head(&obd->obd_next_transno_waitq);
119         INIT_LIST_HEAD(&obd->obd_req_replay_queue);
120         INIT_LIST_HEAD(&obd->obd_lock_replay_queue);
121         INIT_LIST_HEAD(&obd->obd_final_req_queue);
122
123         spin_lock_init(&obd->obd_uncommitted_replies_lock);
124         INIT_LIST_HEAD(&obd->obd_uncommitted_replies);
125
126         len = strlen(name) + 1;
127         OBD_ALLOC(obd->obd_name, len);
128         if (!obd->obd_name)
129                 GOTO(out, rc = -ENOMEM);
130         memcpy(obd->obd_name, name, len);
131         
132         cleanup_phase = 3; /* free obd_name */
133
134         len = strlen(uuid);
135         if (len >= sizeof(obd->obd_uuid)) {
136                 CERROR("uuid must be < "LPSZ" bytes long\n",
137                        sizeof(obd->obd_uuid));
138                 GOTO(out, rc = -EINVAL);
139         }
140         memcpy(obd->obd_uuid.uuid, uuid, len);
141
142         /* do the attach */
143         if (OBP(obd, attach)) {
144                 rc = OBP(obd,attach)(obd, sizeof *lcfg, lcfg);
145                 if (rc)
146                         GOTO(out, rc = -EINVAL);
147         }
148
149         obd->obd_attached = 1;
150         type->typ_refcnt++;
151         CDEBUG(D_IOCTL, "OBD: dev %d attached type %s\n",
152                obd->obd_minor, typename);
153         RETURN(0);
154  out:
155         switch (cleanup_phase) {
156         case 3:
157                 OBD_FREE(obd->obd_name, strlen(obd->obd_name) + 1);
158         case 2:
159                 class_release_dev(obd);
160         case 1:
161                 class_put_type(type);
162         }
163         return rc;
164 }
165
166 static int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
167 {
168         int err = 0;
169         struct obd_export *exp;
170         ENTRY;
171
172         LASSERT(obd == (obd_dev + obd->obd_minor));
173
174         /* have we attached a type to this device? */
175         if (!obd->obd_attached) {
176                 CERROR("Device %d not attached\n", obd->obd_minor);
177                 RETURN(-ENODEV);
178         }
179
180         /* has this been done already? */
181         if (obd->obd_set_up) {
182                 CERROR("Device %d already setup (type %s)\n",
183                        obd->obd_minor, obd->obd_type->typ_name);
184                 RETURN(-EBUSY);
185         }
186
187         atomic_set(&obd->obd_refcount, 0);
188
189         exp = class_new_export(obd);
190         if (exp == NULL)
191                 RETURN(err);
192         memcpy(&exp->exp_client_uuid, &obd->obd_uuid,
193                sizeof(exp->exp_client_uuid));
194         obd->obd_self_export = exp;
195         class_export_put(exp);
196
197         err = obd_setup(obd, sizeof(*lcfg), lcfg);
198         if (err)
199                 GOTO(err_exp, err);
200
201         obd->obd_type->typ_refcnt++;
202         obd->obd_set_up = 1;
203
204         RETURN(err);
205
206 err_exp:
207         class_unlink_export(obd->obd_self_export);
208         obd->obd_self_export = NULL;
209         RETURN(err);
210 }
211
212 static int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg)
213 {
214         int err = 0;
215
216         ENTRY;
217         if (obd->obd_set_up) {
218                 CERROR("OBD device %d still set up\n", obd->obd_minor);
219                 RETURN(-EBUSY);
220         }
221         if (!obd->obd_attached) {
222                 CERROR("OBD device %d not attached\n", obd->obd_minor);
223                 RETURN(-ENODEV);
224         }
225         if (OBP(obd, detach))
226                 err = OBP(obd,detach)(obd);
227
228         if (obd->obd_name) {
229                 OBD_FREE(obd->obd_name, strlen(obd->obd_name)+1);
230                 obd->obd_name = NULL;
231         } else {
232                 CERROR("device %d: no name at detach\n", obd->obd_minor);
233         }
234
235         obd->obd_attached = 0;
236         obd->obd_type->typ_refcnt--;
237         class_put_type(obd->obd_type);
238         class_release_dev(obd);
239         RETURN(err);
240 }
241
242 static void dump_exports(struct obd_device *obd)
243 {
244         struct obd_export *exp, *n;
245
246         list_for_each_entry_safe(exp, n, &obd->obd_exports, exp_obd_chain) {
247                 struct ptlrpc_reply_state *rs;
248                 struct ptlrpc_reply_state *first_reply = NULL;
249                 int                        nreplies = 0;
250
251                 list_for_each_entry (rs, &exp->exp_outstanding_replies,
252                                      rs_exp_list) {
253                         if (nreplies == 0)
254                                 first_reply = rs;
255                         nreplies++;
256                 }
257
258                 CERROR("%s: %p %s %d %d %d: %p %s\n",
259                        obd->obd_name, exp, exp->exp_client_uuid.uuid,
260                        atomic_read(&exp->exp_refcount),
261                        exp->exp_failed, nreplies, first_reply,
262                        nreplies > 3 ? "..." : "");
263         }
264 }
265
266 static int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
267 {
268         int flags = 0;
269         int err = 0;
270         char *flag;
271
272         ENTRY;
273         if (!obd->obd_set_up) {
274                 CERROR("Device %d not setup\n", obd->obd_minor);
275                 RETURN(-ENODEV);
276         }
277
278         if (lcfg->lcfg_inlbuf1) {
279                 for (flag = lcfg->lcfg_inlbuf1; *flag != 0; flag++)
280                         switch (*flag) {
281                         case 'F':
282                                 flags |= OBD_OPT_FORCE;
283                                 break;
284                         case 'A':
285                                 flags |= OBD_OPT_FAILOVER;
286                                 break;
287                         default:
288                                 CERROR("unrecognised flag '%c'\n",
289                                        *flag);
290                         }
291         }
292
293         /* The one reference that should be remaining is the
294          * obd_self_export */
295         if (atomic_read(&obd->obd_refcount) <= 1 ||
296             flags & OBD_OPT_FORCE) {
297                 /* this will stop new connections, and need to
298                    do it before class_disconnect_exports() */
299                 obd->obd_stopping = 1;
300         }
301
302         if (atomic_read(&obd->obd_refcount) > 1) {
303                 struct l_wait_info lwi = LWI_TIMEOUT_INTR(1 * HZ, NULL,
304                                                           NULL, NULL);
305                 int rc;
306
307                 if (!(flags & OBD_OPT_FORCE)) {
308                         CERROR("OBD device %d (%p,%s) has refcount %d\n",
309                                obd->obd_minor, obd, obd->obd_name,
310                                atomic_read(&obd->obd_refcount));
311                         dump_exports(obd);
312                         GOTO(out, err = -EBUSY);
313                 }
314                 class_disconnect_exports(obd, flags);
315                 CDEBUG(D_IOCTL,
316                        "%s: waiting for obd refs to go away: %d\n",
317                        obd->obd_name, atomic_read(&obd->obd_refcount));
318
319                 rc = l_wait_event(obd->obd_refcount_waitq,
320                                   atomic_read(&obd->obd_refcount) < 2, &lwi);
321                 if (rc == 0) {
322                         LASSERT(atomic_read(&obd->obd_refcount) == 1);
323                 } else {
324                         CERROR("wait cancelled cleaning anyway. "
325                                "refcount: %d\n",
326                                atomic_read(&obd->obd_refcount));
327                         dump_exports(obd);
328                 }
329                 CDEBUG(D_IOCTL, "%s: awake, now finishing cleanup\n",
330                        obd->obd_name);
331         }
332
333         if (obd->obd_self_export) {
334                 err = obd_precleanup(obd, flags);
335                 if (err)
336                         GOTO(out, err);
337                 class_unlink_export(obd->obd_self_export);
338                 obd->obd_self_export = NULL;
339         }
340
341         err = obd_cleanup(obd, flags);
342 out:
343         if (!err) {
344                 obd->obd_set_up = obd->obd_stopping = 0;
345                 obd->obd_type->typ_refcnt--;
346                 /* XXX this should be an LASSERT */
347                 if (atomic_read(&obd->obd_refcount) > 0) {
348                         CERROR("%s (%p) still has refcount %d after "
349                                "cleanup.\n", obd->obd_name, obd,
350                                atomic_read(&obd->obd_refcount));
351                         dump_exports(obd);
352                 }
353         }
354
355         RETURN(err);
356 }
357
358 int class_add_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
359 {
360         struct obd_import *imp;
361         struct obd_uuid uuid;
362         int priority, rc;
363         ENTRY;
364
365         if (lcfg->lcfg_inllen1 <= 0 ||
366             lcfg->lcfg_inllen1 > sizeof(struct obd_uuid)) {
367                 CERROR("invalid conn_uuid\n");
368                 RETURN(-EINVAL);
369         }
370         if (lcfg->lcfg_inllen2 != sizeof(int)) {
371                 CERROR("invalid priority\n");
372                 RETURN(-EINVAL);
373         }
374         if (strcmp(obd->obd_type->typ_name, "mdc") &&
375             strcmp(obd->obd_type->typ_name, "osc")) {
376                 CERROR("can't add connection on non-client dev\n");
377                 RETURN(-EINVAL);
378         }
379
380         imp = obd->u.cli.cl_import;
381         if (!imp) {
382                 CERROR("try to add conn on immature client dev\n");
383                 RETURN(-EINVAL);
384         }
385
386         obd_str2uuid(&uuid, lcfg->lcfg_inlbuf1);
387         priority = *((int*) lcfg->lcfg_inlbuf2);
388         rc = obd_add_conn(imp, &uuid, priority);
389
390         RETURN(rc);
391 }
392 int class_del_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
393 {
394         struct obd_import *imp;
395         struct obd_uuid uuid;
396         int rc;
397         ENTRY;
398
399         if (lcfg->lcfg_inllen1 <= 0 ||
400             lcfg->lcfg_inllen1 > sizeof(struct obd_uuid)) {
401                 CERROR("invalid conn_uuid\n");
402                 RETURN(-EINVAL);
403         }
404         if (strcmp(obd->obd_type->typ_name, "mdc") &&
405             strcmp(obd->obd_type->typ_name, "osc")) {
406                 CERROR("can't add connection on non-client dev\n");
407                 RETURN(-EINVAL);
408         }
409
410         imp = obd->u.cli.cl_import;
411         if (!imp) {
412                 CERROR("try to del conn on immature client dev\n");
413                 RETURN(-EINVAL);
414         }
415
416         obd_str2uuid(&uuid, lcfg->lcfg_inlbuf1);
417         rc = obd_del_conn(imp, &uuid);
418
419         RETURN(rc);
420 }
421
422 LIST_HEAD(lustre_profile_list);
423
424 struct lustre_profile *class_get_profile(char * prof)
425 {
426         struct lustre_profile *lprof;
427
428         list_for_each_entry(lprof, &lustre_profile_list, lp_list) {
429                 if (!strcmp(lprof->lp_profile, prof)) {
430                         RETURN(lprof);
431                 }
432         }
433         RETURN(NULL);
434 }
435
436 int class_add_profile(int proflen, char *prof,
437                       int lovlen, char *lov,
438                       int lmvlen, char *lmv)
439 {
440         struct lustre_profile *lprof;
441         int err = 0;
442
443         OBD_ALLOC(lprof, sizeof(*lprof));
444         if (lprof == NULL)
445                 GOTO(out, err = -ENOMEM);
446         INIT_LIST_HEAD(&lprof->lp_list);
447
448         LASSERT(proflen == (strlen(prof) + 1));
449         OBD_ALLOC(lprof->lp_profile, proflen);
450         if (lprof->lp_profile == NULL)
451                 GOTO(out, err = -ENOMEM);
452         memcpy(lprof->lp_profile, prof, proflen);
453
454         LASSERT(lovlen == (strlen(lov) + 1));
455         OBD_ALLOC(lprof->lp_lov, lovlen);
456         if (lprof->lp_profile == NULL)
457                 GOTO(out, err = -ENOMEM);
458         memcpy(lprof->lp_lov, lov, lovlen);
459
460         if (lmvlen > 0) {
461                 LASSERT(lmvlen == (strlen(lmv) + 1));
462                 OBD_ALLOC(lprof->lp_lmv, lmvlen);
463                 if (lprof->lp_lmv == NULL)
464                         GOTO(out, err = -ENOMEM);
465                 memcpy(lprof->lp_lmv, lmv, lmvlen);
466         }
467
468         list_add(&lprof->lp_list, &lustre_profile_list);
469
470 out:
471         RETURN(err);
472 }
473
474 void class_del_profile(char *prof)
475 {
476         struct lustre_profile *lprof;
477
478         lprof = class_get_profile(prof);
479         if (lprof) {
480                 list_del(&lprof->lp_list);
481                 OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
482                 OBD_FREE(lprof->lp_lov, strlen(lprof->lp_lov) + 1);
483                 if (lprof->lp_lmv)
484                         OBD_FREE(lprof->lp_lmv, strlen(lprof->lp_lmv) + 1);
485                 OBD_FREE(lprof, sizeof *lprof);
486         }
487 }
488
489 int class_process_config(struct lustre_cfg *lcfg)
490 {
491         struct obd_device *obd;
492         char str[PTL_NALFMT_SIZE];
493         int err;
494         ENTRY;
495
496         LASSERT(lcfg && !IS_ERR(lcfg));
497
498         CDEBUG(D_IOCTL, "processing cmd: %x\n", lcfg->lcfg_command);
499
500         /* Commands that don't need a device */
501         switch(lcfg->lcfg_command) {
502         case LCFG_ATTACH: {
503                 err = class_attach(lcfg);
504                 GOTO(out, err);
505         }
506         case LCFG_ADD_UUID: {
507                 CDEBUG(D_IOCTL, "adding mapping from uuid %s to nid "LPX64
508                        " (%s), nal %x\n", lcfg->lcfg_inlbuf1, lcfg->lcfg_nid,
509                        portals_nid2str(lcfg->lcfg_nal, lcfg->lcfg_nid, str),
510                        lcfg->lcfg_nal);
511
512                 err = class_add_uuid(lcfg->lcfg_inlbuf1, lcfg->lcfg_nid,
513                                      lcfg->lcfg_nal);
514                 GOTO(out, err);
515         }
516         case LCFG_DEL_UUID: {
517                 CDEBUG(D_IOCTL, "removing mappings for uuid %s\n",
518                        lcfg->lcfg_inlbuf1 == NULL ? "<all uuids>" :
519                        lcfg->lcfg_inlbuf1);
520
521                 err = class_del_uuid(lcfg->lcfg_inlbuf1);
522                 GOTO(out, err);
523         }
524         case LCFG_MOUNTOPT: {
525                 CDEBUG(D_IOCTL, "mountopt: profile %s osc %s mdc %s\n",
526                        lcfg->lcfg_inlbuf1, lcfg->lcfg_inlbuf2,
527                        lcfg->lcfg_inlbuf3);
528                 /* set these mount options somewhere, so ll_fill_super
529                  * can find them. */
530                 err = class_add_profile(lcfg->lcfg_inllen1, lcfg->lcfg_inlbuf1,
531                                         lcfg->lcfg_inllen2, lcfg->lcfg_inlbuf2,
532                                         lcfg->lcfg_inllen3, lcfg->lcfg_inlbuf3);
533                 GOTO(out, err);
534         }
535         case LCFG_DEL_MOUNTOPT: {
536                 CDEBUG(D_IOCTL, "mountopt: profile %s\n", lcfg->lcfg_inlbuf1);
537                 /* set these mount options somewhere, so ll_fill_super
538                  * can find them. */
539                 class_del_profile(lcfg->lcfg_inlbuf1);
540                 GOTO(out, err = 0);
541         }
542         case LCFG_SET_TIMEOUT: {
543                 CDEBUG(D_IOCTL, "changing lustre timeout from %d to %d\n",
544                        obd_timeout,
545                        lcfg->lcfg_num);
546                 obd_timeout = lcfg->lcfg_num;
547                 GOTO(out, err = 0);
548         }
549         case LCFG_SET_UPCALL: {
550                 CDEBUG(D_IOCTL, "setting lustre ucpall to: %s\n",
551                        lcfg->lcfg_inlbuf1);
552                 if (lcfg->lcfg_inllen1 > sizeof obd_lustre_upcall)
553                         GOTO(out, err = -EINVAL);
554                 memcpy(obd_lustre_upcall, lcfg->lcfg_inlbuf1,
555                        lcfg->lcfg_inllen1);
556                 GOTO(out, err = 0);
557         }
558         }
559
560         /* Commands that require a device */
561         obd = class_name2obd(lcfg->lcfg_dev_name);
562         if (obd == NULL) {
563                 if (lcfg->lcfg_dev_name == NULL)
564                         CERROR("this lcfg command requires a device name\n");
565                 else
566                         CERROR("no device for: %s\n", lcfg->lcfg_dev_name);
567
568                 GOTO(out, err = -EINVAL);
569         }
570
571         switch(lcfg->lcfg_command) {
572         case LCFG_SETUP: {
573                 err = class_setup(obd, lcfg);
574                 GOTO(out, err);
575         }
576         case LCFG_DETACH: {
577                 err = class_detach(obd, lcfg);
578                 GOTO(out, err = 0);
579         }
580         case LCFG_CLEANUP: {
581                 err = class_cleanup(obd, lcfg);
582                 GOTO(out, err = 0);
583         }
584         case LCFG_ADD_CONN: {
585                 err = class_add_conn(obd, lcfg);
586                 GOTO(out, err = 0);
587         }
588         case LCFG_DEL_CONN: {
589                 err = class_del_conn(obd, lcfg);
590                 GOTO(out, err = 0);
591         }
592         default: {
593                 err = obd_process_config(obd, sizeof(*lcfg), lcfg);
594                 GOTO(out, err);
595
596         }
597         }
598 out:
599         return err;
600 }
601
602 static int class_config_parse_handler(struct llog_handle * handle,
603                                       struct llog_rec_hdr *rec, void *data)
604 {
605         struct config_llog_instance *cfg = data;
606         int cfg_len = rec->lrh_len;
607         char *cfg_buf = (char*) (rec + 1);
608         int rc = 0;
609         ENTRY;
610
611         if (rec->lrh_type == OBD_CFG_REC) {
612                 char *buf;
613                 struct lustre_cfg *lcfg;
614                 char *old_name = NULL;
615                 int old_len = 0;
616                 char *old_uuid = NULL;
617                 int old_uuid_len = 0;
618                 char *inst_name = NULL;
619                 int inst_len = 0;
620
621                 rc = lustre_cfg_getdata(&buf, cfg_len, cfg_buf, 1);
622                 if (rc)
623                         GOTO(out, rc);
624                 lcfg = (struct lustre_cfg* ) buf;
625
626                 if (cfg && cfg->cfg_instance && lcfg->lcfg_dev_name) {
627                         inst_len = strlen(lcfg->lcfg_dev_name) +
628                                 strlen(cfg->cfg_instance) + 2;
629                         OBD_ALLOC(inst_name, inst_len);
630                         if (inst_name == NULL)
631                                 GOTO(out, rc = -ENOMEM);
632                         sprintf(inst_name, "%s-%s", lcfg->lcfg_dev_name,
633                                 cfg->cfg_instance);
634                         old_name = lcfg->lcfg_dev_name;
635                         old_len = lcfg->lcfg_dev_namelen;
636                         lcfg->lcfg_dev_name = inst_name;
637                         lcfg->lcfg_dev_namelen = strlen(inst_name) + 1;
638                 }
639
640                 if (cfg && lcfg->lcfg_command == LCFG_ATTACH) {
641                         old_uuid = lcfg->lcfg_inlbuf2;
642                         old_uuid_len = lcfg->lcfg_inllen2;
643
644                         lcfg->lcfg_inlbuf2 = (char*)&cfg->cfg_uuid.uuid;
645                         lcfg->lcfg_inllen2 = sizeof(cfg->cfg_uuid);
646                 }
647
648                 rc = class_process_config(lcfg);
649
650                 if (old_name) {
651                         lcfg->lcfg_dev_name = old_name;
652                         lcfg->lcfg_dev_namelen = old_len;
653                         OBD_FREE(inst_name, inst_len);
654                 }
655
656                 if (old_uuid) {
657                         lcfg->lcfg_inlbuf2 = old_uuid;
658                         lcfg->lcfg_inllen2 = old_uuid_len;
659                 }
660
661                 lustre_cfg_freedata(buf, cfg_len);
662         } else if (rec->lrh_type == PTL_CFG_REC) {
663                 struct portals_cfg *pcfg = (struct portals_cfg *)cfg_buf;
664                 if (pcfg->pcfg_command == NAL_CMD_REGISTER_MYNID &&
665                     cfg->cfg_local_nid != PTL_NID_ANY) {
666                         pcfg->pcfg_nid = cfg->cfg_local_nid;
667                 }
668
669                 rc = libcfs_nal_cmd(pcfg);
670         } else {
671                 CERROR("unrecognized record type: 0x%x\n", rec->lrh_type);
672         }
673 out:
674         RETURN(rc);
675 }
676
677 int class_config_process_llog(struct llog_ctxt *ctxt, char *name,
678                               struct config_llog_instance *cfg)
679 {
680         struct llog_handle *llh;
681         int rc, rc2;
682         ENTRY;
683
684         rc = llog_open(ctxt, &llh, NULL, name, 0);
685         if (rc)
686                 RETURN(rc);
687
688         rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
689         if (rc == 0)
690                 rc = llog_process(llh, class_config_parse_handler, cfg, NULL);
691
692         rc2 = llog_close(llh);
693         if (rc == 0)
694                 rc = rc2;
695
696         RETURN(rc);
697 }
698
699 int class_config_dump_handler(struct llog_handle * handle,
700                               struct llog_rec_hdr *rec, void *data)
701 {
702         int cfg_len = rec->lrh_len;
703         char *cfg_buf = (char*) (rec + 1);
704         int rc = 0;
705         ENTRY;
706
707         if (rec->lrh_type == OBD_CFG_REC) {
708                 char *buf;
709                 struct lustre_cfg *lcfg;
710
711                 rc = lustre_cfg_getdata(&buf, cfg_len, cfg_buf, 1);
712                 if (rc)
713                         GOTO(out, rc);
714                 lcfg = (struct lustre_cfg* ) buf;
715
716                 CDEBUG(D_INFO, "lcfg command: 0x%x\n", lcfg->lcfg_command);
717                 if (lcfg->lcfg_dev_name)
718                         CDEBUG(D_INFO, "     devname: %s\n",
719                                lcfg->lcfg_dev_name);
720                 if (lcfg->lcfg_flags)
721                         CDEBUG(D_INFO, "       flags: 0x%x\n", lcfg->lcfg_flags);
722                 if (lcfg->lcfg_nid)
723                         CDEBUG(D_INFO, "         nid: "LPX64"\n",
724                                lcfg->lcfg_nid);
725                 if (lcfg->lcfg_nal)
726                         CDEBUG(D_INFO, "         nal: %x\n", lcfg->lcfg_nal);
727                 if (lcfg->lcfg_num)
728                         CDEBUG(D_INFO, "         nal: %x\n", lcfg->lcfg_num);
729                 if (lcfg->lcfg_inlbuf1)
730                         CDEBUG(D_INFO, "     inlbuf1: %s\n",lcfg->lcfg_inlbuf1);
731                 if (lcfg->lcfg_inlbuf2)
732                         CDEBUG(D_INFO, "     inlbuf2: %s\n",lcfg->lcfg_inlbuf2);
733                 if (lcfg->lcfg_inlbuf3)
734                         CDEBUG(D_INFO, "     inlbuf3: %s\n",lcfg->lcfg_inlbuf3);
735                 if (lcfg->lcfg_inlbuf4)
736                         CDEBUG(D_INFO, "     inlbuf4: %s\n",lcfg->lcfg_inlbuf4);
737                 if (lcfg->lcfg_inlbuf5)
738                         CDEBUG(D_INFO, "     inlbuf5: %s\n",lcfg->lcfg_inlbuf5);
739                 if (lcfg->lcfg_inlbuf6)
740                         CDEBUG(D_INFO, "     inlbuf6: %s\n",lcfg->lcfg_inlbuf6);
741
742                 lustre_cfg_freedata(buf, cfg_len);
743         } else if (rec->lrh_type == PTL_CFG_REC) {
744                 struct portals_cfg *pcfg = (struct portals_cfg *)cfg_buf;
745
746                 CDEBUG(D_INFO, "pcfg command: 0x%x\n", pcfg->pcfg_command);
747                 if (pcfg->pcfg_nal)
748                         CDEBUG(D_INFO, "         nal: %x\n",
749                                pcfg->pcfg_nal);
750                 if (pcfg->pcfg_gw_nal)
751                         CDEBUG(D_INFO, "      gw_nal: %x\n",
752                                pcfg->pcfg_gw_nal);
753                 if (pcfg->pcfg_nid)
754                         CDEBUG(D_INFO, "         nid: "LPX64"\n",
755                                pcfg->pcfg_nid);
756                 if (pcfg->pcfg_nid2)
757                         CDEBUG(D_INFO, "        nid2: "LPX64"\n",
758                                pcfg->pcfg_nid2);
759                 if (pcfg->pcfg_nid3)
760                         CDEBUG(D_INFO, "        nid3: "LPX64"\n",
761                                pcfg->pcfg_nid3);
762                 if (pcfg->pcfg_misc)
763                         CDEBUG(D_INFO, "        misc: %d\n",
764                                pcfg->pcfg_misc);
765                 if (pcfg->pcfg_id)
766                         CDEBUG(D_INFO, "          id: 0x%x\n",
767                                pcfg->pcfg_id);
768                 if (pcfg->pcfg_flags)
769                         CDEBUG(D_INFO, "       flags: 0x%x\n",
770                                pcfg->pcfg_flags);
771         } else {
772                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
773                 rc = -EINVAL;
774         }
775 out:
776         RETURN(rc);
777 }
778
779 int class_config_dump_llog(struct llog_ctxt *ctxt, char *name,
780                            struct config_llog_instance *cfg)
781 {
782         struct llog_handle *llh;
783         int rc, rc2;
784         ENTRY;
785
786         rc = llog_open(ctxt, &llh, NULL, name, 0);
787         if (rc)
788                 RETURN(rc);
789
790         rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
791         if (rc == 0)
792                 rc = llog_process(llh, class_config_dump_handler, cfg, NULL);
793
794         rc2 = llog_close(llh);
795         if (rc == 0)
796                 rc = rc2;
797
798         RETURN(rc);
799 }