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