Whamcloud - gitweb
LU-694 config: make 'jobid_var' global
[fs/lustre-release.git] / lustre / mgs / mgs_llog.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.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011, Whamcloud, Inc.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/mgs/mgs_llog.c
37  *
38  * Lustre Management Server (mgs) config llog creation
39  *
40  * Author: Nathan Rutman <nathan@clusterfs.com>
41  */
42
43 #ifndef EXPORT_SYMTAB
44 #define EXPORT_SYMTAB
45 #endif
46 #define DEBUG_SUBSYSTEM S_MGS
47 #define D_MGS D_CONFIG
48
49 #ifdef __KERNEL__
50 #include <linux/module.h>
51 #include <linux/pagemap.h>
52 #include <linux/fs.h>
53 #endif
54
55 #include <obd.h>
56 #include <obd_lov.h>
57 #include <obd_class.h>
58 #include <lustre_log.h>
59 #include <obd_ost.h>
60 #include <libcfs/list.h>
61 #include <linux/lvfs.h>
62 #include <lustre_fsfilt.h>
63 #include <lustre_disk.h>
64 #include <lustre_param.h>
65 #include <lustre_sec.h>
66 #include "mgs_internal.h"
67
68 /********************** Class functions ********************/
69
70 /* Caller must list_del and OBD_FREE each dentry from the list */
71 int class_dentry_readdir(struct obd_device *obd, struct dentry *dir,
72                                 struct vfsmount *inmnt,
73                                 cfs_list_t *dentry_list){
74         /* see mds_cleanup_pending */
75         struct lvfs_run_ctxt saved;
76         struct file *file;
77         struct dentry *dentry;
78         struct vfsmount *mnt;
79         int rc = 0;
80         ENTRY;
81
82         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
83         dentry = dget(dir);
84         if (IS_ERR(dentry))
85                 GOTO(out_pop, rc = PTR_ERR(dentry));
86         mnt = mntget(inmnt);
87         if (IS_ERR(mnt)) {
88                 l_dput(dentry);
89                 GOTO(out_pop, rc = PTR_ERR(mnt));
90         }
91
92         file = ll_dentry_open(dentry, mnt, O_RDONLY, current_cred());
93         if (IS_ERR(file))
94                 /* dentry_open_it() drops the dentry, mnt refs */
95                 GOTO(out_pop, rc = PTR_ERR(file));
96
97         CFS_INIT_LIST_HEAD(dentry_list);
98         rc = l_readdir(file, dentry_list);
99         filp_close(file, 0);
100         /*  filp_close->fput() drops the dentry, mnt refs */
101
102 out_pop:
103         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
104         RETURN(rc);
105 }
106
107 /******************** DB functions *********************/
108
109 static inline int name_create(char **newname, char *prefix, char *suffix)
110 {
111         LASSERT(newname);
112         OBD_ALLOC(*newname, strlen(prefix) + strlen(suffix) + 1);
113         if (!*newname)
114                 return -ENOMEM;
115         sprintf(*newname, "%s%s", prefix, suffix);
116         return 0;
117 }
118
119 static inline void name_destroy(char **name)
120 {
121         if (*name)
122                 OBD_FREE(*name, strlen(*name) + 1);
123         *name = NULL;
124 }
125
126 struct mgs_fsdb_handler_data
127 {
128         struct fs_db   *fsdb;
129         __u32           ver;
130 };
131
132 /* from the (client) config log, figure out:
133         1. which ost's/mdt's are configured (by index)
134         2. what the last config step is
135         3. COMPAT_146 lov name
136         4. COMPAT_146 mdt lov name
137         5. COMPAT_146 mdc name
138         6. COMPAT_18 osc name
139 */
140 /* It might be better to have a separate db file, instead of parsing the info
141    out of the client log.  This is slow and potentially error-prone. */
142 static int mgs_fsdb_handler(struct llog_handle *llh, struct llog_rec_hdr *rec,
143                             void *data)
144 {
145         struct mgs_fsdb_handler_data *d = (struct mgs_fsdb_handler_data *) data;
146         struct fs_db *fsdb = d->fsdb;
147         int cfg_len = rec->lrh_len;
148         char *cfg_buf = (char*) (rec + 1);
149         struct lustre_cfg *lcfg;
150         __u32 index;
151         int rc = 0;
152         ENTRY;
153
154         if (rec->lrh_type != OBD_CFG_REC) {
155                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
156                 RETURN(-EINVAL);
157         }
158
159         rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
160         if (rc) {
161                 CERROR("Insane cfg\n");
162                 RETURN(rc);
163         }
164
165         lcfg = (struct lustre_cfg *)cfg_buf;
166
167         CDEBUG(D_INFO, "cmd %x %s %s\n", lcfg->lcfg_command,
168                lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
169
170         /* Figure out ost indicies */
171         /* lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1 */
172         if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD ||
173             lcfg->lcfg_command == LCFG_LOV_DEL_OBD) {
174                 index = simple_strtoul(lustre_cfg_string(lcfg, 2),
175                                        NULL, 10);
176                 CDEBUG(D_MGS, "OST index for %s is %u (%s)\n",
177                        lustre_cfg_string(lcfg, 1), index,
178                        lustre_cfg_string(lcfg, 2));
179                 cfs_set_bit(index, fsdb->fsdb_ost_index_map);
180         }
181
182         /* Figure out mdt indicies */
183         /* attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f */
184         if ((lcfg->lcfg_command == LCFG_ATTACH) &&
185             (strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_MDC_NAME) == 0)) {
186                 rc = server_name2index(lustre_cfg_string(lcfg, 0),
187                                        &index, NULL);
188                 if (rc != LDD_F_SV_TYPE_MDT) {
189                         CWARN("Unparsable MDC name %s, assuming index 0\n",
190                               lustre_cfg_string(lcfg, 0));
191                         index = 0;
192                 }
193                 rc = 0;
194                 CDEBUG(D_MGS, "MDT index is %u\n", index);
195                 cfs_set_bit(index, fsdb->fsdb_mdt_index_map);
196                 fsdb->fsdb_mdt_count ++;
197         }
198
199         /* COMPAT_146 */
200         /* figure out the old LOV name. fsdb_gen = 0 means old log */
201         /* #01 L attach 0:lov_mdsA 1:lov 2:cdbe9_lov_mdsA_dc8cf7f3bb */
202         if ((fsdb->fsdb_gen == 0) && (lcfg->lcfg_command == LCFG_ATTACH) &&
203             (strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_LOV_NAME) == 0)) {
204                 cfs_set_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags);
205                 name_destroy(&fsdb->fsdb_clilov);
206                 rc = name_create(&fsdb->fsdb_clilov,
207                                  lustre_cfg_string(lcfg, 0), "");
208                 if (rc)
209                         RETURN(rc);
210                 CDEBUG(D_MGS, "client lov name is %s\n", fsdb->fsdb_clilov);
211         }
212
213         /* figure out the old MDT lov name from the MDT uuid */
214         if ((fsdb->fsdb_gen == 0) && (lcfg->lcfg_command == LCFG_SETUP) &&
215             (strncmp(lustre_cfg_string(lcfg, 0), "MDC_", 4) == 0)) {
216                 char *ptr;
217                 cfs_set_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags);
218                 ptr = strstr(lustre_cfg_string(lcfg, 1), "_UUID");
219                 if (!ptr) {
220                         CERROR("Can't parse MDT uuid %s\n",
221                                lustre_cfg_string(lcfg, 1));
222                         RETURN(-EINVAL);
223                 }
224                 *ptr = '\0';
225                 name_destroy(&fsdb->fsdb_mdtlov);
226                 rc = name_create(&fsdb->fsdb_mdtlov,
227                                  "lov_", lustre_cfg_string(lcfg, 1));
228                 if (rc)
229                         RETURN(rc);
230                 name_destroy(&fsdb->fsdb_mdc);
231                 rc = name_create(&fsdb->fsdb_mdc,
232                                  lustre_cfg_string(lcfg, 0), "");
233                 if (rc)
234                         RETURN(rc);
235                 CDEBUG(D_MGS, "MDT lov name is %s\n", fsdb->fsdb_mdtlov);
236         }
237         /* end COMPAT_146 */
238
239         /*
240          * compat to 1.8, check osc name used by MDT0 to OSTs, bz18548.
241          */
242         if (!cfs_test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags) &&
243             lcfg->lcfg_command == LCFG_ATTACH &&
244             strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_OSC_NAME) == 0) {
245                 if (OBD_OCD_VERSION_MAJOR(d->ver) == 1 &&
246                     OBD_OCD_VERSION_MINOR(d->ver) <= 8) {
247                         CWARN("MDT using 1.8 OSC name scheme\n");
248                         cfs_set_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags);
249                 }
250         }
251
252         if (lcfg->lcfg_command == LCFG_MARKER) {
253                 struct cfg_marker *marker;
254                 marker = lustre_cfg_buf(lcfg, 1);
255
256                 d->ver = marker->cm_vers;
257
258                 /* Keep track of the latest marker step */
259                 fsdb->fsdb_gen = max(fsdb->fsdb_gen, marker->cm_step);
260         }
261
262         RETURN(rc);
263 }
264
265 /* fsdb->fsdb_mutex is already held  in mgs_find_or_make_fsdb*/
266 static int mgs_get_fsdb_from_llog(struct obd_device *obd, struct fs_db *fsdb)
267 {
268         char *logname;
269         struct llog_handle *loghandle;
270         struct lvfs_run_ctxt saved;
271         struct llog_ctxt *ctxt;
272         struct mgs_fsdb_handler_data d = { fsdb, 0 };
273         int rc, rc2;
274         ENTRY;
275
276         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
277         LASSERT(ctxt != NULL);
278         name_create(&logname, fsdb->fsdb_name, "-client");
279         cfs_mutex_lock(&fsdb->fsdb_mutex);
280         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
281         rc = llog_create(ctxt, &loghandle, NULL, logname);
282         if (rc)
283                 GOTO(out_pop, rc);
284
285         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
286         if (rc)
287                 GOTO(out_close, rc);
288
289         if (llog_get_size(loghandle) <= 1)
290                 cfs_set_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags);
291
292         rc = llog_process(loghandle, mgs_fsdb_handler, (void *) &d, NULL);
293         CDEBUG(D_INFO, "get_db = %d\n", rc);
294 out_close:
295         rc2 = llog_close(loghandle);
296         if (!rc)
297                 rc = rc2;
298 out_pop:
299         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
300         cfs_mutex_unlock(&fsdb->fsdb_mutex);
301         name_destroy(&logname);
302         llog_ctxt_put(ctxt);
303
304         RETURN(rc);
305 }
306
307 static void mgs_free_fsdb_srpc(struct fs_db *fsdb)
308 {
309         struct mgs_tgt_srpc_conf *tgtconf;
310
311         /* free target-specific rules */
312         while (fsdb->fsdb_srpc_tgt) {
313                 tgtconf = fsdb->fsdb_srpc_tgt;
314                 fsdb->fsdb_srpc_tgt = tgtconf->mtsc_next;
315
316                 LASSERT(tgtconf->mtsc_tgt);
317
318                 sptlrpc_rule_set_free(&tgtconf->mtsc_rset);
319                 OBD_FREE(tgtconf->mtsc_tgt, strlen(tgtconf->mtsc_tgt) + 1);
320                 OBD_FREE_PTR(tgtconf);
321         }
322
323         /* free general rules */
324         sptlrpc_rule_set_free(&fsdb->fsdb_srpc_gen);
325 }
326
327 struct fs_db *mgs_find_fsdb(struct obd_device *obd, char *fsname)
328 {
329         struct mgs_obd *mgs = &obd->u.mgs;
330         struct fs_db *fsdb;
331         cfs_list_t *tmp;
332
333         cfs_list_for_each(tmp, &mgs->mgs_fs_db_list) {
334                 fsdb = cfs_list_entry(tmp, struct fs_db, fsdb_list);
335                 if (strcmp(fsdb->fsdb_name, fsname) == 0)
336                         return fsdb;
337         }
338         return NULL;
339 }
340
341 /* caller must hold the mgs->mgs_fs_db_lock */
342 static struct fs_db *mgs_new_fsdb(struct obd_device *obd, char *fsname)
343 {
344         struct mgs_obd *mgs = &obd->u.mgs;
345         struct fs_db *fsdb;
346         int rc;
347         ENTRY;
348
349         if (strlen(fsname) >= sizeof(fsdb->fsdb_name)) {
350                 CERROR("fsname %s is too long\n", fsname);
351                 RETURN(NULL);
352         }
353
354         OBD_ALLOC_PTR(fsdb);
355         if (!fsdb)
356                 RETURN(NULL);
357
358         strcpy(fsdb->fsdb_name, fsname);
359         cfs_mutex_init(&fsdb->fsdb_mutex);
360         cfs_set_bit(FSDB_UDESC, &fsdb->fsdb_flags);
361
362         if (strcmp(fsname, MGSSELF_NAME) == 0) {
363                 cfs_set_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags);
364         } else {
365                 OBD_ALLOC(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
366                 OBD_ALLOC(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
367                 if (!fsdb->fsdb_ost_index_map || !fsdb->fsdb_mdt_index_map) {
368                         CERROR("No memory for index maps\n");
369                         GOTO(err, 0);
370                 }
371
372                 rc = name_create(&fsdb->fsdb_mdtlov, fsname, "-mdtlov");
373                 if (rc)
374                         GOTO(err, rc);
375                 rc = name_create(&fsdb->fsdb_mdtlmv, fsname, "-mdtlmv");
376                 if (rc)
377                         GOTO(err, rc);
378                 rc = name_create(&fsdb->fsdb_clilov, fsname, "-clilov");
379                 if (rc)
380                         GOTO(err, rc);
381                 rc = name_create(&fsdb->fsdb_clilmv, fsname, "-clilmv");
382                 if (rc)
383                         GOTO(err, rc);
384
385                 /* initialise data for NID table */
386                 mgs_ir_init_fs(obd, fsdb);
387
388                 lproc_mgs_add_live(obd, fsdb);
389         }
390
391         cfs_list_add(&fsdb->fsdb_list, &mgs->mgs_fs_db_list);
392
393         RETURN(fsdb);
394 err:
395         if (fsdb->fsdb_ost_index_map)
396                 OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
397         if (fsdb->fsdb_mdt_index_map)
398                 OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
399         name_destroy(&fsdb->fsdb_clilov);
400         name_destroy(&fsdb->fsdb_clilmv);
401         name_destroy(&fsdb->fsdb_mdtlov);
402         name_destroy(&fsdb->fsdb_mdtlmv);
403         OBD_FREE_PTR(fsdb);
404         RETURN(NULL);
405 }
406
407 static void mgs_free_fsdb(struct obd_device *obd, struct fs_db *fsdb)
408 {
409         /* wait for anyone with the sem */
410         cfs_mutex_lock(&fsdb->fsdb_mutex);
411         lproc_mgs_del_live(obd, fsdb);
412         cfs_list_del(&fsdb->fsdb_list);
413
414         /* deinitialize fsr */
415         mgs_ir_fini_fs(obd, fsdb);
416
417         if (fsdb->fsdb_ost_index_map)
418                 OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
419         if (fsdb->fsdb_mdt_index_map)
420                 OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
421         name_destroy(&fsdb->fsdb_clilov);
422         name_destroy(&fsdb->fsdb_clilmv);
423         name_destroy(&fsdb->fsdb_mdtlov);
424         name_destroy(&fsdb->fsdb_mdtlmv);
425         name_destroy(&fsdb->fsdb_mdc);
426         mgs_free_fsdb_srpc(fsdb);
427         cfs_mutex_unlock(&fsdb->fsdb_mutex);
428         OBD_FREE_PTR(fsdb);
429 }
430
431 int mgs_init_fsdb_list(struct obd_device *obd)
432 {
433         struct mgs_obd *mgs = &obd->u.mgs;
434         CFS_INIT_LIST_HEAD(&mgs->mgs_fs_db_list);
435         return 0;
436 }
437
438 int mgs_cleanup_fsdb_list(struct obd_device *obd)
439 {
440         struct mgs_obd *mgs = &obd->u.mgs;
441         struct fs_db *fsdb;
442         cfs_list_t *tmp, *tmp2;
443         cfs_mutex_lock(&mgs->mgs_mutex);
444         cfs_list_for_each_safe(tmp, tmp2, &mgs->mgs_fs_db_list) {
445                 fsdb = cfs_list_entry(tmp, struct fs_db, fsdb_list);
446                 mgs_free_fsdb(obd, fsdb);
447         }
448         cfs_mutex_unlock(&mgs->mgs_mutex);
449         return 0;
450 }
451
452 int mgs_find_or_make_fsdb(struct obd_device *obd, char *name,
453                           struct fs_db **dbh)
454 {
455         struct mgs_obd *mgs = &obd->u.mgs;
456         struct fs_db *fsdb;
457         int rc = 0;
458
459         cfs_mutex_lock(&mgs->mgs_mutex);
460         fsdb = mgs_find_fsdb(obd, name);
461         if (fsdb) {
462                 cfs_mutex_unlock(&mgs->mgs_mutex);
463                 *dbh = fsdb;
464                 return 0;
465         }
466
467         CDEBUG(D_MGS, "Creating new db\n");
468         fsdb = mgs_new_fsdb(obd, name);
469         cfs_mutex_unlock(&mgs->mgs_mutex);
470         if (!fsdb)
471                 return -ENOMEM;
472
473         if (!cfs_test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
474                 /* populate the db from the client llog */
475                 rc = mgs_get_fsdb_from_llog(obd, fsdb);
476                 if (rc) {
477                         CERROR("Can't get db from client log %d\n", rc);
478                         mgs_free_fsdb(obd, fsdb);
479                         return rc;
480                 }
481         }
482
483         /* populate srpc rules from params llog */
484         rc = mgs_get_fsdb_srpc_from_llog(obd, fsdb);
485         if (rc) {
486                 CERROR("Can't get db from params log %d\n", rc);
487                 mgs_free_fsdb(obd, fsdb);
488                 return rc;
489         }
490
491         *dbh = fsdb;
492
493         return 0;
494 }
495
496 /* 1 = index in use
497    0 = index unused
498    -1= empty client log */
499 int mgs_check_index(struct obd_device *obd, struct mgs_target_info *mti)
500 {
501         struct fs_db *fsdb;
502         void *imap;
503         int rc = 0;
504         ENTRY;
505
506         LASSERT(!(mti->mti_flags & LDD_F_NEED_INDEX));
507
508         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb);
509         if (rc) {
510                 CERROR("Can't get db for %s\n", mti->mti_fsname);
511                 RETURN(rc);
512         }
513
514         if (cfs_test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags))
515                 RETURN(-1);
516
517         if (mti->mti_flags & LDD_F_SV_TYPE_OST)
518                 imap = fsdb->fsdb_ost_index_map;
519         else if (mti->mti_flags & LDD_F_SV_TYPE_MDT)
520                 imap = fsdb->fsdb_mdt_index_map;
521         else
522                 RETURN(-EINVAL);
523
524         if (cfs_test_bit(mti->mti_stripe_index, imap))
525                 RETURN(1);
526         RETURN(0);
527 }
528
529 static __inline__ int next_index(void *index_map, int map_len)
530 {
531         int i;
532         for (i = 0; i < map_len * 8; i++)
533                  if (!cfs_test_bit(i, index_map)) {
534                          return i;
535                  }
536         CERROR("max index %d exceeded.\n", i);
537         return -1;
538 }
539
540 /* Return codes:
541         0  newly marked as in use
542         <0 err
543         +EALREADY for update of an old index */
544 static int mgs_set_index(struct obd_device *obd, struct mgs_target_info *mti)
545 {
546         struct fs_db *fsdb;
547         void *imap;
548         int rc = 0;
549         ENTRY;
550
551         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb);
552         if (rc) {
553                 CERROR("Can't get db for %s\n", mti->mti_fsname);
554                 RETURN(rc);
555         }
556
557         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
558                 imap = fsdb->fsdb_ost_index_map;
559         } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
560                 imap = fsdb->fsdb_mdt_index_map;
561                 if (fsdb->fsdb_mdt_count >= MAX_MDT_COUNT) {
562                         LCONSOLE_ERROR_MSG(0x13f, "The max mdt count"
563                                            "is %d\n", (int)MAX_MDT_COUNT);
564                         RETURN(-ERANGE);
565                 }
566         } else {
567                 RETURN(-EINVAL);
568         }
569
570         if (mti->mti_flags & LDD_F_NEED_INDEX) {
571                 rc = next_index(imap, INDEX_MAP_SIZE);
572                 if (rc == -1)
573                         RETURN(-ERANGE);
574                 mti->mti_stripe_index = rc;
575                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT)
576                         fsdb->fsdb_mdt_count ++;
577         }
578
579         if (mti->mti_stripe_index >= INDEX_MAP_SIZE * 8) {
580                 LCONSOLE_ERROR_MSG(0x13f, "Server %s requested index %d, "
581                                    "but the max index is %d.\n",
582                                    mti->mti_svname, mti->mti_stripe_index,
583                                    INDEX_MAP_SIZE * 8);
584                 RETURN(-ERANGE);
585         }
586
587         if (cfs_test_bit(mti->mti_stripe_index, imap)) {
588                 if ((mti->mti_flags & LDD_F_VIRGIN) &&
589                     !(mti->mti_flags & LDD_F_WRITECONF)) {
590                         LCONSOLE_ERROR_MSG(0x140, "Server %s requested index "
591                                            "%d, but that index is already in "
592                                            "use. Use --writeconf to force\n",
593                                            mti->mti_svname,
594                                            mti->mti_stripe_index);
595                         RETURN(-EADDRINUSE);
596                 } else {
597                         CDEBUG(D_MGS, "Server %s updating index %d\n",
598                                mti->mti_svname, mti->mti_stripe_index);
599                         RETURN(EALREADY);
600                 }
601         }
602
603         cfs_set_bit(mti->mti_stripe_index, imap);
604         cfs_clear_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags);
605         server_make_name(mti->mti_flags, mti->mti_stripe_index,
606                          mti->mti_fsname, mti->mti_svname);
607
608         CDEBUG(D_MGS, "Set index for %s to %d\n", mti->mti_svname,
609                mti->mti_stripe_index);
610
611         RETURN(0);
612 }
613
614 struct mgs_modify_lookup {
615         struct cfg_marker mml_marker;
616         int               mml_modified;
617 };
618
619 static int mgs_modify_handler(struct llog_handle *llh, struct llog_rec_hdr *rec,
620                               void *data)
621 {
622         struct mgs_modify_lookup *mml = (struct mgs_modify_lookup *)data;
623         struct cfg_marker *marker;
624         struct lustre_cfg *lcfg = (struct lustre_cfg *)(rec + 1);
625         int cfg_len = rec->lrh_len - sizeof(struct llog_rec_hdr) -
626                 sizeof(struct llog_rec_tail);
627         int rc;
628         ENTRY;
629
630         if (rec->lrh_type != OBD_CFG_REC) {
631                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
632                 RETURN(-EINVAL);
633         }
634
635         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
636         if (rc) {
637                 CERROR("Insane cfg\n");
638                 RETURN(rc);
639         }
640
641         /* We only care about markers */
642         if (lcfg->lcfg_command != LCFG_MARKER)
643                 RETURN(0);
644
645         marker = lustre_cfg_buf(lcfg, 1);
646         if ((strcmp(mml->mml_marker.cm_comment, marker->cm_comment) == 0) &&
647             (strcmp(mml->mml_marker.cm_tgtname, marker->cm_tgtname) == 0) &&
648             !(marker->cm_flags & CM_SKIP)) {
649                 /* Found a non-skipped marker match */
650                 CDEBUG(D_MGS, "Changing rec %u marker %d %x->%x: %s %s\n",
651                        rec->lrh_index, marker->cm_step,
652                        marker->cm_flags, mml->mml_marker.cm_flags,
653                        marker->cm_tgtname, marker->cm_comment);
654                 /* Overwrite the old marker llog entry */
655                 marker->cm_flags &= ~CM_EXCLUDE; /* in case we're unexcluding */
656                 marker->cm_flags |= mml->mml_marker.cm_flags;
657                 marker->cm_canceltime = mml->mml_marker.cm_canceltime;
658                 /* Header and tail are added back to lrh_len in
659                    llog_lvfs_write_rec */
660                 rec->lrh_len = cfg_len;
661                 rc = llog_write_rec(llh, rec, NULL, 0, (void *)lcfg,
662                                     rec->lrh_index);
663                 if (!rc)
664                          mml->mml_modified++;
665         }
666
667         RETURN(rc);
668 }
669
670 /* Modify an existing config log record (for CM_SKIP or CM_EXCLUDE) */
671 static int mgs_modify(struct obd_device *obd, struct fs_db *fsdb,
672                       struct mgs_target_info *mti, char *logname,
673                       char *devname, char *comment, int flags)
674 {
675         struct llog_handle *loghandle;
676         struct lvfs_run_ctxt saved;
677         struct llog_ctxt *ctxt;
678         struct mgs_modify_lookup *mml;
679         int rc, rc2;
680         ENTRY;
681
682         CDEBUG(D_MGS, "modify %s/%s/%s fl=%x\n", logname, devname, comment,
683                flags);
684
685         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
686
687         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
688         LASSERT(ctxt != NULL);
689         rc = llog_create(ctxt, &loghandle, NULL, logname);
690         if (rc)
691                 GOTO(out_pop, rc);
692
693         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
694         if (rc)
695                 GOTO(out_close, rc);
696
697         if (llog_get_size(loghandle) <= 1)
698                 GOTO(out_close, rc = 0);
699
700         OBD_ALLOC_PTR(mml);
701         if (!mml)
702                 GOTO(out_close, rc = -ENOMEM);
703         strcpy(mml->mml_marker.cm_comment, comment);
704         strcpy(mml->mml_marker.cm_tgtname, devname);
705         /* Modify mostly means cancel */
706         mml->mml_marker.cm_flags = flags;
707         mml->mml_marker.cm_canceltime = flags ? cfs_time_current_sec() : 0;
708         mml->mml_modified = 0;
709         rc = llog_process(loghandle, mgs_modify_handler, (void *)mml, NULL);
710         if (!rc && !mml->mml_modified)
711                 rc = -ENODEV;
712         OBD_FREE_PTR(mml);
713
714 out_close:
715         rc2 = llog_close(loghandle);
716         if (!rc)
717                 rc = rc2;
718 out_pop:
719         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
720         if (rc && rc != -ENODEV)
721                 CERROR("modify %s/%s failed %d\n",
722                        mti->mti_svname, comment, rc);
723         llog_ctxt_put(ctxt);
724         RETURN(rc);
725 }
726
727 /******************** config log recording functions *********************/
728
729 static int record_lcfg(struct obd_device *obd, struct llog_handle *llh,
730                          struct lustre_cfg *lcfg)
731 {
732         struct lvfs_run_ctxt   saved;
733         struct llog_rec_hdr    rec;
734         int buflen, rc;
735
736         if (!lcfg || !llh)
737                 return -ENOMEM;
738
739         LASSERT(llh->lgh_ctxt);
740
741         buflen = lustre_cfg_len(lcfg->lcfg_bufcount,
742                                 lcfg->lcfg_buflens);
743         rec.lrh_len = llog_data_len(buflen);
744         rec.lrh_type = OBD_CFG_REC;
745
746         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
747         /* idx = -1 means append */
748         rc = llog_write_rec(llh, &rec, NULL, 0, (void *)lcfg, -1);
749         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
750         if (rc)
751                 CERROR("failed %d\n", rc);
752         return rc;
753 }
754
755 static int record_base(struct obd_device *obd, struct llog_handle *llh,
756                      char *cfgname, lnet_nid_t nid, int cmd,
757                      char *s1, char *s2, char *s3, char *s4)
758 {
759         struct lustre_cfg_bufs bufs;
760         struct lustre_cfg     *lcfg;
761         int rc;
762
763         CDEBUG(D_MGS, "lcfg %s %#x %s %s %s %s\n", cfgname,
764                cmd, s1, s2, s3, s4);
765
766         lustre_cfg_bufs_reset(&bufs, cfgname);
767         if (s1)
768                 lustre_cfg_bufs_set_string(&bufs, 1, s1);
769         if (s2)
770                 lustre_cfg_bufs_set_string(&bufs, 2, s2);
771         if (s3)
772                 lustre_cfg_bufs_set_string(&bufs, 3, s3);
773         if (s4)
774                 lustre_cfg_bufs_set_string(&bufs, 4, s4);
775
776         lcfg = lustre_cfg_new(cmd, &bufs);
777         if (!lcfg)
778                 return -ENOMEM;
779         lcfg->lcfg_nid = nid;
780
781         rc = record_lcfg(obd, llh, lcfg);
782
783         lustre_cfg_free(lcfg);
784
785         if (rc) {
786                 CERROR("error %d: lcfg %s %#x %s %s %s %s\n", rc, cfgname,
787                        cmd, s1, s2, s3, s4);
788         }
789         return(rc);
790 }
791
792
793 static inline int record_add_uuid(struct obd_device *obd,
794                                   struct llog_handle *llh,
795                                   uint64_t nid, char *uuid)
796 {
797         return record_base(obd,llh,NULL,nid,LCFG_ADD_UUID,uuid,0,0,0);
798
799 }
800
801 static inline int record_add_conn(struct obd_device *obd,
802                                   struct llog_handle *llh,
803                                   char *devname,
804                                   char *uuid)
805 {
806         return record_base(obd,llh,devname,0,LCFG_ADD_CONN,uuid,0,0,0);
807 }
808
809 static inline int record_attach(struct obd_device *obd, struct llog_handle *llh,
810                                 char *devname, char *type, char *uuid)
811 {
812         return record_base(obd,llh,devname,0,LCFG_ATTACH,type,uuid,0,0);
813 }
814
815 static inline int record_setup(struct obd_device *obd, struct llog_handle *llh,
816                                char *devname,
817                                char *s1, char *s2, char *s3, char *s4)
818 {
819         return record_base(obd,llh,devname,0,LCFG_SETUP,s1,s2,s3,s4);
820 }
821
822 static int record_lov_setup(struct obd_device *obd, struct llog_handle *llh,
823                             char *devname, struct lov_desc *desc)
824 {
825         struct lustre_cfg_bufs bufs;
826         struct lustre_cfg *lcfg;
827         int rc;
828
829         lustre_cfg_bufs_reset(&bufs, devname);
830         lustre_cfg_bufs_set(&bufs, 1, desc, sizeof(*desc));
831         lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
832         if (!lcfg)
833                 return -ENOMEM;
834         rc = record_lcfg(obd, llh, lcfg);
835
836         lustre_cfg_free(lcfg);
837         return rc;
838 }
839
840 static int record_lmv_setup(struct obd_device *obd, struct llog_handle *llh,
841                             char *devname, struct lmv_desc *desc)
842 {
843         struct lustre_cfg_bufs bufs;
844         struct lustre_cfg *lcfg;
845         int rc;
846
847         lustre_cfg_bufs_reset(&bufs, devname);
848         lustre_cfg_bufs_set(&bufs, 1, desc, sizeof(*desc));
849         lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
850
851         rc = record_lcfg(obd, llh, lcfg);
852
853         lustre_cfg_free(lcfg);
854         return rc;
855 }
856
857 static inline int record_mdc_add(struct obd_device *obd,
858                                  struct llog_handle *llh,
859                                  char *logname, char *mdcuuid,
860                                  char *mdtuuid, char *index,
861                                  char *gen)
862 {
863         return record_base(obd,llh,logname,0,LCFG_ADD_MDC,
864                            mdtuuid,index,gen,mdcuuid);
865 }
866
867 static inline int record_lov_add(struct obd_device *obd,
868                                  struct llog_handle *llh,
869                                  char *lov_name, char *ost_uuid,
870                                  char *index, char *gen)
871 {
872         return record_base(obd,llh,lov_name,0,LCFG_LOV_ADD_OBD,
873                            ost_uuid,index,gen,0);
874 }
875
876 static inline int record_mount_opt(struct obd_device *obd,
877                                    struct llog_handle *llh,
878                                    char *profile, char *lov_name,
879                                    char *mdc_name)
880 {
881         return record_base(obd,llh,NULL,0,LCFG_MOUNTOPT,
882                            profile,lov_name,mdc_name,0);
883 }
884
885 static int record_marker(struct obd_device *obd, struct llog_handle *llh,
886                          struct fs_db *fsdb, __u32 flags,
887                          char *tgtname, char *comment)
888 {
889         struct cfg_marker marker;
890         struct lustre_cfg_bufs bufs;
891         struct lustre_cfg *lcfg;
892         int rc;
893
894         if (flags & CM_START)
895                 fsdb->fsdb_gen++;
896         marker.cm_step = fsdb->fsdb_gen;
897         marker.cm_flags = flags;
898         marker.cm_vers = LUSTRE_VERSION_CODE;
899         strncpy(marker.cm_tgtname, tgtname, sizeof(marker.cm_tgtname));
900         strncpy(marker.cm_comment, comment, sizeof(marker.cm_comment));
901         marker.cm_createtime = cfs_time_current_sec();
902         marker.cm_canceltime = 0;
903         lustre_cfg_bufs_reset(&bufs, NULL);
904         lustre_cfg_bufs_set(&bufs, 1, &marker, sizeof(marker));
905         lcfg = lustre_cfg_new(LCFG_MARKER, &bufs);
906         if (!lcfg)
907                 return -ENOMEM;
908         rc = record_lcfg(obd, llh, lcfg);
909
910         lustre_cfg_free(lcfg);
911         return rc;
912 }
913
914 static int record_start_log(struct obd_device *obd,
915                             struct llog_handle **llh, char *name)
916 {
917         static struct obd_uuid cfg_uuid = { .uuid = "config_uuid" };
918         struct lvfs_run_ctxt saved;
919         struct llog_ctxt *ctxt;
920         int rc = 0;
921
922         if (*llh)
923                 GOTO(out, rc = -EBUSY);
924
925         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
926         if (!ctxt)
927                 GOTO(out, rc = -ENODEV);
928
929         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
930         rc = llog_create(ctxt, llh, NULL, name);
931         if (rc == 0)
932                 llog_init_handle(*llh, LLOG_F_IS_PLAIN, &cfg_uuid);
933         else
934                 *llh = NULL;
935
936         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
937         llog_ctxt_put(ctxt);
938
939 out:
940         if (rc) {
941                 CERROR("Can't start log %s: %d\n", name, rc);
942         }
943         RETURN(rc);
944 }
945
946 static int record_end_log(struct obd_device *obd, struct llog_handle **llh)
947 {
948         struct lvfs_run_ctxt saved;
949         int rc = 0;
950
951         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
952
953         rc = llog_close(*llh);
954         *llh = NULL;
955
956         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
957         RETURN(rc);
958 }
959
960 static int mgs_log_is_empty(struct obd_device *obd, char *name)
961 {
962         struct lvfs_run_ctxt saved;
963         struct llog_handle *llh;
964         struct llog_ctxt *ctxt;
965         int rc = 0;
966
967         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
968         LASSERT(ctxt != NULL);
969         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
970         rc = llog_create(ctxt, &llh, NULL, name);
971         if (rc == 0) {
972                 llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
973                 rc = llog_get_size(llh);
974                 llog_close(llh);
975         }
976         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
977         llog_ctxt_put(ctxt);
978         /* header is record 1 */
979         return(rc <= 1);
980 }
981
982 /******************** config "macros" *********************/
983
984 /* write an lcfg directly into a log (with markers) */
985 static int mgs_write_log_direct(struct obd_device *obd, struct fs_db *fsdb,
986                                 char *logname, struct lustre_cfg *lcfg,
987                                 char *devname, char *comment)
988 {
989         struct llog_handle *llh = NULL;
990         int rc;
991         ENTRY;
992
993         if (!lcfg)
994                 RETURN(-ENOMEM);
995
996         rc = record_start_log(obd, &llh, logname);
997         if (rc)
998                 RETURN(rc);
999
1000         /* FIXME These should be a single journal transaction */
1001         rc = record_marker(obd, llh, fsdb, CM_START, devname, comment);
1002
1003         rc = record_lcfg(obd, llh, lcfg);
1004
1005         rc = record_marker(obd, llh, fsdb, CM_END, devname, comment);
1006         rc = record_end_log(obd, &llh);
1007
1008         RETURN(rc);
1009 }
1010
1011 /* write the lcfg in all logs for the given fs */
1012 int mgs_write_log_direct_all(struct obd_device *obd, struct fs_db *fsdb,
1013                              struct mgs_target_info *mti,
1014                              struct lustre_cfg *lcfg,
1015                              char *devname, char *comment)
1016 {
1017         struct mgs_obd *mgs = &obd->u.mgs;
1018         cfs_list_t dentry_list;
1019         struct l_linux_dirent *dirent, *n;
1020         char *fsname = mti->mti_fsname;
1021         char *logname;
1022         int rc = 0, len = strlen(fsname);
1023         ENTRY;
1024
1025         /* We need to set params for any future logs
1026            as well. FIXME Append this file to every new log.
1027            Actually, we should store as params (text), not llogs.  Or
1028            in a database. */
1029         name_create(&logname, fsname, "-params");
1030         if (mgs_log_is_empty(obd, logname)) {
1031                 struct llog_handle *llh = NULL;
1032                 rc = record_start_log(obd, &llh, logname);
1033                 record_end_log(obd, &llh);
1034         }
1035         name_destroy(&logname);
1036         if (rc)
1037                 RETURN(rc);
1038
1039         /* Find all the logs in the CONFIGS directory */
1040         rc = class_dentry_readdir(obd, mgs->mgs_configs_dir,
1041                                   mgs->mgs_vfsmnt, &dentry_list);
1042         if (rc) {
1043                 CERROR("Can't read %s dir\n", MOUNT_CONFIGS_DIR);
1044                 RETURN(rc);
1045         }
1046
1047         /* Could use fsdb index maps instead of directory listing */
1048         cfs_list_for_each_entry_safe(dirent, n, &dentry_list, lld_list) {
1049                 cfs_list_del(&dirent->lld_list);
1050                 /* don't write to sptlrpc rule log */
1051                 if (strncmp(fsname, dirent->lld_name, len) == 0 &&
1052                     strstr(dirent->lld_name, "-sptlrpc") == NULL) {
1053                         CDEBUG(D_MGS, "Changing log %s\n", dirent->lld_name);
1054                         /* Erase any old settings of this same parameter */
1055                         mgs_modify(obd, fsdb, mti, dirent->lld_name, devname,
1056                                    comment, CM_SKIP);
1057                         /* Write the new one */
1058                         if (lcfg) {
1059                                 rc = mgs_write_log_direct(obd, fsdb,
1060                                                           dirent->lld_name,
1061                                                           lcfg, devname,
1062                                                           comment);
1063                                 if (rc)
1064                                         CERROR("err %d writing log %s\n", rc,
1065                                                dirent->lld_name);
1066                         }
1067                 }
1068                 OBD_FREE(dirent, sizeof(*dirent));
1069         }
1070
1071         RETURN(rc);
1072 }
1073
1074 struct temp_comp
1075 {
1076         struct mgs_target_info   *comp_tmti;
1077         struct mgs_target_info   *comp_mti;
1078         struct fs_db             *comp_fsdb;
1079         struct obd_device        *comp_obd;
1080 };
1081
1082 static int mgs_write_log_mdc_to_mdt(struct obd_device *, struct fs_db *,
1083                                     struct mgs_target_info *, char *);
1084 static int mgs_write_log_osc_to_lov(struct obd_device *obd, struct fs_db *fsdb,
1085                                     struct mgs_target_info *mti,
1086                                     char *logname, char *suffix, char *lovname,
1087                                     enum lustre_sec_part sec_part, int flags);
1088 static void name_create_mdt_and_lov(char **logname, char **lovname,
1089                                     struct fs_db *fsdb, int i);
1090
1091 static int mgs_steal_llog_handler(struct llog_handle *llh,
1092                                   struct llog_rec_hdr *rec,
1093                                   void *data)
1094 {
1095         struct obd_device * obd;
1096         struct mgs_target_info *mti, *tmti;
1097         struct fs_db *fsdb;
1098         int cfg_len = rec->lrh_len;
1099         char *cfg_buf = (char*) (rec + 1);
1100         struct lustre_cfg *lcfg;
1101         int rc = 0;
1102         struct llog_handle *mdt_llh = NULL;
1103         static int got_an_osc_or_mdc = 0;
1104         /* 0: not found any osc/mdc;
1105            1: found osc;
1106            2: found mdc;
1107         */
1108         static int last_step = -1;
1109
1110         ENTRY;
1111
1112         mti = ((struct temp_comp*)data)->comp_mti;
1113         tmti = ((struct temp_comp*)data)->comp_tmti;
1114         fsdb = ((struct temp_comp*)data)->comp_fsdb;
1115         obd = ((struct temp_comp*)data)->comp_obd;
1116
1117         if (rec->lrh_type != OBD_CFG_REC) {
1118                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
1119                 RETURN(-EINVAL);
1120         }
1121
1122         rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
1123         if (rc) {
1124                 CERROR("Insane cfg\n");
1125                 RETURN(rc);
1126         }
1127
1128         lcfg = (struct lustre_cfg *)cfg_buf;
1129
1130         if (lcfg->lcfg_command == LCFG_MARKER) {
1131                 struct cfg_marker *marker;
1132                 marker = lustre_cfg_buf(lcfg, 1);
1133                 if (!strncmp(marker->cm_comment,"add osc",7) &&
1134                     (marker->cm_flags & CM_START)){
1135                         got_an_osc_or_mdc = 1;
1136                         strncpy(tmti->mti_svname, marker->cm_tgtname,
1137                                 sizeof(tmti->mti_svname));
1138                         rc = record_start_log(obd, &mdt_llh, mti->mti_svname);
1139                         rc = record_marker(obd, mdt_llh, fsdb, CM_START,
1140                                            mti->mti_svname,"add osc(copied)");
1141                         rc = record_end_log(obd, &mdt_llh);
1142                         last_step = marker->cm_step;
1143                         RETURN(rc);
1144                 }
1145                 if (!strncmp(marker->cm_comment,"add osc",7) &&
1146                     (marker->cm_flags & CM_END)){
1147                         LASSERT(last_step == marker->cm_step);
1148                         last_step = -1;
1149                         got_an_osc_or_mdc = 0;
1150                         rc = record_start_log(obd, &mdt_llh, mti->mti_svname);
1151                         rc = record_marker(obd, mdt_llh, fsdb, CM_END,
1152                                            mti->mti_svname,"add osc(copied)");
1153                         rc = record_end_log(obd, &mdt_llh);
1154                         RETURN(rc);
1155                 }
1156                 if (!strncmp(marker->cm_comment,"add mdc",7) &&
1157                     (marker->cm_flags & CM_START)){
1158                         got_an_osc_or_mdc = 2;
1159                         last_step = marker->cm_step;
1160                         memcpy(tmti->mti_svname, marker->cm_tgtname,
1161                                strlen(marker->cm_tgtname));
1162
1163                         RETURN(rc);
1164                 }
1165                 if (!strncmp(marker->cm_comment,"add mdc",7) &&
1166                     (marker->cm_flags & CM_END)){
1167                         LASSERT(last_step == marker->cm_step);
1168                         last_step = -1;
1169                         got_an_osc_or_mdc = 0;
1170                         RETURN(rc);
1171                 }
1172         }
1173
1174         if (got_an_osc_or_mdc == 0 || last_step < 0)
1175                 RETURN(rc);
1176
1177         if (lcfg->lcfg_command == LCFG_ADD_UUID) {
1178                 uint64_t nodenid;
1179                 nodenid = lcfg->lcfg_nid;
1180
1181                 tmti->mti_nids[tmti->mti_nid_count] = nodenid;
1182                 tmti->mti_nid_count++;
1183
1184                 RETURN(rc);
1185         }
1186
1187         if (lcfg->lcfg_command == LCFG_SETUP) {
1188                 char *target;
1189
1190                 target = lustre_cfg_string(lcfg, 1);
1191                 memcpy(tmti->mti_uuid, target, strlen(target));
1192                 RETURN(rc);
1193         }
1194
1195         /* ignore client side sptlrpc_conf_log */
1196         if (lcfg->lcfg_command == LCFG_SPTLRPC_CONF)
1197                 RETURN(rc);
1198
1199         if (lcfg->lcfg_command == LCFG_ADD_MDC) {
1200                 int index;
1201
1202                 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1)
1203                         RETURN (-EINVAL);
1204
1205                 memcpy(tmti->mti_fsname, mti->mti_fsname,
1206                        strlen(mti->mti_fsname));
1207                 tmti->mti_stripe_index = index;
1208
1209                 mgs_write_log_mdc_to_mdt(obd, fsdb, tmti, mti->mti_svname);
1210                 memset(tmti, 0, sizeof(*tmti));
1211                 RETURN(rc);
1212         }
1213
1214         if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD) {
1215                 int index;
1216                 char mdt_index[9];
1217                 char *logname, *lovname;
1218
1219                 name_create_mdt_and_lov(&logname, &lovname, fsdb,
1220                                         mti->mti_stripe_index);
1221                 sprintf(mdt_index, "-MDT%04x", mti->mti_stripe_index);
1222
1223                 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1) {
1224                         name_destroy(&logname);
1225                         name_destroy(&lovname);
1226                         RETURN(-EINVAL);
1227                 }
1228
1229                 tmti->mti_stripe_index = index;
1230                 mgs_write_log_osc_to_lov(obd, fsdb, tmti, logname,
1231                                          mdt_index, lovname,
1232                                          LUSTRE_SP_MDT, 0);
1233                 name_destroy(&logname);
1234                 name_destroy(&lovname);
1235                 RETURN(rc);
1236         }
1237         RETURN(rc);
1238 }
1239
1240 /* fsdb->fsdb_mutex is already held  in mgs_write_log_target*/
1241 /* stealed from mgs_get_fsdb_from_llog*/
1242 static int mgs_steal_llog_for_mdt_from_client(struct obd_device *obd,
1243                                               char *client_name,
1244                                               struct temp_comp* comp)
1245 {
1246         struct llog_handle *loghandle;
1247         struct lvfs_run_ctxt saved;
1248         struct mgs_target_info *tmti;
1249         struct llog_ctxt *ctxt;
1250         int rc, rc2;
1251         ENTRY;
1252
1253         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
1254         LASSERT(ctxt != NULL);
1255
1256         OBD_ALLOC_PTR(tmti);
1257         if (tmti == NULL)
1258                 RETURN(-ENOMEM);
1259
1260         comp->comp_tmti = tmti;
1261         comp->comp_obd = obd;
1262
1263         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
1264
1265         rc = llog_create(ctxt, &loghandle, NULL, client_name);
1266         if (rc)
1267                 GOTO(out_pop, rc);
1268
1269         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
1270         if (rc)
1271                 GOTO(out_close, rc);
1272
1273         rc = llog_process(loghandle, mgs_steal_llog_handler, (void *)comp, NULL);
1274         CDEBUG(D_MGS, "steal llog re = %d\n", rc);
1275 out_close:
1276         rc2 = llog_close(loghandle);
1277         if (!rc)
1278                 rc = rc2;
1279 out_pop:
1280         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
1281         OBD_FREE_PTR(tmti);
1282         llog_ctxt_put(ctxt);
1283         RETURN(rc);
1284 }
1285
1286 /* lmv is the second thing for client logs */
1287 /* copied from mgs_write_log_lov. Please refer to that.  */
1288 static int mgs_write_log_lmv(struct obd_device *obd, struct fs_db *fsdb,
1289                              struct mgs_target_info *mti,
1290                              char *logname, char *lmvname)
1291 {
1292         struct llog_handle *llh = NULL;
1293         struct lmv_desc *lmvdesc;
1294         char *uuid;
1295         int rc = 0;
1296         ENTRY;
1297
1298         CDEBUG(D_MGS, "Writing lmv(%s) log for %s\n", lmvname,logname);
1299
1300         OBD_ALLOC_PTR(lmvdesc);
1301         if (lmvdesc == NULL)
1302                 RETURN(-ENOMEM);
1303         lmvdesc->ld_active_tgt_count = 0;
1304         lmvdesc->ld_tgt_count = 0;
1305         sprintf((char*)lmvdesc->ld_uuid.uuid, "%s_UUID", lmvname);
1306         uuid = (char *)lmvdesc->ld_uuid.uuid;
1307
1308         rc = record_start_log(obd, &llh, logname);
1309         rc = record_marker(obd, llh, fsdb, CM_START, lmvname, "lmv setup");
1310         rc = record_attach(obd, llh, lmvname, "lmv", uuid);
1311         rc = record_lmv_setup(obd, llh, lmvname, lmvdesc);
1312         rc = record_marker(obd, llh, fsdb, CM_END, lmvname, "lmv setup");
1313         rc = record_end_log(obd, &llh);
1314
1315         OBD_FREE_PTR(lmvdesc);
1316         RETURN(rc);
1317 }
1318
1319 /* lov is the first thing in the mdt and client logs */
1320 static int mgs_write_log_lov(struct obd_device *obd, struct fs_db *fsdb,
1321                              struct mgs_target_info *mti,
1322                              char *logname, char *lovname)
1323 {
1324         struct llog_handle *llh = NULL;
1325         struct lov_desc *lovdesc;
1326         char *uuid;
1327         int rc = 0;
1328         ENTRY;
1329
1330         CDEBUG(D_MGS, "Writing lov(%s) log for %s\n", lovname, logname);
1331
1332         /*
1333         #01 L attach   0:lov_mdsA  1:lov  2:71ccb_lov_mdsA_19f961a9e1
1334         #02 L lov_setup 0:lov_mdsA 1:(struct lov_desc)
1335               uuid=lov1_UUID, stripe count=1, size=1048576, offset=0, pattern=0
1336         */
1337
1338         /* FIXME just make lov_setup accept empty desc (put uuid in buf 2) */
1339         OBD_ALLOC_PTR(lovdesc);
1340         if (lovdesc == NULL)
1341                 RETURN(-ENOMEM);
1342         lovdesc->ld_magic = LOV_DESC_MAGIC;
1343         lovdesc->ld_tgt_count = 0;
1344         /* Defaults.  Can be changed later by lcfg config_param */
1345         lovdesc->ld_default_stripe_count = 1;
1346         lovdesc->ld_pattern = LOV_PATTERN_RAID0;
1347         lovdesc->ld_default_stripe_size = 1024 * 1024;
1348         lovdesc->ld_default_stripe_offset = -1;
1349         lovdesc->ld_qos_maxage = QOS_DEFAULT_MAXAGE;
1350         sprintf((char*)lovdesc->ld_uuid.uuid, "%s_UUID", lovname);
1351         /* can these be the same? */
1352         uuid = (char *)lovdesc->ld_uuid.uuid;
1353
1354         /* This should always be the first entry in a log.
1355         rc = mgs_clear_log(obd, logname); */
1356         rc = record_start_log(obd, &llh, logname);
1357         if (rc)
1358                 GOTO(out, rc);
1359         /* FIXME these should be a single journal transaction */
1360         rc = record_marker(obd, llh, fsdb, CM_START, lovname, "lov setup");
1361         rc = record_attach(obd, llh, lovname, "lov", uuid);
1362         rc = record_lov_setup(obd, llh, lovname, lovdesc);
1363         rc = record_marker(obd, llh, fsdb, CM_END, lovname, "lov setup");
1364         rc = record_end_log(obd, &llh);
1365
1366         EXIT;
1367 out:
1368         OBD_FREE_PTR(lovdesc);
1369         return rc;
1370 }
1371
1372 /* add failnids to open log */
1373 static int mgs_write_log_failnids(struct obd_device *obd,
1374                                   struct mgs_target_info *mti,
1375                                   struct llog_handle *llh,
1376                                   char *cliname)
1377 {
1378         char *failnodeuuid = NULL;
1379         char *ptr = mti->mti_params;
1380         lnet_nid_t nid;
1381         int rc = 0;
1382
1383         /*
1384         #03 L add_uuid  nid=uml1@tcp(0x20000c0a80201) nal=90 0:  1:uml1_UUID
1385         #04 L add_uuid  nid=1@elan(0x1000000000001)   nal=90 0:  1:uml1_UUID
1386         #05 L setup    0:OSC_uml1_ost1_mdsA  1:ost1_UUID  2:uml1_UUID
1387         #06 L add_uuid  nid=uml2@tcp(0x20000c0a80202) nal=90 0:  1:uml2_UUID
1388         #0x L add_uuid  nid=2@elan(0x1000000000002)   nal=90 0:  1:uml2_UUID
1389         #07 L add_conn 0:OSC_uml1_ost1_mdsA  1:uml2_UUID
1390         */
1391
1392         /* Pull failnid info out of params string */
1393         while (class_find_param(ptr, PARAM_FAILNODE, &ptr) == 0) {
1394                 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
1395                         if (failnodeuuid == NULL) {
1396                                 /* We don't know the failover node name,
1397                                    so just use the first nid as the uuid */
1398                                 rc = name_create(&failnodeuuid,
1399                                                  libcfs_nid2str(nid), "");
1400                                 if (rc)
1401                                         return rc;
1402                         }
1403                         CDEBUG(D_MGS, "add nid %s for failover uuid %s, "
1404                                "client %s\n", libcfs_nid2str(nid),
1405                                failnodeuuid, cliname);
1406                         rc = record_add_uuid(obd, llh, nid, failnodeuuid);
1407                 }
1408                 if (failnodeuuid) {
1409                         rc = record_add_conn(obd, llh, cliname, failnodeuuid);
1410                         name_destroy(&failnodeuuid);
1411                         failnodeuuid = NULL;
1412                 }
1413         }
1414
1415         return rc;
1416 }
1417
1418 static int mgs_write_log_mdc_to_lmv(struct obd_device *obd, struct fs_db *fsdb,
1419                                     struct mgs_target_info *mti,
1420                                     char *logname, char *lmvname)
1421 {
1422         struct llog_handle *llh = NULL;
1423         char *mdcname, *nodeuuid, *mdcuuid, *lmvuuid;
1424         char index[6];
1425         int i, rc;
1426         ENTRY;
1427
1428         if (mgs_log_is_empty(obd, logname)) {
1429                 CERROR("log is empty! Logical error\n");
1430                 RETURN(-EINVAL);
1431         }
1432
1433         CDEBUG(D_MGS, "adding mdc for %s to log %s:lmv(%s)\n",
1434                mti->mti_svname, logname, lmvname);
1435
1436         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
1437         name_create(&mdcname, mti->mti_svname, "-mdc");
1438         name_create(&mdcuuid, mdcname, "_UUID");
1439         name_create(&lmvuuid, lmvname, "_UUID");
1440
1441         rc = record_start_log(obd, &llh, logname);
1442         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,
1443                            "add mdc");
1444
1445         for (i = 0; i < mti->mti_nid_count; i++) {
1446                 CDEBUG(D_MGS, "add nid %s for mdt\n",
1447                        libcfs_nid2str(mti->mti_nids[i]));
1448
1449                 rc = record_add_uuid(obd, llh, mti->mti_nids[i], nodeuuid);
1450         }
1451
1452         rc = record_attach(obd, llh, mdcname, LUSTRE_MDC_NAME, lmvuuid);
1453         rc = record_setup(obd, llh, mdcname, mti->mti_uuid, nodeuuid, 0, 0);
1454         rc = mgs_write_log_failnids(obd, mti, llh, mdcname);
1455         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
1456         rc = record_mdc_add(obd, llh, lmvname, mdcuuid, mti->mti_uuid,
1457                             index, "1");
1458         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname,
1459                            "add mdc");
1460         rc = record_end_log(obd, &llh);
1461
1462         name_destroy(&lmvuuid);
1463         name_destroy(&mdcuuid);
1464         name_destroy(&mdcname);
1465         name_destroy(&nodeuuid);
1466         RETURN(rc);
1467 }
1468
1469 /* add new mdc to already existent MDS */
1470 static int mgs_write_log_mdc_to_mdt(struct obd_device *obd, struct fs_db *fsdb,
1471                                     struct mgs_target_info *mti, char *logname)
1472 {
1473         struct llog_handle *llh = NULL;
1474         char *nodeuuid, *mdcname, *mdcuuid, *mdtuuid;
1475         int idx = mti->mti_stripe_index;
1476         char index[9];
1477         int i, rc;
1478
1479         ENTRY;
1480         if (mgs_log_is_empty(obd, logname)) {
1481                 CERROR("log is empty! Logical error\n");
1482                 RETURN (-EINVAL);
1483         }
1484
1485         CDEBUG(D_MGS, "adding mdc index %d to %s\n", idx, logname);
1486
1487         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
1488         snprintf(index, sizeof(index), "-mdc%04x", idx);
1489         name_create(&mdcname, logname, index);
1490         name_create(&mdcuuid, mdcname, "_UUID");
1491         name_create(&mdtuuid, logname, "_UUID");
1492
1493         rc = record_start_log(obd, &llh, logname);
1494         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname, "add mdc");
1495         for (i = 0; i < mti->mti_nid_count; i++) {
1496                 CDEBUG(D_MGS, "add nid %s for mdt\n",
1497                        libcfs_nid2str(mti->mti_nids[i]));
1498                 rc = record_add_uuid(obd, llh, mti->mti_nids[i], nodeuuid);
1499         }
1500         rc = record_attach(obd, llh, mdcname, LUSTRE_MDC_NAME, mdcuuid);
1501         rc = record_setup(obd, llh, mdcname, mti->mti_uuid, nodeuuid, 0, 0);
1502         rc = mgs_write_log_failnids(obd, mti, llh, mdcname);
1503         snprintf(index, sizeof(index), "%d", idx);
1504
1505         rc = record_mdc_add(obd, llh, logname, mdcuuid, mti->mti_uuid,
1506                             index, "1");
1507         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname, "add mdc");
1508         rc = record_end_log(obd, &llh);
1509
1510         name_destroy(&mdcuuid);
1511         name_destroy(&mdcname);
1512         name_destroy(&nodeuuid);
1513         name_destroy(&mdtuuid);
1514         RETURN(rc);
1515 }
1516
1517 static int mgs_write_log_mdt0(struct obd_device *obd, struct fs_db *fsdb,
1518                               struct mgs_target_info *mti)
1519 {
1520         char *log = mti->mti_svname;
1521         struct llog_handle *llh = NULL;
1522         char *uuid, *lovname;
1523         char mdt_index[6];
1524         char *ptr = mti->mti_params;
1525         int rc = 0, failout = 0;
1526         ENTRY;
1527
1528         OBD_ALLOC(uuid, sizeof(struct obd_uuid));
1529         if (uuid == NULL)
1530                 RETURN(-ENOMEM);
1531
1532         if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
1533                 failout = (strncmp(ptr, "failout", 7) == 0);
1534
1535         name_create(&lovname, log, "-mdtlov");
1536         if (mgs_log_is_empty(obd, log))
1537                 rc = mgs_write_log_lov(obd, fsdb, mti, log, lovname);
1538
1539         sprintf(uuid, "%s_UUID", log);
1540         sprintf(mdt_index, "%d", mti->mti_stripe_index);
1541
1542         /* add MDT itself */
1543         rc = record_start_log(obd, &llh, log);
1544         if (rc)
1545                 GOTO(out, rc);
1546
1547         /* FIXME this whole fn should be a single journal transaction */
1548         rc = record_marker(obd, llh, fsdb, CM_START, log, "add mdt");
1549         rc = record_attach(obd, llh, log, LUSTRE_MDT_NAME, uuid);
1550         rc = record_mount_opt(obd, llh, log, lovname, NULL);
1551         rc = record_setup(obd, llh, log, uuid, mdt_index, lovname,
1552                         failout ? "n" : "f");
1553         rc = record_marker(obd, llh, fsdb, CM_END, log, "add mdt");
1554         rc = record_end_log(obd, &llh);
1555 out:
1556         name_destroy(&lovname);
1557         OBD_FREE(uuid, sizeof(struct obd_uuid));
1558         RETURN(rc);
1559 }
1560
1561 static inline void name_create_mdt(char **logname, char *fsname, int i)
1562 {
1563         char mdt_index[9];
1564
1565         sprintf(mdt_index, "-MDT%04x", i);
1566         name_create(logname, fsname, mdt_index);
1567 }
1568
1569 static void name_create_mdt_and_lov(char **logname, char **lovname,
1570                                     struct fs_db *fsdb, int i)
1571 {
1572         name_create_mdt(logname, fsdb->fsdb_name, i);
1573         /* COMPAT_180 */
1574         if (i == 0 && cfs_test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
1575                 name_create(lovname, fsdb->fsdb_name, "-mdtlov");
1576         else
1577                 name_create(lovname, *logname, "-mdtlov");
1578 }
1579
1580 static inline void name_create_mdt_osc(char **oscname, char *ostname,
1581                                        struct fs_db *fsdb, int i)
1582 {
1583         char suffix[16];
1584
1585         if (i == 0 && cfs_test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
1586                 sprintf(suffix, "-osc");
1587         else
1588                 sprintf(suffix, "-osc-MDT%04x", i);
1589         name_create(oscname, ostname, suffix);
1590 }
1591
1592 /* envelope method for all layers log */
1593 static int mgs_write_log_mdt(struct obd_device *obd, struct fs_db *fsdb,
1594                               struct mgs_target_info *mti)
1595 {
1596         struct llog_handle *llh = NULL;
1597         char *cliname;
1598         struct temp_comp comp = { 0 };
1599         int rc, i = 0;
1600         ENTRY;
1601
1602         CDEBUG(D_MGS, "writing new mdt %s\n", mti->mti_svname);
1603
1604 #if 0
1605         /* COMPAT_146 */
1606         if (mti->mti_flags & LDD_F_UPGRADE14) {
1607                 /* We're starting with an old uuid.  Assume old name for lov
1608                    as well since the lov entry already exists in the log. */
1609                 CDEBUG(D_MGS, "old mds uuid %s\n", mti->mti_uuid);
1610                 if (strncmp(mti->mti_uuid, fsdb->fsdb_mdtlov + 4,
1611                             strlen(fsdb->fsdb_mdtlov) - 4) != 0) {
1612                         CERROR("old mds uuid %s doesn't match log %s (%s)\n",
1613                                mti->mti_uuid, fsdb->fsdb_mdtlov,
1614                                fsdb->fsdb_mdtlov + 4);
1615                         RETURN(-EINVAL);
1616                 }
1617         }
1618         /* end COMPAT_146 */
1619 #endif
1620         if (mti->mti_uuid[0] == '\0') {
1621                 /* Make up our own uuid */
1622                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
1623                          "%s_UUID", mti->mti_svname);
1624         }
1625
1626         /* add mdt */
1627         rc = mgs_write_log_mdt0(obd, fsdb, mti);
1628
1629         /* Append the mdt info to the client log */
1630         name_create(&cliname, mti->mti_fsname, "-client");
1631
1632         if (mgs_log_is_empty(obd, cliname)) {
1633                 /* Start client log */
1634                 rc = mgs_write_log_lov(obd, fsdb, mti, cliname,
1635                                        fsdb->fsdb_clilov);
1636                 rc = mgs_write_log_lmv(obd, fsdb, mti, cliname,
1637                                        fsdb->fsdb_clilmv);
1638         }
1639
1640         /*
1641         #09 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
1642         #10 L attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f
1643         #11 L setup    0:MDC_uml1_mdsA_MNT_client  1:mdsA_UUID  2:uml1_UUID
1644         #12 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
1645         #13 L add_conn 0:MDC_uml1_mdsA_MNT_client  1:uml2_UUID
1646         #14 L mount_option 0:  1:client  2:lov1  3:MDC_uml1_mdsA_MNT_client
1647         */
1648
1649 #if 0
1650         /* COMPAT_146 */
1651         if (mti->mti_flags & LDD_F_UPGRADE14) {
1652                 rc = record_start_log(obd, &llh, cliname);
1653                 if (rc)
1654                         GOTO(out, rc);
1655
1656                 rc = record_marker(obd, llh, fsdb, CM_START,
1657                                    mti->mti_svname,"add mdc");
1658
1659                 /* Old client log already has MDC entry, but needs mount opt
1660                    for new client name (lustre-client) */
1661                 /* FIXME Old MDT log already has an old mount opt
1662                    which we should remove (currently handled by
1663                    class_del_profiles()) */
1664                 rc = record_mount_opt(obd, llh, cliname, fsdb->fsdb_clilov,
1665                                       fsdb->fsdb_mdc);
1666                 /* end COMPAT_146 */
1667
1668                 rc = record_marker(obd, llh, fsdb, CM_END,
1669                                    mti->mti_svname, "add mdc");
1670         } else
1671 #endif
1672         {
1673                 /* copy client info about lov/lmv */
1674                 comp.comp_mti = mti;
1675                 comp.comp_fsdb = fsdb;
1676
1677                 rc = mgs_steal_llog_for_mdt_from_client(obd, cliname,
1678                                                         &comp);
1679
1680                 rc = mgs_write_log_mdc_to_lmv(obd, fsdb, mti, cliname,
1681                                               fsdb->fsdb_clilmv);
1682                 /* add mountopts */
1683                 rc = record_start_log(obd, &llh, cliname);
1684                 if (rc)
1685                         GOTO(out, rc);
1686
1687                 rc = record_marker(obd, llh, fsdb, CM_START, cliname,
1688                                    "mount opts");
1689                 rc = record_mount_opt(obd, llh, cliname, fsdb->fsdb_clilov,
1690                                       fsdb->fsdb_clilmv);
1691                 rc = record_marker(obd, llh, fsdb, CM_END, cliname,
1692                                    "mount opts");
1693         }
1694
1695         rc = record_end_log(obd, &llh);
1696 out:
1697         name_destroy(&cliname);
1698
1699         // for_all_existing_mdt except current one
1700         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
1701                 char *mdtname;
1702                 if (i !=  mti->mti_stripe_index &&
1703                     cfs_test_bit(i,  fsdb->fsdb_mdt_index_map)) {
1704                         name_create_mdt(&mdtname, mti->mti_fsname, i);
1705                         rc = mgs_write_log_mdc_to_mdt(obd, fsdb, mti, mdtname);
1706                         name_destroy(&mdtname);
1707                 }
1708         }
1709
1710         RETURN(rc);
1711 }
1712
1713 /* Add the ost info to the client/mdt lov */
1714 static int mgs_write_log_osc_to_lov(struct obd_device *obd, struct fs_db *fsdb,
1715                                     struct mgs_target_info *mti,
1716                                     char *logname, char *suffix, char *lovname,
1717                                     enum lustre_sec_part sec_part, int flags)
1718 {
1719         struct llog_handle *llh = NULL;
1720         char *nodeuuid, *oscname, *oscuuid, *lovuuid, *svname;
1721         char index[6];
1722         int i, rc;
1723
1724         ENTRY;
1725         CDEBUG(D_INFO, "adding osc for %s to log %s\n",
1726                mti->mti_svname, logname);
1727
1728         if (mgs_log_is_empty(obd, logname)) {
1729                 CERROR("log is empty! Logical error\n");
1730                 RETURN (-EINVAL);
1731         }
1732
1733         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
1734         name_create(&svname, mti->mti_svname, "-osc");
1735         name_create(&oscname, svname, suffix);
1736         name_create(&oscuuid, oscname, "_UUID");
1737         name_create(&lovuuid, lovname, "_UUID");
1738
1739         /*
1740         #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
1741         multihomed (#4)
1742         #04 L add_uuid  nid=1@elan(0x1000000000001)  nal=90 0:  1:uml1_UUID
1743         #04 L attach   0:OSC_uml1_ost1_MNT_client  1:osc  2:89070_lov1_a41dff51a
1744         #05 L setup    0:OSC_uml1_ost1_MNT_client  1:ost1_UUID  2:uml1_UUID
1745         failover (#6,7)
1746         #06 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
1747         #07 L add_conn 0:OSC_uml1_ost1_MNT_client  1:uml2_UUID
1748         #08 L lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1
1749         */
1750
1751         rc = record_start_log(obd, &llh, logname);
1752         if (rc)
1753                 GOTO(out, rc);
1754         /* FIXME these should be a single journal transaction */
1755         rc = record_marker(obd, llh, fsdb, CM_START | flags, mti->mti_svname,
1756                            "add osc");
1757         for (i = 0; i < mti->mti_nid_count; i++) {
1758                 CDEBUG(D_MGS, "add nid %s\n", libcfs_nid2str(mti->mti_nids[i]));
1759                 rc = record_add_uuid(obd, llh, mti->mti_nids[i], nodeuuid);
1760         }
1761         rc = record_attach(obd, llh, oscname, LUSTRE_OSC_NAME, lovuuid);
1762         rc = record_setup(obd, llh, oscname, mti->mti_uuid, nodeuuid, 0, 0);
1763         rc = mgs_write_log_failnids(obd, mti, llh, oscname);
1764         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
1765         rc = record_lov_add(obd, llh, lovname, mti->mti_uuid, index, "1");
1766         rc = record_marker(obd, llh, fsdb, CM_END | flags, mti->mti_svname,
1767                            "add osc");
1768         rc = record_end_log(obd, &llh);
1769 out:
1770         name_destroy(&lovuuid);
1771         name_destroy(&oscuuid);
1772         name_destroy(&oscname);
1773         name_destroy(&svname);
1774         name_destroy(&nodeuuid);
1775         RETURN(rc);
1776 }
1777
1778 static int mgs_write_log_ost(struct obd_device *obd, struct fs_db *fsdb,
1779                              struct mgs_target_info *mti)
1780 {
1781         struct llog_handle *llh = NULL;
1782         char *logname, *lovname;
1783         char *ptr = mti->mti_params;
1784         int rc, flags = 0, failout = 0, i;
1785         ENTRY;
1786
1787         CDEBUG(D_MGS, "writing new ost %s\n", mti->mti_svname);
1788
1789         /* The ost startup log */
1790
1791         /* If the ost log already exists, that means that someone reformatted
1792            the ost and it called target_add again. */
1793         if (!mgs_log_is_empty(obd, mti->mti_svname)) {
1794                 LCONSOLE_ERROR_MSG(0x141, "The config log for %s already "
1795                                    "exists, yet the server claims it never "
1796                                    "registered. It may have been reformatted, "
1797                                    "or the index changed. writeconf the MDT to "
1798                                    "regenerate all logs.\n", mti->mti_svname);
1799                 RETURN(-EALREADY);
1800         }
1801
1802         /*
1803         attach obdfilter ost1 ost1_UUID
1804         setup /dev/loop2 ldiskfs f|n errors=remount-ro,user_xattr
1805         */
1806         if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
1807                 failout = (strncmp(ptr, "failout", 7) == 0);
1808         rc = record_start_log(obd, &llh, mti->mti_svname);
1809         if (rc)
1810                 RETURN(rc);
1811         /* FIXME these should be a single journal transaction */
1812         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,"add ost");
1813         if (*mti->mti_uuid == '\0')
1814                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
1815                          "%s_UUID", mti->mti_svname);
1816         rc = record_attach(obd, llh, mti->mti_svname,
1817                            "obdfilter"/*LUSTRE_OST_NAME*/, mti->mti_uuid);
1818         rc = record_setup(obd, llh, mti->mti_svname,
1819                           "dev"/*ignored*/, "type"/*ignored*/,
1820                           failout ? "n" : "f", 0/*options*/);
1821         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname, "add ost");
1822         rc = record_end_log(obd, &llh);
1823
1824         /* We also have to update the other logs where this osc is part of
1825            the lov */
1826
1827         if (cfs_test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
1828                 /* If we're upgrading, the old mdt log already has our
1829                    entry. Let's do a fake one for fun. */
1830                 /* Note that we can't add any new failnids, since we don't
1831                    know the old osc names. */
1832                 flags = CM_SKIP | CM_UPGRADE146;
1833
1834         } else if ((mti->mti_flags & LDD_F_UPDATE) != LDD_F_UPDATE) {
1835                 /* If the update flag isn't set, don't update client/mdt
1836                    logs. */
1837                 flags |= CM_SKIP;
1838                 LCONSOLE_WARN("Client log for %s was not updated; writeconf "
1839                               "the MDT first to regenerate it.\n",
1840                               mti->mti_svname);
1841         }
1842
1843         /* Add ost to all MDT lov defs */
1844         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
1845                 if (cfs_test_bit(i, fsdb->fsdb_mdt_index_map)) {
1846                         char mdt_index[9];
1847
1848                         name_create_mdt_and_lov(&logname, &lovname, fsdb, i);
1849                         sprintf(mdt_index, "-MDT%04x", i);
1850                         mgs_write_log_osc_to_lov(obd, fsdb, mti, logname,
1851                                                  mdt_index, lovname,
1852                                                  LUSTRE_SP_MDT, flags);
1853                         name_destroy(&logname);
1854                         name_destroy(&lovname);
1855                 }
1856         }
1857
1858         /* Append ost info to the client log */
1859         name_create(&logname, mti->mti_fsname, "-client");
1860         if (mgs_log_is_empty(obd, logname)) {
1861                 /* Start client log */
1862                 rc = mgs_write_log_lov(obd, fsdb, mti, logname,
1863                                        fsdb->fsdb_clilov);
1864                 rc = mgs_write_log_lmv(obd, fsdb, mti, logname,
1865                                        fsdb->fsdb_clilmv);
1866         }
1867         mgs_write_log_osc_to_lov(obd, fsdb, mti, logname, "",
1868                                  fsdb->fsdb_clilov, LUSTRE_SP_CLI, flags);
1869         name_destroy(&logname);
1870         RETURN(rc);
1871 }
1872
1873 static __inline__ int mgs_param_empty(char *ptr)
1874 {
1875         char *tmp;
1876
1877         if ((tmp = strchr(ptr, '=')) && (*(++tmp) == '\0'))
1878                 return 1;
1879         return 0;
1880 }
1881
1882 static int mgs_write_log_failnid_internal(struct obd_device *obd,
1883                                           struct fs_db *fsdb,
1884                                           struct mgs_target_info *mti,
1885                                           char *logname, char *cliname)
1886 {
1887         int rc;
1888         struct llog_handle *llh = NULL;
1889
1890         if (mgs_param_empty(mti->mti_params)) {
1891                 /* Remove _all_ failnids */
1892                 rc = mgs_modify(obd, fsdb, mti, logname,
1893                                 mti->mti_svname, "add failnid", CM_SKIP);
1894                 return rc;
1895         }
1896
1897         /* Otherwise failover nids are additive */
1898         rc = record_start_log(obd, &llh, logname);
1899         if (!rc) {
1900                 /* FIXME this should be a single journal transaction */
1901                 rc = record_marker(obd, llh, fsdb, CM_START,
1902                                    mti->mti_svname, "add failnid");
1903                 rc = mgs_write_log_failnids(obd, mti, llh, cliname);
1904                 rc = record_marker(obd, llh, fsdb, CM_END,
1905                                    mti->mti_svname, "add failnid");
1906                 rc = record_end_log(obd, &llh);
1907         }
1908
1909         return rc;
1910 }
1911
1912
1913 /* Add additional failnids to an existing log.
1914    The mdc/osc must have been added to logs first */
1915 /* tcp nids must be in dotted-quad ascii -
1916    we can't resolve hostnames from the kernel. */
1917 static int mgs_write_log_add_failnid(struct obd_device *obd, struct fs_db *fsdb,
1918                                      struct mgs_target_info *mti)
1919 {
1920         char *logname, *cliname;
1921         int rc;
1922         ENTRY;
1923
1924         /* FIXME we currently can't erase the failnids
1925          * given when a target first registers, since they aren't part of
1926          * an "add uuid" stanza */
1927
1928         /* Verify that we know about this target */
1929         if (mgs_log_is_empty(obd, mti->mti_svname)) {
1930                 LCONSOLE_ERROR_MSG(0x142, "The target %s has not registered "
1931                                    "yet. It must be started before failnids "
1932                                    "can be added.\n", mti->mti_svname);
1933                 RETURN(-ENOENT);
1934         }
1935
1936         /* Create mdc/osc client name (e.g. lustre-OST0001-osc) */
1937         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
1938                 name_create(&cliname, mti->mti_svname, "-mdc");
1939         } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1940                 name_create(&cliname, mti->mti_svname, "-osc");
1941         } else {
1942                 RETURN(-EINVAL);
1943         }
1944
1945         /* Add failover nids to the client log */
1946         name_create(&logname, mti->mti_fsname, "-client");
1947         rc = mgs_write_log_failnid_internal(obd, fsdb, mti, logname, cliname);
1948         name_destroy(&logname);
1949         name_destroy(&cliname);
1950
1951         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1952                 /* Add OST failover nids to the MDT logs as well */
1953                 int i;
1954
1955                 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
1956                         if (!cfs_test_bit(i, fsdb->fsdb_mdt_index_map))
1957                                 continue;
1958                         name_create_mdt(&logname, mti->mti_fsname, i);
1959                         name_create_mdt_osc(&cliname, mti->mti_svname, fsdb, i);
1960                         rc = mgs_write_log_failnid_internal(obd, fsdb, mti,
1961                                                             logname, cliname);
1962                         name_destroy(&cliname);
1963                         name_destroy(&logname);
1964                 }
1965         }
1966
1967         RETURN(rc);
1968 }
1969
1970 static int mgs_wlp_lcfg(struct obd_device *obd, struct fs_db *fsdb,
1971                         struct mgs_target_info *mti,
1972                         char *logname, struct lustre_cfg_bufs *bufs,
1973                         char *tgtname, char *ptr)
1974 {
1975         char comment[MTI_NAME_MAXLEN];
1976         char *tmp;
1977         struct lustre_cfg *lcfg;
1978         int rc, del;
1979
1980         /* Erase any old settings of this same parameter */
1981         memcpy(comment, ptr, MTI_NAME_MAXLEN);
1982         comment[MTI_NAME_MAXLEN - 1] = 0;
1983         /* But don't try to match the value. */
1984         if ((tmp = strchr(comment, '=')))
1985             *tmp = 0;
1986         /* FIXME we should skip settings that are the same as old values */
1987         rc = mgs_modify(obd, fsdb, mti, logname, tgtname, comment, CM_SKIP);
1988         del = mgs_param_empty(ptr);
1989
1990         LCONSOLE_INFO("%sing parameter %s.%s in log %s\n", del ? "Disabl" : rc ?
1991                       "Sett" : "Modify", tgtname, comment, logname);
1992         if (del)
1993                 return rc;
1994
1995         lustre_cfg_bufs_reset(bufs, tgtname);
1996         lustre_cfg_bufs_set_string(bufs, 1, ptr);
1997         lcfg = lustre_cfg_new(LCFG_PARAM, bufs);
1998         if (!lcfg)
1999                 return -ENOMEM;
2000         rc = mgs_write_log_direct(obd, fsdb, logname, lcfg, tgtname, comment);
2001         lustre_cfg_free(lcfg);
2002         return rc;
2003 }
2004
2005 /* write global variable settings into log */
2006 static int mgs_write_log_sys(struct obd_device *obd, struct fs_db *fsdb,
2007                         struct mgs_target_info *mti, char *sys, char *ptr)
2008 {
2009         struct lustre_cfg_bufs bufs;
2010         struct lustre_cfg *lcfg;
2011         char *tmp, sep;
2012         int rc, cmd, convert = 1;
2013
2014         if (class_match_param(ptr, PARAM_TIMEOUT, &tmp) == 0) {
2015                 cmd = LCFG_SET_TIMEOUT;
2016         } else if (class_match_param(ptr, PARAM_LDLM_TIMEOUT, &tmp) == 0) {
2017                 cmd = LCFG_SET_LDLM_TIMEOUT;
2018         /* Check for known params here so we can return error to lctl */
2019         } else if ((class_match_param(ptr, PARAM_AT_MIN, &tmp) == 0) ||
2020                 (class_match_param(ptr, PARAM_AT_MAX, &tmp) == 0) ||
2021                 (class_match_param(ptr, PARAM_AT_EXTRA, &tmp) == 0) ||
2022                 (class_match_param(ptr, PARAM_AT_EARLY_MARGIN, &tmp) == 0) ||
2023                 (class_match_param(ptr, PARAM_AT_HISTORY, &tmp) == 0)) {
2024                 cmd = LCFG_PARAM;
2025         } else if (class_match_param(ptr, PARAM_JOBID_VAR, &tmp) == 0) {
2026                 convert = 0; /* Don't convert string value to integer */
2027                 cmd = LCFG_PARAM;
2028         } else {
2029                 return -EINVAL;
2030         }
2031
2032         if (mgs_param_empty(ptr))
2033                 CDEBUG(D_MGS, "global '%s' removed\n", sys);
2034         else
2035                 CDEBUG(D_MGS, "global '%s' val=%s\n", sys, tmp);
2036
2037         lustre_cfg_bufs_reset(&bufs, NULL);
2038         lustre_cfg_bufs_set_string(&bufs, 1, sys);
2039         if (!convert && *tmp != '\0')
2040                 lustre_cfg_bufs_set_string(&bufs, 2, tmp);
2041         lcfg = lustre_cfg_new(cmd, &bufs);
2042         lcfg->lcfg_num = convert ? simple_strtoul(tmp, NULL, 0) : 0;
2043         /* truncate the comment to the parameter name */
2044         ptr = tmp - 1;
2045         sep = *ptr;
2046         *ptr = '\0';
2047         /* modify all servers and clients */
2048         rc = mgs_write_log_direct_all(obd, fsdb, mti,
2049                                 *tmp == '\0' ? NULL : lcfg,
2050                                 mti->mti_fsname, sys);
2051         *ptr = sep;
2052         lustre_cfg_free(lcfg);
2053         return rc;
2054 }
2055
2056 static int mgs_srpc_set_param_disk(struct obd_device *obd,
2057                                    struct fs_db *fsdb,
2058                                    struct mgs_target_info *mti,
2059                                    char *param)
2060 {
2061         struct llog_handle     *llh = NULL;
2062         char                   *logname;
2063         char                   *comment, *ptr;
2064         struct lustre_cfg_bufs  bufs;
2065         struct lustre_cfg      *lcfg;
2066         int                     rc, len;
2067         ENTRY;
2068
2069         /* get comment */
2070         ptr = strchr(param, '=');
2071         LASSERT(ptr);
2072         len = ptr - param;
2073
2074         OBD_ALLOC(comment, len + 1);
2075         if (comment == NULL)
2076                 RETURN(-ENOMEM);
2077         strncpy(comment, param, len);
2078         comment[len] = '\0';
2079
2080         /* prepare lcfg */
2081         lustre_cfg_bufs_reset(&bufs, mti->mti_svname);
2082         lustre_cfg_bufs_set_string(&bufs, 1, param);
2083         lcfg = lustre_cfg_new(LCFG_SPTLRPC_CONF, &bufs);
2084         if (lcfg == NULL)
2085                 GOTO(out_comment, rc = -ENOMEM);
2086
2087         /* construct log name */
2088         rc = name_create(&logname, mti->mti_fsname, "-sptlrpc");
2089         if (rc)
2090                 GOTO(out_lcfg, rc);
2091
2092         if (mgs_log_is_empty(obd, logname)) {
2093                 rc = record_start_log(obd, &llh, logname);
2094                 record_end_log(obd, &llh);
2095                 if (rc)
2096                         GOTO(out, rc);
2097         }
2098
2099         /* obsolete old one */
2100         mgs_modify(obd, fsdb, mti, logname, mti->mti_svname, comment, CM_SKIP);
2101
2102         /* write the new one */
2103         rc = mgs_write_log_direct(obd, fsdb, logname, lcfg,
2104                                   mti->mti_svname, comment);
2105         if (rc)
2106                 CERROR("err %d writing log %s\n", rc, logname);
2107
2108 out:
2109         name_destroy(&logname);
2110 out_lcfg:
2111         lustre_cfg_free(lcfg);
2112 out_comment:
2113         OBD_FREE(comment, len + 1);
2114         RETURN(rc);
2115 }
2116
2117 static int mgs_srpc_set_param_udesc_mem(struct fs_db *fsdb,
2118                                         char *param)
2119 {
2120         char    *ptr;
2121
2122         /* disable the adjustable udesc parameter for now, i.e. use default
2123          * setting that client always ship udesc to MDT if possible. to enable
2124          * it simply remove the following line */
2125         goto error_out;
2126
2127         ptr = strchr(param, '=');
2128         if (ptr == NULL)
2129                 goto error_out;
2130         *ptr++ = '\0';
2131
2132         if (strcmp(param, PARAM_SRPC_UDESC))
2133                 goto error_out;
2134
2135         if (strcmp(ptr, "yes") == 0) {
2136                 cfs_set_bit(FSDB_UDESC, &fsdb->fsdb_flags);
2137                 CWARN("Enable user descriptor shipping from client to MDT\n");
2138         } else if (strcmp(ptr, "no") == 0) {
2139                 cfs_clear_bit(FSDB_UDESC, &fsdb->fsdb_flags);
2140                 CWARN("Disable user descriptor shipping from client to MDT\n");
2141         } else {
2142                 *(ptr - 1) = '=';
2143                 goto error_out;
2144         }
2145         return 0;
2146
2147 error_out:
2148         CERROR("Invalid param: %s\n", param);
2149         return -EINVAL;
2150 }
2151
2152 static int mgs_srpc_set_param_mem(struct fs_db *fsdb,
2153                                   const char *svname,
2154                                   char *param)
2155 {
2156         struct sptlrpc_rule      rule;
2157         struct sptlrpc_rule_set *rset;
2158         int                      rc;
2159         ENTRY;
2160
2161         if (strncmp(param, PARAM_SRPC, sizeof(PARAM_SRPC) - 1) != 0) {
2162                 CERROR("Invalid sptlrpc parameter: %s\n", param);
2163                 RETURN(-EINVAL);
2164         }
2165
2166         if (strncmp(param, PARAM_SRPC_UDESC,
2167                     sizeof(PARAM_SRPC_UDESC) - 1) == 0) {
2168                 RETURN(mgs_srpc_set_param_udesc_mem(fsdb, param));
2169         }
2170
2171         if (strncmp(param, PARAM_SRPC_FLVR, sizeof(PARAM_SRPC_FLVR) - 1) != 0) {
2172                 CERROR("Invalid sptlrpc flavor parameter: %s\n", param);
2173                 RETURN(-EINVAL);
2174         }
2175
2176         param += sizeof(PARAM_SRPC_FLVR) - 1;
2177
2178         rc = sptlrpc_parse_rule(param, &rule);
2179         if (rc)
2180                 RETURN(rc);
2181
2182         /* mgs rules implies must be mgc->mgs */
2183         if (cfs_test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
2184                 if ((rule.sr_from != LUSTRE_SP_MGC &&
2185                      rule.sr_from != LUSTRE_SP_ANY) ||
2186                     (rule.sr_to != LUSTRE_SP_MGS &&
2187                      rule.sr_to != LUSTRE_SP_ANY))
2188                         RETURN(-EINVAL);
2189         }
2190
2191         /* preapre room for this coming rule. svcname format should be:
2192          * - fsname: general rule
2193          * - fsname-tgtname: target-specific rule
2194          */
2195         if (strchr(svname, '-')) {
2196                 struct mgs_tgt_srpc_conf *tgtconf;
2197                 int                       found = 0;
2198
2199                 for (tgtconf = fsdb->fsdb_srpc_tgt; tgtconf != NULL;
2200                      tgtconf = tgtconf->mtsc_next) {
2201                         if (!strcmp(tgtconf->mtsc_tgt, svname)) {
2202                                 found = 1;
2203                                 break;
2204                         }
2205                 }
2206
2207                 if (!found) {
2208                         int name_len;
2209
2210                         OBD_ALLOC_PTR(tgtconf);
2211                         if (tgtconf == NULL)
2212                                 RETURN(-ENOMEM);
2213
2214                         name_len = strlen(svname);
2215
2216                         OBD_ALLOC(tgtconf->mtsc_tgt, name_len + 1);
2217                         if (tgtconf->mtsc_tgt == NULL) {
2218                                 OBD_FREE_PTR(tgtconf);
2219                                 RETURN(-ENOMEM);
2220                         }
2221                         memcpy(tgtconf->mtsc_tgt, svname, name_len);
2222
2223                         tgtconf->mtsc_next = fsdb->fsdb_srpc_tgt;
2224                         fsdb->fsdb_srpc_tgt = tgtconf;
2225                 }
2226
2227                 rset = &tgtconf->mtsc_rset;
2228         } else {
2229                 rset = &fsdb->fsdb_srpc_gen;
2230         }
2231
2232         rc = sptlrpc_rule_set_merge(rset, &rule);
2233
2234         RETURN(rc);
2235 }
2236
2237 static int mgs_srpc_set_param(struct obd_device *obd,
2238                               struct fs_db *fsdb,
2239                               struct mgs_target_info *mti,
2240                               char *param)
2241 {
2242         char                   *copy;
2243         int                     rc, copy_size;
2244         ENTRY;
2245
2246 #ifndef HAVE_GSS
2247         RETURN(-EINVAL);
2248 #endif
2249         /* keep a copy of original param, which could be destroied
2250          * during parsing */
2251         copy_size = strlen(param) + 1;
2252         OBD_ALLOC(copy, copy_size);
2253         if (copy == NULL)
2254                 return -ENOMEM;
2255         memcpy(copy, param, copy_size);
2256
2257         rc = mgs_srpc_set_param_mem(fsdb, mti->mti_svname, param);
2258         if (rc)
2259                 goto out_free;
2260
2261         /* previous steps guaranteed the syntax is correct */
2262         rc = mgs_srpc_set_param_disk(obd, fsdb, mti, copy);
2263         if (rc)
2264                 goto out_free;
2265
2266         if (cfs_test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
2267                 /*
2268                  * for mgs rules, make them effective immediately.
2269                  */
2270                 LASSERT(fsdb->fsdb_srpc_tgt == NULL);
2271                 sptlrpc_target_update_exp_flavor(obd, &fsdb->fsdb_srpc_gen);
2272         }
2273
2274 out_free:
2275         OBD_FREE(copy, copy_size);
2276         RETURN(rc);
2277 }
2278
2279 struct mgs_srpc_read_data {
2280         struct fs_db   *msrd_fsdb;
2281         int             msrd_skip;
2282 };
2283
2284 static int mgs_srpc_read_handler(struct llog_handle *llh,
2285                                  struct llog_rec_hdr *rec,
2286                                  void *data)
2287 {
2288         struct mgs_srpc_read_data *msrd = (struct mgs_srpc_read_data *) data;
2289         struct cfg_marker         *marker;
2290         struct lustre_cfg         *lcfg = (struct lustre_cfg *)(rec + 1);
2291         char                      *svname, *param;
2292         int                        cfg_len, rc;
2293         ENTRY;
2294
2295         if (rec->lrh_type != OBD_CFG_REC) {
2296                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
2297                 RETURN(-EINVAL);
2298         }
2299
2300         cfg_len = rec->lrh_len - sizeof(struct llog_rec_hdr) -
2301                   sizeof(struct llog_rec_tail);
2302
2303         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
2304         if (rc) {
2305                 CERROR("Insane cfg\n");
2306                 RETURN(rc);
2307         }
2308
2309         if (lcfg->lcfg_command == LCFG_MARKER) {
2310                 marker = lustre_cfg_buf(lcfg, 1);
2311
2312                 if (marker->cm_flags & CM_START &&
2313                     marker->cm_flags & CM_SKIP)
2314                         msrd->msrd_skip = 1;
2315                 if (marker->cm_flags & CM_END)
2316                         msrd->msrd_skip = 0;
2317
2318                 RETURN(0);
2319         }
2320
2321         if (msrd->msrd_skip)
2322                 RETURN(0);
2323
2324         if (lcfg->lcfg_command != LCFG_SPTLRPC_CONF) {
2325                 CERROR("invalid command (%x)\n", lcfg->lcfg_command);
2326                 RETURN(0);
2327         }
2328
2329         svname = lustre_cfg_string(lcfg, 0);
2330         if (svname == NULL) {
2331                 CERROR("svname is empty\n");
2332                 RETURN(0);
2333         }
2334
2335         param = lustre_cfg_string(lcfg, 1);
2336         if (param == NULL) {
2337                 CERROR("param is empty\n");
2338                 RETURN(0);
2339         }
2340
2341         rc = mgs_srpc_set_param_mem(msrd->msrd_fsdb, svname, param);
2342         if (rc)
2343                 CERROR("read sptlrpc record error (%d): %s\n", rc, param);
2344
2345         RETURN(0);
2346 }
2347
2348 int mgs_get_fsdb_srpc_from_llog(struct obd_device *obd,
2349                                 struct fs_db *fsdb)
2350 {
2351         struct llog_handle        *llh = NULL;
2352         struct lvfs_run_ctxt       saved;
2353         struct llog_ctxt          *ctxt;
2354         char                      *logname;
2355         struct mgs_srpc_read_data  msrd;
2356         int                        rc;
2357         ENTRY;
2358
2359         /* construct log name */
2360         rc = name_create(&logname, fsdb->fsdb_name, "-sptlrpc");
2361         if (rc)
2362                 RETURN(rc);
2363
2364         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
2365         LASSERT(ctxt != NULL);
2366
2367         if (mgs_log_is_empty(obd, logname))
2368                 GOTO(out, rc = 0);
2369
2370         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2371
2372         rc = llog_create(ctxt, &llh, NULL, logname);
2373         if (rc)
2374                 GOTO(out_pop, rc);
2375
2376         rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
2377         if (rc)
2378                 GOTO(out_close, rc);
2379
2380         if (llog_get_size(llh) <= 1)
2381                 GOTO(out_close, rc = 0);
2382
2383         msrd.msrd_fsdb = fsdb;
2384         msrd.msrd_skip = 0;
2385
2386         rc = llog_process(llh, mgs_srpc_read_handler, (void *) &msrd, NULL);
2387
2388 out_close:
2389         llog_close(llh);
2390 out_pop:
2391         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2392 out:
2393         llog_ctxt_put(ctxt);
2394         name_destroy(&logname);
2395
2396         if (rc)
2397                 CERROR("failed to read sptlrpc config database: %d\n", rc);
2398         RETURN(rc);
2399 }
2400
2401 /* Permanent settings of all parameters by writing into the appropriate
2402  * configuration logs.
2403  * A parameter with null value ("<param>='\0'") means to erase it out of
2404  * the logs.
2405  */
2406 static int mgs_write_log_param(struct obd_device *obd, struct fs_db *fsdb,
2407                                struct mgs_target_info *mti, char *ptr)
2408 {
2409         struct lustre_cfg_bufs bufs;
2410         char *logname;
2411         char *tmp;
2412         int rc = 0, rc2 = 0;
2413         ENTRY;
2414
2415         /* For various parameter settings, we have to figure out which logs
2416            care about them (e.g. both mdt and client for lov settings) */
2417         CDEBUG(D_MGS, "next param '%s'\n", ptr);
2418
2419         /* The params are stored in MOUNT_DATA_FILE and modified via
2420            tunefs.lustre, or set using lctl conf_param */
2421
2422         /* Processed in lustre_start_mgc */
2423         if (class_match_param(ptr, PARAM_MGSNODE, NULL) == 0)
2424                 GOTO(end, rc);
2425
2426         /* Processed in ost/mdt */
2427         if (class_match_param(ptr, PARAM_NETWORK, NULL) == 0)
2428                 GOTO(end, rc);
2429
2430         /* Processed in mgs_write_log_ost */
2431         if (class_match_param(ptr, PARAM_FAILMODE, NULL) == 0) {
2432                 if (mti->mti_flags & LDD_F_PARAM) {
2433                         LCONSOLE_ERROR_MSG(0x169, "%s can only be "
2434                                            "changed with tunefs.lustre"
2435                                            "and --writeconf\n", ptr);
2436                         rc = -EPERM;
2437                 }
2438                 GOTO(end, rc);
2439         }
2440
2441         if (class_match_param(ptr, PARAM_SRPC, NULL) == 0) {
2442                 rc = mgs_srpc_set_param(obd, fsdb, mti, ptr);
2443                 GOTO(end, rc);
2444         }
2445
2446         if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
2447                 /* Add a failover nidlist */
2448                 rc = 0;
2449                 /* We already processed failovers params for new
2450                    targets in mgs_write_log_target */
2451                 if (mti->mti_flags & LDD_F_PARAM) {
2452                         CDEBUG(D_MGS, "Adding failnode\n");
2453                         rc = mgs_write_log_add_failnid(obd, fsdb, mti);
2454                 }
2455                 GOTO(end, rc);
2456         }
2457
2458         if (class_match_param(ptr, PARAM_SYS, &tmp) == 0) {
2459                 rc = mgs_write_log_sys(obd, fsdb, mti, ptr, tmp);
2460                 GOTO(end, rc);
2461         }
2462
2463         if (class_match_param(ptr, PARAM_OSC""PARAM_ACTIVE, &tmp) == 0) {
2464                 /* active=0 means off, anything else means on */
2465                 int flag = (*tmp == '0') ? CM_EXCLUDE : 0;
2466                 int i;
2467
2468                 if (!(mti->mti_flags & LDD_F_SV_TYPE_OST)) {
2469                         LCONSOLE_ERROR_MSG(0x144, "%s: Only OSCs can "
2470                                            "be (de)activated.\n",
2471                                            mti->mti_svname);
2472                         GOTO(end, rc = -EINVAL);
2473                 }
2474                 LCONSOLE_WARN("Permanently %sactivating %s\n",
2475                               flag ? "de": "re", mti->mti_svname);
2476                 /* Modify clilov */
2477                 name_create(&logname, mti->mti_fsname, "-client");
2478                 rc = mgs_modify(obd, fsdb, mti, logname,
2479                                 mti->mti_svname, "add osc", flag);
2480                 name_destroy(&logname);
2481                 if (rc)
2482                         goto active_err;
2483                 /* Modify mdtlov */
2484                 /* Add to all MDT logs for CMD */
2485                 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
2486                         if (!cfs_test_bit(i, fsdb->fsdb_mdt_index_map))
2487                                 continue;
2488                         name_create_mdt(&logname, mti->mti_fsname, i);
2489                         rc = mgs_modify(obd, fsdb, mti, logname,
2490                                         mti->mti_svname, "add osc", flag);
2491                         name_destroy(&logname);
2492                         if (rc)
2493                                 goto active_err;
2494                 }
2495         active_err:
2496                 if (rc) {
2497                         LCONSOLE_ERROR_MSG(0x145, "Couldn't find %s in"
2498                                            "log (%d). No permanent "
2499                                            "changes were made to the "
2500                                            "config log.\n",
2501                                            mti->mti_svname, rc);
2502                         if (cfs_test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags))
2503                                 LCONSOLE_ERROR_MSG(0x146, "This may be"
2504                                                    " because the log"
2505                                                    "is in the old 1.4"
2506                                                    "style. Consider "
2507                                                    " --writeconf to "
2508                                                    "update the logs.\n");
2509                         GOTO(end, rc);
2510                 }
2511                 /* Fall through to osc proc for deactivating live OSC
2512                    on running MDT / clients. */
2513         }
2514         /* Below here, let obd's XXX_process_config methods handle it */
2515
2516         /* All lov. in proc */
2517         if (class_match_param(ptr, PARAM_LOV, NULL) == 0) {
2518                 char *mdtlovname;
2519
2520                 CDEBUG(D_MGS, "lov param %s\n", ptr);
2521                 if (!(mti->mti_flags & LDD_F_SV_TYPE_MDT)) {
2522                         LCONSOLE_ERROR_MSG(0x147, "LOV params must be "
2523                                            "set on the MDT, not %s. "
2524                                            "Ignoring.\n",
2525                                            mti->mti_svname);
2526                         GOTO(end, rc = 0);
2527                 }
2528
2529                 /* Modify mdtlov */
2530                 if (mgs_log_is_empty(obd, mti->mti_svname))
2531                         GOTO(end, rc = -ENODEV);
2532
2533                 name_create_mdt_and_lov(&logname, &mdtlovname, fsdb,
2534                                         mti->mti_stripe_index);
2535                 rc = mgs_wlp_lcfg(obd, fsdb, mti, mti->mti_svname,
2536                                   &bufs, mdtlovname, ptr);
2537                 name_destroy(&logname);
2538                 name_destroy(&mdtlovname);
2539                 if (rc)
2540                         GOTO(end, rc);
2541
2542                 /* Modify clilov */
2543                 name_create(&logname, mti->mti_fsname, "-client");
2544                 rc = mgs_wlp_lcfg(obd, fsdb, mti, logname, &bufs,
2545                                   fsdb->fsdb_clilov, ptr);
2546                 name_destroy(&logname);
2547                 GOTO(end, rc);
2548         }
2549
2550         /* All osc., mdc., llite. params in proc */
2551         if ((class_match_param(ptr, PARAM_OSC, NULL) == 0) ||
2552             (class_match_param(ptr, PARAM_MDC, NULL) == 0) ||
2553             (class_match_param(ptr, PARAM_LLITE, NULL) == 0)) {
2554                 char *cname;
2555                 if (memcmp(ptr, PARAM_LLITE, strlen(PARAM_LLITE)) == 0) {
2556                         name_create(&cname, mti->mti_fsname, "-client");
2557                         /* Add the client type to match the obdname in
2558                            class_config_llog_handler */
2559                 } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
2560                         /* COMPAT_146 */
2561                         if (fsdb->fsdb_mdc)
2562                                 name_create(&cname, fsdb->fsdb_mdc, "");
2563                         else
2564                                 name_create(&cname, mti->mti_svname,
2565                                             "-mdc");
2566                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
2567                         /* COMPAT_146 */
2568                         if (cfs_test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
2569                                 LCONSOLE_ERROR_MSG(0x148, "Upgraded "
2570                                                    "client logs for %s"
2571                                                    " cannot be "
2572                                                    "modified. Consider"
2573                                                    " updating the "
2574                                                    "configuration with"
2575                                                    " --writeconf\n",
2576                                                    mti->mti_svname);
2577                                 /* We don't know the names of all the
2578                                    old oscs*/
2579                                 GOTO(end, rc = -EINVAL);
2580                         }
2581                         name_create(&cname, mti->mti_svname, "-osc");
2582                 } else {
2583                         GOTO(end, rc = -EINVAL);
2584                 }
2585
2586                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
2587
2588                 /* Modify client */
2589                 name_create(&logname, mti->mti_fsname, "-client");
2590                 rc = mgs_wlp_lcfg(obd, fsdb, mti, logname, &bufs,
2591                                   cname, ptr);
2592
2593                 /* osc params affect the MDT as well */
2594                 if (!rc && (mti->mti_flags & LDD_F_SV_TYPE_OST)) {
2595                         int i;
2596
2597                         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
2598                                 if (!cfs_test_bit(i, fsdb->fsdb_mdt_index_map))
2599                                         continue;
2600                                 name_destroy(&cname);
2601                                 name_create_mdt_osc(&cname, mti->mti_svname,
2602                                                     fsdb, i);
2603                                 name_destroy(&logname);
2604                                 name_create_mdt(&logname, mti->mti_fsname, i);
2605                                 if (!mgs_log_is_empty(obd, logname))
2606                                         rc = mgs_wlp_lcfg(obd, fsdb,mti,logname,
2607                                                           &bufs, cname, ptr);
2608                                 if (rc)
2609                                         break;
2610                         }
2611                 }
2612                 name_destroy(&logname);
2613                 name_destroy(&cname);
2614                 GOTO(end, rc);
2615         }
2616
2617         /* All mdt. params in proc */
2618         if (class_match_param(ptr, PARAM_MDT, NULL) == 0) {
2619                 int i;
2620                 __u32 idx;
2621
2622                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
2623                 if (strncmp(mti->mti_svname, mti->mti_fsname,
2624                             MTI_NAME_MAXLEN) == 0)
2625                         /* device is unspecified completely? */
2626                         rc = LDD_F_SV_TYPE_MDT | LDD_F_SV_ALL;
2627                 else
2628                         rc = server_name2index(mti->mti_svname, &idx, NULL);
2629                 if (rc < 0)
2630                         goto active_err;
2631                 if ((rc & LDD_F_SV_TYPE_MDT) == 0)
2632                         goto active_err;
2633                 if (rc & LDD_F_SV_ALL) {
2634                         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
2635                                 if (!cfs_test_bit(i,
2636                                                   fsdb->fsdb_mdt_index_map))
2637                                         continue;
2638                                 name_create_mdt(&logname, mti->mti_fsname, i);
2639                                 rc = mgs_wlp_lcfg(obd, fsdb, mti,
2640                                                   logname, &bufs,
2641                                                   logname, ptr);
2642                                 name_destroy(&logname);
2643                                 if (rc)
2644                                         goto active_err;
2645                         }
2646                 } else {
2647                         rc = mgs_wlp_lcfg(obd, fsdb, mti,
2648                                           mti->mti_svname, &bufs,
2649                                           mti->mti_svname, ptr);
2650                         if (rc)
2651                                 goto active_err;
2652                 }
2653                 GOTO(end, rc);
2654         }
2655
2656         /* All mdd., ost. params in proc */
2657         if ((class_match_param(ptr, PARAM_MDD, NULL) == 0) ||
2658             (class_match_param(ptr, PARAM_OST, NULL) == 0)) {
2659                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
2660                 if (mgs_log_is_empty(obd, mti->mti_svname))
2661                         GOTO(end, rc = -ENODEV);
2662
2663                 rc = mgs_wlp_lcfg(obd, fsdb, mti, mti->mti_svname,
2664                                   &bufs, mti->mti_svname, ptr);
2665                 GOTO(end, rc);
2666         }
2667
2668         LCONSOLE_WARN("Ignoring unrecognized param '%s'\n", ptr);
2669         rc2 = -ENOSYS;
2670
2671 end:
2672         if (rc)
2673                 CERROR("err %d on param '%s'\n", rc, ptr);
2674
2675         RETURN(rc ?: rc2);
2676 }
2677
2678 /* Not implementing automatic failover nid addition at this time. */
2679 int mgs_check_failnid(struct obd_device *obd, struct mgs_target_info *mti)
2680 {
2681 #if 0
2682         struct fs_db *fsdb;
2683         int rc;
2684         ENTRY;
2685
2686         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb);
2687         if (rc)
2688                 RETURN(rc);
2689
2690         if (mgs_log_is_empty(obd, mti->mti_svname))
2691                 /* should never happen */
2692                 RETURN(-ENOENT);
2693
2694         CDEBUG(D_MGS, "Checking for new failnids for %s\n", mti->mti_svname);
2695
2696         /* FIXME We can just check mti->params to see if we're already in
2697            the failover list.  Modify mti->params for rewriting back at
2698            server_register_target(). */
2699
2700         cfs_mutex_lock(&fsdb->fsdb_mutex);
2701         rc = mgs_write_log_add_failnid(obd, fsdb, mti);
2702         cfs_mutex_unlock(&fsdb->fsdb_mutex);
2703
2704         RETURN(rc);
2705 #endif
2706         return 0;
2707 }
2708
2709 int mgs_write_log_target(struct obd_device *obd,
2710                          struct mgs_target_info *mti,
2711                          struct fs_db *fsdb)
2712 {
2713         int rc = -EINVAL;
2714         char *buf, *params;
2715         ENTRY;
2716
2717         /* set/check the new target index */
2718         rc = mgs_set_index(obd, mti);
2719         if (rc < 0) {
2720                 CERROR("Can't get index (%d)\n", rc);
2721                 RETURN(rc);
2722         }
2723
2724         /* COMPAT_146 */
2725         if (mti->mti_flags & LDD_F_UPGRADE14) {
2726                 if (rc == EALREADY) {
2727                         LCONSOLE_INFO("Found index %d for %s 1.4 log, "
2728                                       "upgrading\n", mti->mti_stripe_index,
2729                                       mti->mti_svname);
2730                 } else {
2731                         LCONSOLE_ERROR_MSG(0x149, "Failed to find %s in the old"
2732                                            " client log. Apparently it is not "
2733                                            "part of this filesystem, or the old"
2734                                            " log is wrong.\nUse 'writeconf' on "
2735                                            "the MDT to force log regeneration."
2736                                            "\n", mti->mti_svname);
2737                         /* Not in client log?  Upgrade anyhow...*/
2738                         /* Argument against upgrading: reformat MDT,
2739                            upgrade OST, then OST will start but will be SKIPped
2740                            in client logs.  Maybe error now is better. */
2741                         /* RETURN(-EINVAL); */
2742                 }
2743                 /* end COMPAT_146 */
2744         } else {
2745                 if (rc == EALREADY) {
2746                         LCONSOLE_WARN("Found index %d for %s, updating log\n",
2747                                       mti->mti_stripe_index, mti->mti_svname);
2748                         /* We would like to mark old log sections as invalid
2749                            and add new log sections in the client and mdt logs.
2750                            But if we add new sections, then live clients will
2751                            get repeat setup instructions for already running
2752                            osc's. So don't update the client/mdt logs. */
2753                         mti->mti_flags &= ~LDD_F_UPDATE;
2754                 }
2755         }
2756
2757         cfs_mutex_lock(&fsdb->fsdb_mutex);
2758
2759         if (mti->mti_flags &
2760             (LDD_F_VIRGIN | LDD_F_UPGRADE14 | LDD_F_WRITECONF)) {
2761                 /* Generate a log from scratch */
2762                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
2763                         rc = mgs_write_log_mdt(obd, fsdb, mti);
2764                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
2765                         rc = mgs_write_log_ost(obd, fsdb, mti);
2766                 } else {
2767                         CERROR("Unknown target type %#x, can't create log for "
2768                                "%s\n", mti->mti_flags, mti->mti_svname);
2769                 }
2770                 if (rc) {
2771                         CERROR("Can't write logs for %s (%d)\n",
2772                                mti->mti_svname, rc);
2773                         GOTO(out_up, rc);
2774                 }
2775         } else {
2776                 /* Just update the params from tunefs in mgs_write_log_params */
2777                 CDEBUG(D_MGS, "Update params for %s\n", mti->mti_svname);
2778                 mti->mti_flags |= LDD_F_PARAM;
2779         }
2780
2781         /* allocate temporary buffer, where class_get_next_param will
2782            make copy of a current  parameter */
2783         OBD_ALLOC(buf, strlen(mti->mti_params) + 1);
2784         if (buf == NULL)
2785                 GOTO(out_up, rc = -ENOMEM);
2786         params = mti->mti_params;
2787         while (params != NULL) {
2788                 rc = class_get_next_param(&params, buf);
2789                 if (rc) {
2790                         if (rc == 1)
2791                                 /* there is no next parameter, that is
2792                                    not an error */
2793                                 rc = 0;
2794                         break;
2795                 }
2796                 CDEBUG(D_MGS, "remaining string: '%s', param: '%s'\n",
2797                        params, buf);
2798                 rc = mgs_write_log_param(obd, fsdb, mti, buf);
2799                 if (rc)
2800                         break;
2801         }
2802
2803         OBD_FREE(buf, strlen(mti->mti_params) + 1);
2804
2805 out_up:
2806         cfs_mutex_unlock(&fsdb->fsdb_mutex);
2807         RETURN(rc);
2808 }
2809
2810 /* COMPAT_146 */
2811 /* verify that we can handle the old config logs */
2812 int mgs_upgrade_sv_14(struct obd_device *obd, struct mgs_target_info *mti,
2813                       struct fs_db *fsdb)
2814 {
2815         int rc = 0;
2816         ENTRY;
2817
2818         /* Create ost log normally, as servers register.  Servers
2819            register with their old uuids (from last_rcvd), so old
2820            (MDT and client) logs should work.
2821          - new MDT won't know about old OSTs, only the ones that have
2822            registered, so we need the old MDT log to get the LOV right
2823            in order for old clients to work.
2824          - Old clients connect to the MDT, not the MGS, for their logs, and
2825            will therefore receive the old client log from the MDT /LOGS dir.
2826          - Old clients can continue to use and connect to old or new OSTs
2827          - New clients will contact the MGS for their log
2828         */
2829
2830         LCONSOLE_INFO("upgrading server %s from pre-1.6\n", mti->mti_svname);
2831         server_mti_print("upgrade", mti);
2832
2833         if (cfs_test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
2834                 LCONSOLE_ERROR_MSG(0x14a, "The old client log %s-client is "
2835                                    "missing.  Was tunefs.lustre successful?\n",
2836                                    mti->mti_fsname);
2837                 RETURN(-ENOENT);
2838         }
2839
2840         if (fsdb->fsdb_gen == 0) {
2841                 /* There were no markers in the client log, meaning we have
2842                    not updated the logs for this fs */
2843                 CDEBUG(D_MGS, "found old, unupdated client log\n");
2844         }
2845
2846         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
2847                 if (mgs_log_is_empty(obd, mti->mti_svname)) {
2848                         LCONSOLE_ERROR_MSG(0x14b, "The old MDT log %s is "
2849                                            "missing. Was tunefs.lustre "
2850                                            "successful?\n",
2851                                            mti->mti_svname);
2852                         RETURN(-ENOENT);
2853                 }
2854                 /* We're starting with an old uuid.  Assume old name for lov
2855                    as well since the lov entry already exists in the log. */
2856                 CDEBUG(D_MGS, "old mds uuid %s\n", mti->mti_uuid);
2857                 if (strncmp(mti->mti_uuid, fsdb->fsdb_mdtlov + 4,
2858                             strlen(fsdb->fsdb_mdtlov) - 4) != 0) {
2859                         CERROR("old mds uuid %s doesn't match log %s (%s)\n",
2860                                mti->mti_uuid, fsdb->fsdb_mdtlov,
2861                                fsdb->fsdb_mdtlov + 4);
2862                         RETURN(-EINVAL);
2863                 }
2864         }
2865
2866         if (!cfs_test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
2867                 LCONSOLE_ERROR_MSG(0x14c, "%s-client is supposedly an old "
2868                                    "log, but no old LOV or MDT was found. "
2869                                    "Consider updating the configuration with"
2870                                    " --writeconf.\n", mti->mti_fsname);
2871         }
2872
2873         RETURN(rc);
2874 }
2875 /* end COMPAT_146 */
2876
2877 int mgs_erase_log(struct obd_device *obd, char *name)
2878 {
2879         struct lvfs_run_ctxt saved;
2880         struct llog_ctxt *ctxt;
2881         struct llog_handle *llh;
2882         int rc = 0;
2883
2884         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
2885         LASSERT(ctxt != NULL);
2886
2887         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2888         rc = llog_create(ctxt, &llh, NULL, name);
2889         if (rc == 0) {
2890                 llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
2891                 rc = llog_destroy(llh);
2892                 llog_free_handle(llh);
2893         }
2894         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2895         llog_ctxt_put(ctxt);
2896
2897         if (rc)
2898                 CERROR("failed to clear log %s: %d\n", name, rc);
2899
2900         return(rc);
2901 }
2902
2903 /* erase all logs for the given fs */
2904 int mgs_erase_logs(struct obd_device *obd, char *fsname)
2905 {
2906         struct mgs_obd *mgs = &obd->u.mgs;
2907         struct fs_db *fsdb;
2908         cfs_list_t dentry_list;
2909         struct l_linux_dirent *dirent, *n;
2910         int rc, len = strlen(fsname);
2911         char *suffix;
2912         ENTRY;
2913
2914         /* Find all the logs in the CONFIGS directory */
2915         rc = class_dentry_readdir(obd, mgs->mgs_configs_dir,
2916                                   mgs->mgs_vfsmnt, &dentry_list);
2917         if (rc) {
2918                 CERROR("Can't read %s dir\n", MOUNT_CONFIGS_DIR);
2919                 RETURN(rc);
2920         }
2921
2922         cfs_mutex_lock(&mgs->mgs_mutex);
2923
2924         /* Delete the fs db */
2925         fsdb = mgs_find_fsdb(obd, fsname);
2926         if (fsdb)
2927                 mgs_free_fsdb(obd, fsdb);
2928
2929         cfs_list_for_each_entry_safe(dirent, n, &dentry_list, lld_list) {
2930                 cfs_list_del(&dirent->lld_list);
2931                 suffix = strrchr(dirent->lld_name, '-');
2932                 if (suffix != NULL) {
2933                         if ((len == suffix - dirent->lld_name) &&
2934                             (strncmp(fsname, dirent->lld_name, len) == 0)) {
2935                                 CDEBUG(D_MGS, "Removing log %s\n",
2936                                        dirent->lld_name);
2937                                 mgs_erase_log(obd, dirent->lld_name);
2938                         }
2939                 }
2940                 OBD_FREE(dirent, sizeof(*dirent));
2941         }
2942
2943         cfs_mutex_unlock(&mgs->mgs_mutex);
2944
2945         RETURN(rc);
2946 }
2947
2948 /* from llog_swab */
2949 static void print_lustre_cfg(struct lustre_cfg *lcfg)
2950 {
2951         int i;
2952         ENTRY;
2953
2954         CDEBUG(D_MGS, "lustre_cfg: %p\n", lcfg);
2955         CDEBUG(D_MGS, "\tlcfg->lcfg_version: %#x\n", lcfg->lcfg_version);
2956
2957         CDEBUG(D_MGS, "\tlcfg->lcfg_command: %#x\n", lcfg->lcfg_command);
2958         CDEBUG(D_MGS, "\tlcfg->lcfg_num: %#x\n", lcfg->lcfg_num);
2959         CDEBUG(D_MGS, "\tlcfg->lcfg_flags: %#x\n", lcfg->lcfg_flags);
2960         CDEBUG(D_MGS, "\tlcfg->lcfg_nid: %s\n", libcfs_nid2str(lcfg->lcfg_nid));
2961
2962         CDEBUG(D_MGS, "\tlcfg->lcfg_bufcount: %d\n", lcfg->lcfg_bufcount);
2963         if (lcfg->lcfg_bufcount < LUSTRE_CFG_MAX_BUFCOUNT)
2964                 for (i = 0; i < lcfg->lcfg_bufcount; i++) {
2965                         CDEBUG(D_MGS, "\tlcfg->lcfg_buflens[%d]: %d %s\n",
2966                                i, lcfg->lcfg_buflens[i],
2967                                lustre_cfg_string(lcfg, i));
2968                 }
2969         EXIT;
2970 }
2971
2972 /* Set a permanent (config log) param for a target or fs
2973  * \param lcfg buf0 may contain the device (testfs-MDT0000) name
2974  *             buf1 contains the single parameter
2975  */
2976 int mgs_setparam(struct obd_device *obd, struct lustre_cfg *lcfg, char *fsname)
2977 {
2978         struct fs_db *fsdb;
2979         struct mgs_target_info *mti;
2980         char *devname, *param;
2981         char *ptr, *tmp;
2982         __u32 index;
2983         int rc = 0;
2984         ENTRY;
2985
2986         print_lustre_cfg(lcfg);
2987
2988         /* lustre, lustre-mdtlov, lustre-client, lustre-MDT0000 */
2989         devname = lustre_cfg_string(lcfg, 0);
2990         param = lustre_cfg_string(lcfg, 1);
2991         if (!devname) {
2992                 /* Assume device name embedded in param:
2993                    lustre-OST0000.osc.max_dirty_mb=32 */
2994                 ptr = strchr(param, '.');
2995                 if (ptr) {
2996                         devname = param;
2997                         *ptr = 0;
2998                         param = ptr + 1;
2999                 }
3000         }
3001         if (!devname) {
3002                 LCONSOLE_ERROR_MSG(0x14d, "No target specified: %s\n", param);
3003                 RETURN(-ENOSYS);
3004         }
3005
3006         /* Extract fsname */
3007         ptr = strrchr(devname, '-');
3008         memset(fsname, 0, MTI_NAME_MAXLEN);
3009         if (ptr && (server_name2index(ptr, &index, NULL) >= 0)) {
3010                 /* param related to llite isn't allowed to set by OST or MDT */
3011                 if (strncmp(param, PARAM_LLITE, sizeof(PARAM_LLITE)) == 0)
3012                         RETURN(-EINVAL);
3013
3014                 strncpy(fsname, devname, ptr - devname);
3015         } else {
3016                 /* assume devname is the fsname */
3017                 strncpy(fsname, devname, MTI_NAME_MAXLEN);
3018         }
3019         fsname[MTI_NAME_MAXLEN - 1] = 0;
3020         CDEBUG(D_MGS, "setparam fs='%s' device='%s'\n", fsname, devname);
3021
3022         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb);
3023         if (rc)
3024                 RETURN(rc);
3025         if (!cfs_test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags) &&
3026             cfs_test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
3027                 CERROR("No filesystem targets for %s.  cfg_device from lctl "
3028                        "is '%s'\n", fsname, devname);
3029                 mgs_free_fsdb(obd, fsdb);
3030                 RETURN(-EINVAL);
3031         }
3032
3033         /* Create a fake mti to hold everything */
3034         OBD_ALLOC_PTR(mti);
3035         if (!mti)
3036                 GOTO(out, rc = -ENOMEM);
3037         strncpy(mti->mti_fsname, fsname, MTI_NAME_MAXLEN);
3038         strncpy(mti->mti_svname, devname, MTI_NAME_MAXLEN);
3039         strncpy(mti->mti_params, param, sizeof(mti->mti_params));
3040         rc = server_name2index(mti->mti_svname, &mti->mti_stripe_index, &tmp);
3041         if (rc < 0)
3042                 /* Not a valid server; may be only fsname */
3043                 rc = 0;
3044         else
3045                 /* Strip -osc or -mdc suffix from svname */
3046                 if (server_make_name(rc, mti->mti_stripe_index, mti->mti_fsname,
3047                                      mti->mti_svname))
3048                         GOTO(out, rc = -EINVAL);
3049
3050         mti->mti_flags = rc | LDD_F_PARAM;
3051
3052         cfs_mutex_lock(&fsdb->fsdb_mutex);
3053         rc = mgs_write_log_param(obd, fsdb, mti, mti->mti_params);
3054         cfs_mutex_unlock(&fsdb->fsdb_mutex);
3055
3056         /*
3057          * Revoke lock so everyone updates.  Should be alright if
3058          * someone was already reading while we were updating the logs,
3059          * so we don't really need to hold the lock while we're
3060          * writing (above).
3061          */
3062         mgs_revoke_lock(obd, fsdb, CONFIG_T_CONFIG);
3063 out:
3064         OBD_FREE_PTR(mti);
3065         RETURN(rc);
3066 }
3067
3068 static int mgs_write_log_pool(struct obd_device *obd, char *logname,
3069                               struct fs_db *fsdb, char *lovname,
3070                               enum lcfg_command_type cmd,
3071                               char *poolname, char *fsname,
3072                               char *ostname, char *comment)
3073 {
3074         struct llog_handle *llh = NULL;
3075         int rc;
3076
3077         rc = record_start_log(obd, &llh, logname);
3078         if (rc)
3079                 return rc;
3080         rc = record_marker(obd, llh, fsdb, CM_START, lovname, comment);
3081         record_base(obd, llh, lovname, 0, cmd, poolname, fsname, ostname, 0);
3082         rc = record_marker(obd, llh, fsdb, CM_END, lovname, comment);
3083         rc = record_end_log(obd, &llh);
3084
3085         return rc;
3086 }
3087
3088 int mgs_pool_cmd(struct obd_device *obd, enum lcfg_command_type cmd,
3089                  char *fsname, char *poolname, char *ostname)
3090 {
3091         struct fs_db *fsdb;
3092         char *lovname;
3093         char *logname;
3094         char *label = NULL, *canceled_label = NULL;
3095         int label_sz;
3096         struct mgs_target_info *mti = NULL;
3097         int rc, i;
3098         ENTRY;
3099
3100         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb);
3101         if (rc) {
3102                 CERROR("Can't get db for %s\n", fsname);
3103                 RETURN(rc);
3104         }
3105         if (cfs_test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
3106                 CERROR("%s is not defined\n", fsname);
3107                 mgs_free_fsdb(obd, fsdb);
3108                 RETURN(-EINVAL);
3109         }
3110
3111         label_sz = 10 + strlen(fsname) + strlen(poolname);
3112
3113         /* check if ostname match fsname */
3114         if (ostname != NULL) {
3115                 char *ptr;
3116
3117                 ptr = strrchr(ostname, '-');
3118                 if ((ptr == NULL) ||
3119                     (strncmp(fsname, ostname, ptr-ostname) != 0))
3120                         RETURN(-EINVAL);
3121                 label_sz += strlen(ostname);
3122         }
3123
3124         OBD_ALLOC(label, label_sz);
3125         if (label == NULL)
3126                 GOTO(out, rc = -ENOMEM);
3127
3128         switch(cmd) {
3129         case LCFG_POOL_NEW: {
3130                 sprintf(label,
3131                         "new %s.%s", fsname, poolname);
3132                 break;
3133         }
3134         case LCFG_POOL_ADD: {
3135                 sprintf(label,
3136                         "add %s.%s.%s", fsname, poolname, ostname);
3137                 break;
3138         }
3139         case LCFG_POOL_REM: {
3140                 OBD_ALLOC(canceled_label, label_sz);
3141                 if (canceled_label == NULL)
3142                          GOTO(out, rc = -ENOMEM);
3143                 sprintf(label,
3144                         "rem %s.%s.%s", fsname, poolname, ostname);
3145                 sprintf(canceled_label,
3146                         "add %s.%s.%s", fsname, poolname, ostname);
3147                 break;
3148         }
3149         case LCFG_POOL_DEL: {
3150                 OBD_ALLOC(canceled_label, label_sz);
3151                 if (canceled_label == NULL)
3152                          GOTO(out, rc = -ENOMEM);
3153                 sprintf(label,
3154                         "del %s.%s", fsname, poolname);
3155                 sprintf(canceled_label,
3156                         "new %s.%s", fsname, poolname);
3157                 break;
3158         }
3159         default: {
3160                 break;
3161         }
3162         }
3163
3164         cfs_mutex_lock(&fsdb->fsdb_mutex);
3165
3166         if (canceled_label != NULL) {
3167                 OBD_ALLOC_PTR(mti);
3168                 if (mti == NULL)
3169                         GOTO(out, rc = -ENOMEM);
3170         }
3171
3172         /* write pool def to all MDT logs */
3173         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
3174                  if (cfs_test_bit(i,  fsdb->fsdb_mdt_index_map)) {
3175                         name_create_mdt_and_lov(&logname, &lovname, fsdb, i);
3176
3177                         if (canceled_label != NULL) {
3178                                 strcpy(mti->mti_svname, "lov pool");
3179                                 mgs_modify(obd, fsdb, mti, logname, lovname,
3180                                            canceled_label, CM_SKIP);
3181                         }
3182
3183                         mgs_write_log_pool(obd, logname, fsdb, lovname,
3184                                            cmd, fsname, poolname, ostname,
3185                                            label);
3186                         name_destroy(&logname);
3187                         name_destroy(&lovname);
3188                 }
3189         }
3190
3191         name_create(&logname, fsname, "-client");
3192         if (canceled_label != NULL)
3193                 mgs_modify(obd, fsdb, mti, logname, fsdb->fsdb_clilov,
3194                            canceled_label, CM_SKIP);
3195
3196         mgs_write_log_pool(obd, logname, fsdb, fsdb->fsdb_clilov,
3197                            cmd, fsname, poolname, ostname, label);
3198         name_destroy(&logname);
3199
3200         cfs_mutex_unlock(&fsdb->fsdb_mutex);
3201         /* request for update */
3202         mgs_revoke_lock(obd, fsdb, CONFIG_T_CONFIG);
3203
3204         EXIT;
3205 out:
3206         if (label != NULL)
3207                 OBD_FREE(label, label_sz);
3208
3209         if (canceled_label != NULL)
3210                 OBD_FREE(canceled_label, label_sz);
3211
3212         if (mti != NULL)
3213                 OBD_FREE_PTR(mti);
3214
3215         return rc;
3216 }
3217
3218 #if 0
3219 /******************** unused *********************/
3220 static int mgs_backup_llog(struct obd_device *obd, char* fsname)
3221 {
3222         struct file *filp, *bak_filp;
3223         struct lvfs_run_ctxt saved;
3224         char *logname, *buf;
3225         loff_t soff = 0 , doff = 0;
3226         int count = 4096, len;
3227         int rc = 0;
3228
3229         OBD_ALLOC(logname, PATH_MAX);
3230         if (logname == NULL)
3231                 return -ENOMEM;
3232
3233         OBD_ALLOC(buf, count);
3234         if (!buf)
3235                 GOTO(out , rc = -ENOMEM);
3236
3237         len = snprintf(logname, PATH_MAX, "%s/%s.bak",
3238                        MOUNT_CONFIGS_DIR, fsname);
3239
3240         if (len >= PATH_MAX - 1) {
3241                 GOTO(out, -ENAMETOOLONG);
3242         }
3243
3244         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
3245
3246         bak_filp = l_filp_open(logname, O_RDWR|O_CREAT|O_TRUNC, 0660);
3247         if (IS_ERR(bak_filp)) {
3248                 rc = PTR_ERR(bak_filp);
3249                 CERROR("backup logfile open %s: %d\n", logname, rc);
3250                 GOTO(pop, rc);
3251         }
3252         sprintf(logname, "%s/%s", MOUNT_CONFIGS_DIR, fsname);
3253         filp = l_filp_open(logname, O_RDONLY, 0);
3254         if (IS_ERR(filp)) {
3255                 rc = PTR_ERR(filp);
3256                 CERROR("logfile open %s: %d\n", logname, rc);
3257                 GOTO(close1f, rc);
3258         }
3259
3260         while ((rc = lustre_fread(filp, buf, count, &soff)) > 0) {
3261                 rc = lustre_fwrite(bak_filp, buf, count, &doff);
3262                 break;
3263         }
3264
3265         filp_close(filp, 0);
3266 close1f:
3267         filp_close(bak_filp, 0);
3268 pop:
3269         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
3270 out:
3271         if (buf)
3272                 OBD_FREE(buf, count);
3273         OBD_FREE(logname, PATH_MAX);
3274         return rc;
3275 }
3276
3277 #endif