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