Whamcloud - gitweb
b=12007
[fs/lustre-release.git] / lustre / obdclass / obd_config.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (c) 2001-2006 Cluster File Systems, Inc.
5  *
6  *   This file is part of the Lustre file system, http://www.lustre.org
7  *   Lustre is a trademark of Cluster File Systems, Inc.
8  *
9  *   You may have signed or agreed to another license before downloading
10  *   this software.  If so, you are bound by the terms and conditions
11  *   of that agreement, and the following does not apply to you.  See the
12  *   LICENSE file included with this distribution for more information.
13  *
14  *   If you did not agree to a different license, then this copy of Lustre
15  *   is open source software; you can redistribute it and/or modify it
16  *   under the terms of version 2 of the GNU General Public License as
17  *   published by the Free Software Foundation.
18  *
19  *   In either case, Lustre is distributed in the hope that it will be
20  *   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
21  *   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  *   license text for more details.
23  *
24  * Config API
25  *
26  */
27
28 #define DEBUG_SUBSYSTEM S_CLASS
29 #ifdef __KERNEL__
30 #include <obd_class.h>
31 #include <linux/string.h>
32 #else
33 #include <liblustre.h>
34 #include <obd_class.h>
35 #include <obd.h>
36 #endif
37 #include <lustre_log.h>
38 #include <lprocfs_status.h>
39 #include <libcfs/list.h>
40 #include <lustre_param.h>
41
42 /*********** string parsing utils *********/
43
44 /* returns 0 if we find this key in the buffer, else 1 */
45 int class_find_param(char *buf, char *key, char **valp)
46 {
47         char *ptr;
48
49         if (!buf) 
50                 return 1;
51
52         if ((ptr = strstr(buf, key)) == NULL) 
53                 return 1;
54
55         if (valp) 
56                 *valp = ptr + strlen(key);
57         
58         return 0;
59 }
60
61 /* returns 0 if this is the first key in the buffer, else 1.
62    valp points to first char after key. */
63 int class_match_param(char *buf, char *key, char **valp)
64 {
65         if (!buf) 
66                 return 1;
67
68         if (memcmp(buf, key, strlen(key)) != 0) 
69                 return 1;
70
71         if (valp) 
72                 *valp = buf + strlen(key);
73         
74         return 0;
75 }
76
77 /* 0 is good nid, 
78    1 not found
79    < 0 error
80    endh is set to next separator */
81 int class_parse_nid(char *buf, lnet_nid_t *nid, char **endh)
82 {
83         char tmp, *endp;
84
85         if (!buf) 
86                 return 1;
87         while (*buf == ',' || *buf == ':') 
88                 buf++;
89         if (*buf == ' ' || *buf == '/' || *buf == '\0') 
90                 return 1;
91
92         /* nid separators or end of nids */
93         endp = strpbrk(buf, ",: /");
94         if (endp == NULL) 
95                 endp = buf + strlen(buf);
96
97         tmp = *endp;
98         *endp = '\0';
99         *nid = libcfs_str2nid(buf);
100         if (*nid == LNET_NID_ANY) {
101                 LCONSOLE_ERROR("Can't parse NID '%s'\n", buf);
102                 *endp = tmp;
103                 return -EINVAL;
104         }
105         *endp = tmp;
106
107         if (endh) 
108                 *endh = endp;
109         CDEBUG(D_INFO, "Nid %s\n", libcfs_nid2str(*nid));
110         return 0;
111 }
112
113 EXPORT_SYMBOL(class_find_param);
114 EXPORT_SYMBOL(class_match_param);
115 EXPORT_SYMBOL(class_parse_nid);
116
117 /********************** class fns **********************/
118
119 /* Create a new device and set the type, name and uuid.  If
120  * successful, the new device can be accessed by either name or uuid.
121  */
122 int class_attach(struct lustre_cfg *lcfg)
123 {
124         struct obd_device *obd = NULL;
125         char *typename, *name, *uuid;
126         int rc, len;
127         ENTRY;
128
129         if (!LUSTRE_CFG_BUFLEN(lcfg, 1)) {
130                 CERROR("No type passed!\n");
131                 RETURN(-EINVAL);
132         }
133         typename = lustre_cfg_string(lcfg, 1);
134
135         if (!LUSTRE_CFG_BUFLEN(lcfg, 0)) {
136                 CERROR("No name passed!\n");
137                 RETURN(-EINVAL);
138         }
139         name = lustre_cfg_string(lcfg, 0);
140
141         if (!LUSTRE_CFG_BUFLEN(lcfg, 2)) {
142                 CERROR("No UUID passed!\n");
143                 RETURN(-EINVAL);
144         }
145         uuid = lustre_cfg_string(lcfg, 2);
146
147         CDEBUG(D_IOCTL, "attach type %s name: %s uuid: %s\n",
148                MKSTR(typename), MKSTR(name), MKSTR(uuid));
149
150         /* Mountconf transitional hack, should go away after 1.6.
151            1.4.7 uses the old names, so translate back if the
152            mountconf flag is set.
153            1.6 should set this flag, and translate the other way here
154            if not set. */
155         if (lcfg->lcfg_flags & LCFG_FLG_MOUNTCONF){
156                 char *tmp = NULL;
157                 if (strcmp(typename, "mds") == 0)
158                         tmp = "mdt";
159                 if (strcmp(typename, "mdt") == 0)
160                         tmp = "mds";
161                 if (strcmp(typename, "osd") == 0)
162                         tmp = "obdfilter";
163                 if (tmp) {
164                         LCONSOLE_WARN("Using type %s for %s %s\n", tmp,
165                                       MKSTR(typename), MKSTR(name));
166                         typename = tmp;
167                 }
168         }
169
170         obd = class_newdev(typename, name);
171         if (IS_ERR(obd)) {
172                 /* Already exists or out of obds */
173                 rc = PTR_ERR(obd);
174                 obd = NULL;
175                 CERROR("Cannot create device %s of type %s : %d\n",
176                        name, typename, rc);
177                 GOTO(out, rc);
178         }
179         LASSERTF(obd != NULL, "Cannot get obd device %s of type %s\n",
180                  name, typename);
181         LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC, 
182                  "obd %p obd_magic %08X != %08X\n",
183                  obd, obd->obd_magic, OBD_DEVICE_MAGIC);
184         LASSERTF(strncmp(obd->obd_name, name, strlen(name)) == 0, "%p obd_name %s != %s\n",
185                  obd, obd->obd_name, name);
186
187         CFS_INIT_LIST_HEAD(&obd->obd_exports);
188         CFS_INIT_LIST_HEAD(&obd->obd_exports_timed);
189         spin_lock_init(&obd->obd_dev_lock);
190         sema_init(&obd->obd_dev_sem, 1);
191         sema_init(&obd->obd_proc_exp_sem, 1);
192         spin_lock_init(&obd->obd_osfs_lock);
193         /* obd->obd_osfs_age must be set to a value in the distant
194          * past to guarantee a fresh statfs is fetched on mount. */
195         obd->obd_osfs_age = cfs_time_shift_64(-1000);
196
197         /* XXX belongs in setup not attach  */
198         /* recovery data */
199         cfs_init_timer(&obd->obd_recovery_timer);
200         spin_lock_init(&obd->obd_processing_task_lock);
201         cfs_waitq_init(&obd->obd_next_transno_waitq);
202         CFS_INIT_LIST_HEAD(&obd->obd_recovery_queue);
203         CFS_INIT_LIST_HEAD(&obd->obd_delayed_reply_queue);
204
205         spin_lock_init(&obd->obd_uncommitted_replies_lock);
206         CFS_INIT_LIST_HEAD(&obd->obd_uncommitted_replies);
207
208         len = strlen(uuid);
209         if (len >= sizeof(obd->obd_uuid)) {
210                 CERROR("uuid must be < "LPSZ" bytes long\n",
211                        sizeof(obd->obd_uuid));
212                 GOTO(out, rc = -EINVAL);
213         }
214         memcpy(obd->obd_uuid.uuid, uuid, len);
215
216         /* do the attach */
217         if (OBP(obd, attach)) {
218                 rc = OBP(obd,attach)(obd, sizeof *lcfg, lcfg);
219                 if (rc)
220                         GOTO(out, rc = -EINVAL);
221         }
222
223         /* Detach drops this */
224         spin_lock(&obd->obd_dev_lock);
225         atomic_set(&obd->obd_refcount, 1);
226         spin_unlock(&obd->obd_dev_lock);
227
228         obd->obd_attached = 1;
229         CDEBUG(D_IOCTL, "OBD: dev %d attached type %s with refcount %d\n",
230                obd->obd_minor, typename, atomic_read(&obd->obd_refcount));
231         RETURN(0);
232  out:
233         if (obd != NULL) {
234                 class_release_dev(obd);
235         }
236         return rc;
237 }
238
239 int class_setup(struct obd_device *obd, struct lustre_cfg *lcfg)
240 {
241         int err = 0;
242         struct obd_export *exp;
243         ENTRY;
244
245         LASSERT(obd != NULL);
246         LASSERTF(obd == class_num2obd(obd->obd_minor), "obd %p != obd_devs[%d] %p\n", 
247                  obd, obd->obd_minor, class_num2obd(obd->obd_minor));
248         LASSERTF(obd->obd_magic == OBD_DEVICE_MAGIC, "obd %p obd_magic %08x != %08x\n", 
249                  obd, obd->obd_magic, OBD_DEVICE_MAGIC);
250
251         /* have we attached a type to this device? */
252         if (!obd->obd_attached) {
253                 CERROR("Device %d not attached\n", obd->obd_minor);
254                 RETURN(-ENODEV);
255         }
256
257         if (obd->obd_set_up) {
258                 CERROR("Device %d already setup (type %s)\n",
259                        obd->obd_minor, obd->obd_type->typ_name);
260                 RETURN(-EEXIST);
261         }
262
263         /* is someone else setting us up right now? (attach inits spinlock) */
264         spin_lock(&obd->obd_dev_lock);
265         if (obd->obd_starting) {
266                 spin_unlock(&obd->obd_dev_lock);
267                 CERROR("Device %d setup in progress (type %s)\n",
268                        obd->obd_minor, obd->obd_type->typ_name);
269                 RETURN(-EEXIST);
270         }
271         /* just leave this on forever.  I can't use obd_set_up here because
272            other fns check that status, and we're not actually set up yet. */
273         obd->obd_starting = 1;
274         spin_unlock(&obd->obd_dev_lock);
275
276         exp = class_new_export(obd, &obd->obd_uuid);
277         if (IS_ERR(exp))
278                 RETURN(PTR_ERR(exp));
279         obd->obd_self_export = exp;
280         list_del_init(&exp->exp_obd_chain_timed);
281         class_export_put(exp);
282
283         err = obd_setup(obd, sizeof(*lcfg), lcfg);
284         if (err)
285                 GOTO(err_exp, err);
286
287         obd->obd_set_up = 1;
288         spin_lock(&obd->obd_dev_lock);
289         /* cleanup drops this */
290         class_incref(obd);
291         spin_unlock(&obd->obd_dev_lock);
292
293         CDEBUG(D_IOCTL, "finished setup of obd %s (uuid %s)\n",
294                obd->obd_name, obd->obd_uuid.uuid);
295
296         RETURN(0);
297
298 err_exp:
299         CERROR("setup %s failed (%d)\n", obd->obd_name, err);
300         class_unlink_export(obd->obd_self_export);
301         obd->obd_self_export = NULL;
302         obd->obd_starting = 0;
303         RETURN(err);
304 }
305
306 int class_detach(struct obd_device *obd, struct lustre_cfg *lcfg)
307 {
308         ENTRY;
309
310         if (obd->obd_set_up) {
311                 CERROR("OBD device %d still set up\n", obd->obd_minor);
312                 RETURN(-EBUSY);
313         }
314
315         spin_lock(&obd->obd_dev_lock);
316         if (!obd->obd_attached) {
317                 spin_unlock(&obd->obd_dev_lock);
318                 CERROR("OBD device %d not attached\n", obd->obd_minor);
319                 RETURN(-ENODEV);
320         }
321         obd->obd_attached = 0;
322         spin_unlock(&obd->obd_dev_lock);
323
324         CDEBUG(D_IOCTL, "detach on obd %s (uuid %s)\n",
325                obd->obd_name, obd->obd_uuid.uuid);
326
327         class_decref(obd);
328         
329         /* not strictly necessary, but cleans up eagerly */
330         obd_zombie_impexp_cull();
331         
332         RETURN(0);
333 }
334
335 static void dump_exports(struct obd_device *obd)
336 {
337         struct obd_export *exp, *n;
338
339         list_for_each_entry_safe(exp, n, &obd->obd_exports, exp_obd_chain) {
340                 struct ptlrpc_reply_state *rs;
341                 struct ptlrpc_reply_state *first_reply = NULL;
342                 int                        nreplies = 0;
343
344                 list_for_each_entry (rs, &exp->exp_outstanding_replies,
345                                      rs_exp_list) {
346                         if (nreplies == 0)
347                                 first_reply = rs;
348                         nreplies++;
349                 }
350
351                 CDEBUG(D_IOCTL, "%s: %p %s %s %d %d %d: %p %s\n",
352                        obd->obd_name, exp, exp->exp_client_uuid.uuid,
353                        obd_export_nid2str(exp),
354                        atomic_read(&exp->exp_refcount),
355                        exp->exp_failed, nreplies, first_reply,
356                        nreplies > 3 ? "..." : "");
357         }
358 }
359
360 int class_cleanup(struct obd_device *obd, struct lustre_cfg *lcfg)
361 {
362         int err = 0;
363         char *flag;
364         ENTRY;
365
366         OBD_RACE(OBD_FAIL_LDLM_RECOV_CLIENTS);
367
368         if (!obd->obd_set_up) {
369                 CERROR("Device %d not setup\n", obd->obd_minor);
370                 RETURN(-ENODEV);
371         }
372
373         spin_lock(&obd->obd_dev_lock);
374         if (obd->obd_stopping) {
375                 spin_unlock(&obd->obd_dev_lock);
376                 CERROR("OBD %d already stopping\n", obd->obd_minor);
377                 RETURN(-ENODEV);
378         }
379         /* Leave this on forever */
380         obd->obd_stopping = 1;
381         spin_unlock(&obd->obd_dev_lock);
382
383         if (lcfg->lcfg_bufcount >= 2 && LUSTRE_CFG_BUFLEN(lcfg, 1) > 0) {
384                 for (flag = lustre_cfg_string(lcfg, 1); *flag != 0; flag++)
385                         switch (*flag) {
386                         case 'F':
387                                 obd->obd_force = 1;
388                                 break;
389                         case 'A':
390                                 LCONSOLE_WARN("Failing over %s\n", 
391                                               obd->obd_name);
392                                 obd->obd_fail = 1;
393                                 obd->obd_no_transno = 1;
394                                 obd->obd_no_recov = 1;
395                                 /* Set the obd readonly if we can */
396                                 if (OBP(obd, iocontrol))
397                                         obd_iocontrol(OBD_IOC_SET_READONLY,
398                                                       obd->obd_self_export,
399                                                       0, NULL, NULL);
400                                 break;
401                         default:
402                                 CERROR("unrecognised flag '%c'\n",
403                                        *flag);
404                         }
405         }
406
407         /* The three references that should be remaining are the
408          * obd_self_export and the attach and setup references. */
409         if (atomic_read(&obd->obd_refcount) > 3) {
410 #if 0           /* We should never fail to cleanup with mountconf */ 
411                 if (!(obd->obd_fail || obd->obd_force)) {
412                         CERROR("OBD %s is still busy with %d references\n"
413                                "You should stop active file system users,"
414                                " or use the --force option to cleanup.\n",
415                                obd->obd_name, atomic_read(&obd->obd_refcount));
416                         dump_exports(obd);
417                         /* Allow a failed cleanup to try again. */
418                         obd->obd_stopping = 0;
419                         RETURN(-EBUSY);
420                 }
421 #endif
422                 /* refcounf - 3 might be the number of real exports 
423                    (excluding self export). But class_incref is called
424                    by other things as well, so don't count on it. */
425                 CDEBUG(D_IOCTL, "%s: forcing exports to disconnect: %d\n",
426                        obd->obd_name, atomic_read(&obd->obd_refcount) - 3);
427                 dump_exports(obd);
428                 class_disconnect_exports(obd);
429         }
430
431         LASSERT(obd->obd_self_export);
432
433         /* Precleanup stage 1, we must make sure all exports (other than the
434            self-export) get destroyed. */
435         err = obd_precleanup(obd, OBD_CLEANUP_EXPORTS);
436         if (err)
437                 CERROR("Precleanup %s returned %d\n",
438                        obd->obd_name, err);
439
440         class_decref(obd);
441         obd->obd_set_up = 0;
442
443         RETURN(0);
444 }
445
446 struct obd_device *class_incref(struct obd_device *obd)
447 {
448         atomic_inc(&obd->obd_refcount);
449         CDEBUG(D_INFO, "incref %s (%p) now %d\n", obd->obd_name, obd,
450                atomic_read(&obd->obd_refcount));
451
452         return obd;
453 }
454
455 void class_decref(struct obd_device *obd)
456 {
457         int err;
458         int refs;
459
460         spin_lock(&obd->obd_dev_lock);
461         atomic_dec(&obd->obd_refcount);
462         refs = atomic_read(&obd->obd_refcount);
463         spin_unlock(&obd->obd_dev_lock);
464
465         CDEBUG(D_INFO, "Decref %s (%p) now %d\n", obd->obd_name, obd, refs);
466
467         if ((refs == 1) && obd->obd_stopping) {
468                 /* All exports (other than the self-export) have been
469                    destroyed; there should be no more in-progress ops
470                    by this point.*/
471                 /* if we're not stopping, we didn't finish setup */
472                 /* Precleanup stage 2,  do other type-specific
473                    cleanup requiring the self-export. */
474                 err = obd_precleanup(obd, OBD_CLEANUP_SELF_EXP);
475                 if (err)
476                         CERROR("Precleanup %s returned %d\n",
477                                obd->obd_name, err);
478                 obd->obd_self_export->exp_flags |=
479                         (obd->obd_fail ? OBD_OPT_FAILOVER : 0) |
480                         (obd->obd_force ? OBD_OPT_FORCE : 0);
481                 /* note that we'll recurse into class_decref again */
482                 class_unlink_export(obd->obd_self_export);
483                 return;
484         }
485
486         if (refs == 0) {
487                 CDEBUG(D_CONFIG, "finishing cleanup of obd %s (%s)\n",
488                        obd->obd_name, obd->obd_uuid.uuid);
489                 LASSERT(!obd->obd_attached);
490                 if (obd->obd_stopping) {
491                         /* If we're not stopping, we were never set up */
492                         err = obd_cleanup(obd);
493                         if (err)
494                                 CERROR("Cleanup %s returned %d\n",
495                                        obd->obd_name, err);
496                 }
497                 if (OBP(obd, detach)) {
498                         err = OBP(obd,detach)(obd);
499                         if (err)
500                                 CERROR("Detach returned %d\n", err);
501                 }
502                 class_release_dev(obd);
503         }
504 }
505
506 int class_add_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
507 {
508         struct obd_import *imp;
509         struct obd_uuid uuid;
510         int rc;
511         ENTRY;
512
513         if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 ||
514             LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(struct obd_uuid)) {
515                 CERROR("invalid conn_uuid\n");
516                 RETURN(-EINVAL);
517         }
518         if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
519             strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME) && 
520             strcmp(obd->obd_type->typ_name, LUSTRE_MGC_NAME)) {
521                 CERROR("can't add connection on non-client dev\n");
522                 RETURN(-EINVAL);
523         }
524
525         imp = obd->u.cli.cl_import;
526         if (!imp) {
527                 CERROR("try to add conn on immature client dev\n");
528                 RETURN(-EINVAL);
529         }
530
531         obd_str2uuid(&uuid, lustre_cfg_string(lcfg, 1));
532         rc = obd_add_conn(imp, &uuid, lcfg->lcfg_num);
533
534         RETURN(rc);
535 }
536
537 int class_del_conn(struct obd_device *obd, struct lustre_cfg *lcfg)
538 {
539         struct obd_import *imp;
540         struct obd_uuid uuid;
541         int rc;
542         ENTRY;
543
544         if (LUSTRE_CFG_BUFLEN(lcfg, 1) < 1 ||
545             LUSTRE_CFG_BUFLEN(lcfg, 1) > sizeof(struct obd_uuid)) {
546                 CERROR("invalid conn_uuid\n");
547                 RETURN(-EINVAL);
548         }
549         if (strcmp(obd->obd_type->typ_name, LUSTRE_MDC_NAME) &&
550             strcmp(obd->obd_type->typ_name, LUSTRE_OSC_NAME)) {
551                 CERROR("can't del connection on non-client dev\n");
552                 RETURN(-EINVAL);
553         }
554
555         imp = obd->u.cli.cl_import;
556         if (!imp) {
557                 CERROR("try to del conn on immature client dev\n");
558                 RETURN(-EINVAL);
559         }
560
561         obd_str2uuid(&uuid, lustre_cfg_string(lcfg, 1));
562         rc = obd_del_conn(imp, &uuid);
563
564         RETURN(rc);
565 }
566
567 CFS_LIST_HEAD(lustre_profile_list);
568
569 struct lustre_profile *class_get_profile(char * prof)
570 {
571         struct lustre_profile *lprof;
572
573         ENTRY;
574         list_for_each_entry(lprof, &lustre_profile_list, lp_list) {
575                 if (!strcmp(lprof->lp_profile, prof)) {
576                         RETURN(lprof);
577                 }
578         }
579         RETURN(NULL);
580 }
581
582 int class_add_profile(int proflen, char *prof, int osclen, char *osc,
583                       int mdclen, char *mdc)
584 {
585         struct lustre_profile *lprof;
586         int err = 0;
587         ENTRY;
588
589         CDEBUG(D_CONFIG, "Add profile %s\n", prof);
590
591         OBD_ALLOC(lprof, sizeof(*lprof));
592         if (lprof == NULL)
593                 RETURN(-ENOMEM);
594         CFS_INIT_LIST_HEAD(&lprof->lp_list);
595
596         LASSERT(proflen == (strlen(prof) + 1));
597         OBD_ALLOC(lprof->lp_profile, proflen);
598         if (lprof->lp_profile == NULL)
599                 GOTO(out, err = -ENOMEM);
600         memcpy(lprof->lp_profile, prof, proflen);
601
602         LASSERT(osclen == (strlen(osc) + 1));
603         OBD_ALLOC(lprof->lp_osc, osclen);
604         if (lprof->lp_osc == NULL)
605                 GOTO(out, err = -ENOMEM);
606         memcpy(lprof->lp_osc, osc, osclen);
607
608         if (mdclen > 0) {
609                 LASSERT(mdclen == (strlen(mdc) + 1));
610                 OBD_ALLOC(lprof->lp_mdc, mdclen);
611                 if (lprof->lp_mdc == NULL)
612                         GOTO(out, err = -ENOMEM);
613                 memcpy(lprof->lp_mdc, mdc, mdclen);
614         }
615
616         list_add(&lprof->lp_list, &lustre_profile_list);
617         RETURN(err);
618
619 out:
620         if (lprof->lp_mdc)
621                 OBD_FREE(lprof->lp_mdc, mdclen);
622         if (lprof->lp_osc)
623                 OBD_FREE(lprof->lp_osc, osclen);
624         if (lprof->lp_profile)
625                 OBD_FREE(lprof->lp_profile, proflen);
626         OBD_FREE(lprof, sizeof(*lprof));        
627         RETURN(err);
628 }
629
630 void class_del_profile(char *prof)
631 {
632         struct lustre_profile *lprof;
633         ENTRY;
634
635         CDEBUG(D_CONFIG, "Del profile %s\n", prof);
636
637         lprof = class_get_profile(prof);
638         if (lprof) {
639                 list_del(&lprof->lp_list);
640                 OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
641                 OBD_FREE(lprof->lp_osc, strlen(lprof->lp_osc) + 1);
642                 if (lprof->lp_mdc)
643                         OBD_FREE(lprof->lp_mdc, strlen(lprof->lp_mdc) + 1);
644                 OBD_FREE(lprof, sizeof *lprof);
645         }
646         EXIT;
647 }
648
649 /* COMPAT_146 */
650 void class_del_profiles(void)
651 {
652         struct lustre_profile *lprof, *n;
653         ENTRY;
654
655         list_for_each_entry_safe(lprof, n, &lustre_profile_list, lp_list) {
656                 list_del(&lprof->lp_list);
657                 OBD_FREE(lprof->lp_profile, strlen(lprof->lp_profile) + 1);
658                 OBD_FREE(lprof->lp_osc, strlen(lprof->lp_osc) + 1);
659                 if (lprof->lp_mdc)
660                         OBD_FREE(lprof->lp_mdc, strlen(lprof->lp_mdc) + 1);
661                 OBD_FREE(lprof, sizeof *lprof);
662         }
663         EXIT;
664 }
665
666 /* We can't call ll_process_config directly because it lives in a module that
667    must be loaded after this one. */
668 static int (*client_process_config)(struct lustre_cfg *lcfg) = NULL;
669
670 void lustre_register_client_process_config(int (*cpc)(struct lustre_cfg *lcfg))
671 {
672         client_process_config = cpc;
673 }
674 EXPORT_SYMBOL(lustre_register_client_process_config);
675
676 int class_process_config(struct lustre_cfg *lcfg)
677 {
678         struct obd_device *obd;
679         int err;
680
681         LASSERT(lcfg && !IS_ERR(lcfg));
682         CDEBUG(D_IOCTL, "processing cmd: %x\n", lcfg->lcfg_command);
683
684         /* Commands that don't need a device */
685         switch(lcfg->lcfg_command) {
686         case LCFG_ATTACH: {
687                 err = class_attach(lcfg);
688                 GOTO(out, err);
689         }
690         case LCFG_ADD_UUID: {
691                 CDEBUG(D_IOCTL, "adding mapping from uuid %s to nid "LPX64
692                        " (%s)\n", lustre_cfg_string(lcfg, 1),
693                        lcfg->lcfg_nid, libcfs_nid2str(lcfg->lcfg_nid));
694
695                 err = class_add_uuid(lustre_cfg_string(lcfg, 1), lcfg->lcfg_nid);
696                 GOTO(out, err);
697         }
698         case LCFG_DEL_UUID: {
699                 CDEBUG(D_IOCTL, "removing mappings for uuid %s\n",
700                        (lcfg->lcfg_bufcount < 2 || LUSTRE_CFG_BUFLEN(lcfg, 1) == 0)
701                        ? "<all uuids>" : lustre_cfg_string(lcfg, 1));
702
703                 err = class_del_uuid(lustre_cfg_string(lcfg, 1));
704                 GOTO(out, err);
705         }
706         case LCFG_MOUNTOPT: {
707                 CDEBUG(D_IOCTL, "mountopt: profile %s osc %s mdc %s\n",
708                        lustre_cfg_string(lcfg, 1),
709                        lustre_cfg_string(lcfg, 2),
710                        lustre_cfg_string(lcfg, 3));
711                 /* set these mount options somewhere, so ll_fill_super
712                  * can find them. */
713                 err = class_add_profile(LUSTRE_CFG_BUFLEN(lcfg, 1),
714                                         lustre_cfg_string(lcfg, 1),
715                                         LUSTRE_CFG_BUFLEN(lcfg, 2),
716                                         lustre_cfg_string(lcfg, 2),
717                                         LUSTRE_CFG_BUFLEN(lcfg, 3),
718                                         lustre_cfg_string(lcfg, 3));
719                 GOTO(out, err);
720         }
721         case LCFG_DEL_MOUNTOPT: {
722                 CDEBUG(D_IOCTL, "mountopt: profile %s\n",
723                        lustre_cfg_string(lcfg, 1));
724                 class_del_profile(lustre_cfg_string(lcfg, 1));
725                 GOTO(out, err = 0);
726         }
727         case LCFG_SET_TIMEOUT: {
728                 CDEBUG(D_IOCTL, "changing lustre timeout from %d to %d\n",
729                        obd_timeout, lcfg->lcfg_num);
730                 obd_timeout = max(lcfg->lcfg_num, 1U);
731                 GOTO(out, err = 0);
732         }
733         case LCFG_SET_UPCALL: {
734                 LCONSOLE_ERROR("recovery upcall is deprecated\n");
735                 /* COMPAT_146 Don't fail on old configs */
736                 GOTO(out, err = 0);
737         }
738         case LCFG_MARKER: {
739                 struct cfg_marker *marker;
740                 marker = lustre_cfg_buf(lcfg, 1);
741                 CDEBUG(D_IOCTL, "marker %d (%#x) %.16s %s\n", marker->cm_step,
742                       marker->cm_flags, marker->cm_tgtname, marker->cm_comment);
743                 GOTO(out, err = 0);
744         }
745         case LCFG_PARAM: {
746                 /* llite has no obd */
747                 if ((class_match_param(lustre_cfg_string(lcfg, 1), 
748                                        PARAM_LLITE, 0) == 0) &&
749                     client_process_config) {
750                         err = (*client_process_config)(lcfg);
751                         GOTO(out, err);
752                 }
753                 /* Fall through */
754                 break;
755         }
756         }
757
758         /* Commands that require a device */
759         obd = class_name2obd(lustre_cfg_string(lcfg, 0));
760         if (obd == NULL) {
761                 if (!LUSTRE_CFG_BUFLEN(lcfg, 0))
762                         CERROR("this lcfg command requires a device name\n");
763                 else
764                         CERROR("no device for: %s\n",
765                                lustre_cfg_string(lcfg, 0));
766
767                 GOTO(out, err = -EINVAL);
768         }
769
770         switch(lcfg->lcfg_command) {
771         case LCFG_SETUP: {
772                 err = class_setup(obd, lcfg);
773                 GOTO(out, err);
774         }
775         case LCFG_DETACH: {
776                 err = class_detach(obd, lcfg);
777                 GOTO(out, err = 0);
778         }
779         case LCFG_CLEANUP: {
780                 err = class_cleanup(obd, lcfg);
781                 GOTO(out, err = 0);
782         }
783         case LCFG_ADD_CONN: {
784                 err = class_add_conn(obd, lcfg);
785                 GOTO(out, err = 0);
786         }
787         case LCFG_DEL_CONN: {
788                 err = class_del_conn(obd, lcfg);
789                 GOTO(out, err = 0);
790         }
791         default: {
792                 err = obd_process_config(obd, sizeof(*lcfg), lcfg);
793                 GOTO(out, err);
794
795         }
796         }
797 out:
798         if ((err < 0) && !(lcfg->lcfg_command & LCFG_REQUIRED)) {
799                 CWARN("Ignoring error %d on optional command %#x\n", err, 
800                       lcfg->lcfg_command);
801                 err = 0;
802         }
803         return err;
804 }
805
806 int class_process_proc_param(char *prefix, struct lprocfs_vars *lvars, 
807                              struct lustre_cfg *lcfg, void *data)
808 {
809 #ifdef __KERNEL__
810         struct lprocfs_vars *var;
811         char *key, *sval;
812         int i, vallen;
813         int matched = 0, j = 0;
814         int rc = 0;
815         ENTRY;
816
817         if (lcfg->lcfg_command != LCFG_PARAM) {
818                 CERROR("Unknown command: %d\n", lcfg->lcfg_command);
819                 RETURN(-EINVAL);
820         }
821
822         /* e.g. tunefs.lustre --param mdt.group_upcall=foo /r/tmp/lustre-mdt
823            or   lctl conf_param lustre-MDT0000.mdt.group_upcall=bar
824            or   lctl conf_param lustre-OST0000.osc.max_dirty_mb=36 */
825         for (i = 1; i < lcfg->lcfg_bufcount; i++) {
826                 key = lustre_cfg_buf(lcfg, i);
827                 /* Strip off prefix */
828                 class_match_param(key, prefix, &key);
829                 sval = strchr(key, '=');
830                 if (!sval || (*(sval + 1) == 0)) {
831                         CERROR("Can't parse param %s\n", key);
832                         rc = -EINVAL;
833                         /* continue parsing other params */
834                         continue;
835                 }
836                 sval++;
837                 vallen = strlen(sval);
838                 matched = 0;
839                 j = 0;
840                 /* Search proc entries */
841                 while (lvars[j].name) {
842                         var = &lvars[j];
843                         if (class_match_param(key, (char *)var->name, 0) == 0) {
844                                 matched++;
845                                 rc = -EROFS;
846                                 if (var->write_fptr) {
847                                         mm_segment_t oldfs;
848                                         oldfs = get_fs();
849                                         set_fs(KERNEL_DS);
850                                         rc = (var->write_fptr)(NULL, sval,
851                                                                vallen, data);
852                                         set_fs(oldfs);
853                                 }
854                                 if (rc < 0) 
855                                         CERROR("writing proc entry %s err %d\n", 
856                                                var->name, rc);
857                                 break;
858                         }
859                         j++;
860                 }    
861                 if (!matched) {
862                         CERROR("%s: unknown param %s\n",
863                                lustre_cfg_string(lcfg, 0), key);
864                         rc = -EINVAL;
865                         /* continue parsing other params */
866                 } else {
867                         LCONSOLE_INFO("%s.%.*s: set parameter %.*s=%s\n", 
868                                       lustre_cfg_string(lcfg, 0),
869                                       strlen(prefix) - 1, prefix,
870                                       sval - key - 1, key, sval);
871                 }
872         }
873         
874         if (rc > 0) 
875                 rc = 0;
876         RETURN(rc);
877 #else
878         CDEBUG(D_CONFIG, "liblustre can't process params.\n");
879         /* Don't throw config error */
880         RETURN(0);
881 #endif
882 }
883
884 int class_config_dump_handler(struct llog_handle * handle,
885                               struct llog_rec_hdr *rec, void *data);
886
887 #ifdef __KERNEL__
888 extern int lustre_check_exclusion(struct super_block *sb, char *svname);
889 #else
890 #define lustre_check_exclusion(a,b)  0
891 #endif
892
893 static int class_config_llog_handler(struct llog_handle * handle,
894                                      struct llog_rec_hdr *rec, void *data)
895 {
896         struct config_llog_instance *clli = data;
897         int cfg_len = rec->lrh_len;
898         char *cfg_buf = (char*) (rec + 1);
899         int rc = 0;
900         ENTRY;
901         
902         //class_config_dump_handler(handle, rec, data);
903
904         switch (rec->lrh_type) {
905         case OBD_CFG_REC: {
906                 struct lustre_cfg *lcfg, *lcfg_new;
907                 struct lustre_cfg_bufs bufs;
908                 char *inst_name = NULL;
909                 int inst_len = 0;
910                 int inst = 0;
911
912                 lcfg = (struct lustre_cfg *)cfg_buf;
913                 if (lcfg->lcfg_version == __swab32(LUSTRE_CFG_VERSION))
914                         lustre_swab_lustre_cfg(lcfg);
915
916                 rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
917                 if (rc)
918                         GOTO(out, rc);
919
920                 /* Figure out config state info */
921                 if (lcfg->lcfg_command == LCFG_MARKER) {
922                         struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
923                         CDEBUG(D_CONFIG, "Marker, inst_flg=%#x mark_flg=%#x\n",
924                                clli->cfg_flags, marker->cm_flags);
925                         if (marker->cm_flags & CM_START) {
926                                 /* all previous flags off */
927                                 clli->cfg_flags = CFG_F_MARKER;
928                                 if (marker->cm_flags & CM_SKIP) { 
929                                         clli->cfg_flags |= CFG_F_SKIP;
930                                         CDEBUG(D_CONFIG, "SKIP #%d\n",
931                                                marker->cm_step);
932                                 } else if ((marker->cm_flags & CM_EXCLUDE) ||
933                                            lustre_check_exclusion(clli->cfg_sb, 
934                                                           marker->cm_tgtname)) {
935                                         clli->cfg_flags |= CFG_F_EXCLUDE;
936                                         CDEBUG(D_CONFIG, "EXCLUDE %d\n",
937                                                marker->cm_step);
938                                 }
939                         } else if (marker->cm_flags & CM_END) {
940                                 clli->cfg_flags = 0;
941                         }
942                 }
943                 /* A config command without a start marker before it is 
944                    illegal (post 146) */
945                 if (!(clli->cfg_flags & CFG_F_COMPAT146) &&
946                     !(clli->cfg_flags & CFG_F_MARKER) && 
947                     (lcfg->lcfg_command != LCFG_MARKER)) {
948                         CWARN("Config not inside markers, ignoring! (%#x)\n", 
949                               clli->cfg_flags);
950                         clli->cfg_flags |= CFG_F_SKIP;
951                 }
952
953                 if (clli->cfg_flags & CFG_F_SKIP) {
954                         CDEBUG(D_CONFIG, "skipping %#x\n",
955                                clli->cfg_flags);
956                         rc = 0;
957                         /* No processing! */
958                         break;
959                 }
960
961                 if ((clli->cfg_flags & CFG_F_EXCLUDE) && 
962                     (lcfg->lcfg_command == LCFG_LOV_ADD_OBD))
963                         /* Add inactive instead */
964                         lcfg->lcfg_command = LCFG_LOV_ADD_INA;
965
966                 lustre_cfg_bufs_init(&bufs, lcfg);
967
968                 if (clli && clli->cfg_instance && 
969                     LUSTRE_CFG_BUFLEN(lcfg, 0) > 0){
970                         inst = 1;
971                         inst_len = LUSTRE_CFG_BUFLEN(lcfg, 0) +
972                                 strlen(clli->cfg_instance) + 1;
973                         OBD_ALLOC(inst_name, inst_len);
974                         if (inst_name == NULL)
975                                 GOTO(out, rc = -ENOMEM);
976                         sprintf(inst_name, "%s-%s",
977                                 lustre_cfg_string(lcfg, 0),
978                                 clli->cfg_instance);
979                         lustre_cfg_bufs_set_string(&bufs, 0, inst_name);
980                         CDEBUG(D_CONFIG, "cmd %x, instance name: %s\n", 
981                                lcfg->lcfg_command, inst_name);
982                 }
983
984                 /* we override the llog's uuid for clients, to insure they
985                 are unique */
986                 if (clli && clli->cfg_instance && 
987                     lcfg->lcfg_command == LCFG_ATTACH) {
988                         lustre_cfg_bufs_set_string(&bufs, 2,
989                                                    clli->cfg_uuid.uuid);
990                 }
991
992                 lcfg_new = lustre_cfg_new(lcfg->lcfg_command, &bufs);
993
994                 lcfg_new->lcfg_num   = lcfg->lcfg_num;
995                 lcfg_new->lcfg_flags = lcfg->lcfg_flags;
996
997                 /* XXX Hack to try to remain binary compatible with
998                  * pre-newconfig logs */
999                 if (lcfg->lcfg_nal != 0 &&      /* pre-newconfig log? */
1000                     (lcfg->lcfg_nid >> 32) == 0) {
1001                         __u32 addr = (__u32)(lcfg->lcfg_nid & 0xffffffff);
1002
1003                         lcfg_new->lcfg_nid =
1004                                 LNET_MKNID(LNET_MKNET(lcfg->lcfg_nal, 0), addr);
1005                         CWARN("Converted pre-newconfig NAL %d NID %x to %s\n",
1006                               lcfg->lcfg_nal, addr,
1007                               libcfs_nid2str(lcfg_new->lcfg_nid));
1008                 } else {
1009                         lcfg_new->lcfg_nid = lcfg->lcfg_nid;
1010                 }
1011
1012                 lcfg_new->lcfg_nal = 0; /* illegal value for obsolete field */
1013
1014                 rc = class_process_config(lcfg_new);
1015                 lustre_cfg_free(lcfg_new);
1016
1017                 if (inst)
1018                         OBD_FREE(inst_name, inst_len);
1019                 break;
1020         }
1021         default:
1022                 CERROR("Unknown llog record type %#x encountered\n",
1023                        rec->lrh_type);
1024                 break;
1025         }
1026 out:
1027         if (rc) {
1028                 CERROR("Err %d on cfg command:\n", rc);
1029                 class_config_dump_handler(handle, rec, data);
1030         }
1031         RETURN(rc);
1032 }
1033
1034 int class_config_parse_llog(struct llog_ctxt *ctxt, char *name,
1035                             struct config_llog_instance *cfg)
1036 {
1037         struct llog_process_cat_data cd = {0, 0};
1038         struct llog_handle *llh;
1039         int rc, rc2;
1040         ENTRY;
1041
1042         CDEBUG(D_INFO, "looking up llog %s\n", name);
1043         rc = llog_create(ctxt, &llh, NULL, name);
1044         if (rc)
1045                 RETURN(rc);
1046
1047         rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
1048         if (rc)
1049                 GOTO(parse_out, rc);
1050
1051         /* continue processing from where we last stopped to end-of-log */
1052         if (cfg)
1053                 cd.first_idx = cfg->cfg_last_idx;
1054         cd.last_idx = 0;
1055
1056         rc = llog_process(llh, class_config_llog_handler, cfg, &cd);
1057
1058         CDEBUG(D_CONFIG, "Processed log %s gen %d-%d (rc=%d)\n", name, 
1059                cd.first_idx + 1, cd.last_idx, rc);
1060         if (cfg)
1061                 cfg->cfg_last_idx = cd.last_idx;
1062
1063 parse_out:
1064         rc2 = llog_close(llh);
1065         if (rc == 0)
1066                 rc = rc2;
1067
1068         RETURN(rc);
1069 }
1070
1071 int class_config_dump_handler(struct llog_handle * handle,
1072                               struct llog_rec_hdr *rec, void *data)
1073 {
1074         int cfg_len = rec->lrh_len;
1075         char *cfg_buf = (char*) (rec + 1);
1076         char *outstr, *ptr, *end;
1077         int rc = 0;
1078         ENTRY;
1079
1080         OBD_ALLOC(outstr, 256);
1081         end = outstr + 256;
1082         ptr = outstr;
1083         if (!outstr) {
1084                 RETURN(-ENOMEM);
1085         }
1086         if (rec->lrh_type == OBD_CFG_REC) {
1087                 struct lustre_cfg *lcfg;
1088                 int i;
1089
1090                 rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
1091                 if (rc)
1092                         GOTO(out, rc);
1093                 lcfg = (struct lustre_cfg *)cfg_buf;
1094
1095                 ptr += snprintf(ptr, end-ptr, "cmd=%05x ",
1096                                 lcfg->lcfg_command);
1097                 if (lcfg->lcfg_flags) {
1098                         ptr += snprintf(ptr, end-ptr, "flags=%#08x ",
1099                                         lcfg->lcfg_flags);
1100                 }
1101                 if (lcfg->lcfg_num) {
1102                         ptr += snprintf(ptr, end-ptr, "num=%#08x ",
1103                                         lcfg->lcfg_num);
1104                 }
1105                 if (lcfg->lcfg_nid) {
1106                         ptr += snprintf(ptr, end-ptr, "nid=%s("LPX64")\n     ",
1107                                         libcfs_nid2str(lcfg->lcfg_nid),
1108                                         lcfg->lcfg_nid);
1109                 }
1110                 if (lcfg->lcfg_command == LCFG_MARKER) {
1111                         struct cfg_marker *marker = lustre_cfg_buf(lcfg, 1);
1112                         ptr += snprintf(ptr, end-ptr, "marker=%d(%#x)%s '%s'",
1113                                         marker->cm_step, marker->cm_flags, 
1114                                         marker->cm_tgtname, marker->cm_comment);
1115                 } else {
1116                         for (i = 0; i <  lcfg->lcfg_bufcount; i++) {
1117                                 ptr += snprintf(ptr, end-ptr, "%d:%s  ", i,
1118                                                 lustre_cfg_string(lcfg, i));
1119                         }
1120                 }
1121                 LCONSOLE(D_WARNING, "   %s\n", outstr);
1122         } else {
1123                 LCONSOLE(D_WARNING, "unhandled lrh_type: %#x\n", rec->lrh_type);
1124                 rc = -EINVAL;
1125         }
1126 out:
1127         OBD_FREE(outstr, 256);
1128         RETURN(rc);
1129 }
1130
1131 int class_config_dump_llog(struct llog_ctxt *ctxt, char *name,
1132                            struct config_llog_instance *cfg)
1133 {
1134         struct llog_handle *llh;
1135         int rc, rc2;
1136         ENTRY;
1137
1138         LCONSOLE_INFO("Dumping config log %s\n", name);
1139
1140         rc = llog_create(ctxt, &llh, NULL, name);
1141         if (rc)
1142                 RETURN(rc);
1143
1144         rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
1145         if (rc)
1146                 GOTO(parse_out, rc);
1147
1148         rc = llog_process(llh, class_config_dump_handler, cfg, NULL);
1149 parse_out:
1150         rc2 = llog_close(llh);
1151         if (rc == 0)
1152                 rc = rc2;
1153
1154         LCONSOLE_INFO("End config log %s\n", name);
1155         RETURN(rc);
1156
1157 }
1158
1159 /* Cleanup and detach */
1160 int class_manual_cleanup(struct obd_device *obd)
1161 {
1162         struct lustre_cfg *lcfg;
1163         struct lustre_cfg_bufs bufs;
1164         int rc;
1165         char flags[3]="";
1166         ENTRY;
1167
1168         if (!obd) {
1169                 CERROR("empty cleanup\n");
1170                 RETURN(-EALREADY);
1171         }
1172
1173         if (obd->obd_force)
1174                 strcat(flags, "F");
1175         if (obd->obd_fail)
1176                 strcat(flags, "A");
1177
1178         CDEBUG(D_CONFIG, "Manual cleanup of %s (flags='%s')\n",
1179                obd->obd_name, flags);
1180
1181         lustre_cfg_bufs_reset(&bufs, obd->obd_name);
1182         lustre_cfg_bufs_set_string(&bufs, 1, flags);
1183         lcfg = lustre_cfg_new(LCFG_CLEANUP, &bufs);
1184
1185         rc = class_process_config(lcfg);
1186         if (rc) {
1187                 CERROR("cleanup failed %d: %s\n", rc, obd->obd_name);
1188                 GOTO(out, rc);
1189         }
1190
1191         /* the lcfg is almost the same for both ops */
1192         lcfg->lcfg_command = LCFG_DETACH;
1193         rc = class_process_config(lcfg);
1194         if (rc)
1195                 CERROR("detach failed %d: %s\n", rc, obd->obd_name);
1196 out:
1197         lustre_cfg_free(lcfg);
1198         RETURN(rc);
1199 }
1200