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