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