staging/lustre: Add spaces preferred around that '{+, -, *, /, |, <<, >>, &}'
[linux-2.6-microblaze.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
418         /* wait for already-arrived-connections to finish. */
419         while (obd->obd_conn_inprogress > 0) {
420                 spin_unlock(&obd->obd_dev_lock);
421
422                 cond_resched();
423
424                 spin_lock(&obd->obd_dev_lock);
425         }
426         spin_unlock(&obd->obd_dev_lock);
427
428         if (lcfg->lcfg_bufcount >= 2 && LUSTRE_CFG_BUFLEN(lcfg, 1) > 0) {
429                 for (flag = lustre_cfg_string(lcfg, 1); *flag != 0; flag++)
430                         switch (*flag) {
431                         case 'F':
432                                 obd->obd_force = 1;
433                                 break;
434                         case 'A':
435                                 LCONSOLE_WARN("Failing over %s\n",
436                                               obd->obd_name);
437                                 obd->obd_fail = 1;
438                                 obd->obd_no_transno = 1;
439                                 obd->obd_no_recov = 1;
440                                 if (OBP(obd, iocontrol)) {
441                                         obd_iocontrol(OBD_IOC_SYNC,
442                                                       obd->obd_self_export,
443                                                       0, NULL, NULL);
444                                 }
445                                 break;
446                         default:
447                                 CERROR("Unrecognised flag '%c'\n", *flag);
448                         }
449         }
450
451         LASSERT(obd->obd_self_export);
452
453         /* Precleanup, we must make sure all exports get destroyed. */
454         err = obd_precleanup(obd, OBD_CLEANUP_EXPORTS);
455         if (err)
456                 CERROR("Precleanup %s returned %d\n",
457                        obd->obd_name, err);
458
459         /* destroy an uuid-export hash body */
460         if (obd->obd_uuid_hash) {
461                 cfs_hash_putref(obd->obd_uuid_hash);
462                 obd->obd_uuid_hash = NULL;
463         }
464
465         class_decref(obd, "setup", obd);
466         obd->obd_set_up = 0;
467
468         return 0;
469 }
470
471 struct obd_device *class_incref(struct obd_device *obd,
472                                 const char *scope, const void *source)
473 {
474         lu_ref_add_atomic(&obd->obd_reference, scope, source);
475         atomic_inc(&obd->obd_refcount);
476         CDEBUG(D_INFO, "incref %s (%p) now %d\n", obd->obd_name, obd,
477                atomic_read(&obd->obd_refcount));
478
479         return obd;
480 }
481 EXPORT_SYMBOL(class_incref);
482
483 void class_decref(struct obd_device *obd, const char *scope, const void *source)
484 {
485         int err;
486         int refs;
487
488         spin_lock(&obd->obd_dev_lock);
489         atomic_dec(&obd->obd_refcount);
490         refs = atomic_read(&obd->obd_refcount);
491         spin_unlock(&obd->obd_dev_lock);
492         lu_ref_del(&obd->obd_reference, scope, source);
493
494         CDEBUG(D_INFO, "Decref %s (%p) now %d\n", obd->obd_name, obd, refs);
495
496         if ((refs == 1) && obd->obd_stopping) {
497                 /* All exports have been destroyed; there should
498                  * be no more in-progress ops by this point.
499                  */
500
501                 spin_lock(&obd->obd_self_export->exp_lock);
502                 obd->obd_self_export->exp_flags |= exp_flags_from_obd(obd);
503                 spin_unlock(&obd->obd_self_export->exp_lock);
504
505                 /* note that we'll recurse into class_decref again */
506                 class_unlink_export(obd->obd_self_export);
507                 return;
508         }
509
510         if (refs == 0) {
511                 CDEBUG(D_CONFIG, "finishing cleanup of obd %s (%s)\n",
512                        obd->obd_name, obd->obd_uuid.uuid);
513                 LASSERT(!obd->obd_attached);
514                 if (obd->obd_stopping) {
515                         /* If we're not stopping, we were never set up */
516                         err = obd_cleanup(obd);
517                         if (err)
518                                 CERROR("Cleanup %s returned %d\n",
519                                        obd->obd_name, err);
520                 }
521                 class_release_dev(obd);
522         }
523 }
524 EXPORT_SYMBOL(class_decref);
525
526 /** Add a failover nid location.
527  * Client obd types contact server obd types using this nid list.
528  */
529 static int class_add_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
530 {
531         struct obd_import *imp;
532         struct obd_uuid uuid;
533         int rc;
534
535         if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 ||
536             LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(struct obd_uuid)) {
537                 CERROR("invalid conn_uuid\n");
538                 return -EINVAL;
539         }
540         if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
541             strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME) &&
542             strcmp(obd->obd_type->typ_name, LUSTRE_OSP_NAME) &&
543             strcmp(obd->obd_type->typ_name, LUSTRE_LWP_NAME) &&
544             strcmp(obd->obd_type->typ_name, LUSTRE_MGC_NAME)) {
545                 CERROR("can't add connection on non-client dev\n");
546                 return -EINVAL;
547         }
548
549         imp = obd->u.cli.cl_import;
550         if (!imp) {
551                 CERROR("try to add conn on immature client dev\n");
552                 return -EINVAL;
553         }
554
555         obd_str2uuid(&uuid, lustre_cfg_string(lcfg, 1));
556         rc = obd_add_conn(imp, &uuid, lcfg->lcfg_num);
557
558         return rc;
559 }
560
561 /** Remove a failover nid location.
562  */
563 static int class_del_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
564 {
565         struct obd_import *imp;
566         struct obd_uuid uuid;
567         int rc;
568
569         if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 ||
570             LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(struct obd_uuid)) {
571                 CERROR("invalid conn_uuid\n");
572                 return -EINVAL;
573         }
574         if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
575             strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME)) {
576                 CERROR("can't del connection on non-client dev\n");
577                 return -EINVAL;
578         }
579
580         imp = obd->u.cli.cl_import;
581         if (!imp) {
582                 CERROR("try to del conn on immature client dev\n");
583                 return -EINVAL;
584         }
585
586         obd_str2uuid(&uuid, lustre_cfg_string(lcfg, 1));
587         rc = obd_del_conn(imp, &uuid);
588
589         return rc;
590 }
591
592 static LIST_HEAD(lustre_profile_list);
593
594 struct lustre_profile *class_get_profile(const char *prof)
595 {
596         struct lustre_profile *lprof;
597
598         list_for_each_entry(lprof, &lustre_profile_list, lp_list) {
599                 if (!strcmp(lprof->lp_profile, prof)) {
600                         return lprof;
601                 }
602         }
603         return NULL;
604 }
605 EXPORT_SYMBOL(class_get_profile);
606
607 /** Create a named "profile".
608  * This defines the mdc and osc names to use for a client.
609  * This also is used to define the lov to be used by a mdt.
610  */
611 static int class_add_profile(int proflen, char *prof, int osclen, char *osc,
612                              int mdclen, char *mdc)
613 {
614         struct lustre_profile *lprof;
615         int err = 0;
616
617         CDEBUG(D_CONFIG, "Add profile %s\n", prof);
618
619         lprof = kzalloc(sizeof(*lprof), GFP_NOFS);
620         if (!lprof)
621                 return -ENOMEM;
622         INIT_LIST_HEAD(&lprof->lp_list);
623
624         LASSERT(proflen == (strlen(prof) + 1));
625         lprof->lp_profile = kmemdup(prof, proflen, GFP_NOFS);
626         if (!lprof->lp_profile) {
627                 err = -ENOMEM;
628                 goto free_lprof;
629         }
630
631         LASSERT(osclen == (strlen(osc) + 1));
632         lprof->lp_dt = kmemdup(osc, osclen, GFP_NOFS);
633         if (!lprof->lp_dt) {
634                 err = -ENOMEM;
635                 goto free_lp_profile;
636         }
637
638         if (mdclen > 0) {
639                 LASSERT(mdclen == (strlen(mdc) + 1));
640                 lprof->lp_md = kmemdup(mdc, mdclen, GFP_NOFS);
641                 if (!lprof->lp_md) {
642                         err = -ENOMEM;
643                         goto free_lp_dt;
644                 }
645         }
646
647         list_add(&lprof->lp_list, &lustre_profile_list);
648         return err;
649
650 free_lp_dt:
651         kfree(lprof->lp_dt);
652 free_lp_profile:
653         kfree(lprof->lp_profile);
654 free_lprof:
655         kfree(lprof);
656         return err;
657 }
658
659 void class_del_profile(const char *prof)
660 {
661         struct lustre_profile *lprof;
662
663         CDEBUG(D_CONFIG, "Del profile %s\n", prof);
664
665         lprof = class_get_profile(prof);
666         if (lprof) {
667                 list_del(&lprof->lp_list);
668                 kfree(lprof->lp_profile);
669                 kfree(lprof->lp_dt);
670                 kfree(lprof->lp_md);
671                 kfree(lprof);
672         }
673 }
674 EXPORT_SYMBOL(class_del_profile);
675
676 /* COMPAT_146 */
677 void class_del_profiles(void)
678 {
679         struct lustre_profile *lprof, *n;
680
681         list_for_each_entry_safe(lprof, n, &lustre_profile_list, lp_list) {
682                 list_del(&lprof->lp_list);
683                 kfree(lprof->lp_profile);
684                 kfree(lprof->lp_dt);
685                 kfree(lprof->lp_md);
686                 kfree(lprof);
687         }
688 }
689 EXPORT_SYMBOL(class_del_profiles);
690
691 static int class_set_global(char *ptr, int val, struct lustre_cfg *lcfg)
692 {
693         if (class_match_param(ptr, PARAM_AT_MIN, NULL) == 0)
694                 at_min = val;
695         else if (class_match_param(ptr, PARAM_AT_MAX, NULL) == 0)
696                 at_max = val;
697         else if (class_match_param(ptr, PARAM_AT_EXTRA, NULL) == 0)
698                 at_extra = val;
699         else if (class_match_param(ptr, PARAM_AT_EARLY_MARGIN, NULL) == 0)
700                 at_early_margin = val;
701         else if (class_match_param(ptr, PARAM_AT_HISTORY, NULL) == 0)
702                 at_history = val;
703         else if (class_match_param(ptr, PARAM_JOBID_VAR, NULL) == 0)
704                 strlcpy(obd_jobid_var, lustre_cfg_string(lcfg, 2),
705                         JOBSTATS_JOBID_VAR_MAX_LEN + 1);
706         else
707                 return -EINVAL;
708
709         CDEBUG(D_IOCTL, "global %s = %d\n", ptr, val);
710         return 0;
711 }
712
713 /* We can't call ll_process_config or lquota_process_config directly because
714  * it lives in a module that must be loaded after this one.
715  */
716 static int (*client_process_config)(struct lustre_cfg *lcfg);
717 static int (*quota_process_config)(struct lustre_cfg *lcfg);
718
719 void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg))
720 {
721         client_process_config = cpc;
722 }
723 EXPORT_SYMBOL(lustre_register_client_process_config);
724
725 static int process_param2_config(struct lustre_cfg *lcfg)
726 {
727         char *param = lustre_cfg_string(lcfg, 1);
728         char *upcall = lustre_cfg_string(lcfg, 2);
729         char *argv[] = {
730                 [0] = "/usr/sbin/lctl",
731                 [1] = "set_param",
732                 [2] = param,
733                 [3] = NULL
734         };
735         ktime_t start;
736         ktime_t end;
737         int             rc;
738
739         /* Add upcall processing here. Now only lctl is supported */
740         if (strcmp(upcall, LCTL_UPCALL) != 0) {
741                 CERROR("Unsupported upcall %s\n", upcall);
742                 return -EINVAL;
743         }
744
745         start = ktime_get();
746         rc = call_usermodehelper(argv[0], argv, NULL, 1);
747         end = ktime_get();
748
749         if (rc < 0) {
750                 CERROR(
751                        "lctl: error invoking upcall %s %s %s: rc = %d; time %ldus\n",
752                        argv[0], argv[1], argv[2], rc,
753                        (long)ktime_us_delta(end, start));
754         } else {
755                 CDEBUG(D_HA, "lctl: invoked upcall %s %s %s, time %ldus\n",
756                        argv[0], argv[1], argv[2],
757                        (long)ktime_us_delta(end, start));
758                        rc = 0;
759         }
760
761         return rc;
762 }
763
764 /** Process configuration commands given in lustre_cfg form.
765  * These may come from direct calls (e.g. class_manual_cleanup)
766  * or processing the config llog, or ioctl from lctl.
767  */
768 int class_process_config(struct lustre_cfg *lcfg)
769 {
770         struct obd_device *obd;
771         int err;
772
773         LASSERT(lcfg && !IS_ERR(lcfg));
774         CDEBUG(D_IOCTL, "processing cmd: %x\n", lcfg->lcfg_command);
775
776         /* Commands that don't need a device */
777         switch (lcfg->lcfg_command) {
778         case LCFG_ATTACH: {
779                 err = class_attach(lcfg);
780                 goto out;
781         }
782         case LCFG_ADD_UUID: {
783                 CDEBUG(D_IOCTL, "adding mapping from uuid %s to nid %#llx (%s)\n",
784                        lustre_cfg_string(lcfg, 1), lcfg->lcfg_nid,
785                        libcfs_nid2str(lcfg->lcfg_nid));
786
787                 err = class_add_uuid(lustre_cfg_string(lcfg, 1), lcfg->lcfg_nid);
788                 goto out;
789         }
790         case LCFG_DEL_UUID: {
791                 CDEBUG(D_IOCTL, "removing mappings for uuid %s\n",
792                        (lcfg->lcfg_bufcount < 2 || LUSTRE_CFG_BUFLEN(lcfg, 1) == 0)
793                        ? "<all uuids>" : lustre_cfg_string(lcfg, 1));
794
795                 err = class_del_uuid(lustre_cfg_string(lcfg, 1));
796                 goto out;
797         }
798         case LCFG_MOUNTOPT: {
799                 CDEBUG(D_IOCTL, "mountopt: profile %s osc %s mdc %s\n",
800                        lustre_cfg_string(lcfg, 1),
801                        lustre_cfg_string(lcfg, 2),
802                        lustre_cfg_string(lcfg, 3));
803                 /* set these mount options somewhere, so ll_fill_super
804                  * can find them.
805                  */
806                 err = class_add_profile(LUSTRE_CFG_BUFLEN(lcfg, 1),
807                                         lustre_cfg_string(lcfg, 1),
808                                         LUSTRE_CFG_BUFLEN(lcfg, 2),
809                                         lustre_cfg_string(lcfg, 2),
810                                         LUSTRE_CFG_BUFLEN(lcfg, 3),
811                                         lustre_cfg_string(lcfg, 3));
812                 goto out;
813         }
814         case LCFG_DEL_MOUNTOPT: {
815                 CDEBUG(D_IOCTL, "mountopt: profile %s\n",
816                        lustre_cfg_string(lcfg, 1));
817                 class_del_profile(lustre_cfg_string(lcfg, 1));
818                 err = 0;
819                 goto out;
820         }
821         case LCFG_SET_TIMEOUT: {
822                 CDEBUG(D_IOCTL, "changing lustre timeout from %d to %d\n",
823                        obd_timeout, lcfg->lcfg_num);
824                 obd_timeout = max(lcfg->lcfg_num, 1U);
825                 obd_timeout_set = 1;
826                 err = 0;
827                 goto out;
828         }
829         case LCFG_SET_LDLM_TIMEOUT: {
830                 /* ldlm_timeout is not used on the client */
831                 err = 0;
832                 goto out;
833         }
834         case LCFG_SET_UPCALL: {
835                 LCONSOLE_ERROR_MSG(0x15a, "recovery upcall is deprecated\n");
836                 /* COMPAT_146 Don't fail on old configs */
837                 err = 0;
838                 goto out;
839         }
840         case LCFG_MARKER: {
841                 struct cfg_marker *marker;
842
843                 marker = lustre_cfg_buf(lcfg, 1);
844                 CDEBUG(D_IOCTL, "marker %d (%#x) %.16s %s\n", marker->cm_step,
845                        marker->cm_flags, marker->cm_tgtname, marker->cm_comment);
846                 err = 0;
847                 goto out;
848         }
849         case LCFG_PARAM: {
850                 char *tmp;
851                 /* llite has no obd */
852                 if ((class_match_param(lustre_cfg_string(lcfg, 1),
853                                        PARAM_LLITE, NULL) == 0) &&
854                     client_process_config) {
855                         err = (*client_process_config)(lcfg);
856                         goto out;
857                 } else if ((class_match_param(lustre_cfg_string(lcfg, 1),
858                                               PARAM_SYS, &tmp) == 0)) {
859                         /* Global param settings */
860                         err = class_set_global(tmp, lcfg->lcfg_num, lcfg);
861                         /*
862                          * Client or server should not fail to mount if
863                          * it hits an unknown configuration parameter.
864                          */
865                         if (err != 0)
866                                 CWARN("Ignoring unknown param %s\n", tmp);
867
868                         err = 0;
869                         goto out;
870                 } else if ((class_match_param(lustre_cfg_string(lcfg, 1),
871                                               PARAM_QUOTA, &tmp) == 0) &&
872                            quota_process_config) {
873                         err = (*quota_process_config)(lcfg);
874                         goto out;
875                 }
876
877                 break;
878         }
879         case LCFG_SET_PARAM: {
880                 err = process_param2_config(lcfg);
881                 goto out;
882         }
883         }
884         /* Commands that require a device */
885         obd = class_name2obd(lustre_cfg_string(lcfg, 0));
886         if (!obd) {
887                 if (!LUSTRE_CFG_BUFLEN(lcfg, 0))
888                         CERROR("this lcfg command requires a device name\n");
889                 else
890                         CERROR("no device for: %s\n",
891                                lustre_cfg_string(lcfg, 0));
892
893                 err = -EINVAL;
894                 goto out;
895         }
896
897         switch (lcfg->lcfg_command) {
898         case LCFG_SETUP: {
899                 err = class_setup(obd, lcfg);
900                 goto out;
901         }
902         case LCFG_DETACH: {
903                 err = class_detach(obd, lcfg);
904                 err = 0;
905                 goto out;
906         }
907         case LCFG_CLEANUP: {
908                 err = class_cleanup(obd, lcfg);
909                 err = 0;
910                 goto out;
911         }
912         case LCFG_ADD_CONN: {
913                 err = class_add_conn(obd, lcfg);
914                 err = 0;
915                 goto out;
916         }
917         case LCFG_DEL_CONN: {
918                 err = class_del_conn(obd, lcfg);
919                 err = 0;
920                 goto out;
921         }
922         case LCFG_POOL_NEW: {
923                 err = obd_pool_new(obd, lustre_cfg_string(lcfg, 2));
924                 err = 0;
925                 goto out;
926         }
927         case LCFG_POOL_ADD: {
928                 err = obd_pool_add(obd, lustre_cfg_string(lcfg, 2),
929                                    lustre_cfg_string(lcfg, 3));
930                 err = 0;
931                 goto out;
932         }
933         case LCFG_POOL_REM: {
934                 err = obd_pool_rem(obd, lustre_cfg_string(lcfg, 2),
935                                    lustre_cfg_string(lcfg, 3));
936                 err = 0;
937                 goto out;
938         }
939         case LCFG_POOL_DEL: {
940                 err = obd_pool_del(obd, lustre_cfg_string(lcfg, 2));
941                 err = 0;
942                 goto out;
943         }
944         default: {
945                 err = obd_process_config(obd, sizeof(*lcfg), lcfg);
946                 goto out;
947         }
948         }
949 out:
950         if ((err < 0) && !(lcfg->lcfg_command & LCFG_REQUIRED)) {
951                 CWARN("Ignoring error %d on optional command %#x\n", err,
952                       lcfg->lcfg_command);
953                 err = 0;
954         }
955         return err;
956 }
957 EXPORT_SYMBOL(class_process_config);
958
959 int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars,
960                              struct lustre_cfg *lcfg, void *data)
961 {
962         struct lprocfs_vars *var;
963         struct file fakefile;
964         struct seq_file fake_seqfile;
965         char *key, *sval;
966         int i, keylen, vallen;
967         int matched = 0, j = 0;
968         int rc = 0;
969         int skip = 0;
970
971         if (lcfg->lcfg_command != LCFG_PARAM) {
972                 CERROR("Unknown command: %d\n", lcfg->lcfg_command);
973                 return -EINVAL;
974         }
975
976         /* fake a seq file so that var->fops->write can work... */
977         fakefile.private_data = &fake_seqfile;
978         fake_seqfile.private = data;
979         /* e.g. tunefs.lustre --param mdt.group_upcall=foo /r/tmp/lustre-mdt
980          * or   lctl conf_param lustre-MDT0000.mdt.group_upcall=bar
981          * or   lctl conf_param lustre-OST0000.osc.max_dirty_mb=36
982          */
983         for (i = 1; i < lcfg->lcfg_bufcount; i++) {
984                 key = lustre_cfg_buf(lcfg, i);
985                 /* Strip off prefix */
986                 if (class_match_param(key, prefix, &key)) {
987                         /*
988                          * If the prefix doesn't match, return error so we
989                          * can pass it down the stack
990                          */
991                         return -ENOSYS;
992                 }
993                 sval = strchr(key, '=');
994                 if (!sval || (*(sval + 1) == 0)) {
995                         CERROR("Can't parse param %s (missing '=')\n", key);
996                         /* rc = -EINVAL;        continue parsing other params */
997                         continue;
998                 }
999                 keylen = sval - key;
1000                 sval++;
1001                 vallen = strlen(sval);
1002                 matched = 0;
1003                 j = 0;
1004                 /* Search proc entries */
1005                 while (lvars[j].name) {
1006                         var = &lvars[j];
1007                         if (!class_match_param(key, var->name, NULL) &&
1008                             keylen == strlen(var->name)) {
1009                                 matched++;
1010                                 rc = -EROFS;
1011                                 if (var->fops && var->fops->write) {
1012                                         mm_segment_t oldfs;
1013
1014                                         oldfs = get_fs();
1015                                         set_fs(KERNEL_DS);
1016                                         rc = var->fops->write(&fakefile, sval,
1017                                                                 vallen, NULL);
1018                                         set_fs(oldfs);
1019                                 }
1020                                 break;
1021                         }
1022                         j++;
1023                 }
1024                 if (!matched) {
1025                         CERROR("%.*s: %s unknown param %s\n",
1026                                (int)strlen(prefix) - 1, prefix,
1027                                (char *)lustre_cfg_string(lcfg, 0), key);
1028                         /* rc = -EINVAL;        continue parsing other params */
1029                         skip++;
1030                 } else if (rc < 0) {
1031                         CERROR("%s: error writing proc entry '%s': rc = %d\n",
1032                                prefix, var->name, rc);
1033                         rc = 0;
1034                 } else {
1035                         CDEBUG(D_CONFIG, "%s.%.*s: Set parameter %.*s=%s\n",
1036                                lustre_cfg_string(lcfg, 0),
1037                                (int)strlen(prefix) - 1, prefix,
1038                                (int)(sval - key - 1), key, sval);
1039                 }
1040         }
1041
1042         if (rc > 0)
1043                 rc = 0;
1044         if (!rc && skip)
1045                 rc = skip;
1046         return rc;
1047 }
1048 EXPORT_SYMBOL(class_process_proc_param);
1049
1050 extern int lustre_check_exclusion(struct super_block *sb, char *svname);
1051
1052 /** Parse a configuration llog, doing various manipulations on them
1053  * for various reasons, (modifications for compatibility, skip obsolete
1054  * records, change uuids, etc), then class_process_config() resulting
1055  * net records.
1056  */
1057 int class_config_llog_handler(const struct lu_env *env,
1058                               struct llog_handle *handle,
1059                               struct llog_rec_hdr *rec, void *data)
1060 {
1061         struct config_llog_instance *clli = data;
1062         int cfg_len = rec->lrh_len;
1063         char *cfg_buf = (char *)(rec + 1);
1064         int rc = 0;
1065
1066         switch (rec->lrh_type) {
1067         case OBD_CFG_REC: {
1068                 struct lustre_cfg *lcfg, *lcfg_new;
1069                 struct lustre_cfg_bufs bufs;
1070                 char *inst_name = NULL;
1071                 int inst_len = 0;
1072                 int inst = 0, swab = 0;
1073
1074                 lcfg = (struct lustre_cfg *)cfg_buf;
1075                 if (lcfg->lcfg_version == __swab32(LUSTRE_CFG_VERSION)) {
1076                         lustre_swab_lustre_cfg(lcfg);
1077                         swab = 1;
1078                 }
1079
1080                 rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
1081                 if (rc)
1082                         goto out;
1083
1084                 /* Figure out config state info */
1085                 if (lcfg->lcfg_command == LCFG_MARKER) {
1086                         struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
1087
1088                         lustre_swab_cfg_marker(marker, swab,
1089                                                LUSTRE_CFG_BUFLEN(lcfg, 1));
1090                         CDEBUG(D_CONFIG, "Marker, inst_flg=%#x mark_flg=%#x\n",
1091                                clli->cfg_flags, marker->cm_flags);
1092                         if (marker->cm_flags & CM_START) {
1093                                 /* all previous flags off */
1094                                 clli->cfg_flags = CFG_F_MARKER;
1095                                 if (marker->cm_flags & CM_SKIP) {
1096                                         clli->cfg_flags |= CFG_F_SKIP;
1097                                         CDEBUG(D_CONFIG, "SKIP #%d\n",
1098                                                marker->cm_step);
1099                                 } else if ((marker->cm_flags & CM_EXCLUDE) ||
1100                                            (clli->cfg_sb &&
1101                                             lustre_check_exclusion(clli->cfg_sb,
1102                                                          marker->cm_tgtname))) {
1103                                         clli->cfg_flags |= CFG_F_EXCLUDE;
1104                                         CDEBUG(D_CONFIG, "EXCLUDE %d\n",
1105                                                marker->cm_step);
1106                                 }
1107                         } else if (marker->cm_flags & CM_END) {
1108                                 clli->cfg_flags = 0;
1109                         }
1110                 }
1111                 /* A config command without a start marker before it is
1112                  * illegal (post 146)
1113                  */
1114                 if (!(clli->cfg_flags & CFG_F_COMPAT146) &&
1115                     !(clli->cfg_flags & CFG_F_MARKER) &&
1116                     (lcfg->lcfg_command != LCFG_MARKER)) {
1117                         CWARN("Config not inside markers, ignoring! (inst: %p, uuid: %s, flags: %#x)\n",
1118                               clli->cfg_instance,
1119                               clli->cfg_uuid.uuid, clli->cfg_flags);
1120                         clli->cfg_flags |= CFG_F_SKIP;
1121                 }
1122                 if (clli->cfg_flags & CFG_F_SKIP) {
1123                         CDEBUG(D_CONFIG, "skipping %#x\n",
1124                                clli->cfg_flags);
1125                         rc = 0;
1126                         /* No processing! */
1127                         break;
1128                 }
1129
1130                 /*
1131                  * For interoperability between 1.8 and 2.0,
1132                  * rename "mds" obd device type to "mdt".
1133                  */
1134                 {
1135                         char *typename = lustre_cfg_string(lcfg, 1);
1136                         char *index = lustre_cfg_string(lcfg, 2);
1137
1138                         if ((lcfg->lcfg_command == LCFG_ATTACH && typename &&
1139                              strcmp(typename, "mds") == 0)) {
1140                                 CWARN("For 1.8 interoperability, rename obd type from mds to mdt\n");
1141                                 typename[2] = 't';
1142                         }
1143                         if ((lcfg->lcfg_command == LCFG_SETUP && index &&
1144                              strcmp(index, "type") == 0)) {
1145                                 CDEBUG(D_INFO, "For 1.8 interoperability, set this index to '0'\n");
1146                                 index[0] = '0';
1147                                 index[1] = 0;
1148                         }
1149                 }
1150
1151                 if (clli->cfg_flags & CFG_F_EXCLUDE) {
1152                         CDEBUG(D_CONFIG, "cmd: %x marked EXCLUDED\n",
1153                                lcfg->lcfg_command);
1154                         if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD)
1155                                 /* Add inactive instead */
1156                                 lcfg->lcfg_command = LCFG_LOV_ADD_INA;
1157                 }
1158
1159                 lustre_cfg_bufs_init(&bufs, lcfg);
1160
1161                 if (clli && clli->cfg_instance &&
1162                     LUSTRE_CFG_BUFLEN(lcfg, 0) > 0) {
1163                         inst = 1;
1164                         inst_len = LUSTRE_CFG_BUFLEN(lcfg, 0) +
1165                                    sizeof(clli->cfg_instance) * 2 + 4;
1166                         inst_name = kasprintf(GFP_NOFS, "%s-%p",
1167                                               lustre_cfg_string(lcfg, 0),
1168                                               clli->cfg_instance);
1169                         if (!inst_name) {
1170                                 rc = -ENOMEM;
1171                                 goto out;
1172                         }
1173                         lustre_cfg_bufs_set_string(&bufs, 0, inst_name);
1174                         CDEBUG(D_CONFIG, "cmd %x, instance name: %s\n",
1175                                lcfg->lcfg_command, inst_name);
1176                 }
1177
1178                 /* we override the llog's uuid for clients, to insure they
1179                  * are unique
1180                  */
1181                 if (clli && clli->cfg_instance &&
1182                     lcfg->lcfg_command == LCFG_ATTACH) {
1183                         lustre_cfg_bufs_set_string(&bufs, 2,
1184                                                    clli->cfg_uuid.uuid);
1185                 }
1186                 /*
1187                  * sptlrpc config record, we expect 2 data segments:
1188                  *  [0]: fs_name/target_name,
1189                  *  [1]: rule string
1190                  * moving them to index [1] and [2], and insert MGC's
1191                  * obdname at index [0].
1192                  */
1193                 if (clli && !clli->cfg_instance &&
1194                     lcfg->lcfg_command == LCFG_SPTLRPC_CONF) {
1195                         lustre_cfg_bufs_set(&bufs, 2, bufs.lcfg_buf[1],
1196                                             bufs.lcfg_buflen[1]);
1197                         lustre_cfg_bufs_set(&bufs, 1, bufs.lcfg_buf[0],
1198                                             bufs.lcfg_buflen[0]);
1199                         lustre_cfg_bufs_set_string(&bufs, 0,
1200                                                    clli->cfg_obdname);
1201                 }
1202
1203                 lcfg_new = lustre_cfg_new(lcfg->lcfg_command, &bufs);
1204
1205                 lcfg_new->lcfg_num   = lcfg->lcfg_num;
1206                 lcfg_new->lcfg_flags = lcfg->lcfg_flags;
1207
1208                 /* XXX Hack to try to remain binary compatible with
1209                  * pre-newconfig logs
1210                  */
1211                 if (lcfg->lcfg_nal != 0 &&      /* pre-newconfig log? */
1212                     (lcfg->lcfg_nid >> 32) == 0) {
1213                         __u32 addr = (__u32)(lcfg->lcfg_nid & 0xffffffff);
1214
1215                         lcfg_new->lcfg_nid =
1216                                 LNET_MKNID(LNET_MKNET(lcfg->lcfg_nal, 0), addr);
1217                         CWARN("Converted pre-newconfig NAL %d NID %x to %s\n",
1218                               lcfg->lcfg_nal, addr,
1219                               libcfs_nid2str(lcfg_new->lcfg_nid));
1220                 } else {
1221                         lcfg_new->lcfg_nid = lcfg->lcfg_nid;
1222                 }
1223
1224                 lcfg_new->lcfg_nal = 0; /* illegal value for obsolete field */
1225
1226                 rc = class_process_config(lcfg_new);
1227                 lustre_cfg_free(lcfg_new);
1228
1229                 if (inst)
1230                         kfree(inst_name);
1231                 break;
1232         }
1233         default:
1234                 CERROR("Unknown llog record type %#x encountered\n",
1235                        rec->lrh_type);
1236                 break;
1237         }
1238 out:
1239         if (rc) {
1240                 CERROR("%s: cfg command failed: rc = %d\n",
1241                        handle->lgh_ctxt->loc_obd->obd_name, rc);
1242                 class_config_dump_handler(NULL, handle, rec, data);
1243         }
1244         return rc;
1245 }
1246 EXPORT_SYMBOL(class_config_llog_handler);
1247
1248 int class_config_parse_llog(const struct lu_env *env, struct llog_ctxt *ctxt,
1249                             char *name, struct config_llog_instance *cfg)
1250 {
1251         struct llog_process_cat_data     cd = {0, 0};
1252         struct llog_handle              *llh;
1253         llog_cb_t                        callback;
1254         int                              rc;
1255
1256         CDEBUG(D_INFO, "looking up llog %s\n", name);
1257         rc = llog_open(env, ctxt, &llh, NULL, name, LLOG_OPEN_EXISTS);
1258         if (rc)
1259                 return rc;
1260
1261         rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL);
1262         if (rc)
1263                 goto parse_out;
1264
1265         /* continue processing from where we last stopped to end-of-log */
1266         if (cfg) {
1267                 cd.lpcd_first_idx = cfg->cfg_last_idx;
1268                 callback = cfg->cfg_callback;
1269                 LASSERT(callback);
1270         } else {
1271                 callback = class_config_llog_handler;
1272         }
1273
1274         cd.lpcd_last_idx = 0;
1275
1276         rc = llog_process(env, llh, callback, cfg, &cd);
1277
1278         CDEBUG(D_CONFIG, "Processed log %s gen %d-%d (rc=%d)\n", name,
1279                cd.lpcd_first_idx + 1, cd.lpcd_last_idx, rc);
1280         if (cfg)
1281                 cfg->cfg_last_idx = cd.lpcd_last_idx;
1282
1283 parse_out:
1284         llog_close(env, llh);
1285         return rc;
1286 }
1287 EXPORT_SYMBOL(class_config_parse_llog);
1288
1289 /**
1290  * parse config record and output dump in supplied buffer.
1291  * This is separated from class_config_dump_handler() to use
1292  * for ioctl needs as well
1293  */
1294 static int class_config_parse_rec(struct llog_rec_hdr *rec, char *buf,
1295                                   int size)
1296 {
1297         struct lustre_cfg       *lcfg = (struct lustre_cfg *)(rec + 1);
1298         char                    *ptr = buf;
1299         char                    *end = buf + size;
1300         int                      rc = 0;
1301
1302         LASSERT(rec->lrh_type == OBD_CFG_REC);
1303         rc = lustre_cfg_sanity_check(lcfg, rec->lrh_len);
1304         if (rc < 0)
1305                 return rc;
1306
1307         ptr += snprintf(ptr, end - ptr, "cmd=%05x ", lcfg->lcfg_command);
1308         if (lcfg->lcfg_flags)
1309                 ptr += snprintf(ptr, end - ptr, "flags=%#08x ",
1310                                 lcfg->lcfg_flags);
1311
1312         if (lcfg->lcfg_num)
1313                 ptr += snprintf(ptr, end - ptr, "num=%#08x ", lcfg->lcfg_num);
1314
1315         if (lcfg->lcfg_nid) {
1316                 char nidstr[LNET_NIDSTR_SIZE];
1317
1318                 libcfs_nid2str_r(lcfg->lcfg_nid, nidstr, sizeof(nidstr));
1319                 ptr += snprintf(ptr, end - ptr, "nid=%s(%#llx)\n     ",
1320                                 nidstr, lcfg->lcfg_nid);
1321         }
1322
1323         if (lcfg->lcfg_command == LCFG_MARKER) {
1324                 struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
1325
1326                 ptr += snprintf(ptr, end - ptr, "marker=%d(%#x)%s '%s'",
1327                                 marker->cm_step, marker->cm_flags,
1328                                 marker->cm_tgtname, marker->cm_comment);
1329         } else {
1330                 int i;
1331
1332                 for (i = 0; i <  lcfg->lcfg_bufcount; i++) {
1333                         ptr += snprintf(ptr, end - ptr, "%d:%s  ", i,
1334                                         lustre_cfg_string(lcfg, i));
1335                 }
1336         }
1337         ptr += snprintf(ptr, end - ptr, "\n");
1338         /* return consumed bytes */
1339         rc = ptr - buf;
1340         return rc;
1341 }
1342
1343 int class_config_dump_handler(const struct lu_env *env,
1344                               struct llog_handle *handle,
1345                               struct llog_rec_hdr *rec, void *data)
1346 {
1347         char    *outstr;
1348         int      rc = 0;
1349
1350         outstr = kzalloc(256, GFP_NOFS);
1351         if (!outstr)
1352                 return -ENOMEM;
1353
1354         if (rec->lrh_type == OBD_CFG_REC) {
1355                 class_config_parse_rec(rec, outstr, 256);
1356                 LCONSOLE(D_WARNING, "   %s", outstr);
1357         } else {
1358                 LCONSOLE(D_WARNING, "unhandled lrh_type: %#x\n", rec->lrh_type);
1359                 rc = -EINVAL;
1360         }
1361
1362         kfree(outstr);
1363         return rc;
1364 }
1365
1366 /** Call class_cleanup and class_detach.
1367  * "Manual" only in the sense that we're faking lcfg commands.
1368  */
1369 int class_manual_cleanup(struct obd_device *obd)
1370 {
1371         char                flags[3] = "";
1372         struct lustre_cfg      *lcfg;
1373         struct lustre_cfg_bufs  bufs;
1374         int                  rc;
1375
1376         if (!obd) {
1377                 CERROR("empty cleanup\n");
1378                 return -EALREADY;
1379         }
1380
1381         if (obd->obd_force)
1382                 strcat(flags, "F");
1383         if (obd->obd_fail)
1384                 strcat(flags, "A");
1385
1386         CDEBUG(D_CONFIG, "Manual cleanup of %s (flags='%s')\n",
1387                obd->obd_name, flags);
1388
1389         lustre_cfg_bufs_reset(&bufs, obd->obd_name);
1390         lustre_cfg_bufs_set_string(&bufs, 1, flags);
1391         lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
1392         if (!lcfg)
1393                 return -ENOMEM;
1394
1395         rc = class_process_config(lcfg);
1396         if (rc) {
1397                 CERROR("cleanup failed %d: %s\n", rc, obd->obd_name);
1398                 goto out;
1399         }
1400
1401         /* the lcfg is almost the same for both ops */
1402         lcfg->lcfg_command = LCFG_DETACH;
1403         rc = class_process_config(lcfg);
1404         if (rc)
1405                 CERROR("detach failed %d: %s\n", rc, obd->obd_name);
1406 out:
1407         lustre_cfg_free(lcfg);
1408         return rc;
1409 }
1410 EXPORT_SYMBOL(class_manual_cleanup);
1411
1412 /*
1413  * uuid<->export lustre hash operations
1414  */
1415
1416 static unsigned
1417 uuid_hash(struct cfs_hash *hs, const void *key, unsigned mask)
1418 {
1419         return cfs_hash_djb2_hash(((struct obd_uuid *)key)->uuid,
1420                                   sizeof(((struct obd_uuid *)key)->uuid), mask);
1421 }
1422
1423 static void *
1424 uuid_key(struct hlist_node *hnode)
1425 {
1426         struct obd_export *exp;
1427
1428         exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
1429
1430         return &exp->exp_client_uuid;
1431 }
1432
1433 /*
1434  * NOTE: It is impossible to find an export that is in failed
1435  *       state with this function
1436  */
1437 static int
1438 uuid_keycmp(const void *key, struct hlist_node *hnode)
1439 {
1440         struct obd_export *exp;
1441
1442         LASSERT(key);
1443         exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
1444
1445         return obd_uuid_equals(key, &exp->exp_client_uuid) &&
1446                !exp->exp_failed;
1447 }
1448
1449 static void *
1450 uuid_export_object(struct hlist_node *hnode)
1451 {
1452         return hlist_entry(hnode, struct obd_export, exp_uuid_hash);
1453 }
1454
1455 static void
1456 uuid_export_get(struct cfs_hash *hs, struct hlist_node *hnode)
1457 {
1458         struct obd_export *exp;
1459
1460         exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
1461         class_export_get(exp);
1462 }
1463
1464 static void
1465 uuid_export_put_locked(struct cfs_hash *hs, struct hlist_node *hnode)
1466 {
1467         struct obd_export *exp;
1468
1469         exp = hlist_entry(hnode, struct obd_export, exp_uuid_hash);
1470         class_export_put(exp);
1471 }
1472
1473 static struct cfs_hash_ops uuid_hash_ops = {
1474         .hs_hash        = uuid_hash,
1475         .hs_key         = uuid_key,
1476         .hs_keycmp      = uuid_keycmp,
1477         .hs_object      = uuid_export_object,
1478         .hs_get         = uuid_export_get,
1479         .hs_put_locked  = uuid_export_put_locked,
1480 };