Whamcloud - gitweb
5bf82b33fd16630c02833a027ab97cb85f55e92c
[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 <portals/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 int class_attach(struct lustre_cfg *lcfg)
47 {
48         int minor;
49         struct obd_type *type;
50         int err = 0;
51         int len;
52         char *typename;
53         char *name;
54         char *uuid;
55         struct obd_device *obd;
56         int dev;
57                  
58         if (!lcfg->lcfg_inllen1 || !lcfg->lcfg_inlbuf1) {
59                 CERROR("No type passed!\n");
60                 RETURN(-EINVAL);
61         }
62         if (lcfg->lcfg_inlbuf1[lcfg->lcfg_inllen1 - 1] != 0) {
63                 CERROR("Type not nul terminated!\n");
64                 RETURN(-EINVAL);
65         }
66         typename = lcfg->lcfg_inlbuf1;
67
68         if (!lcfg->lcfg_dev_namelen || !lcfg->lcfg_dev_name) {
69                 CERROR("No name passed!\n");
70                 RETURN(-EINVAL);
71         }
72         if (lcfg->lcfg_dev_name[lcfg->lcfg_dev_namelen - 1] != 0) {
73                 CERROR("Name not nul terminated!\n");
74                 RETURN(-EINVAL);
75         }
76         name = lcfg->lcfg_dev_name;
77
78         if (!lcfg->lcfg_inllen2 || !lcfg->lcfg_inlbuf2) {
79                 CERROR("No UUID passed!\n");
80                 RETURN(-EINVAL);
81         }
82         if (lcfg->lcfg_inlbuf2[lcfg->lcfg_inllen2 - 1] != 0) {
83                 CERROR("UUID not nul terminated!\n");
84                 RETURN(-EINVAL);
85         }
86         uuid = lcfg->lcfg_inlbuf2;
87
88         CDEBUG(D_IOCTL, "attach type %s name: %s uuid: %s\n",
89                MKSTR(lcfg->lcfg_inlbuf1),
90                MKSTR(lcfg->lcfg_dev_name), MKSTR(lcfg->lcfg_inlbuf2));
91
92         /* find the type */
93         type = class_get_type(typename);
94         if (!type) {
95                 CERROR("OBD: unknown type: %s\n", typename);
96                 RETURN(-EINVAL);
97         }
98         
99         obd = class_name2obd(name);
100         if (obd != NULL) {
101                 CERROR("obd %s already attached\n", name);
102                 RETURN(-EEXIST);
103         }
104
105         obd = class_newdev(&dev);
106         if (obd == NULL)
107                 RETURN(-EINVAL);
108
109         /* have we attached a type to this device */
110         if (obd->obd_attached || obd->obd_type) {
111                 CERROR("OBD: Device %d already typed as %s.\n",
112                        obd->obd_minor, MKSTR(obd->obd_type->typ_name));
113                 RETURN(-EBUSY);
114         }
115
116         LASSERT(obd == (obd_dev + obd->obd_minor));
117
118         minor = obd->obd_minor;
119         memset(obd, 0, sizeof(*obd));
120         obd->obd_minor = minor;
121         obd->obd_type = type;
122         INIT_LIST_HEAD(&obd->obd_exports);
123         obd->obd_num_exports = 0;
124         spin_lock_init(&obd->obd_dev_lock);
125         init_waitqueue_head(&obd->obd_refcount_waitq);
126         
127         /* XXX belongs in setup not attach  */
128         /* recovery data */
129         spin_lock_init(&obd->obd_processing_task_lock);
130         init_waitqueue_head(&obd->obd_next_transno_waitq);
131         INIT_LIST_HEAD(&obd->obd_recovery_queue);
132         INIT_LIST_HEAD(&obd->obd_delayed_reply_queue);
133         
134         init_waitqueue_head(&obd->obd_commit_waitq);
135         
136         len = strlen(name) + 1;
137         OBD_ALLOC(obd->obd_name, len);
138         if (!obd->obd_name) {
139                 class_put_type(obd->obd_type);
140                 obd->obd_type = NULL;
141                 RETURN(-ENOMEM);
142         }
143         memcpy(obd->obd_name, name, len);
144         
145         len = strlen(uuid);
146         if (len >= sizeof(obd->obd_uuid)) {
147                 CERROR("uuid must be < "LPSZ" bytes long\n",
148                        sizeof(obd->obd_uuid));
149                 OBD_FREE(obd->obd_name, strlen(obd->obd_name) + 1);
150                 class_put_type(obd->obd_type);
151                 obd->obd_type = NULL;
152                 RETURN(-EINVAL);
153         }
154         memcpy(obd->obd_uuid.uuid, uuid, len);
155
156         /* do the attach */
157         if (OBP(obd, attach))
158                 err = OBP(obd,attach)(obd, sizeof *lcfg, lcfg);
159
160         if (err) {
161                 OBD_FREE(obd->obd_name, strlen(obd->obd_name) + 1);
162                 class_put_type(obd->obd_type);
163                 obd->obd_type = NULL;
164         } else {
165                 obd->obd_attached = 1;
166                 type->typ_refcnt++;
167                 CDEBUG(D_IOCTL, "OBD: dev %d attached type %s\n",
168                        obd->obd_minor, typename);
169         }
170         RETURN(err);
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         /* has this been done already? */
188         if (obd->obd_set_up) {
189                 CERROR("Device %d already setup (type %s)\n",
190                        obd->obd_minor, obd->obd_type->typ_name);
191                 RETURN(-EBUSY);
192         }
193
194         atomic_set(&obd->obd_refcount, 0);
195  
196         exp = class_new_export(obd);
197         if (exp == NULL) 
198                 RETURN(err);
199         memcpy(&exp->exp_client_uuid, &obd->obd_uuid, 
200                sizeof(exp->exp_client_uuid));
201         obd->obd_self_export = exp;
202         class_export_put(exp);
203
204         err = obd_setup(obd, sizeof(*lcfg), lcfg);
205         if (err) 
206                 GOTO(err_exp, err);
207         
208         obd->obd_type->typ_refcnt++;
209         obd->obd_set_up = 1;
210
211         RETURN(err);
212
213 err_exp:
214         class_unlink_export(obd->obd_self_export);
215         obd->obd_self_export = NULL;
216         RETURN(err);
217 }
218
219 int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg)
220 {
221         int minor;
222         int err = 0;
223
224         ENTRY;
225         if (obd->obd_set_up) {
226                 CERROR("OBD device %d still set up\n", obd->obd_minor);
227                 RETURN(-EBUSY);
228         }
229         if (!obd->obd_attached) {
230                 CERROR("OBD device %d not attached\n", obd->obd_minor);
231                 RETURN(-ENODEV);
232         }
233         if (OBP(obd, detach))
234                 err = OBP(obd,detach)(obd);
235
236         if (obd->obd_name) {
237                 OBD_FREE(obd->obd_name, strlen(obd->obd_name)+1);
238                 obd->obd_name = NULL;
239         } else 
240                 CERROR("device %d: no name at detach\n", obd->obd_minor);
241
242         obd->obd_attached = 0;
243         obd->obd_type->typ_refcnt--;
244         class_put_type(obd->obd_type);
245         obd->obd_type = NULL;
246         minor = obd->obd_minor;
247         memset(obd, 0, sizeof(*obd));
248         obd->obd_minor = minor;
249         RETURN(err);
250 }
251
252 static void dump_exports(struct obd_device *obd)
253 {
254         struct obd_export *exp, *n;
255
256         list_for_each_entry_safe(exp, n, &obd->obd_exports, exp_obd_chain) {
257                 CERROR("%s: %p %s %d %d %p\n",
258                        obd->obd_name, exp, exp->exp_client_uuid.uuid,
259                        atomic_read(&exp->exp_refcount),
260                        exp->exp_failed, exp->exp_outstanding_reply );
261         }
262 }
263
264 int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
265 {
266         int flags = 0;
267         int err = 0;
268         char *flag;
269         
270         ENTRY;
271         if (!obd->obd_set_up) {
272                 CERROR("Device %d not setup\n", obd->obd_minor);
273                 RETURN(-ENODEV);
274         }
275
276         if (lcfg->lcfg_inlbuf1) {
277                 for (flag = lcfg->lcfg_inlbuf1; *flag != 0; flag++)
278                         switch (*flag) {
279                         case 'F':
280                                 flags |= OBD_OPT_FORCE;
281                                 break;
282                         case 'A':
283                                 flags |= OBD_OPT_FAILOVER;
284                                 break;
285                         default:
286                                 CERROR("unrecognised flag '%c'\n",
287                                        *flag);
288                         }
289         }
290
291         /* The one reference that should be remaining is the
292          * obd_self_export */
293         if (atomic_read(&obd->obd_refcount) <= 1 ||
294             flags & OBD_OPT_FORCE) {
295                 /* this will stop new connections, and need to
296                    do it before class_disconnect_exports() */
297                 obd->obd_stopping = 1;
298         }
299
300         if (atomic_read(&obd->obd_refcount) > 1) {
301                 struct l_wait_info lwi = LWI_TIMEOUT_INTR(1 * HZ, NULL,
302                                                           NULL, NULL);
303                 int rc;
304
305                 if (!(flags & OBD_OPT_FORCE)) {
306                         CERROR("OBD device %d (%p) has refcount %d\n",
307                                obd->obd_minor, obd,
308                                atomic_read(&obd->obd_refcount));
309                         dump_exports(obd);
310                         GOTO(out, err = -EBUSY);
311                 }
312                 class_disconnect_exports(obd, flags);
313                 CDEBUG(D_IOCTL,
314                        "%s: waiting for obd refs to go away: %d\n",
315                        obd->obd_name, atomic_read(&obd->obd_refcount));
316
317                 rc = l_wait_event(obd->obd_refcount_waitq,
318                                   atomic_read(&obd->obd_refcount) < 2, &lwi);
319                 if (rc == 0) {
320                         LASSERT(atomic_read(&obd->obd_refcount) == 1);
321                 } else {
322                         CERROR("wait cancelled cleaning anyway. "
323                                "refcount: %d\n",
324                                atomic_read(&obd->obd_refcount));
325                         dump_exports(obd);
326                 }
327                 CDEBUG(D_IOCTL, "%s: awake, now finishing cleanup\n",
328                        obd->obd_name);
329         }
330
331         if (obd->obd_self_export) {
332                 err = obd_precleanup(obd, flags);
333                 if (err) 
334                         GOTO(out, err);
335                 class_unlink_export(obd->obd_self_export);
336                 obd->obd_self_export = NULL;
337         }
338
339         err = obd_cleanup(obd, flags);
340 out:
341         if (!err) {
342                 obd->obd_set_up = obd->obd_stopping = 0;
343                 obd->obd_type->typ_refcnt--;
344                 /* XXX this should be an LASSERT */
345                 if (atomic_read(&obd->obd_refcount) > 0) 
346                         CERROR("%s still has refcount %d after "
347                                "cleanup.\n", obd->obd_name,
348                                atomic_read(&obd->obd_refcount));
349         } 
350
351         RETURN(err);
352
353 }
354
355 LIST_HEAD(lustre_profile_list);
356
357 struct lustre_profile *class_get_profile(char * prof)
358 {
359         struct lustre_profile *lprof;
360         
361         list_for_each_entry(lprof, &lustre_profile_list, lp_list) {
362                 if (!strcmp(lprof->lp_profile, prof)) {
363                         RETURN(lprof);
364                 }
365         }
366         RETURN(NULL);
367 }
368
369 int class_add_profile(int proflen, char *prof, 
370                       int osclen, char *osc, 
371                       int mdclen, char *mdc)
372 {
373         struct lustre_profile *lprof;
374         int err = 0;
375
376         OBD_ALLOC(lprof, sizeof(*lprof));
377         if (lprof == NULL)
378                 GOTO(out, err = -ENOMEM);
379         INIT_LIST_HEAD(&lprof->lp_list);
380
381         LASSERT(proflen == (strlen(prof) + 1));
382         OBD_ALLOC(lprof->lp_profile, proflen);
383         if (lprof->lp_profile == NULL)
384                 GOTO(out, err = -ENOMEM);
385         memcpy(lprof->lp_profile, prof, proflen);
386         
387         LASSERT(osclen == (strlen(osc) + 1));
388         OBD_ALLOC(lprof->lp_osc, osclen);
389         if (lprof->lp_profile == NULL)
390                 GOTO(out, err = -ENOMEM);
391         memcpy(lprof->lp_osc, osc, osclen);
392
393         if (mdclen > 0) {
394                 LASSERT(mdclen == (strlen(mdc) + 1));
395                 OBD_ALLOC(lprof->lp_mdc, mdclen);
396                 if (lprof->lp_mdc == NULL)
397                         GOTO(out, err = -ENOMEM);
398                 memcpy(lprof->lp_mdc, mdc, mdclen);
399         }
400
401         list_add(&lprof->lp_list, &lustre_profile_list);
402
403 out:
404         RETURN(err);
405 }
406
407 void class_del_profile(char *prof)
408 {
409         struct lustre_profile *lprof;
410         
411         lprof = class_get_profile(prof);
412         if (lprof) {
413                 list_del(&lprof->lp_list);
414                 OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
415                 OBD_FREE(lprof->lp_osc, strlen(lprof->lp_osc) + 1);
416                 if (lprof->lp_mdc)
417                         OBD_FREE(lprof->lp_mdc, strlen(lprof->lp_mdc) + 1);
418                 OBD_FREE(lprof, sizeof *lprof);
419         }
420 }
421
422 int class_process_config(struct lustre_cfg *lcfg)
423 {
424         struct obd_device *obd;
425         char str[PTL_NALFMT_SIZE];
426         int err;
427
428         LASSERT(lcfg && !IS_ERR(lcfg));
429
430         CDEBUG(D_IOCTL, "processing cmd: %x\n", lcfg->lcfg_command);
431
432         /* Commands that don't need a device */
433         switch(lcfg->lcfg_command) {
434         case LCFG_ATTACH: {
435                 err = class_attach(lcfg);
436                 GOTO(out, err);
437         }
438         case LCFG_ADD_UUID: {
439                 CDEBUG(D_IOCTL, "adding mapping from uuid %s to nid "LPX64
440                        " (%s), nal %d\n", lcfg->lcfg_inlbuf1, lcfg->lcfg_nid,
441                        portals_nid2str(lcfg->lcfg_nal, lcfg->lcfg_nid, str),
442                        lcfg->lcfg_nal);
443
444                 err = class_add_uuid(lcfg->lcfg_inlbuf1, lcfg->lcfg_nid,
445                                      lcfg->lcfg_nal);
446                 GOTO(out, err);
447         }
448         case LCFG_DEL_UUID: {
449                 CDEBUG(D_IOCTL, "removing mappings for uuid %s\n",
450                        lcfg->lcfg_inlbuf1 == NULL ? "<all uuids>" :
451                        lcfg->lcfg_inlbuf1);
452
453                 err = class_del_uuid(lcfg->lcfg_inlbuf1);
454                 GOTO(out, err);
455         }
456         case LCFG_MOUNTOPT: {
457                 CDEBUG(D_IOCTL, "mountopt: profile %s osc %s mdc %s\n", 
458                        lcfg->lcfg_inlbuf1, lcfg->lcfg_inlbuf2, lcfg->lcfg_inlbuf3);
459                 /* set these mount options somewhere, so ll_fill_super
460                  * can find them. */
461                 err = class_add_profile(lcfg->lcfg_inllen1, lcfg->lcfg_inlbuf1, 
462                                         lcfg->lcfg_inllen2, lcfg->lcfg_inlbuf2, 
463                                         lcfg->lcfg_inllen3, lcfg->lcfg_inlbuf3);
464                 GOTO(out, err);
465         }
466         case LCFG_DEL_MOUNTOPT: {
467                 CDEBUG(D_IOCTL, "mountopt: profile %s\n", lcfg->lcfg_inlbuf1);
468                 /* set these mount options somewhere, so ll_fill_super
469                  * can find them. */
470                 class_del_profile(lcfg->lcfg_inlbuf1);
471                 GOTO(out, err = 0);
472         }
473         case LCFG_SET_TIMEOUT: {
474                 CDEBUG(D_IOCTL, "changing lustre timeout from %d to %d\n", 
475                        obd_timeout,
476                        lcfg->lcfg_num);
477                 obd_timeout = lcfg->lcfg_num;
478                 GOTO(out, err = 0);
479         }
480         case LCFG_SET_UPCALL: {
481                 CDEBUG(D_IOCTL, "setting lustre ucpall to: %s\n", 
482                        lcfg->lcfg_inlbuf1);
483                 if (lcfg->lcfg_inllen1 > sizeof obd_lustre_upcall)
484                         GOTO(out, err = -EINVAL);
485                 memcpy(obd_lustre_upcall, lcfg->lcfg_inlbuf1, 
486                        lcfg->lcfg_inllen1);
487                 GOTO(out, err = 0);
488         }
489         }
490         
491
492         /* Commands that require a device */
493         obd = class_name2obd(lcfg->lcfg_dev_name);
494         if (obd == NULL) {
495                 if (lcfg->lcfg_dev_name == NULL) {
496                         CERROR("this lcfg command requires a device name\n");
497                 } else {
498                         CERROR("no device for: %s\n", lcfg->lcfg_dev_name);
499                 }
500                 GOTO(out, err = -EINVAL);
501         }
502             
503         switch(lcfg->lcfg_command) {
504         case LCFG_SETUP: {
505                 err = class_setup(obd, lcfg);
506                 GOTO(out, err);
507         }
508         case LCFG_DETACH: {
509                 err = class_detach(obd, lcfg);
510                 GOTO(out, err = 0);
511         }
512         case LCFG_CLEANUP: {
513                 err = class_cleanup(obd, lcfg);
514                 GOTO(out, err = 0);
515         }
516         default: { 
517                 CERROR("Unknown command: %d\n", lcfg->lcfg_command);
518                 GOTO(out, err = -EINVAL);
519
520         }
521         }
522 out:
523         RETURN(err);
524 }
525             
526 static int class_config_llog_handler(struct llog_handle * handle,
527                                      struct llog_rec_hdr *rec, void *data)
528 {
529         struct config_llog_instance *cfg = data;
530         int cfg_len = rec->lrh_len;
531         char *cfg_buf = (char*) (rec + 1);
532         int rc = 0;
533
534         if (rec->lrh_type == OBD_CFG_REC) {
535                 char *buf;
536                 struct lustre_cfg *lcfg;
537                 char *old_name = NULL;
538                 int old_len = 0;
539                 char *old_uuid = NULL;
540                 int old_uuid_len = 0;
541                 char *inst_name = NULL;
542                 int inst_len = 0;
543
544                 rc = lustre_cfg_getdata(&buf, cfg_len, cfg_buf, 1);
545                 if (rc) 
546                         GOTO(out, rc);
547                 lcfg = (struct lustre_cfg* ) buf;
548
549                 if (cfg && cfg->cfg_instance && lcfg->lcfg_dev_name) {
550                         inst_len = strlen(lcfg->lcfg_dev_name) + 
551                                 strlen(cfg->cfg_instance) + 2;
552                         OBD_ALLOC(inst_name, inst_len);
553                         if (inst_name == NULL) 
554                                 GOTO(out, rc = -ENOMEM);
555                         sprintf(inst_name, "%s-%s", lcfg->lcfg_dev_name, 
556                                 cfg->cfg_instance);
557                         old_name = lcfg->lcfg_dev_name;
558                         old_len = lcfg->lcfg_dev_namelen;
559                         lcfg->lcfg_dev_name = inst_name;
560                         lcfg->lcfg_dev_namelen = strlen(inst_name) + 1;
561                 }
562                 
563                 if (cfg && lcfg->lcfg_command == LCFG_ATTACH) {
564                         old_uuid = lcfg->lcfg_inlbuf2;
565                         old_uuid_len = lcfg->lcfg_inllen2;
566
567                         lcfg->lcfg_inlbuf2 = (char*)&cfg->cfg_uuid.uuid;
568                         lcfg->lcfg_inllen2 = sizeof(cfg->cfg_uuid);
569                 }
570
571                 rc = class_process_config(lcfg);
572
573                 if (old_name) {
574                         lcfg->lcfg_dev_name = old_name;
575                         lcfg->lcfg_dev_namelen = old_len;
576                         OBD_FREE(inst_name, inst_len);
577                 }
578               
579                 if (old_uuid) {
580                         lcfg->lcfg_inlbuf2 = old_uuid;
581                         lcfg->lcfg_inllen2 = old_uuid_len;
582                 }
583                 
584                 lustre_cfg_freedata(buf, cfg_len);
585         } else if (rec->lrh_type == PTL_CFG_REC) {
586                 struct portals_cfg *pcfg = (struct portals_cfg *)cfg_buf;
587                 if (pcfg->pcfg_command ==NAL_CMD_REGISTER_MYNID &&
588                     cfg->cfg_local_nid != PTL_NID_ANY) {
589                         pcfg->pcfg_nid = cfg->cfg_local_nid;
590                 }
591
592                 rc = kportal_nal_cmd(pcfg);
593         }
594 out:
595         RETURN(rc);
596 }
597
598 int class_config_parse_llog(struct llog_ctxt *ctxt, char *name, 
599                           struct config_llog_instance *cfg)
600 {
601         struct llog_handle *llh;
602         int rc, rc2;
603         ENTRY;
604
605         rc = llog_create(ctxt, &llh, NULL, name);
606         if (rc) 
607                 RETURN(rc);
608
609         rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
610         if (rc) 
611                 GOTO(parse_out, rc);
612
613         rc = llog_process(llh, class_config_llog_handler, cfg, NULL);
614 parse_out:
615         rc2 = llog_close(llh);
616         if (rc == 0)
617                 rc = rc2;
618
619         RETURN(rc);
620
621 }
622
623 static int class_config_dump_handler(struct llog_handle * handle,
624                                      struct llog_rec_hdr *rec, void *data)
625 {
626         int cfg_len = rec->lrh_len;
627         char *cfg_buf = (char*) (rec + 1);
628         int rc = 0;
629
630         if (rec->lrh_type == OBD_CFG_REC) {
631                 char *buf;
632                 struct lustre_cfg *lcfg;
633
634                 rc = lustre_cfg_getdata(&buf, cfg_len, cfg_buf, 1);
635                 if (rc) 
636                         GOTO(out, rc);
637                 lcfg = (struct lustre_cfg* ) buf;
638                 
639                 CDEBUG(D_INFO, "lcfg command: %x\n", lcfg->lcfg_command);
640                 if (lcfg->lcfg_dev_name)
641                         CDEBUG(D_INFO, "     devname: %s\n",
642                                lcfg->lcfg_dev_name);
643                 if (lcfg->lcfg_flags)
644                         CDEBUG(D_INFO, "       flags: %x\n", lcfg->lcfg_flags);
645                 if (lcfg->lcfg_nid)
646                         CDEBUG(D_INFO, "         nid: "LPX64"\n",
647                                lcfg->lcfg_nid);
648                 if (lcfg->lcfg_nal)
649                         CDEBUG(D_INFO, "         nal: %x\n", lcfg->lcfg_nal);
650                 if (lcfg->lcfg_num)
651                         CDEBUG(D_INFO, "         nal: %x\n", lcfg->lcfg_num);
652                 if (lcfg->lcfg_inlbuf1)
653                         CDEBUG(D_INFO, "     inlbuf1: %s\n",lcfg->lcfg_inlbuf1);
654                 if (lcfg->lcfg_inlbuf2)
655                         CDEBUG(D_INFO, "     inlbuf1: %s\n",lcfg->lcfg_inlbuf2);
656                 if (lcfg->lcfg_inlbuf3)
657                         CDEBUG(D_INFO, "     inlbuf1: %s\n",lcfg->lcfg_inlbuf3);
658                 if (lcfg->lcfg_inlbuf4)
659                         CDEBUG(D_INFO, "     inlbuf1: %s\n",lcfg->lcfg_inlbuf4);
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
665                 CDEBUG(D_INFO, "pcfg command: %d\n", pcfg->pcfg_command);
666                 if (pcfg->pcfg_nal)
667                         CDEBUG(D_INFO, "         nal: %d\n",
668                                pcfg->pcfg_nal);
669                 if (pcfg->pcfg_gw_nal)
670                         CDEBUG(D_INFO, "      gw_nal: %d\n",
671                                pcfg->pcfg_gw_nal);
672                 if (pcfg->pcfg_nid)
673                         CDEBUG(D_INFO, "         nid: "LPX64"\n",
674                                pcfg->pcfg_nid);
675                 if (pcfg->pcfg_nid2)
676                         CDEBUG(D_INFO, "         nid: "LPX64"\n",
677                                pcfg->pcfg_nid2);
678                 if (pcfg->pcfg_nid3)
679                         CDEBUG(D_INFO, "         nid: "LPX64"\n",
680                                pcfg->pcfg_nid3);
681                 if (pcfg->pcfg_misc)
682                         CDEBUG(D_INFO, "         nid: %d\n",
683                                pcfg->pcfg_misc);
684                 if (pcfg->pcfg_id)
685                         CDEBUG(D_INFO, "          id: %x\n",
686                                pcfg->pcfg_id);
687                 if (pcfg->pcfg_flags)
688                         CDEBUG(D_INFO, "       flags: %x\n",
689                                pcfg->pcfg_flags);
690         }
691 out:
692         RETURN(rc);
693 }
694
695 int class_config_dump_llog(struct llog_ctxt *ctxt, char *name, 
696                           struct config_llog_instance *cfg)
697 {
698         struct llog_handle *llh;
699         int rc, rc2;
700         ENTRY;
701
702         rc = llog_create(ctxt, &llh, NULL, name);
703         if (rc) 
704                 RETURN(rc);
705
706         rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
707         if (rc) 
708                 GOTO(parse_out, rc);
709
710         rc = llog_process(llh, class_config_dump_handler, cfg, NULL);
711 parse_out:
712         rc2 = llog_close(llh);
713         if (rc == 0)
714                 rc = rc2;
715
716         RETURN(rc);
717
718 }
719