Whamcloud - gitweb
Branch 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  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/obdclass/obd_config.c
37  *
38  * Config API
39  */
40
41 #define DEBUG_SUBSYSTEM S_CLASS
42 #ifdef __KERNEL__
43 #include <obd_class.h>
44 #include <linux/string.h>
45 #else
46 #include <liblustre.h>
47 #include <obd_class.h>
48 #include <obd.h>
49 #endif
50 #include <lustre_log.h>
51 #include <lprocfs_status.h>
52 #include <libcfs/list.h>
53 #include <lustre_param.h>
54 #include <class_hash.h>
55
56 static lustre_hash_ops_t uuid_hash_ops;
57 static lustre_hash_ops_t nid_hash_ops;
58 static lustre_hash_ops_t nid_stat_hash_ops;
59
60 /*********** string parsing utils *********/
61
62 /* returns 0 if we find this key in the buffer, else 1 */
63 int class_find_param(char *buf, char *key, char **valp)
64 {
65         char *ptr;
66
67         if (!buf)
68                 return 1;
69
70         if ((ptr = strstr(buf, key)) == NULL)
71                 return 1;
72
73         if (valp)
74                 *valp = ptr + strlen(key);
75
76         return 0;
77 }
78
79 /* returns 0 if this is the first key in the buffer, else 1.
80    valp points to first char after key. */
81 int class_match_param(char *buf, char *key, char **valp)
82 {
83         if (!buf)
84                 return 1;
85
86         if (memcmp(buf, key, strlen(key)) != 0)
87                 return 1;
88
89         if (valp)
90                 *valp = buf + strlen(key);
91
92         return 0;
93 }
94
95 /* 0 is good nid,
96    1 not found
97    < 0 error
98    endh is set to next separator */
99 int class_parse_nid(char *buf, lnet_nid_t *nid, char **endh)
100 {
101         char tmp, *endp;
102
103         if (!buf)
104                 return 1;
105         while (*buf == ',' || *buf == ':')
106                 buf++;
107         if (*buf == ' ' || *buf == '/' || *buf == '\0')
108                 return 1;
109
110         /* nid separators or end of nids */
111         endp = strpbrk(buf, ",: /");
112         if (endp == NULL)
113                 endp = buf + strlen(buf);
114
115         tmp = *endp;
116         *endp = '\0';
117         *nid = libcfs_str2nid(buf);
118         if (*nid == LNET_NID_ANY) {
119                 LCONSOLE_ERROR_MSG(0x159, "Can't parse NID '%s'\n", buf);
120                 *endp = tmp;
121                 return -EINVAL;
122         }
123         *endp = tmp;
124
125         if (endh)
126                 *endh = endp;
127         CDEBUG(D_INFO, "Nid %s\n", libcfs_nid2str(*nid));
128         return 0;
129 }
130
131 EXPORT_SYMBOL(class_find_param);
132 EXPORT_SYMBOL(class_match_param);
133 EXPORT_SYMBOL(class_parse_nid);
134
135 /********************** class fns **********************/
136
137 /**
138  * Create a new device and set the type, name and uuid.  If successful, the new
139  * device can be accessed by either name or uuid.
140  */
141 int class_attach(struct lustre_cfg *lcfg)
142 {
143         struct obd_device *obd = NULL;
144         char *typename, *name, *uuid;
145         int rc, len;
146         ENTRY;
147
148         if (!LUSTRE_CFG_BUFLEN(lcfg, 1)) {
149                 CERROR("No type passed!\n");
150                 RETURN(-EINVAL);
151         }
152         typename = lustre_cfg_string(lcfg, 1);
153
154         if (!LUSTRE_CFG_BUFLEN(lcfg, 0)) {
155                 CERROR("No name passed!\n");
156                 RETURN(-EINVAL);
157         }
158         name = lustre_cfg_string(lcfg, 0);
159
160         if (!LUSTRE_CFG_BUFLEN(lcfg, 2)) {
161                 CERROR("No UUID passed!\n");
162                 RETURN(-EINVAL);
163         }
164         uuid = lustre_cfg_string(lcfg, 2);
165
166         CDEBUG(D_IOCTL, "attach type %s name: %s uuid: %s\n",
167                MKSTR(typename), MKSTR(name), MKSTR(uuid));
168
169         obd = class_newdev(typename, name);
170         if (IS_ERR(obd)) {
171                 /* Already exists or out of obds */
172                 rc = PTR_ERR(obd);
173                 obd = NULL;
174                 CERROR("Cannot create device %s of type %s : %d\n",
175                        name, typename, rc);
176                 GOTO(out, rc);
177         }
178         LASSERTF(obd != NULL, "Cannot get obd device %s of type %s\n",
179                  name, typename);
180         LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC,
181                  "obd %p obd_magic %08X != %08X\n",
182                  obd, obd->obd_magic, OBD_DEVICE_MAGIC);
183         LASSERTF(strncmp(obd->obd_name, name, strlen(name)) == 0, "%p obd_name %s != %s\n",
184                  obd, obd->obd_name, name);
185
186         rwlock_init(&obd->obd_pool_lock);
187         obd->obd_pool_limit = 0;
188         obd->obd_pool_slv = 0;
189
190         CFS_INIT_LIST_HEAD(&obd->obd_exports);
191         CFS_INIT_LIST_HEAD(&obd->obd_exports_timed);
192         CFS_INIT_LIST_HEAD(&obd->obd_nid_stats);
193         spin_lock_init(&obd->obd_nid_lock);
194         spin_lock_init(&obd->obd_dev_lock);
195         sema_init(&obd->obd_dev_sem, 1);
196         spin_lock_init(&obd->obd_osfs_lock);
197         /* obd->obd_osfs_age must be set to a value in the distant
198          * past to guarantee a fresh statfs is fetched on mount. */
199         obd->obd_osfs_age = cfs_time_shift_64(-1000);
200
201         /* XXX belongs in setup not attach  */
202         /* recovery data */
203         cfs_init_timer(&obd->obd_recovery_timer);
204         spin_lock_init(&obd->obd_processing_task_lock);
205         cfs_waitq_init(&obd->obd_next_transno_waitq);
206         cfs_waitq_init(&obd->obd_evict_inprogress_waitq);
207         CFS_INIT_LIST_HEAD(&obd->obd_req_replay_queue);
208         CFS_INIT_LIST_HEAD(&obd->obd_lock_replay_queue);
209         CFS_INIT_LIST_HEAD(&obd->obd_final_req_queue);
210
211         llog_group_init(&obd->obd_olg, FILTER_GROUP_LLOG);
212
213         spin_lock_init(&obd->obd_uncommitted_replies_lock);
214         CFS_INIT_LIST_HEAD(&obd->obd_uncommitted_replies);
215
216         len = strlen(uuid);
217         if (len >= sizeof(obd->obd_uuid)) {
218                 CERROR("uuid must be < %d bytes long\n",
219                        (int)sizeof(obd->obd_uuid));
220                 GOTO(out, rc = -EINVAL);
221         }
222         memcpy(obd->obd_uuid.uuid, uuid, len);
223
224         /* do the attach */
225         if (OBP(obd, attach)) {
226                 rc = OBP(obd,attach)(obd, sizeof *lcfg, lcfg);
227                 if (rc)
228                         GOTO(out, rc = -EINVAL);
229         }
230
231         /* Detach drops this */
232         spin_lock(&obd->obd_dev_lock);
233         atomic_set(&obd->obd_refcount, 1);
234         spin_unlock(&obd->obd_dev_lock);
235         lu_ref_init(&obd->obd_reference);
236         lu_ref_add(&obd->obd_reference, "attach", obd);
237
238         obd->obd_attached = 1;
239         CDEBUG(D_IOCTL, "OBD: dev %d attached type %s with refcount %d\n",
240                obd->obd_minor, typename, atomic_read(&obd->obd_refcount));
241         RETURN(0);
242  out:
243         if (obd != NULL) {
244                 class_release_dev(obd);
245         }
246         return rc;
247 }
248
249 int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
250 {
251         int err = 0;
252         struct obd_export *exp;
253         ENTRY;
254
255         LASSERT(obd != NULL);
256         LASSERTF(obd == class_num2obd(obd->obd_minor),
257                  "obd %p != obd_devs[%d] %p\n",
258                  obd, obd->obd_minor, class_num2obd(obd->obd_minor));
259         LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC,
260                  "obd %p obd_magic %08x != %08x\n",
261                  obd, obd->obd_magic, OBD_DEVICE_MAGIC);
262
263         /* have we attached a type to this device? */
264         if (!obd->obd_attached) {
265                 CERROR("Device %d not attached\n", obd->obd_minor);
266                 RETURN(-ENODEV);
267         }
268
269         if (obd->obd_set_up) {
270                 CERROR("Device %d already setup (type %s)\n",
271                        obd->obd_minor, obd->obd_type->typ_name);
272                 RETURN(-EEXIST);
273         }
274
275         /* is someone else setting us up right now? (attach inits spinlock) */
276         spin_lock(&obd->obd_dev_lock);
277         if (obd->obd_starting) {
278                 spin_unlock(&obd->obd_dev_lock);
279                 CERROR("Device %d setup in progress (type %s)\n",
280                        obd->obd_minor, obd->obd_type->typ_name);
281                 RETURN(-EEXIST);
282         }
283         /* just leave this on forever.  I can't use obd_set_up here because
284            other fns check that status, and we're not actually set up yet. */
285         obd->obd_starting = 1;
286         obd->obd_uuid_hash = NULL;
287         obd->obd_nid_hash = NULL;
288         obd->obd_nid_stats_hash = NULL;
289         spin_unlock(&obd->obd_dev_lock);
290
291         /* create an uuid-export lustre hash */
292         obd->obd_uuid_hash = lustre_hash_init("UUID_HASH", 128, 128,
293                                               &uuid_hash_ops, 0);
294         if (!obd->obd_uuid_hash)
295                 GOTO(err_hash, err = -ENOMEM);
296  
297         /* create a nid-export lustre hash */
298         obd->obd_nid_hash = lustre_hash_init("NID_HASH", 128, 128,
299                                              &nid_hash_ops, 0);
300         if (!obd->obd_nid_hash)
301                 GOTO(err_hash, err = -ENOMEM);
302  
303         /* create a nid-stats lustre hash */
304         obd->obd_nid_stats_hash = lustre_hash_init("NID_STATS", 128, 128,
305                                                    &nid_stat_hash_ops, 0);
306         if (!obd->obd_nid_stats_hash)
307                 GOTO(err_hash, err = -ENOMEM);
308
309         exp = class_new_export(obd, &obd->obd_uuid);
310         if (IS_ERR(exp))
311                 GOTO(err_hash, err = PTR_ERR(exp));
312
313         obd->obd_self_export = exp;
314         list_del_init(&exp->exp_obd_chain_timed);
315         class_export_put(exp);
316
317         err = obd_setup(obd, lcfg);
318         if (err)
319                 GOTO(err_exp, err);
320
321         obd->obd_set_up = 1;
322
323         spin_lock(&obd->obd_dev_lock);
324         /* cleanup drops this */
325         class_incref(obd, "setup", obd);
326         spin_unlock(&obd->obd_dev_lock);
327
328         CDEBUG(D_IOCTL, "finished setup of obd %s (uuid %s)\n",
329                obd->obd_name, obd->obd_uuid.uuid);
330
331         RETURN(0);
332 err_exp:
333         class_unlink_export(obd->obd_self_export);
334         obd->obd_self_export = NULL;
335 err_hash:
336         if (obd->obd_uuid_hash) {
337                 lustre_hash_exit(obd->obd_uuid_hash);
338                 obd->obd_uuid_hash = NULL;
339         }
340         if (obd->obd_nid_hash) {
341                 lustre_hash_exit(obd->obd_nid_hash);
342                 obd->obd_nid_hash = NULL;
343         }
344         if (obd->obd_nid_stats_hash) {
345                 lustre_hash_exit(obd->obd_nid_stats_hash);
346                 obd->obd_nid_stats_hash = NULL;
347         }
348         obd->obd_starting = 0;
349         CERROR("setup %s failed (%d)\n", obd->obd_name, err);
350         return err;
351 }
352
353 int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg)
354 {
355         ENTRY;
356
357         if (obd->obd_set_up) {
358                 CERROR("OBD device %d still set up\n", obd->obd_minor);
359                 RETURN(-EBUSY);
360         }
361
362         spin_lock(&obd->obd_dev_lock);
363         if (!obd->obd_attached) {
364                 spin_unlock(&obd->obd_dev_lock);
365                 CERROR("OBD device %d not attached\n", obd->obd_minor);
366                 RETURN(-ENODEV);
367         }
368         obd->obd_attached = 0;
369         spin_unlock(&obd->obd_dev_lock);
370
371         CDEBUG(D_IOCTL, "detach on obd %s (uuid %s)\n",
372                obd->obd_name, obd->obd_uuid.uuid);
373
374         class_decref(obd, "attach", obd);
375
376         /* not strictly necessary, but cleans up eagerly */
377         obd_zombie_impexp_cull();
378
379         RETURN(0);
380 }
381
382 static void dump_exports(struct obd_device *obd)
383 {
384         struct obd_export *exp, *n;
385
386         list_for_each_entry_safe(exp, n, &obd->obd_exports, exp_obd_chain) {
387                 struct ptlrpc_reply_state *rs;
388                 struct ptlrpc_reply_state *first_reply = NULL;
389                 int                        nreplies = 0;
390
391                 list_for_each_entry (rs, &exp->exp_outstanding_replies,
392                                      rs_exp_list) {
393                         if (nreplies == 0)
394                                 first_reply = rs;
395                         nreplies++;
396                 }
397
398                 CDEBUG(D_IOCTL, "%s: %p %s %s %d %d %d: %p %s\n",
399                        obd->obd_name, exp, exp->exp_client_uuid.uuid,
400                        obd_export_nid2str(exp),
401                        atomic_read(&exp->exp_refcount),
402                        exp->exp_failed, nreplies, first_reply,
403                        nreplies > 3 ? "..." : "");
404         }
405 }
406
407 int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
408 {
409         int err = 0;
410         char *flag;
411         ENTRY;
412
413         OBD_RACE(OBD_FAIL_LDLM_RECOV_CLIENTS);
414
415         if (!obd->obd_set_up) {
416                 CERROR("Device %d not setup\n", obd->obd_minor);
417                 RETURN(-ENODEV);
418         }
419
420         spin_lock(&obd->obd_dev_lock);
421         if (obd->obd_stopping) {
422                 spin_unlock(&obd->obd_dev_lock);
423                 CERROR("OBD %d already stopping\n", obd->obd_minor);
424                 RETURN(-ENODEV);
425         }
426         /* Leave this on forever */
427         obd->obd_stopping = 1;
428         spin_unlock(&obd->obd_dev_lock);
429
430         if (lcfg->lcfg_bufcount >= 2 && LUSTRE_CFG_BUFLEN(lcfg, 1) > 0) {
431                 for (flag = lustre_cfg_string(lcfg, 1); *flag != 0; flag++)
432                         switch (*flag) {
433                         case 'F':
434                                 obd->obd_force = 1;
435                                 break;
436                         case 'A':
437                                 LCONSOLE_WARN("Failing over %s\n",
438                                               obd->obd_name);
439                                 obd->obd_fail = 1;
440                                 obd->obd_no_transno = 1;
441                                 obd->obd_no_recov = 1;
442                                 if (OBP(obd, iocontrol)) {
443                                         obd_iocontrol(OBD_IOC_SYNC,
444                                                       obd->obd_self_export,
445                                                       0, NULL, NULL);
446                                  /* Set the obd readonly if we can */
447                                         obd_iocontrol(OBD_IOC_SET_READONLY,
448                                                       obd->obd_self_export,
449                                                       0, NULL, NULL);
450                                 }
451                                 break;
452                         default:
453                                 CERROR("unrecognised flag '%c'\n",
454                                        *flag);
455                         }
456         }
457
458         /* The three references that should be remaining are the
459          * obd_self_export and the attach and setup references. */
460         if (atomic_read(&obd->obd_refcount) > 3) {
461 #if 0           /* We should never fail to cleanup with mountconf */
462                 if (!(obd->obd_fail || obd->obd_force)) {
463                         CERROR("OBD %s is still busy with %d references\n"
464                                "You should stop active file system users,"
465                                " or use the --force option to cleanup.\n",
466                                obd->obd_name, atomic_read(&obd->obd_refcount));
467                         dump_exports(obd);
468                         /* Allow a failed cleanup to try again. */
469                         obd->obd_stopping = 0;
470                 }
471 #endif
472                 /* refcounf - 3 might be the number of real exports
473                    (excluding self export). But class_incref is called
474                    by other things as well, so don't count on it. */
475                 CDEBUG(D_IOCTL, "%s: forcing exports to disconnect: %d\n",
476                        obd->obd_name, atomic_read(&obd->obd_refcount) - 3);
477                 dump_exports(obd);
478                 class_disconnect_exports(obd);
479         }
480         LASSERT(obd->obd_self_export);
481
482         /* destroy an uuid-export hash body */
483         lustre_hash_exit(obd->obd_uuid_hash);
484
485         /* destroy a nid-export hash body */
486         lustre_hash_exit(obd->obd_nid_hash);
487
488         /* destroy a nid-stats hash body */
489         lustre_hash_exit(obd->obd_nid_stats_hash);
490
491         /* Precleanup, we must make sure all exports get destroyed. */
492         err = obd_precleanup(obd, OBD_CLEANUP_EXPORTS);
493         if (err)
494                 CERROR("Precleanup %s returned %d\n",
495                        obd->obd_name, err);
496         class_decref(obd, "setup", obd);
497         obd->obd_set_up = 0;
498         RETURN(0);
499 }
500
501 struct obd_device *class_incref(struct obd_device *obd,
502                                 const char *scope, const void *source)
503 {
504         lu_ref_add_atomic(&obd->obd_reference, scope, source);
505         atomic_inc(&obd->obd_refcount);
506         CDEBUG(D_INFO, "incref %s (%p) now %d\n", obd->obd_name, obd,
507                atomic_read(&obd->obd_refcount));
508
509         return obd;
510 }
511
512 void class_decref(struct obd_device *obd, const char *scope, const void *source)
513 {
514         int err;
515         int refs;
516
517         spin_lock(&obd->obd_dev_lock);
518         atomic_dec(&obd->obd_refcount);
519         refs = atomic_read(&obd->obd_refcount);
520         spin_unlock(&obd->obd_dev_lock);
521         lu_ref_del(&obd->obd_reference, scope, source);
522
523         CDEBUG(D_INFO, "Decref %s (%p) now %d\n", obd->obd_name, obd, refs);
524
525         if ((refs == 1) && obd->obd_stopping) {
526                 /* All exports have been destroyed; there should
527                    be no more in-progress ops by this point.*/
528
529                 spin_lock(&obd->obd_self_export->exp_lock);
530                 obd->obd_self_export->exp_flags |=
531                         (obd->obd_fail ? OBD_OPT_FAILOVER : 0) |
532                         (obd->obd_force ? OBD_OPT_FORCE : 0);
533                 spin_unlock(&obd->obd_self_export->exp_lock);
534
535                 /* note that we'll recurse into class_decref again */
536                 class_unlink_export(obd->obd_self_export);
537                 return;
538         }
539
540         if (refs == 0) {
541                 CDEBUG(D_CONFIG, "finishing cleanup of obd %s (%s)\n",
542                        obd->obd_name, obd->obd_uuid.uuid);
543                 LASSERT(!obd->obd_attached);
544                 if (obd->obd_stopping) {
545                         /* If we're not stopping, we were never set up */
546                         err = obd_cleanup(obd);
547                         if (err)
548                                 CERROR("Cleanup %s returned %d\n",
549                                        obd->obd_name, err);
550                 }
551                 if (OBP(obd, detach)) {
552                         err = OBP(obd,detach)(obd);
553                         if (err)
554                                 CERROR("Detach returned %d\n", err);
555                 }
556                 class_release_dev(obd);
557         }
558 }
559
560 int class_add_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
561 {
562         struct obd_import *imp;
563         struct obd_uuid uuid;
564         int rc;
565         ENTRY;
566
567         if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 ||
568             LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(struct obd_uuid)) {
569                 CERROR("invalid conn_uuid\n");
570                 RETURN(-EINVAL);
571         }
572         if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
573             strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME) &&
574             strcmp(obd->obd_type->typ_name, LUSTRE_MGC_NAME)) {
575                 CERROR("can't add connection on non-client dev\n");
576                 RETURN(-EINVAL);
577         }
578
579         imp = obd->u.cli.cl_import;
580         if (!imp) {
581                 CERROR("try to add conn on immature client dev\n");
582                 RETURN(-EINVAL);
583         }
584
585         obd_str2uuid(&uuid, lustre_cfg_string(lcfg, 1));
586         rc = obd_add_conn(imp, &uuid, lcfg->lcfg_num);
587
588         RETURN(rc);
589 }
590
591 int class_del_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
592 {
593         struct obd_import *imp;
594         struct obd_uuid uuid;
595         int rc;
596         ENTRY;
597
598         if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 ||
599             LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(struct obd_uuid)) {
600                 CERROR("invalid conn_uuid\n");
601                 RETURN(-EINVAL);
602         }
603         if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
604             strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME)) {
605                 CERROR("can't del connection on non-client dev\n");
606                 RETURN(-EINVAL);
607         }
608
609         imp = obd->u.cli.cl_import;
610         if (!imp) {
611                 CERROR("try to del conn on immature client dev\n");
612                 RETURN(-EINVAL);
613         }
614
615         obd_str2uuid(&uuid, lustre_cfg_string(lcfg, 1));
616         rc = obd_del_conn(imp, &uuid);
617
618         RETURN(rc);
619 }
620
621 CFS_LIST_HEAD(lustre_profile_list);
622
623 struct lustre_profile *class_get_profile(const char * prof)
624 {
625         struct lustre_profile *lprof;
626
627         ENTRY;
628         list_for_each_entry(lprof, &lustre_profile_list, lp_list) {
629                 if (!strcmp(lprof->lp_profile, prof)) {
630                         RETURN(lprof);
631                 }
632         }
633         RETURN(NULL);
634 }
635
636 int class_add_profile(int proflen, char *prof, int osclen, char *osc,
637                       int mdclen, char *mdc)
638 {
639         struct lustre_profile *lprof;
640         int err = 0;
641         ENTRY;
642
643         CDEBUG(D_CONFIG, "Add profile %s\n", prof);
644
645         OBD_ALLOC(lprof, sizeof(*lprof));
646         if (lprof == NULL)
647                 RETURN(-ENOMEM);
648         CFS_INIT_LIST_HEAD(&lprof->lp_list);
649
650         LASSERT(proflen == (strlen(prof) + 1));
651         OBD_ALLOC(lprof->lp_profile, proflen);
652         if (lprof->lp_profile == NULL)
653                 GOTO(out, err = -ENOMEM);
654         memcpy(lprof->lp_profile, prof, proflen);
655
656         LASSERT(osclen == (strlen(osc) + 1));
657         OBD_ALLOC(lprof->lp_dt, osclen);
658         if (lprof->lp_dt == NULL)
659                 GOTO(out, err = -ENOMEM);
660         memcpy(lprof->lp_dt, osc, osclen);
661
662         if (mdclen > 0) {
663                 LASSERT(mdclen == (strlen(mdc) + 1));
664                 OBD_ALLOC(lprof->lp_md, mdclen);
665                 if (lprof->lp_md == NULL)
666                         GOTO(out, err = -ENOMEM);
667                 memcpy(lprof->lp_md, mdc, mdclen);
668         }
669
670         list_add(&lprof->lp_list, &lustre_profile_list);
671         RETURN(err);
672
673 out:
674         if (lprof->lp_md)
675                 OBD_FREE(lprof->lp_md, mdclen);
676         if (lprof->lp_dt)
677                 OBD_FREE(lprof->lp_dt, osclen);
678         if (lprof->lp_profile)
679                 OBD_FREE(lprof->lp_profile, proflen);
680         OBD_FREE(lprof, sizeof(*lprof));
681         RETURN(err);
682 }
683
684 void class_del_profile(const char *prof)
685 {
686         struct lustre_profile *lprof;
687         ENTRY;
688
689         CDEBUG(D_CONFIG, "Del profile %s\n", prof);
690
691         lprof = class_get_profile(prof);
692         if (lprof) {
693                 list_del(&lprof->lp_list);
694                 OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
695                 OBD_FREE(lprof->lp_dt, strlen(lprof->lp_dt) + 1);
696                 if (lprof->lp_md)
697                         OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1);
698                 OBD_FREE(lprof, sizeof *lprof);
699         }
700         EXIT;
701 }
702
703 /* COMPAT_146 */
704 void class_del_profiles(void)
705 {
706         struct lustre_profile *lprof, *n;
707         ENTRY;
708
709         list_for_each_entry_safe(lprof, n, &lustre_profile_list, lp_list) {
710                 list_del(&lprof->lp_list);
711                 OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
712                 OBD_FREE(lprof->lp_dt, strlen(lprof->lp_dt) + 1);
713                 if (lprof->lp_md)
714                         OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1);
715                 OBD_FREE(lprof, sizeof *lprof);
716         }
717         EXIT;
718 }
719
720 /* We can't call ll_process_config directly because it lives in a module that
721    must be loaded after this one. */
722 static int (*client_process_config)(struct lustre_cfg *lcfg) = NULL;
723
724 void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg))
725 {
726         client_process_config = cpc;
727 }
728 EXPORT_SYMBOL(lustre_register_client_process_config);
729
730 int class_process_config(struct lustre_cfg *lcfg)
731 {
732         struct obd_device *obd;
733         int err;
734
735         LASSERT(lcfg && !IS_ERR(lcfg));
736         CDEBUG(D_IOCTL, "processing cmd: %x\n", lcfg->lcfg_command);
737
738         /* Commands that don't need a device */
739         switch(lcfg->lcfg_command) {
740         case LCFG_ATTACH: {
741                 err = class_attach(lcfg);
742                 GOTO(out, err);
743         }
744         case LCFG_ADD_UUID: {
745                 CDEBUG(D_IOCTL, "adding mapping from uuid %s to nid "LPX64
746                        " (%s)\n", lustre_cfg_string(lcfg, 1),
747                        lcfg->lcfg_nid, libcfs_nid2str(lcfg->lcfg_nid));
748
749                 err = class_add_uuid(lustre_cfg_string(lcfg, 1), lcfg->lcfg_nid);
750                 GOTO(out, err);
751         }
752         case LCFG_DEL_UUID: {
753                 CDEBUG(D_IOCTL, "removing mappings for uuid %s\n",
754                        (lcfg->lcfg_bufcount < 2 || LUSTRE_CFG_BUFLEN(lcfg, 1) == 0)
755                        ? "<all uuids>" : lustre_cfg_string(lcfg, 1));
756
757                 err = class_del_uuid(lustre_cfg_string(lcfg, 1));
758                 GOTO(out, err);
759         }
760         case LCFG_MOUNTOPT: {
761                 CDEBUG(D_IOCTL, "mountopt: profile %s osc %s mdc %s\n",
762                        lustre_cfg_string(lcfg, 1),
763                        lustre_cfg_string(lcfg, 2),
764                        lustre_cfg_string(lcfg, 3));
765                 /* set these mount options somewhere, so ll_fill_super
766                  * can find them. */
767                 err = class_add_profile(LUSTRE_CFG_BUFLEN(lcfg, 1),
768                                         lustre_cfg_string(lcfg, 1),
769                                         LUSTRE_CFG_BUFLEN(lcfg, 2),
770                                         lustre_cfg_string(lcfg, 2),
771                                         LUSTRE_CFG_BUFLEN(lcfg, 3),
772                                         lustre_cfg_string(lcfg, 3));
773                 GOTO(out, err);
774         }
775         case LCFG_DEL_MOUNTOPT: {
776                 CDEBUG(D_IOCTL, "mountopt: profile %s\n",
777                        lustre_cfg_string(lcfg, 1));
778                 class_del_profile(lustre_cfg_string(lcfg, 1));
779                 GOTO(out, err = 0);
780         }
781         case LCFG_SET_TIMEOUT: {
782                 CDEBUG(D_IOCTL, "changing lustre timeout from %d to %d\n",
783                        obd_timeout, lcfg->lcfg_num);
784                 obd_timeout = max(lcfg->lcfg_num, 1U);
785                 GOTO(out, err = 0);
786         }
787         case LCFG_SET_UPCALL: {
788                 LCONSOLE_ERROR_MSG(0x15a, "recovery upcall is deprecated\n");
789                 /* COMPAT_146 Don't fail on old configs */
790                 GOTO(out, err = 0);
791         }
792         case LCFG_MARKER: {
793                 struct cfg_marker *marker;
794                 marker = lustre_cfg_buf(lcfg, 1);
795                 CDEBUG(D_IOCTL, "marker %d (%#x) %.16s %s\n", marker->cm_step,
796                        marker->cm_flags, marker->cm_tgtname, marker->cm_comment);
797                 GOTO(out, err = 0);
798         }
799         case LCFG_PARAM: {
800                 /* llite has no obd */
801                 if ((class_match_param(lustre_cfg_string(lcfg, 1),
802                                        PARAM_LLITE, 0) == 0) &&
803                     client_process_config) {
804                         err = (*client_process_config)(lcfg);
805                         GOTO(out, err);
806                 }
807                 /* Fall through */
808                 break;
809         }
810         }
811
812         /* Commands that require a device */
813         obd = class_name2obd(lustre_cfg_string(lcfg, 0));
814         if (obd == NULL) {
815                 if (!LUSTRE_CFG_BUFLEN(lcfg, 0))
816                         CERROR("this lcfg command requires a device name\n");
817                 else
818                         CERROR("no device for: %s\n",
819                                lustre_cfg_string(lcfg, 0));
820
821                 GOTO(out, err = -EINVAL);
822         }
823
824         switch(lcfg->lcfg_command) {
825         case LCFG_SETUP: {
826                 err = class_setup(obd, lcfg);
827                 GOTO(out, err);
828         }
829         case LCFG_DETACH: {
830                 err = class_detach(obd, lcfg);
831                 GOTO(out, err = 0);
832         }
833         case LCFG_CLEANUP: {
834                 err = class_cleanup(obd, lcfg);
835                 GOTO(out, err = 0);
836         }
837         case LCFG_ADD_CONN: {
838                 err = class_add_conn(obd, lcfg);
839                 GOTO(out, err = 0);
840         }
841         case LCFG_DEL_CONN: {
842                 err = class_del_conn(obd, lcfg);
843                 GOTO(out, err = 0);
844         }
845         case LCFG_POOL_NEW: {
846                 err = obd_pool_new(obd, lustre_cfg_string(lcfg, 2));
847                 GOTO(out, err = 0);
848                 break;
849         }
850         case LCFG_POOL_ADD: {
851                 err = obd_pool_add(obd, lustre_cfg_string(lcfg, 2),
852                                    lustre_cfg_string(lcfg, 3));
853                 GOTO(out, err = 0);
854                 break;
855         }
856         case LCFG_POOL_REM: {
857                 err = obd_pool_rem(obd, lustre_cfg_string(lcfg, 2),
858                                    lustre_cfg_string(lcfg, 3));
859                 GOTO(out, err = 0);
860                 break;
861         }
862         case LCFG_POOL_DEL: {
863                 err = obd_pool_del(obd, lustre_cfg_string(lcfg, 2));
864                 GOTO(out, err = 0);
865                 break;
866         }
867         default: {
868                 err = obd_process_config(obd, sizeof(*lcfg), lcfg);
869                 GOTO(out, err);
870
871         }
872         }
873 out:
874         if ((err < 0) && !(lcfg->lcfg_command & LCFG_REQUIRED)) {
875                 CWARN("Ignoring error %d on optional command %#x\n", err,
876                       lcfg->lcfg_command);
877                 err = 0;
878         }
879         return err;
880 }
881
882 int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars,
883                              struct lustre_cfg *lcfg, void *data)
884 {
885 #ifdef __KERNEL__
886         struct lprocfs_vars *var;
887         char *key, *sval;
888         int i, keylen, vallen;
889         int matched = 0, j = 0;
890         int rc = 0;
891         ENTRY;
892
893         if (lcfg->lcfg_command != LCFG_PARAM) {
894                 CERROR("Unknown command: %d\n", lcfg->lcfg_command);
895                 RETURN(-EINVAL);
896         }
897
898         /* e.g. tunefs.lustre --param mdt.group_upcall=foo /r/tmp/lustre-mdt
899            or   lctl conf_param lustre-MDT0000.mdt.group_upcall=bar
900            or   lctl conf_param lustre-OST0000.osc.max_dirty_mb=36 */
901         for (i = 1; i < lcfg->lcfg_bufcount; i++) {
902                 key = lustre_cfg_buf(lcfg, i);
903                 /* Strip off prefix */
904                 class_match_param(key, prefix, &key);
905                 sval = strchr(key, '=');
906                 if (!sval || (*(sval + 1) == 0)) {
907                         CERROR("Can't parse param %s (missing '=')\n", key);
908                         /* rc = -EINVAL; continue parsing other params */
909                         continue;
910                 }
911                 keylen = sval - key;
912                 sval++;
913                 vallen = strlen(sval);
914                 matched = 0;
915                 j = 0;
916                 /* Search proc entries */
917                 while (lvars[j].name) {
918                         var = &lvars[j];
919                         if (class_match_param(key, (char *)var->name, 0) == 0 &&
920                             keylen == strlen(var->name)) {
921                                 matched++;
922                                 rc = -EROFS;
923                                 if (var->write_fptr) {
924                                         mm_segment_t oldfs;
925                                         oldfs = get_fs();
926                                         set_fs(KERNEL_DS);
927                                         rc = (var->write_fptr)(NULL, sval,
928                                                                vallen, data);
929                                         set_fs(oldfs);
930                                 }
931                                 if (rc < 0)
932                                         CERROR("writing proc entry %s err %d\n",
933                                                var->name, rc);
934                                 break;
935                         }
936                         j++;
937                 }
938                 if (!matched) {
939                         /* If the prefix doesn't match, return error so we
940                            can pass it down the stack */
941                         if (strnchr(key, keylen, '.'))
942                             RETURN(-ENOSYS);
943                         CERROR("%s: unknown param %s\n",
944                                (char *)lustre_cfg_string(lcfg, 0), key);
945                         /* rc = -EINVAL;        continue parsing other params */
946                 } else {
947                         LCONSOLE_INFO("%s.%.*s: set parameter %.*s=%s\n",
948                                       lustre_cfg_string(lcfg, 0),
949                                       (int)strlen(prefix) - 1, prefix,
950                                       (int)(sval - key - 1), key, sval);
951                 }
952         }
953
954         if (rc > 0)
955                 rc = 0;
956         RETURN(rc);
957 #else
958         CDEBUG(D_CONFIG, "liblustre can't process params.\n");
959         /* Don't throw config error */
960         RETURN(0);
961 #endif
962 }
963
964 int class_config_dump_handler(struct llog_handle * handle,
965                               struct llog_rec_hdr *rec, void *data);
966
967 #ifdef __KERNEL__
968 extern int lustre_check_exclusion(struct super_block *sb, char *svname);
969 #else
970 #define lustre_check_exclusion(a,b)  0
971 #endif
972
973 static int class_config_llog_handler(struct llog_handle * handle,
974                                      struct llog_rec_hdr *rec, void *data)
975 {
976         struct config_llog_instance *clli = data;
977         int cfg_len = rec->lrh_len;
978         char *cfg_buf = (char*) (rec + 1);
979         int rc = 0;
980         ENTRY;
981
982         //class_config_dump_handler(handle, rec, data);
983
984         switch (rec->lrh_type) {
985         case OBD_CFG_REC: {
986                 struct lustre_cfg *lcfg, *lcfg_new;
987                 struct lustre_cfg_bufs bufs;
988                 char *inst_name = NULL;
989                 int inst_len = 0;
990                 int inst = 0, swab = 0;
991
992                 lcfg = (struct lustre_cfg *)cfg_buf;
993                 if (lcfg->lcfg_version == __swab32(LUSTRE_CFG_VERSION)) {
994                         lustre_swab_lustre_cfg(lcfg);
995                         swab = 1;
996                 }
997
998                 rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
999                 if (rc)
1000                         GOTO(out, rc);
1001
1002                 /* Figure out config state info */
1003                 if (lcfg->lcfg_command == LCFG_MARKER) {
1004                         struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
1005                         lustre_swab_cfg_marker(marker, swab,
1006                                                LUSTRE_CFG_BUFLEN(lcfg, 1));
1007                         CDEBUG(D_CONFIG, "Marker, inst_flg=%#x mark_flg=%#x\n",
1008                                clli->cfg_flags, marker->cm_flags);
1009                         if (marker->cm_flags & CM_START) {
1010                                 /* all previous flags off */
1011                                 clli->cfg_flags = CFG_F_MARKER;
1012                                 if (marker->cm_flags & CM_SKIP) {
1013                                         clli->cfg_flags |= CFG_F_SKIP;
1014                                         CDEBUG(D_CONFIG, "SKIP #%d\n",
1015                                                marker->cm_step);
1016                                 } else if ((marker->cm_flags & CM_EXCLUDE) ||
1017                                            lustre_check_exclusion(clli->cfg_sb,
1018                                                           marker->cm_tgtname)) {
1019                                         clli->cfg_flags |= CFG_F_EXCLUDE;
1020                                         CDEBUG(D_CONFIG, "EXCLUDE %d\n",
1021                                                marker->cm_step);
1022                                 }
1023                         } else if (marker->cm_flags & CM_END) {
1024                                 clli->cfg_flags = 0;
1025                         }
1026                 }
1027                 /* A config command without a start marker before it is
1028                    illegal (post 146) */
1029                 if (!(clli->cfg_flags & CFG_F_COMPAT146) &&
1030                     !(clli->cfg_flags & CFG_F_MARKER) &&
1031                     (lcfg->lcfg_command != LCFG_MARKER)) {
1032                         CWARN("Config not inside markers, ignoring! "
1033                               "(inst: %s, uuid: %s, flags: %#x)\n",
1034                               clli->cfg_instance ? clli->cfg_instance : "<null>",
1035                               clli->cfg_uuid.uuid, clli->cfg_flags);
1036                         clli->cfg_flags |= CFG_F_SKIP;
1037                 }
1038                 if (clli->cfg_flags & CFG_F_SKIP) {
1039                         CDEBUG(D_CONFIG, "skipping %#x\n",
1040                                clli->cfg_flags);
1041                         rc = 0;
1042                         /* No processing! */
1043                         break;
1044                 }
1045
1046                 if ((clli->cfg_flags & CFG_F_EXCLUDE) &&
1047                     (lcfg->lcfg_command == LCFG_LOV_ADD_OBD))
1048                         /* Add inactive instead */
1049                         lcfg->lcfg_command = LCFG_LOV_ADD_INA;
1050
1051                 lustre_cfg_bufs_init(&bufs, lcfg);
1052
1053                 if (clli && clli->cfg_instance &&
1054                     LUSTRE_CFG_BUFLEN(lcfg, 0) > 0){
1055                         inst = 1;
1056                         inst_len = LUSTRE_CFG_BUFLEN(lcfg, 0) +
1057                                 strlen(clli->cfg_instance) + 1;
1058                         OBD_ALLOC(inst_name, inst_len);
1059                         if (inst_name == NULL)
1060                                 GOTO(out, rc = -ENOMEM);
1061                         sprintf(inst_name, "%s-%s",
1062                                 lustre_cfg_string(lcfg, 0),
1063                                 clli->cfg_instance);
1064                         lustre_cfg_bufs_set_string(&bufs, 0, inst_name);
1065                         CDEBUG(D_CONFIG, "cmd %x, instance name: %s\n",
1066                                lcfg->lcfg_command, inst_name);
1067                 }
1068
1069                 /* we override the llog's uuid for clients, to insure they
1070                 are unique */
1071                 if (clli && clli->cfg_instance &&
1072                     lcfg->lcfg_command == LCFG_ATTACH) {
1073                         lustre_cfg_bufs_set_string(&bufs, 2,
1074                                                    clli->cfg_uuid.uuid);
1075                 }
1076
1077                 lcfg_new = lustre_cfg_new(lcfg->lcfg_command, &bufs);
1078
1079                 lcfg_new->lcfg_num   = lcfg->lcfg_num;
1080                 lcfg_new->lcfg_flags = lcfg->lcfg_flags;
1081
1082                 /* XXX Hack to try to remain binary compatible with
1083                  * pre-newconfig logs */
1084                 if (lcfg->lcfg_nal != 0 &&      /* pre-newconfig log? */
1085                     (lcfg->lcfg_nid >> 32) == 0) {
1086                         __u32 addr = (__u32)(lcfg->lcfg_nid & 0xffffffff);
1087
1088                         lcfg_new->lcfg_nid =
1089                                 LNET_MKNID(LNET_MKNET(lcfg->lcfg_nal, 0), addr);
1090                         CWARN("Converted pre-newconfig NAL %d NID %x to %s\n",
1091                               lcfg->lcfg_nal, addr,
1092                               libcfs_nid2str(lcfg_new->lcfg_nid));
1093                 } else {
1094                         lcfg_new->lcfg_nid = lcfg->lcfg_nid;
1095                 }
1096
1097                 lcfg_new->lcfg_nal = 0; /* illegal value for obsolete field */
1098
1099                 rc = class_process_config(lcfg_new);
1100                 lustre_cfg_free(lcfg_new);
1101
1102                 if (inst)
1103                         OBD_FREE(inst_name, inst_len);
1104                 break;
1105         }
1106         default:
1107                 CERROR("Unknown llog record type %#x encountered\n",
1108                        rec->lrh_type);
1109                 break;
1110         }
1111 out:
1112         if (rc) {
1113                 CERROR("Err %d on cfg command:\n", rc);
1114                 class_config_dump_handler(handle, rec, data);
1115         }
1116         RETURN(rc);
1117 }
1118
1119 int class_config_parse_llog(struct llog_ctxt *ctxt, char *name,
1120                             struct config_llog_instance *cfg)
1121 {
1122         struct llog_process_cat_data cd = {0, 0};
1123         struct llog_handle *llh;
1124         int rc, rc2;
1125         ENTRY;
1126
1127         CDEBUG(D_INFO, "looking up llog %s\n", name);
1128         rc = llog_create(ctxt, &llh, NULL, name);
1129         if (rc)
1130                 RETURN(rc);
1131
1132         rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
1133         if (rc)
1134                 GOTO(parse_out, rc);
1135
1136         /* continue processing from where we last stopped to end-of-log */
1137         if (cfg)
1138                 cd.lpcd_first_idx = cfg->cfg_last_idx;
1139         cd.lpcd_last_idx = 0;
1140
1141         rc = llog_process(llh, class_config_llog_handler, cfg, &cd);
1142
1143         CDEBUG(D_CONFIG, "Processed log %s gen %d-%d (rc=%d)\n", name,
1144                cd.lpcd_first_idx + 1, cd.lpcd_last_idx, rc);
1145
1146         if (cfg)
1147                 cfg->cfg_last_idx = cd.lpcd_last_idx;
1148
1149 parse_out:
1150         rc2 = llog_close(llh);
1151         if (rc == 0)
1152                 rc = rc2;
1153
1154         RETURN(rc);
1155 }
1156
1157 int class_config_dump_handler(struct llog_handle * handle,
1158                               struct llog_rec_hdr *rec, void *data)
1159 {
1160         int cfg_len = rec->lrh_len;
1161         char *cfg_buf = (char*) (rec + 1);
1162         char *outstr, *ptr, *end;
1163         int rc = 0;
1164         ENTRY;
1165
1166         OBD_ALLOC(outstr, 256);
1167         end = outstr + 256;
1168         ptr = outstr;
1169         if (!outstr) {
1170                 RETURN(-ENOMEM);
1171         }
1172         if (rec->lrh_type == OBD_CFG_REC) {
1173                 struct lustre_cfg *lcfg;
1174                 int i;
1175
1176                 rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
1177                 if (rc)
1178                         GOTO(out, rc);
1179                 lcfg = (struct lustre_cfg *)cfg_buf;
1180
1181                 ptr += snprintf(ptr, end-ptr, "cmd=%05x ",
1182                                 lcfg->lcfg_command);
1183                 if (lcfg->lcfg_flags) {
1184                         ptr += snprintf(ptr, end-ptr, "flags=%#08x ",
1185                                         lcfg->lcfg_flags);
1186                 }
1187                 if (lcfg->lcfg_num) {
1188                         ptr += snprintf(ptr, end-ptr, "num=%#08x ",
1189                                         lcfg->lcfg_num);
1190                 }
1191                 if (lcfg->lcfg_nid) {
1192                         ptr += snprintf(ptr, end-ptr, "nid=%s("LPX64")\n     ",
1193                                         libcfs_nid2str(lcfg->lcfg_nid),
1194                                         lcfg->lcfg_nid);
1195                 }
1196                 if (lcfg->lcfg_command == LCFG_MARKER) {
1197                         struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
1198                         ptr += snprintf(ptr, end-ptr, "marker=%d(%#x)%s '%s'",
1199                                         marker->cm_step, marker->cm_flags,
1200                                         marker->cm_tgtname, marker->cm_comment);
1201                 } else {
1202                         for (i = 0; i <  lcfg->lcfg_bufcount; i++) {
1203                                 ptr += snprintf(ptr, end-ptr, "%d:%s  ", i,
1204                                                 lustre_cfg_string(lcfg, i));
1205                         }
1206                 }
1207                 LCONSOLE(D_WARNING, "   %s\n", outstr);
1208         } else {
1209                 LCONSOLE(D_WARNING, "unhandled lrh_type: %#x\n", rec->lrh_type);
1210                 rc = -EINVAL;
1211         }
1212 out:
1213         OBD_FREE(outstr, 256);
1214         RETURN(rc);
1215 }
1216
1217 int class_config_dump_llog(struct llog_ctxt *ctxt, char *name,
1218                            struct config_llog_instance *cfg)
1219 {
1220         struct llog_handle *llh;
1221         int rc, rc2;
1222         ENTRY;
1223
1224         LCONSOLE_INFO("Dumping config log %s\n", name);
1225
1226         rc = llog_create(ctxt, &llh, NULL, name);
1227         if (rc)
1228                 RETURN(rc);
1229
1230         rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
1231         if (rc)
1232                 GOTO(parse_out, rc);
1233
1234         rc = llog_process(llh, class_config_dump_handler, cfg, NULL);
1235 parse_out:
1236         rc2 = llog_close(llh);
1237         if (rc == 0)
1238                 rc = rc2;
1239
1240         LCONSOLE_INFO("End config log %s\n", name);
1241         RETURN(rc);
1242
1243 }
1244
1245 /* Cleanup and detach */
1246 int class_manual_cleanup(struct obd_device *obd)
1247 {
1248         struct lustre_cfg *lcfg;
1249         struct lustre_cfg_bufs bufs;
1250         int rc;
1251         char flags[3]="";
1252         ENTRY;
1253
1254         if (!obd) {
1255                 CERROR("empty cleanup\n");
1256                 RETURN(-EALREADY);
1257         }
1258
1259         if (obd->obd_force)
1260                 strcat(flags, "F");
1261         if (obd->obd_fail)
1262                 strcat(flags, "A");
1263
1264         CDEBUG(D_CONFIG, "Manual cleanup of %s (flags='%s')\n",
1265                obd->obd_name, flags);
1266
1267         lustre_cfg_bufs_reset(&bufs, obd->obd_name);
1268         lustre_cfg_bufs_set_string(&bufs, 1, flags);
1269         lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
1270
1271         rc = class_process_config(lcfg);
1272         if (rc) {
1273                 CERROR("cleanup failed %d: %s\n", rc, obd->obd_name);
1274                 GOTO(out, rc);
1275         }
1276
1277         /* the lcfg is almost the same for both ops */
1278         lcfg->lcfg_command = LCFG_DETACH;
1279         rc = class_process_config(lcfg);
1280         if (rc)
1281                 CERROR("detach failed %d: %s\n", rc, obd->obd_name);
1282 out:
1283         lustre_cfg_free(lcfg);
1284         RETURN(rc);
1285 }
1286
1287 /*
1288  * uuid<->export lustre hash operations
1289  */
1290
1291 static unsigned
1292 uuid_hash(lustre_hash_t *lh,  void *key, unsigned mask)
1293 {
1294         return lh_djb2_hash(((struct obd_uuid *)key)->uuid,
1295                             sizeof(((struct obd_uuid *)key)->uuid), mask);
1296 }
1297
1298 static void *
1299 uuid_key(struct hlist_node *hnode)
1300 {
1301         struct obd_export *exp;
1302
1303         exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
1304
1305         RETURN(&exp->exp_client_uuid);
1306 }
1307
1308 /*
1309  * NOTE: It is impossible to find an export that is in failed
1310  *       state with this function
1311  */
1312 static int
1313 uuid_compare(void *key, struct hlist_node *hnode)
1314 {
1315         struct obd_export *exp;
1316
1317         LASSERT(key);
1318         exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
1319
1320         RETURN(obd_uuid_equals((struct obd_uuid *)key,&exp->exp_client_uuid) &&
1321                !exp->exp_failed);
1322 }
1323
1324 static void *
1325 uuid_export_get(struct hlist_node *hnode)
1326 {
1327         struct obd_export *exp;
1328
1329         exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
1330         class_export_get(exp);
1331
1332         RETURN(exp);
1333 }
1334
1335 static void *
1336 uuid_export_put(struct hlist_node *hnode)
1337 {
1338         struct obd_export *exp;
1339
1340         exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
1341         class_export_put(exp);
1342
1343         RETURN(exp);
1344 }
1345
1346 static lustre_hash_ops_t uuid_hash_ops = {
1347         .lh_hash    = uuid_hash,
1348         .lh_key     = uuid_key,
1349         .lh_compare = uuid_compare,
1350         .lh_get     = uuid_export_get,
1351         .lh_put     = uuid_export_put,
1352 };
1353
1354
1355 /*
1356  * nid<->export hash operations
1357  */
1358
1359 static unsigned
1360 nid_hash(lustre_hash_t *lh,  void *key, unsigned mask)
1361 {
1362         return lh_djb2_hash(key, sizeof(lnet_nid_t), mask);
1363 }
1364
1365 static void *
1366 nid_key(struct hlist_node *hnode)
1367 {
1368         struct obd_export *exp;
1369
1370         exp = hlist_entry(hnode, struct obd_export, exp_nid_hash);
1371
1372         RETURN(&exp->exp_connection->c_peer.nid);
1373 }
1374
1375 /*
1376  * NOTE: It is impossible to find an export that is in failed
1377  *       state with this function
1378  */
1379 static int
1380 nid_compare(void *key, struct hlist_node *hnode)
1381 {
1382         struct obd_export *exp;
1383
1384         LASSERT(key);
1385         exp = hlist_entry(hnode, struct obd_export, exp_nid_hash);
1386
1387         RETURN(exp->exp_connection->c_peer.nid == *(lnet_nid_t *)key &&
1388                !exp->exp_failed);
1389 }
1390
1391 static void *
1392 nid_export_get(struct hlist_node *hnode)
1393 {
1394         struct obd_export *exp;
1395
1396         exp = hlist_entry(hnode, struct obd_export, exp_nid_hash);
1397         class_export_get(exp);
1398
1399         RETURN(exp);
1400 }
1401
1402 static void *
1403 nid_export_put(struct hlist_node *hnode)
1404 {
1405         struct obd_export *exp;
1406
1407         exp = hlist_entry(hnode, struct obd_export, exp_nid_hash);
1408         class_export_put(exp);
1409
1410         RETURN(exp);
1411 }
1412
1413 static lustre_hash_ops_t nid_hash_ops = {
1414         .lh_hash    = nid_hash,
1415         .lh_key     = nid_key,
1416         .lh_compare = nid_compare,
1417         .lh_get     = nid_export_get,
1418         .lh_put     = nid_export_put,
1419 };
1420
1421
1422 /*
1423  * nid<->nidstats hash operations
1424  */
1425
1426 static void *
1427 nidstats_key(struct hlist_node *hnode)
1428 {
1429         struct nid_stat *ns;
1430
1431         ns = hlist_entry(hnode, struct nid_stat, nid_hash);
1432
1433         RETURN(&ns->nid);
1434 }
1435
1436 static int
1437 nidstats_compare(void *key, struct hlist_node *hnode)
1438 {
1439         RETURN(*(lnet_nid_t *)nidstats_key(hnode) == *(lnet_nid_t *)key);
1440 }
1441
1442 static void *
1443 nidstats_get(struct hlist_node *hnode)
1444 {
1445         struct nid_stat *ns;
1446
1447         ns = hlist_entry(hnode, struct nid_stat, nid_hash);
1448         ns->nid_exp_ref_count++;
1449
1450         RETURN(ns);
1451 }
1452
1453 static void *
1454 nidstats_put(struct hlist_node *hnode)
1455 {
1456         struct nid_stat *ns;
1457
1458         ns = hlist_entry(hnode, struct nid_stat, nid_hash);
1459         ns->nid_exp_ref_count--;
1460
1461         RETURN(ns);
1462 }
1463
1464 static lustre_hash_ops_t nid_stat_hash_ops = {
1465         .lh_hash    = nid_hash,
1466         .lh_key     = nidstats_key,
1467         .lh_compare = nidstats_compare,
1468         .lh_get     = nidstats_get,
1469         .lh_put     = nidstats_put,
1470 };