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