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