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