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