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