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