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