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