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