Whamcloud - gitweb
Branch 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 /********************** Class functions ********************/
52
53 /* Caller must list_del and OBD_FREE each dentry from the list */
54 int class_dentry_readdir(struct obd_device *obd, struct dentry *dir,
55                                 struct vfsmount *inmnt,
56                                 struct list_head *dentry_list){
57         /* see mds_cleanup_pending */
58         struct lvfs_run_ctxt saved;
59         struct file *file;
60         struct dentry *dentry;
61         struct vfsmount *mnt;
62         int rc = 0;
63         ENTRY;
64
65         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
66         dentry = dget(dir);
67         if (IS_ERR(dentry))
68                 GOTO(out_pop, rc = PTR_ERR(dentry));
69         mnt = mntget(inmnt);
70         if (IS_ERR(mnt)) {
71                 l_dput(dentry);
72                 GOTO(out_pop, rc = PTR_ERR(mnt));
73         }
74
75         file = dentry_open(dentry, mnt, O_RDONLY);
76         if (IS_ERR(file))
77                 /* dentry_open_it() drops the dentry, mnt refs */
78                 GOTO(out_pop, rc = PTR_ERR(file));
79
80         INIT_LIST_HEAD(dentry_list);
81         rc = l_readdir(file, dentry_list);
82         filp_close(file, 0);
83         /*  filp_close->fput() drops the dentry, mnt refs */
84
85 out_pop:
86         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
87         RETURN(rc);
88 }
89
90 /******************** DB functions *********************/
91
92 static inline int name_create(char **newname, char *prefix, char *suffix)
93 {
94         LASSERT(newname);
95         OBD_ALLOC(*newname, strlen(prefix) + strlen(suffix) + 1);
96         if (!*newname) 
97                 return -ENOMEM;
98         sprintf(*newname, "%s%s", prefix, suffix);
99         return 0;
100 }
101
102 static inline void name_destroy(char **name)
103 {        
104         if (*name)
105                 OBD_FREE(*name, strlen(*name) + 1);
106         *name = NULL;
107 }
108
109 /* from the (client) config log, figure out:
110         1. which ost's/mdt's are configured (by index)
111         2. what the last config step is
112         3. COMPAT_146 lov name
113         4. COMPAT_146 mdt lov name
114         5. COMPAT_146 mdc name 
115 */
116 /* It might be better to have a separate db file, instead of parsing the info
117    out of the client log.  This is slow and potentially error-prone. */
118 static int mgs_fsdb_handler(struct llog_handle *llh, struct llog_rec_hdr *rec, 
119                             void *data)
120 {
121         struct fs_db *fsdb = (struct fs_db *)data;
122         int cfg_len = rec->lrh_len;
123         char *cfg_buf = (char*) (rec + 1);
124         struct lustre_cfg *lcfg;
125         __u32 index;
126         int rc = 0;
127         ENTRY;
128
129         if (rec->lrh_type != OBD_CFG_REC) {
130                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
131                 RETURN(-EINVAL);
132         }
133
134         rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
135         if (rc) {
136                 CERROR("Insane cfg\n");
137                 RETURN(rc);
138         }
139
140         lcfg = (struct lustre_cfg *)cfg_buf;
141
142         CDEBUG(D_INFO, "cmd %x %s %s\n", lcfg->lcfg_command,
143                lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
144
145         /* Figure out ost indicies */
146         /* lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1 */
147         if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD ||
148             lcfg->lcfg_command == LCFG_LOV_DEL_OBD) {
149                 index = simple_strtoul(lustre_cfg_string(lcfg, 2),
150                                        NULL, 10);
151                 CDEBUG(D_MGS, "OST index for %s is %u (%s)\n",
152                        lustre_cfg_string(lcfg, 1), index,
153                        lustre_cfg_string(lcfg, 2));
154                 set_bit(index, fsdb->fsdb_ost_index_map);
155         }
156
157         /* Figure out mdt indicies */
158         /* attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f */
159         if ((lcfg->lcfg_command == LCFG_ATTACH) &&
160             (strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_MDC_NAME) == 0)) {
161                 rc = server_name2index(lustre_cfg_string(lcfg, 0),
162                                        &index, NULL);
163                 if (rc != LDD_F_SV_TYPE_MDT) {
164                         CWARN("Unparsable MDC name %s, assuming index 0\n",
165                               lustre_cfg_string(lcfg, 0));
166                         index = 0;
167                 }
168                 rc = 0;
169                 CDEBUG(D_MGS, "MDT index is %u\n", index);
170                 set_bit(index, fsdb->fsdb_mdt_index_map);
171         }
172
173         /* COMPAT_146 */
174         /* figure out the old LOV name. fsdb_gen = 0 means old log */
175         /* #01 L attach 0:lov_mdsA 1:lov 2:cdbe9_lov_mdsA_dc8cf7f3bb */
176         if ((fsdb->fsdb_gen == 0) && (lcfg->lcfg_command == LCFG_ATTACH) &&
177             (strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_LOV_NAME) == 0)) {
178                 fsdb->fsdb_flags |= FSDB_OLDLOG14;
179                 name_destroy(&fsdb->fsdb_clilov);
180                 rc = name_create(&fsdb->fsdb_clilov, 
181                                  lustre_cfg_string(lcfg, 0), "");
182                 if (rc) 
183                         RETURN(rc);
184                 CDEBUG(D_MGS, "client lov name is %s\n", fsdb->fsdb_clilov);
185         }
186
187         /* figure out the old MDT lov name from the MDT uuid */
188         if ((fsdb->fsdb_gen == 0) && (lcfg->lcfg_command == LCFG_SETUP) &&
189             (strncmp(lustre_cfg_string(lcfg, 0), "MDC_", 4) == 0)) {
190                 char *ptr;
191                 fsdb->fsdb_flags |= FSDB_OLDLOG14;
192                 ptr = strstr(lustre_cfg_string(lcfg, 1), "_UUID");
193                 if (!ptr) {
194                         CERROR("Can't parse MDT uuid %s\n", 
195                                lustre_cfg_string(lcfg, 1));
196                         RETURN(-EINVAL);
197                 }
198                 *ptr = '\0';
199                 name_destroy(&fsdb->fsdb_mdtlov);
200                 rc = name_create(&fsdb->fsdb_mdtlov, 
201                                  "lov_", lustre_cfg_string(lcfg, 1));
202                 if (rc) 
203                         RETURN(rc);
204                 name_destroy(&fsdb->fsdb_mdc);
205                 rc = name_create(&fsdb->fsdb_mdc, 
206                                  lustre_cfg_string(lcfg, 0), "");
207                 if (rc) 
208                         RETURN(rc);
209                 CDEBUG(D_MGS, "MDT lov name is %s\n", fsdb->fsdb_mdtlov);
210         }
211         /* end COMPAT_146 */
212
213         /* Keep track of the latest marker step */
214         if (lcfg->lcfg_command == LCFG_MARKER) {
215                 struct cfg_marker *marker;
216                 marker = lustre_cfg_buf(lcfg, 1);
217                 fsdb->fsdb_gen = max(fsdb->fsdb_gen, marker->cm_step);
218         }
219
220         RETURN(rc);
221 }
222
223 /* fsdb->fsdb_sem is already held  in mgs_find_or_make_fsdb*/
224 static int mgs_get_fsdb_from_llog(struct obd_device *obd, struct fs_db *fsdb)
225 {
226         char *logname;
227         struct llog_handle *loghandle;
228         struct lvfs_run_ctxt saved;
229         int rc, rc2;
230         ENTRY;
231
232         name_create(&logname, fsdb->fsdb_name, "-client");
233         down(&fsdb->fsdb_sem);
234         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
235
236         rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
237                          &loghandle, NULL, logname);
238         if (rc)
239                 GOTO(out_pop, rc);
240
241         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
242         if (rc)
243                 GOTO(out_close, rc);
244
245         if (llog_get_size(loghandle) <= 1)
246                 fsdb->fsdb_flags |= FSDB_LOG_EMPTY;
247
248         rc = llog_process(loghandle, mgs_fsdb_handler, (void *)fsdb, NULL);
249         CDEBUG(D_INFO, "get_db = %d\n", rc);
250 out_close:
251         rc2 = llog_close(loghandle);
252         if (!rc)
253                 rc = rc2;
254
255 out_pop:
256         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
257         up(&fsdb->fsdb_sem);
258         name_destroy(&logname);
259
260         RETURN(rc);
261 }
262
263 static struct fs_db *mgs_find_fsdb(struct obd_device *obd, char *fsname)
264 {
265         struct mgs_obd *mgs = &obd->u.mgs;
266         struct fs_db *fsdb;
267         struct list_head *tmp;
268
269         list_for_each(tmp, &mgs->mgs_fs_db_list) {
270                 fsdb = list_entry(tmp, struct fs_db, fsdb_list);
271                 if (strcmp(fsdb->fsdb_name, fsname) == 0)
272                         return fsdb;
273         }
274         return NULL;
275 }
276
277 /* caller must hold the mgs->mgs_fs_db_lock */
278 static struct fs_db *mgs_new_fsdb(struct obd_device *obd, char *fsname)
279 {
280         struct mgs_obd *mgs = &obd->u.mgs;
281         struct fs_db *fsdb;
282         int rc;
283         ENTRY;
284
285         OBD_ALLOC_PTR(fsdb);
286         if (!fsdb)
287                 RETURN(NULL);
288
289         OBD_ALLOC(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
290         OBD_ALLOC(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
291         if (!fsdb->fsdb_ost_index_map || !fsdb->fsdb_mdt_index_map) {
292                 CERROR("No memory for index maps\n");
293                 GOTO(err, 0);
294         }
295
296         strncpy(fsdb->fsdb_name, fsname, sizeof(fsdb->fsdb_name));
297         fsdb->fsdb_name[sizeof(fsdb->fsdb_name) - 1] = 0;
298         rc = name_create(&fsdb->fsdb_mdtlov, fsname, "-mdtlov");
299         if (rc) 
300                 GOTO(err, rc);
301         rc = name_create(&fsdb->fsdb_mdtlmv, fsname, "-mdtlmv");
302         if (rc) 
303                 GOTO(err, rc);
304         rc = name_create(&fsdb->fsdb_clilov, fsname, "-clilov");
305         if (rc) 
306                 GOTO(err, rc);
307
308         rc = name_create(&fsdb->fsdb_clilmv, fsname, "-clilmv");
309         if (rc) 
310                 GOTO(err, rc);
311
312         sema_init(&fsdb->fsdb_sem, 1);
313         list_add(&fsdb->fsdb_list, &mgs->mgs_fs_db_list);
314         lproc_mgs_add_live(obd, fsdb);
315
316         RETURN(fsdb);
317 err:
318         if (fsdb->fsdb_ost_index_map)
319                 OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
320         if (fsdb->fsdb_mdt_index_map)
321                 OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
322         name_destroy(&fsdb->fsdb_clilov);
323         name_destroy(&fsdb->fsdb_clilmv);
324         name_destroy(&fsdb->fsdb_mdtlov); 
325         name_destroy(&fsdb->fsdb_mdtlmv); 
326         OBD_FREE_PTR(fsdb);
327         RETURN(NULL);
328 }
329
330 static void mgs_free_fsdb(struct obd_device *obd, struct fs_db *fsdb)
331 {
332         /* wait for anyone with the sem */
333         down(&fsdb->fsdb_sem);
334         lproc_mgs_del_live(obd, fsdb);
335         list_del(&fsdb->fsdb_list);
336         OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
337         OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
338         name_destroy(&fsdb->fsdb_clilov); 
339         name_destroy(&fsdb->fsdb_clilmv); 
340         name_destroy(&fsdb->fsdb_mdtlov); 
341         name_destroy(&fsdb->fsdb_mdtlmv); 
342         name_destroy(&fsdb->fsdb_mdc); 
343         OBD_FREE_PTR(fsdb);
344 }
345
346 int mgs_init_fsdb_list(struct obd_device *obd)
347 {
348         struct mgs_obd *mgs = &obd->u.mgs;
349         INIT_LIST_HEAD(&mgs->mgs_fs_db_list);
350         return 0;
351 }
352
353 int mgs_cleanup_fsdb_list(struct obd_device *obd)
354 {
355         struct mgs_obd *mgs = &obd->u.mgs;
356         struct fs_db *fsdb;
357         struct list_head *tmp, *tmp2;
358         down(&mgs->mgs_sem);
359         list_for_each_safe(tmp, tmp2, &mgs->mgs_fs_db_list) {
360                 fsdb = list_entry(tmp, struct fs_db, fsdb_list);
361                 mgs_free_fsdb(obd, fsdb);
362         }
363         up(&mgs->mgs_sem);
364         return 0;
365 }
366
367 static int mgs_find_or_make_fsdb(struct obd_device *obd, char *name, 
368                                struct fs_db **dbh)
369 {
370         struct mgs_obd *mgs = &obd->u.mgs;
371         struct fs_db *fsdb;
372         int rc = 0;
373
374         down(&mgs->mgs_sem);
375         fsdb = mgs_find_fsdb(obd, name);
376         if (fsdb) {
377                 up(&mgs->mgs_sem);
378                 *dbh = fsdb;
379                 return 0;
380         }
381
382         CDEBUG(D_MGS, "Creating new db\n");
383         fsdb = mgs_new_fsdb(obd, name);
384         up(&mgs->mgs_sem);
385         if (!fsdb)
386                 return -ENOMEM;
387
388         /* populate the db from the client llog */
389         rc = mgs_get_fsdb_from_llog(obd, fsdb);
390         if (rc) {
391                 CERROR("Can't get db from client log %d\n", rc);
392                 mgs_free_fsdb(obd, fsdb);
393                 return rc;
394         }
395
396         *dbh = fsdb;
397
398         return 0;
399 }
400
401 /* 1 = index in use
402    0 = index unused
403    -1= empty client log */
404 int mgs_check_index(struct obd_device *obd, struct mgs_target_info *mti)
405 {
406         struct fs_db *fsdb;
407         void *imap;
408         int rc = 0;
409         ENTRY;
410
411         LASSERT(!(mti->mti_flags & LDD_F_NEED_INDEX));
412
413         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb);
414         if (rc) {
415                 CERROR("Can't get db for %s\n", mti->mti_fsname);
416                 RETURN(rc);
417         }
418
419         if (fsdb->fsdb_flags & FSDB_LOG_EMPTY)
420                 RETURN(-1);
421
422         if (mti->mti_flags & LDD_F_SV_TYPE_OST)
423                 imap = fsdb->fsdb_ost_index_map;
424         else if (mti->mti_flags & LDD_F_SV_TYPE_MDT)
425                 imap = fsdb->fsdb_mdt_index_map;
426         else
427                 RETURN(-EINVAL);
428
429         if (test_bit(mti->mti_stripe_index, imap))
430                 RETURN(1);
431         RETURN(0);
432 }
433
434 static __inline__ int next_index(void *index_map, int map_len)
435 {
436         int i;
437         for (i = 0; i < map_len * 8; i++)
438                  if (!test_bit(i, index_map)) {
439                          return i;
440                  }
441         CERROR("max index %d exceeded.\n", i);
442         return -1;
443 }
444
445 /* Return codes:
446         0  newly marked as in use
447         <0 err
448         +EALREADY for update of an old index */
449 int mgs_set_index(struct obd_device *obd, struct mgs_target_info *mti)
450 {
451         struct fs_db *fsdb;
452         void *imap;
453         int rc = 0;
454         ENTRY;
455
456         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb);
457         if (rc) {
458                 CERROR("Can't get db for %s\n", mti->mti_fsname);
459                 RETURN(rc);
460         }
461
462         if (mti->mti_flags & LDD_F_SV_TYPE_OST)
463                 imap = fsdb->fsdb_ost_index_map;
464         else if (mti->mti_flags & LDD_F_SV_TYPE_MDT)
465                 imap = fsdb->fsdb_mdt_index_map;
466         else
467                 RETURN(-EINVAL);
468
469         if (mti->mti_flags & LDD_F_NEED_INDEX) {
470                 rc = next_index(imap, INDEX_MAP_SIZE);
471                 if (rc == -1)
472                         RETURN(-ERANGE);
473                 mti->mti_stripe_index = rc;
474         }
475
476         if (mti->mti_stripe_index >= INDEX_MAP_SIZE * 8) {
477                 LCONSOLE_ERROR_MSG(0x13f, "Server %s requested index %d, "
478                                    "but the max index is %d.\n",
479                                    mti->mti_svname, mti->mti_stripe_index,
480                                    INDEX_MAP_SIZE * 8);
481                 RETURN(-ERANGE);
482         }
483
484         if (test_bit(mti->mti_stripe_index, imap)) {
485                 if (mti->mti_flags & LDD_F_VIRGIN) {
486                         LCONSOLE_ERROR_MSG(0x140, "Server %s requested index "
487                                            "%d, but that index is already in "
488                                            "use\n", mti->mti_svname,
489                                            mti->mti_stripe_index);
490                         RETURN(-EADDRINUSE);
491                 } else {
492                         CDEBUG(D_MGS, "Server %s updating index %d\n",
493                                mti->mti_svname, mti->mti_stripe_index);
494                         RETURN(EALREADY);
495                 }
496         }
497
498         set_bit(mti->mti_stripe_index, imap);
499         fsdb->fsdb_flags &= ~FSDB_LOG_EMPTY;
500         server_make_name(mti->mti_flags, mti->mti_stripe_index,
501                          mti->mti_fsname, mti->mti_svname);
502
503         CDEBUG(D_MGS, "Set index for %s to %d\n", mti->mti_svname,
504                mti->mti_stripe_index);
505
506         RETURN(0);
507 }
508
509 struct mgs_modify_lookup {
510         struct cfg_marker mml_marker;
511         int               mml_modified;
512 };
513
514 static int mgs_modify_handler(struct llog_handle *llh, struct llog_rec_hdr *rec, 
515                               void *data)
516 {
517         struct mgs_modify_lookup *mml = (struct mgs_modify_lookup *)data;
518         struct cfg_marker *marker;
519         struct lustre_cfg *lcfg = (struct lustre_cfg *)(rec + 1);
520         int cfg_len = rec->lrh_len - sizeof(struct llog_rec_hdr) - 
521                 sizeof(struct llog_rec_tail);
522         int rc;
523         ENTRY;
524
525         if (rec->lrh_type != OBD_CFG_REC) {
526                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
527                 RETURN(-EINVAL);
528         }
529
530         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
531         if (rc) {
532                 CERROR("Insane cfg\n");
533                 RETURN(rc);
534         }
535
536         /* We only care about markers */
537         if (lcfg->lcfg_command != LCFG_MARKER)
538                 RETURN(0); 
539         
540         marker = lustre_cfg_buf(lcfg, 1);
541         if ((strcmp(mml->mml_marker.cm_comment, marker->cm_comment) == 0) && 
542             (strcmp(mml->mml_marker.cm_tgtname, marker->cm_tgtname) == 0) &&
543             !(marker->cm_flags & CM_SKIP)) {
544                 /* Found a non-skipped marker match */
545                 CDEBUG(D_MGS, "Changing rec %u marker %d %x->%x: %s %s\n",
546                        rec->lrh_index, marker->cm_step, 
547                        marker->cm_flags, mml->mml_marker.cm_flags,
548                        marker->cm_tgtname, marker->cm_comment);
549                 /* Overwrite the old marker llog entry */
550                 marker->cm_flags &= ~CM_EXCLUDE; /* in case we're unexcluding */
551                 marker->cm_flags |= mml->mml_marker.cm_flags;
552                 marker->cm_canceltime = mml->mml_marker.cm_canceltime;
553                 /* Header and tail are added back to lrh_len in 
554                    llog_lvfs_write_rec */
555                 rec->lrh_len = cfg_len; 
556                 rc = llog_write_rec(llh, rec, NULL, 0, (void *)lcfg, 
557                                     rec->lrh_index);
558                 if (!rc) 
559                          mml->mml_modified++;
560         }
561
562         RETURN(rc);
563 }
564
565 /* Modify an existing config log record (for CM_SKIP or CM_EXCLUDE) */
566 static int mgs_modify(struct obd_device *obd, struct fs_db *fsdb,
567                       struct mgs_target_info *mti, char *logname, 
568                       char *devname, char *comment, int flags)
569 {
570         struct llog_handle *loghandle;
571         struct lvfs_run_ctxt saved;
572         struct mgs_modify_lookup *mml;
573         int rc, rc2;
574         ENTRY;
575
576         CDEBUG(D_MGS, "modify %s/%s/%s\n", logname, devname, comment);
577
578         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
579         
580         rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
581                          &loghandle, NULL, logname);
582         if (rc)
583                 GOTO(out_pop, rc);
584
585         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
586         if (rc)
587                 GOTO(out_close, rc);
588
589         if (llog_get_size(loghandle) <= 1)
590                 GOTO(out_close, rc = 0);
591
592         OBD_ALLOC_PTR(mml);
593         if (!mml) 
594                 GOTO(out_close, rc = -ENOMEM);
595         strcpy(mml->mml_marker.cm_comment, comment);
596         strcpy(mml->mml_marker.cm_tgtname, devname);
597         /* Modify mostly means cancel */
598         mml->mml_marker.cm_flags = flags;
599         mml->mml_marker.cm_canceltime = flags ? cfs_time_current_sec() : 0;
600         mml->mml_modified = 0;
601         rc = llog_process(loghandle, mgs_modify_handler, (void *)mml, NULL);
602         if (!rc && !mml->mml_modified) 
603                 rc = -ENODEV;
604         OBD_FREE_PTR(mml);
605
606 out_close:
607         rc2 = llog_close(loghandle);
608         if (!rc)
609                 rc = rc2;
610
611 out_pop:
612         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
613         if (rc && rc != -ENODEV) 
614                 CERROR("modify %s/%s failed %d\n",
615                        mti->mti_svname, comment, rc);
616
617         RETURN(rc);
618 }
619
620 /******************** config log recording functions *********************/
621
622 static int record_lcfg(struct obd_device *obd, struct llog_handle *llh,
623                          struct lustre_cfg *lcfg)
624 {
625         struct lvfs_run_ctxt   saved;
626         struct llog_rec_hdr    rec;
627         int buflen, rc;
628
629         if (!lcfg || !llh) 
630                 return -ENOMEM;
631
632         LASSERT(llh->lgh_ctxt);        
633
634         buflen = lustre_cfg_len(lcfg->lcfg_bufcount,
635                                 lcfg->lcfg_buflens);
636         rec.lrh_len = llog_data_len(buflen);
637         rec.lrh_type = OBD_CFG_REC;
638
639         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
640         /* idx = -1 means append */
641         rc = llog_write_rec(llh, &rec, NULL, 0, (void *)lcfg, -1);
642         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
643         if (rc) 
644                 CERROR("failed %d\n", rc);
645         return rc;
646 }
647
648 static int record_base(struct obd_device *obd, struct llog_handle *llh,
649                      char *cfgname, lnet_nid_t nid, int cmd,
650                      char *s1, char *s2, char *s3, char *s4)
651 {
652         struct lustre_cfg_bufs bufs;
653         struct lustre_cfg     *lcfg;
654         int rc;
655
656         CDEBUG(D_MGS, "lcfg %s %#x %s %s %s %s\n", cfgname,
657                cmd, s1, s2, s3, s4);
658
659         lustre_cfg_bufs_reset(&bufs, cfgname);
660         if (s1)
661                 lustre_cfg_bufs_set_string(&bufs, 1, s1);
662         if (s2)
663                 lustre_cfg_bufs_set_string(&bufs, 2, s2);
664         if (s3)
665                 lustre_cfg_bufs_set_string(&bufs, 3, s3);
666         if (s4)
667                 lustre_cfg_bufs_set_string(&bufs, 4, s4);
668
669         lcfg = lustre_cfg_new(cmd, &bufs);
670         if (!lcfg) 
671                 return -ENOMEM;
672         lcfg->lcfg_nid = nid;
673
674         rc = record_lcfg(obd, llh, lcfg);
675
676         lustre_cfg_free(lcfg);
677
678         if (rc) {
679                 CERROR("error %d: lcfg %s %#x %s %s %s %s\n", rc, cfgname,
680                        cmd, s1, s2, s3, s4);
681         }
682         return(rc);
683 }
684
685
686 static inline int record_add_uuid(struct obd_device *obd,
687                                   struct llog_handle *llh,
688                                   uint64_t nid, char *uuid)
689 {
690         return record_base(obd,llh,NULL,nid,LCFG_ADD_UUID,uuid,0,0,0);
691
692 }
693
694 static inline int record_add_conn(struct obd_device *obd,
695                                   struct llog_handle *llh,
696                                   char *devname,
697                                   char *uuid)
698 {
699         return record_base(obd,llh,devname,0,LCFG_ADD_CONN,uuid,0,0,0);
700 }
701
702 static inline int record_attach(struct obd_device *obd, struct llog_handle *llh,
703                                 char *devname, char *type, char *uuid)
704 {
705         return record_base(obd,llh,devname,0,LCFG_ATTACH,type,uuid,0,0);
706 }
707
708 static inline int record_setup(struct obd_device *obd, struct llog_handle *llh,
709                                char *devname,
710                                char *s1, char *s2, char *s3, char *s4)
711 {
712         return record_base(obd,llh,devname,0,LCFG_SETUP,s1,s2,s3,s4);
713 }
714
715 static inline int record_sec_flavor(struct obd_device *obd,
716                                     struct llog_handle *llh, char *devname,
717                                     struct sec_flavor_config *conf)
718 {
719         struct lustre_cfg_bufs bufs;
720         struct lustre_cfg *lcfg;
721         int rc;
722
723         lustre_cfg_bufs_reset(&bufs, devname);
724         lustre_cfg_bufs_set(&bufs, 1, conf, sizeof(*conf));
725         lcfg = lustre_cfg_new(LCFG_SEC_FLAVOR, &bufs);
726
727         rc = record_lcfg(obd, llh, lcfg);
728
729         lustre_cfg_free(lcfg);
730         return rc;
731 }
732
733 static int record_lov_setup(struct obd_device *obd, struct llog_handle *llh,
734                             char *devname, struct lov_desc *desc)
735 {
736         struct lustre_cfg_bufs bufs;
737         struct lustre_cfg *lcfg;
738         int rc;
739
740         lustre_cfg_bufs_reset(&bufs, devname);
741         lustre_cfg_bufs_set(&bufs, 1, desc, sizeof(*desc));
742         lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
743         if (!lcfg) 
744                 return -ENOMEM;
745         rc = record_lcfg(obd, llh, lcfg);
746
747         lustre_cfg_free(lcfg);
748         return rc;
749 }
750
751 static int record_lmv_setup(struct obd_device *obd, struct llog_handle *llh,
752                             char *devname, struct lmv_desc *desc)
753 {
754         struct lustre_cfg_bufs bufs;
755         struct lustre_cfg *lcfg;
756         int rc;
757
758         lustre_cfg_bufs_reset(&bufs, devname);
759         lustre_cfg_bufs_set(&bufs, 1, desc, sizeof(*desc));
760         lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
761
762         rc = record_lcfg(obd, llh, lcfg);
763
764         lustre_cfg_free(lcfg);
765         return rc;
766 }
767
768 static inline int record_mdc_add(struct obd_device *obd,
769                                  struct llog_handle *llh,
770                                  char *logname, char *mdcuuid,
771                                  char *mdtuuid, char *index,
772                                  char *gen)
773 {
774         return record_base(obd,llh,logname,0,LCFG_ADD_MDC,
775                            mdtuuid,index,gen,mdcuuid);
776 }
777
778 static inline int record_lov_add(struct obd_device *obd,
779                                  struct llog_handle *llh,
780                                  char *lov_name, char *ost_uuid,
781                                  char *index, char *gen)
782 {
783         return record_base(obd,llh,lov_name,0,LCFG_LOV_ADD_OBD,
784                            ost_uuid,index,gen,0);
785 }
786
787 static inline int record_mount_opt(struct obd_device *obd,
788                                    struct llog_handle *llh,
789                                    char *profile, char *lov_name,
790                                    char *mdc_name)
791 {
792         return record_base(obd,llh,NULL,0,LCFG_MOUNTOPT,
793                            profile,lov_name,mdc_name,0);
794 }
795
796 static int record_marker(struct obd_device *obd, struct llog_handle *llh,
797                          struct fs_db *fsdb, __u32 flags,
798                          char *tgtname, char *comment)
799 {
800         struct cfg_marker marker;
801         struct lustre_cfg_bufs bufs;
802         struct lustre_cfg *lcfg;
803         int rc;
804
805         if (flags & CM_START)
806                 fsdb->fsdb_gen++;
807         marker.cm_step = fsdb->fsdb_gen;
808         marker.cm_flags = flags;
809         marker.cm_vers = LUSTRE_VERSION_CODE;
810         strncpy(marker.cm_tgtname, tgtname, sizeof(marker.cm_tgtname)); 
811         strncpy(marker.cm_comment, comment, sizeof(marker.cm_comment)); 
812         marker.cm_createtime = cfs_time_current_sec();
813         marker.cm_canceltime = 0;
814         lustre_cfg_bufs_reset(&bufs, NULL);
815         lustre_cfg_bufs_set(&bufs, 1, &marker, sizeof(marker));
816         lcfg = lustre_cfg_new(LCFG_MARKER, &bufs);
817         if (!lcfg) 
818                 return -ENOMEM;
819         rc = record_lcfg(obd, llh, lcfg);
820
821         lustre_cfg_free(lcfg);
822         return rc;
823 }
824
825 static int record_start_log(struct obd_device *obd,
826                             struct llog_handle **llh, char *name)
827 {
828         static struct obd_uuid cfg_uuid = { .uuid = "config_uuid" };
829         struct lvfs_run_ctxt saved;
830         int rc = 0;
831
832         if (*llh) {
833                 GOTO(out, rc = -EBUSY);
834         }
835
836         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
837
838         rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
839                          llh, NULL, name);
840         if (rc == 0)
841                 llog_init_handle(*llh, LLOG_F_IS_PLAIN, &cfg_uuid);
842         else
843                 *llh = NULL;
844
845         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
846
847 out:
848         if (rc) {
849                 CERROR("Can't start log %s: %d\n", name, rc);
850         }
851         RETURN(rc);
852 }
853
854 static int record_end_log(struct obd_device *obd, struct llog_handle **llh)
855 {
856         struct lvfs_run_ctxt saved;
857         int rc = 0;
858
859         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
860
861         rc = llog_close(*llh);
862         *llh = NULL;
863
864         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
865         RETURN(rc);
866 }
867
868 static int mgs_log_is_empty(struct obd_device *obd, char *name)
869 {
870         struct lvfs_run_ctxt saved;
871         struct llog_handle *llh;
872         int rc = 0;
873
874         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
875         rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
876                          &llh, NULL, name);
877         if (rc == 0) {
878                 llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
879                 rc = llog_get_size(llh);
880                 llog_close(llh);
881         }
882         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
883         /* header is record 1 */
884         return(rc <= 1);
885 }
886
887 /******************** config "macros" *********************/
888
889 /* write an lcfg directly into a log (with markers) */
890 static int mgs_write_log_direct(struct obd_device *obd, struct fs_db *fsdb,
891                                 char *logname, struct lustre_cfg *lcfg, 
892                                 char *devname, char *comment)
893 {
894         struct llog_handle *llh = NULL;
895         int rc;
896         ENTRY;
897
898         if (!lcfg) 
899                 RETURN(-ENOMEM);
900
901         rc = record_start_log(obd, &llh, logname);
902         if (rc) 
903                 RETURN(rc);
904
905         /* FIXME These should be a single journal transaction */
906         rc = record_marker(obd, llh, fsdb, CM_START, devname, comment); 
907         
908         rc = record_lcfg(obd, llh, lcfg);
909
910         rc = record_marker(obd, llh, fsdb, CM_END, devname, comment);
911         rc = record_end_log(obd, &llh);
912
913         RETURN(rc);
914 }
915
916 /* write the lcfg in all logs for the given fs */
917 int mgs_write_log_direct_all(struct obd_device *obd, struct fs_db *fsdb,
918                              struct mgs_target_info *mti, 
919                              struct lustre_cfg *lcfg,
920                              char *devname, char *comment)
921 {
922         struct mgs_obd *mgs = &obd->u.mgs;
923         struct list_head dentry_list;
924         struct l_linux_dirent *dirent, *n;
925         char *fsname = mti->mti_fsname;
926         char *logname;
927         int rc = 0, len = strlen(fsname);
928         ENTRY;
929         
930         /* We need to set params for any future logs 
931            as well. FIXME Append this file to every new log. 
932            Actually, we should store as params (text), not llogs.  Or
933            in a database. */
934         name_create(&logname, fsname, "-params");
935         if (mgs_log_is_empty(obd, logname)) {
936                 struct llog_handle *llh = NULL;
937                 rc = record_start_log(obd, &llh, logname);
938                 record_end_log(obd, &llh);
939         }
940         name_destroy(&logname);
941         if (rc) 
942                 RETURN(rc);
943
944         /* Find all the logs in the CONFIGS directory */
945         rc = class_dentry_readdir(obd, mgs->mgs_configs_dir,
946                                   mgs->mgs_vfsmnt, &dentry_list);
947         if (rc) {
948                 CERROR("Can't read %s dir\n", MOUNT_CONFIGS_DIR);
949                 RETURN(rc);
950         }
951
952         /* Could use fsdb index maps instead of directory listing */
953         list_for_each_entry_safe(dirent, n, &dentry_list, lld_list) {
954                 list_del(&dirent->lld_list);
955                 if (strncmp(fsname, dirent->lld_name, len) == 0) {
956                         CDEBUG(D_MGS, "Changing log %s\n", dirent->lld_name);
957                         /* Erase any old settings of this same parameter */
958                         mgs_modify(obd, fsdb, mti, dirent->lld_name, devname, 
959                                    comment, CM_SKIP);
960                         /* Write the new one */
961                         rc = mgs_write_log_direct(obd, fsdb, dirent->lld_name,
962                                                   lcfg, devname, comment);
963                         if (rc)
964                                 CERROR("err %d writing log %s\n", rc, 
965                                        dirent->lld_name);
966                 }
967                 OBD_FREE(dirent, sizeof(*dirent));
968         }
969
970         RETURN(rc);
971 }
972
973 struct temp_comp
974 {
975         struct mgs_target_info   *comp_tmti;
976         struct mgs_target_info   *comp_mti;
977         struct fs_db             *comp_fsdb;
978         struct obd_device        *comp_obd;
979         struct sec_flavor_config  comp_sec;
980 };
981
982 static int mgs_write_log_mdc_to_mdt(struct obd_device *, struct fs_db *,
983                                     struct mgs_target_info *,
984                                     struct sec_flavor_config *, char *);
985
986 static int mgs_steal_llog_handler(struct llog_handle *llh,
987                                   struct llog_rec_hdr *rec,
988                                   void *data)
989 {
990         struct obd_device * obd;
991         struct mgs_target_info *mti, *tmti;
992         struct fs_db *fsdb;
993         int cfg_len = rec->lrh_len;
994         char *cfg_buf = (char*) (rec + 1);
995         struct lustre_cfg *lcfg;
996         struct sec_flavor_config *sec_conf;
997         int rc = 0;
998         struct llog_handle *mdt_llh = NULL;
999         static int got_an_osc_or_mdc = 0;
1000         /* 0: not found any osc/mdc;
1001            1: found osc;
1002            2: found mdc;
1003         */
1004         static int last_step = -1;
1005
1006         ENTRY;
1007
1008         mti = ((struct temp_comp*)data)->comp_mti;
1009         tmti = ((struct temp_comp*)data)->comp_tmti;
1010         fsdb = ((struct temp_comp*)data)->comp_fsdb;
1011         obd = ((struct temp_comp*)data)->comp_obd;
1012         sec_conf = &((struct temp_comp*)data)->comp_sec;
1013
1014         if (rec->lrh_type != OBD_CFG_REC) {
1015                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
1016                 RETURN(-EINVAL);
1017         }
1018
1019         rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
1020         if (rc) {
1021                 CERROR("Insane cfg\n");
1022                 RETURN(rc);
1023         }
1024
1025         lcfg = (struct lustre_cfg *)cfg_buf;
1026
1027         if (lcfg->lcfg_command == LCFG_MARKER) {
1028                 struct cfg_marker *marker;
1029                 marker = lustre_cfg_buf(lcfg, 1);
1030                 if (!strncmp(marker->cm_comment,"add osc",7) &&
1031                     (marker->cm_flags & CM_START)){
1032                         got_an_osc_or_mdc = 1;
1033                         rc = record_start_log(obd, &mdt_llh, mti->mti_svname);
1034                         rc = record_marker(obd, mdt_llh, fsdb, CM_START,
1035                                            mti->mti_svname,"add osc(copied)");
1036                         rc = record_end_log(obd, &mdt_llh);
1037                         last_step = marker->cm_step;
1038                         RETURN(rc);
1039                 }
1040                 if (!strncmp(marker->cm_comment,"add osc",7) &&
1041                     (marker->cm_flags & CM_END)){
1042                         LASSERT(last_step == marker->cm_step);
1043                         last_step = -1;
1044                         got_an_osc_or_mdc = 0;
1045                         rc = record_start_log(obd, &mdt_llh, mti->mti_svname);
1046                         rc = record_marker(obd, mdt_llh, fsdb, CM_END,
1047                                            mti->mti_svname,"add osc(copied)");
1048                         rc = record_end_log(obd, &mdt_llh);
1049                         RETURN(rc);
1050                 }
1051                 if (!strncmp(marker->cm_comment,"add mdc",7) &&
1052                     (marker->cm_flags & CM_START)){
1053                         got_an_osc_or_mdc = 2;
1054                         last_step = marker->cm_step;
1055                         memcpy(tmti->mti_svname, marker->cm_tgtname,
1056                                strlen(marker->cm_tgtname));
1057
1058                         RETURN(rc);
1059                 }
1060                 if (!strncmp(marker->cm_comment,"add mdc",7) &&
1061                     (marker->cm_flags & CM_END)){
1062                         LASSERT(last_step == marker->cm_step);
1063                         last_step = -1;
1064                         got_an_osc_or_mdc = 0;
1065                         RETURN(rc);
1066                 }
1067         }
1068
1069         if (got_an_osc_or_mdc == 0 || last_step < 0)
1070                 RETURN(rc);
1071         
1072         if (lcfg->lcfg_command == LCFG_ADD_UUID) {
1073                 uint64_t nodenid;
1074                 nodenid = lcfg->lcfg_nid;
1075                 
1076                 tmti->mti_nids[tmti->mti_nid_count] = nodenid;
1077                 tmti->mti_nid_count++;
1078
1079                 RETURN(rc);
1080         }
1081
1082         if (lcfg->lcfg_command == LCFG_SETUP) {
1083                 char *target;
1084
1085                 target = lustre_cfg_string(lcfg, 1);
1086                 memcpy(tmti->mti_uuid, target, strlen(target));
1087                 RETURN(rc);
1088         }
1089
1090         if (lcfg->lcfg_command == LCFG_SEC_FLAVOR) {
1091                 memcpy(sec_conf, lustre_cfg_buf(lcfg, 1), sizeof(*sec_conf));
1092                 RETURN(rc);
1093         }
1094
1095         if (lcfg->lcfg_command == LCFG_ADD_MDC) {
1096                 int index;
1097
1098                 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1)
1099                         RETURN (-EINVAL);
1100
1101                 memcpy(tmti->mti_fsname, mti->mti_fsname,
1102                        strlen(mti->mti_fsname));
1103                 tmti->mti_stripe_index = index;
1104
1105                 mgs_write_log_mdc_to_mdt(obd, fsdb, tmti, sec_conf,
1106                                          mti->mti_svname);
1107                 memset(tmti, 0, sizeof(*tmti));
1108                 RETURN(rc);
1109         }
1110         RETURN(rc);
1111 }
1112
1113 /* fsdb->fsdb_sem is already held  in mgs_write_log_target*/
1114 /* stealed from mgs_get_fsdb_from_llog*/
1115 static int mgs_steal_llog_for_mdt_from_client(struct obd_device *obd,
1116                                               char *client_name,
1117                                               struct temp_comp* comp)
1118 {
1119         struct llog_handle *loghandle;
1120         struct lvfs_run_ctxt saved;
1121         struct mgs_target_info *tmti;
1122         int rc, rc2;
1123         ENTRY;
1124
1125         OBD_ALLOC_PTR(tmti);
1126         if (tmti == NULL)
1127                 RETURN(-ENOMEM);
1128
1129         comp->comp_tmti = tmti;
1130         comp->comp_obd = obd;
1131
1132         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
1133
1134         rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
1135                          &loghandle, NULL, client_name);
1136         if (rc)
1137                 GOTO(out_pop, rc);
1138
1139         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
1140         if (rc)
1141                 GOTO(out_close, rc);
1142
1143         rc = llog_process(loghandle, mgs_steal_llog_handler, (void *)comp, NULL);
1144         CDEBUG(D_MGS, "steal llog re = %d\n", rc);
1145 out_close:
1146         rc2 = llog_close(loghandle);
1147         if (!rc)
1148                 rc = rc2;
1149 out_pop:
1150         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
1151         OBD_FREE_PTR(tmti);
1152         RETURN(rc);
1153 }
1154
1155 /* lmv is the second thing for client logs */
1156 /* copied from mgs_write_log_lov. Please refer to that.  */
1157 static int mgs_write_log_lmv(struct obd_device *obd, struct fs_db *fsdb,
1158                              struct mgs_target_info *mti,
1159                              char *logname, char *lmvname)
1160 {
1161         struct llog_handle *llh = NULL;
1162         struct lmv_desc *lmvdesc;
1163         char *uuid;
1164         int rc = 0;
1165         ENTRY;
1166
1167         CDEBUG(D_MGS, "Writing lmv(%s) log for %s\n", lmvname,logname);
1168
1169         OBD_ALLOC(lmvdesc, sizeof(*lmvdesc));
1170         if (lmvdesc == NULL)
1171                 RETURN(-ENOMEM);
1172         lmvdesc->ld_active_tgt_count = 0;
1173         lmvdesc->ld_tgt_count = 0;
1174         sprintf((char*)lmvdesc->ld_uuid.uuid, "%s_UUID", lmvname);
1175         uuid = (char *)lmvdesc->ld_uuid.uuid;
1176
1177         rc = record_start_log(obd, &llh, logname);
1178         rc = record_marker(obd, llh, fsdb, CM_START, lmvname, "lmv setup");
1179         rc = record_attach(obd, llh, lmvname, "lmv", uuid);
1180         rc = record_lmv_setup(obd, llh, lmvname, lmvdesc);
1181         rc = record_marker(obd, llh, fsdb, CM_END, lmvname, "lmv setup");
1182         rc = record_end_log(obd, &llh);
1183
1184         OBD_FREE(lmvdesc, sizeof(*lmvdesc));
1185         RETURN(rc);
1186 }
1187 /***************************************END PROTO**********************/
1188
1189 /* lov is the first thing in the mdt and client logs */
1190 static int mgs_write_log_lov(struct obd_device *obd, struct fs_db *fsdb,
1191                              struct mgs_target_info *mti,
1192                              char *logname, char *lovname)
1193 {
1194         struct llog_handle *llh = NULL;
1195         struct lov_desc *lovdesc;
1196         char *uuid;
1197         int rc = 0;
1198         ENTRY;
1199
1200         CDEBUG(D_MGS, "Writing lov(%s) log for %s\n", lovname, logname);
1201
1202         /*
1203         #01 L attach   0:lov_mdsA  1:lov  2:71ccb_lov_mdsA_19f961a9e1
1204         #02 L lov_setup 0:lov_mdsA 1:(struct lov_desc)
1205               uuid=lov1_UUID, stripe count=1, size=1048576, offset=0, pattern=0
1206         */
1207
1208         /* FIXME just make lov_setup accept empty desc (put uuid in buf 2) */
1209         OBD_ALLOC(lovdesc, sizeof(*lovdesc));
1210         if (lovdesc == NULL)
1211                 RETURN(-ENOMEM);
1212         lovdesc->ld_magic = LOV_DESC_MAGIC;
1213         lovdesc->ld_tgt_count = 0;
1214         /* Defaults.  Can be changed later by lcfg config_param */
1215         lovdesc->ld_default_stripe_count = 1;
1216         lovdesc->ld_pattern = LOV_PATTERN_RAID0;
1217         lovdesc->ld_default_stripe_size = 1024 * 1024;
1218         lovdesc->ld_default_stripe_offset = 0;
1219         lovdesc->ld_qos_maxage = QOS_DEFAULT_MAXAGE;
1220         sprintf((char*)lovdesc->ld_uuid.uuid, "%s_UUID", lovname);
1221         /* can these be the same? */
1222         uuid = (char *)lovdesc->ld_uuid.uuid;
1223
1224         /* This should always be the first entry in a log.
1225         rc = mgs_clear_log(obd, logname); */
1226         rc = record_start_log(obd, &llh, logname);
1227         if (rc) 
1228                 GOTO(out, rc);
1229         /* FIXME these should be a single journal transaction */
1230         rc = record_marker(obd, llh, fsdb, CM_START, lovname, "lov setup"); 
1231         rc = record_attach(obd, llh, lovname, "lov", uuid);
1232         rc = record_lov_setup(obd, llh, lovname, lovdesc);
1233         rc = record_marker(obd, llh, fsdb, CM_END, lovname, "lov setup");
1234         rc = record_end_log(obd, &llh);
1235 out:        
1236         OBD_FREE(lovdesc, sizeof(*lovdesc));
1237         RETURN(rc);
1238 }
1239
1240 /* add failnids to open log */
1241 static int mgs_write_log_failnids(struct obd_device *obd,
1242                                   struct mgs_target_info *mti,
1243                                   struct llog_handle *llh,
1244                                   char *cliname)
1245 {
1246         char *failnodeuuid = NULL;
1247         char *ptr = mti->mti_params;
1248         lnet_nid_t nid;
1249         int rc = 0;
1250
1251         /*
1252         #03 L add_uuid  nid=uml1@tcp(0x20000c0a80201) nal=90 0:  1:uml1_UUID
1253         #04 L add_uuid  nid=1@elan(0x1000000000001)   nal=90 0:  1:uml1_UUID
1254         #05 L setup    0:OSC_uml1_ost1_mdsA  1:ost1_UUID  2:uml1_UUID
1255         #06 L add_uuid  nid=uml2@tcp(0x20000c0a80202) nal=90 0:  1:uml2_UUID
1256         #0x L add_uuid  nid=2@elan(0x1000000000002)   nal=90 0:  1:uml2_UUID
1257         #07 L add_conn 0:OSC_uml1_ost1_mdsA  1:uml2_UUID
1258         */
1259
1260         /* Pull failnid info out of params string */
1261         while (class_find_param(ptr, PARAM_FAILNODE, &ptr) == 0) {
1262                 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
1263                         if (failnodeuuid == NULL) {
1264                                 /* We don't know the failover node name,
1265                                    so just use the first nid as the uuid */
1266                                 rc = name_create(&failnodeuuid,
1267                                                  libcfs_nid2str(nid), "");
1268                                 if (rc) 
1269                                         return rc;
1270                         }
1271                         CDEBUG(D_MGS, "add nid %s for failover uuid %s, "
1272                                "client %s\n", libcfs_nid2str(nid),
1273                                failnodeuuid, cliname);
1274                         rc = record_add_uuid(obd, llh, nid, failnodeuuid);
1275                 }
1276                 if (failnodeuuid) {
1277                         rc = record_add_conn(obd, llh, cliname, failnodeuuid);
1278                         name_destroy(&failnodeuuid);
1279                         failnodeuuid = NULL;
1280                 }
1281         }
1282
1283         return rc;
1284 }
1285
1286 static
1287 void extract_sec_flavor(char *params, char *key, char **ptr)
1288 {
1289         char *val = NULL, *tail;
1290         int   len;
1291
1292         *ptr = NULL;
1293
1294         if (class_find_param(params, key, &val))
1295                 return;
1296
1297         tail = strchr(val, ' ');
1298         if (tail == NULL)
1299                 len = strlen(val);
1300         else
1301                 len = tail - val;
1302
1303         OBD_ALLOC(*ptr, len + 1);
1304         if (*ptr == NULL)
1305                 return;
1306
1307         memcpy(*ptr, val, len);
1308         (*ptr)[len] = '\0';
1309 }
1310
1311 static int mgs_write_log_mdc_to_lmv(struct obd_device *obd, struct fs_db *fsdb,
1312                                     struct mgs_target_info *mti,
1313                                     struct sec_flavor_config *sec_conf,
1314                                     char *logname, char *lmvname)
1315 {
1316         struct llog_handle *llh = NULL;
1317         char *mdcname, *nodeuuid, *mdcuuid, *lmvuuid;
1318         char index[5];
1319         int i, rc;
1320         ENTRY;
1321         
1322         if (mgs_log_is_empty(obd, logname)) {
1323                 CERROR("log is empty! Logical error\n");
1324                 RETURN(-EINVAL);
1325         }
1326
1327         CDEBUG(D_MGS, "adding mdc for %s to log %s:lmv(%s)\n",
1328                mti->mti_svname, logname, lmvname);
1329
1330         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
1331         name_create(&mdcname, mti->mti_svname, "-mdc");
1332         name_create(&mdcuuid, mdcname, "_UUID");
1333         name_create(&lmvuuid, lmvname, "_UUID");
1334
1335         rc = record_start_log(obd, &llh, logname);
1336         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,
1337                            "add mdc");
1338
1339         for (i = 0; i < mti->mti_nid_count; i++) {
1340                 CDEBUG(D_MGS, "add nid %s for mdt\n", 
1341                        libcfs_nid2str(mti->mti_nids[i]));
1342                        
1343                 rc = record_add_uuid(obd, llh, mti->mti_nids[i], nodeuuid);
1344         }
1345
1346         rc = record_attach(obd, llh, mdcname, LUSTRE_MDC_NAME, lmvuuid);
1347         rc = record_setup(obd, llh, mdcname, mti->mti_uuid, nodeuuid, 0, 0);
1348         rc = record_sec_flavor(obd, llh, mdcname, sec_conf);
1349         rc = mgs_write_log_failnids(obd, mti, llh, mdcname);
1350         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
1351         rc = record_mdc_add(obd, llh, lmvname, mdcuuid, mti->mti_uuid,
1352                             index, "1");
1353         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname,
1354                            "add mdc"); 
1355         rc = record_end_log(obd, &llh);
1356
1357         name_destroy(&lmvuuid);
1358         name_destroy(&mdcuuid);
1359         name_destroy(&mdcname);
1360         name_destroy(&nodeuuid);
1361         RETURN(rc);
1362 }
1363
1364 /* add new mdc to already existent MDS */
1365 static int mgs_write_log_mdc_to_mdt(struct obd_device *obd, struct fs_db *fsdb,
1366                                     struct mgs_target_info *mti,
1367                                     struct sec_flavor_config *sec_conf,
1368                                     char *logname)
1369 {
1370         struct llog_handle *llh = NULL;
1371         char *nodeuuid, *mdcname, *mdcuuid, *mdtuuid;
1372         int idx = mti->mti_stripe_index;
1373         char index[9];
1374         int i, rc;
1375
1376         ENTRY;
1377         if (mgs_log_is_empty(obd, mti->mti_svname)) {
1378                 CERROR("log is empty! Logical error\n");
1379                 RETURN (-EINVAL);
1380         }
1381
1382         CDEBUG(D_MGS, "adding mdc index %d to %s\n", idx, logname);
1383
1384         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
1385         snprintf(index, sizeof(index), "-mdc%04x", idx);
1386         name_create(&mdcname, logname, index);
1387         name_create(&mdcuuid, mdcname, "_UUID");
1388         name_create(&mdtuuid, logname, "_UUID");
1389
1390         rc = record_start_log(obd, &llh, logname);
1391         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname, "add mdc");
1392         for (i = 0; i < mti->mti_nid_count; i++) {
1393                 CDEBUG(D_MGS, "add nid %s for mdt\n",
1394                        libcfs_nid2str(mti->mti_nids[i]));
1395                 rc = record_add_uuid(obd, llh, mti->mti_nids[i], nodeuuid);
1396         }
1397         rc = record_attach(obd, llh, mdcname, LUSTRE_MDC_NAME, mdcuuid);
1398         rc = record_setup(obd, llh, mdcname, mti->mti_uuid, nodeuuid, 0, 0);
1399         rc = record_sec_flavor(obd, llh, mdcname, sec_conf);
1400         rc = mgs_write_log_failnids(obd, mti, llh, mdcname);
1401         snprintf(index, sizeof(index), "%d", idx);
1402
1403         rc = record_mdc_add(obd, llh, logname, mdcuuid, mti->mti_uuid,
1404                             index, "1");
1405         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname, "add mdc"); 
1406         rc = record_end_log(obd, &llh);
1407
1408         name_destroy(&mdcuuid);
1409         name_destroy(&mdcname);
1410         name_destroy(&nodeuuid);
1411         name_destroy(&mdtuuid);
1412         RETURN(rc);
1413 }
1414
1415 static int mgs_write_log_mdt0(struct obd_device *obd, struct fs_db *fsdb,
1416                               struct mgs_target_info *mti)
1417 {
1418         char *log = mti->mti_svname;
1419         struct llog_handle *llh = NULL;
1420         char *uuid, *lovname;
1421         char mdt_index[5];
1422         char *ptr = mti->mti_params;
1423         int rc = 0, failout = 0;
1424         ENTRY;
1425
1426         OBD_ALLOC(uuid, sizeof(struct obd_uuid));
1427         if (uuid == NULL)
1428                 RETURN(-ENOMEM);
1429
1430         if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0) 
1431                 failout = (strncmp(ptr, "failout", 7) == 0);
1432
1433         name_create(&lovname, log, "-mdtlov");
1434         if (mgs_log_is_empty(obd, log))
1435                 rc = mgs_write_log_lov(obd, fsdb, mti, log, lovname);
1436
1437         sprintf(uuid, "%s_UUID", log);
1438         sprintf(mdt_index,"%d",mti->mti_stripe_index);        
1439
1440         /* add MDT itself */
1441         rc = record_start_log(obd, &llh, log);
1442         if (rc) 
1443                 GOTO(out, rc);
1444         
1445         /* FIXME this whole fn should be a single journal transaction */
1446         rc = record_marker(obd, llh, fsdb, CM_START, log, "add mdt");
1447         rc = record_attach(obd, llh, log, LUSTRE_MDT_NAME, uuid);
1448         rc = record_mount_opt(obd, llh, log, lovname, NULL);
1449         rc = record_setup(obd, llh, log, uuid, mdt_index, lovname, 
1450                         failout ? "n" : "f");
1451         rc = record_marker(obd, llh, fsdb, CM_END, log, "add mdt");
1452         rc = record_end_log(obd, &llh);
1453 out:
1454         name_destroy(&lovname);
1455         OBD_FREE(uuid, sizeof(struct obd_uuid));
1456         RETURN(rc);
1457 }
1458
1459 /* envelope method for all layers log */
1460 static int mgs_write_log_mdt(struct obd_device *obd, struct fs_db *fsdb,
1461                               struct mgs_target_info *mti)
1462 {
1463         char *cliname, *sec;
1464         struct llog_handle *llh = NULL;
1465         struct temp_comp comp = { 0 };
1466         struct sec_flavor_config sec_conf_mdt, sec_conf_cli;
1467         char mdt_index[9];
1468         int rc, i = 0;
1469         ENTRY;
1470
1471         CDEBUG(D_MGS, "writing new mdt %s\n", mti->mti_svname);
1472
1473 #if 0
1474         /* COMPAT_146 */
1475         if (mti->mti_flags & LDD_F_UPGRADE14) {
1476                 /* We're starting with an old uuid.  Assume old name for lov
1477                    as well since the lov entry already exists in the log. */
1478                 CDEBUG(D_MGS, "old mds uuid %s\n", mti->mti_uuid);
1479                 if (strncmp(mti->mti_uuid, fsdb->fsdb_mdtlov + 4, 
1480                             strlen(fsdb->fsdb_mdtlov) - 4) != 0) {
1481                         CERROR("old mds uuid %s doesn't match log %s (%s)\n",
1482                                mti->mti_uuid, fsdb->fsdb_mdtlov, 
1483                                fsdb->fsdb_mdtlov + 4);
1484                         RETURN(-EINVAL);
1485                 }
1486         }
1487         /* end COMPAT_146 */
1488 #endif
1489         if (mti->mti_uuid[0] == '\0') {
1490                 /* Make up our own uuid */
1491                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
1492                          "%s_UUID", mti->mti_svname);
1493         }
1494
1495         /* security flavor */
1496         extract_sec_flavor(mti->mti_params, PARAM_SEC_RPC_MDT, &sec);
1497         rc = sptlrpc_parse_flavor(LUSTRE_MDT, LUSTRE_MDT, sec, &sec_conf_mdt);
1498         name_destroy(&sec);
1499         if (rc)
1500                 RETURN(rc);
1501
1502         extract_sec_flavor(mti->mti_params, PARAM_SEC_RPC_CLI, &sec);
1503         rc = sptlrpc_parse_flavor(LUSTRE_CLI, LUSTRE_MDT, sec, &sec_conf_cli);
1504         name_destroy(&sec);
1505         if (rc)
1506                 RETURN(rc);
1507
1508         /* add mdt */
1509         rc = mgs_write_log_mdt0(obd, fsdb, mti);
1510         
1511         /* Append the mdt info to the client log */
1512         name_create(&cliname, mti->mti_fsname, "-client");
1513         
1514         if (mgs_log_is_empty(obd, cliname)) { 
1515                 /* Start client log */
1516                 rc = mgs_write_log_lov(obd, fsdb, mti, cliname, 
1517                                        fsdb->fsdb_clilov);
1518                 rc = mgs_write_log_lmv(obd, fsdb, mti, cliname, 
1519                                        fsdb->fsdb_clilmv);
1520         }
1521
1522         /* 
1523         #09 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
1524         #10 L attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f
1525         #11 L setup    0:MDC_uml1_mdsA_MNT_client  1:mdsA_UUID  2:uml1_UUID
1526         #12 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
1527         #13 L add_conn 0:MDC_uml1_mdsA_MNT_client  1:uml2_UUID
1528         #14 L mount_option 0:  1:client  2:lov1  3:MDC_uml1_mdsA_MNT_client
1529         */
1530         
1531 #if 0
1532         /* COMPAT_146 */
1533         if (mti->mti_flags & LDD_F_UPGRADE14) { 
1534                 rc = record_start_log(obd, &llh, cliname);
1535                 if (rc) 
1536                         GOTO(out, rc);
1537         
1538                 rc = record_marker(obd, llh, fsdb, CM_START, 
1539                                    mti->mti_svname,"add mdc");
1540                                    
1541                 /* Old client log already has MDC entry, but needs mount opt 
1542                    for new client name (lustre-client) */
1543                 /* FIXME Old MDT log already has an old mount opt 
1544                    which we should remove (currently handled by
1545                    class_del_profiles()) */
1546                 rc = record_mount_opt(obd, llh, cliname, fsdb->fsdb_clilov,
1547                                       fsdb->fsdb_mdc);
1548                 /* end COMPAT_146 */
1549                 
1550                 rc = record_marker(obd, llh, fsdb, CM_END, 
1551                                    mti->mti_svname, "add mdc");
1552         } else
1553 #endif
1554         {
1555                 /* copy client info about lov/lmv */
1556                 comp.comp_mti = mti;
1557                 comp.comp_fsdb = fsdb;
1558                 
1559                 rc = mgs_steal_llog_for_mdt_from_client(obd, cliname, 
1560                                                         &comp);
1561
1562                 rc = mgs_write_log_mdc_to_lmv(obd, fsdb, mti, &sec_conf_cli,
1563                                               cliname, fsdb->fsdb_clilmv);
1564                 /* add mountopts */
1565                 rc = record_start_log(obd, &llh, cliname);
1566                 if (rc) 
1567                         GOTO(out, rc);
1568
1569                 rc = record_marker(obd, llh, fsdb, CM_START, cliname, 
1570                                    "mount opts");
1571                 rc = record_mount_opt(obd, llh, cliname, fsdb->fsdb_clilov,
1572                                       fsdb->fsdb_clilmv);
1573                 rc = record_marker(obd, llh, fsdb, CM_END, cliname, 
1574                                    "mount opts"); 
1575         }
1576                            
1577         rc = record_end_log(obd, &llh);
1578 out:
1579         name_destroy(&cliname);
1580         
1581         // for_all_existing_mdt except current one
1582         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
1583                 char *mdtname;
1584                 if (i !=  mti->mti_stripe_index &&
1585                     test_bit(i,  fsdb->fsdb_mdt_index_map)) {
1586                         sprintf(mdt_index,"-MDT%04x",i);
1587                         
1588                         name_create(&mdtname, mti->mti_fsname, mdt_index);
1589                         rc = mgs_write_log_mdc_to_mdt(obd, fsdb, mti,
1590                                                       &sec_conf_mdt, mdtname);
1591                         name_destroy(&mdtname);
1592                 }
1593         }
1594         
1595         RETURN(rc);
1596 }
1597
1598 /* Add the ost info to the client/mdt lov */
1599 static int mgs_write_log_osc_to_lov(struct obd_device *obd, struct fs_db *fsdb,
1600                                     struct mgs_target_info *mti,
1601                                     char *logname, char *suffix, char *lovname,
1602                                     struct sec_flavor_config *sec_conf,
1603                                     int flags)
1604 {
1605         struct llog_handle *llh = NULL;
1606         char *nodeuuid, *oscname, *oscuuid, *lovuuid, *svname;
1607         char index[5];
1608         int i, rc;
1609
1610         ENTRY;
1611         CDEBUG(D_INFO, "adding osc for %s to log %s\n",
1612                mti->mti_svname, logname);
1613         
1614         if (mgs_log_is_empty(obd, logname)) {
1615                 /* The first item in the log must be the lov, so we have
1616                    somewhere to add our osc. */
1617                 rc = mgs_write_log_lov(obd, fsdb, mti, logname, lovname);
1618         }
1619   
1620         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
1621         name_create(&svname, mti->mti_svname, "-osc");
1622         name_create(&oscname, svname, suffix);
1623         name_create(&oscuuid, oscname, "_UUID");
1624         name_create(&lovuuid, lovname, "_UUID");
1625
1626         /*
1627         #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
1628         multihomed (#4)
1629         #04 L add_uuid  nid=1@elan(0x1000000000001)  nal=90 0:  1:uml1_UUID
1630         #04 L attach   0:OSC_uml1_ost1_MNT_client  1:osc  2:89070_lov1_a41dff51a
1631         #05 L setup    0:OSC_uml1_ost1_MNT_client  1:ost1_UUID  2:uml1_UUID
1632         failover (#6,7)
1633         #06 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
1634         #07 L add_conn 0:OSC_uml1_ost1_MNT_client  1:uml2_UUID
1635         #08 L lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1
1636         */
1637         
1638         rc = record_start_log(obd, &llh, logname);
1639         if (rc) 
1640                 GOTO(out, rc);
1641         /* FIXME these should be a single journal transaction */
1642         rc = record_marker(obd, llh, fsdb, CM_START | flags, mti->mti_svname,
1643                            "add osc"); 
1644         for (i = 0; i < mti->mti_nid_count; i++) {
1645                 CDEBUG(D_MGS, "add nid %s\n", libcfs_nid2str(mti->mti_nids[i]));
1646                 rc = record_add_uuid(obd, llh, mti->mti_nids[i], nodeuuid);
1647         }
1648         rc = record_attach(obd, llh, oscname, LUSTRE_OSC_NAME, lovuuid);
1649         rc = record_setup(obd, llh, oscname, mti->mti_uuid, nodeuuid, 0, 0);
1650         rc = record_sec_flavor(obd, llh, oscname, sec_conf);
1651         rc = mgs_write_log_failnids(obd, mti, llh, oscname);
1652         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
1653         rc = record_lov_add(obd, llh, lovname, mti->mti_uuid, index, "1");
1654         rc = record_marker(obd, llh, fsdb, CM_END | flags, mti->mti_svname,
1655                            "add osc"); 
1656         rc = record_end_log(obd, &llh);
1657 out:        
1658         name_destroy(&lovuuid);
1659         name_destroy(&oscuuid);
1660         name_destroy(&oscname);
1661         name_destroy(&svname);
1662         name_destroy(&nodeuuid);
1663         RETURN(rc);
1664 }
1665
1666 static int mgs_write_log_ost(struct obd_device *obd, struct fs_db *fsdb,
1667                              struct mgs_target_info *mti)
1668 {
1669         struct llog_handle *llh = NULL;
1670         char *logname, *lovname, *sec;
1671         char mdt_index[9];
1672         char *ptr = mti->mti_params;
1673         struct sec_flavor_config sec_conf_mdt, sec_conf_cli;
1674         int rc, flags = 0, failout = 0, i;
1675         ENTRY;
1676         
1677         CDEBUG(D_MGS, "writing new ost %s\n", mti->mti_svname);
1678
1679         /* The ost startup log */
1680
1681         /* If the ost log already exists, that means that someone reformatted
1682            the ost and it called target_add again. */
1683         if (!mgs_log_is_empty(obd, mti->mti_svname)) {
1684                 LCONSOLE_ERROR_MSG(0x141, "The config log for %s already "
1685                                    "exists, yet the server claims it never "
1686                                    "registered. It may have been reformatted, "
1687                                    "or the index changed. writeconf the MDT to "
1688                                    "regenerate all logs.\n", mti->mti_svname);
1689                 RETURN(-EALREADY);
1690         }
1691
1692         /* security flavors */
1693         extract_sec_flavor(mti->mti_params, PARAM_SEC_RPC_MDT, &sec);
1694         rc = sptlrpc_parse_flavor(LUSTRE_MDT, LUSTRE_OST, sec, &sec_conf_mdt);
1695         name_destroy(&sec);
1696         if (rc)
1697                 RETURN(rc);
1698
1699         extract_sec_flavor(mti->mti_params, PARAM_SEC_RPC_CLI, &sec);
1700         rc = sptlrpc_parse_flavor(LUSTRE_CLI, LUSTRE_OST, sec, &sec_conf_cli);
1701         name_destroy(&sec);
1702         if (rc)
1703                 RETURN(rc);
1704
1705         /*
1706         attach obdfilter ost1 ost1_UUID
1707         setup /dev/loop2 ldiskfs f|n errors=remount-ro,user_xattr
1708         */
1709         if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0) 
1710                 failout = (strncmp(ptr, "failout", 7) == 0);
1711         rc = record_start_log(obd, &llh, mti->mti_svname);
1712         if (rc) 
1713                 RETURN(rc);
1714         /* FIXME these should be a single journal transaction */
1715         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,"add ost"); 
1716         if (*mti->mti_uuid == '\0') 
1717                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
1718                          "%s_UUID", mti->mti_svname);
1719         rc = record_attach(obd, llh, mti->mti_svname,
1720                            "obdfilter"/*LUSTRE_OST_NAME*/, mti->mti_uuid);
1721         rc = record_setup(obd, llh, mti->mti_svname,
1722                           "dev"/*ignored*/, "type"/*ignored*/,
1723                           failout ? "n" : "f", 0/*options*/);
1724         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname, "add ost"); 
1725         rc = record_end_log(obd, &llh);
1726
1727         /* We also have to update the other logs where this osc is part of 
1728            the lov */
1729
1730         if (fsdb->fsdb_flags & FSDB_OLDLOG14) {
1731                 /* If we're upgrading, the old mdt log already has our
1732                    entry. Let's do a fake one for fun. */
1733                 /* Note that we can't add any new failnids, since we don't
1734                    know the old osc names. */
1735                 flags = CM_SKIP | CM_UPGRADE146;
1736         
1737         } else if ((mti->mti_flags & LDD_F_UPDATE) != LDD_F_UPDATE) {
1738                 /* If the update flag isn't set, don't update client/mdt
1739                    logs. */
1740                 flags |= CM_SKIP;
1741                 LCONSOLE_WARN("Client log for %s was not updated; writeconf "
1742                               "the MDT first to regenerate it.\n",
1743                               mti->mti_svname);
1744         }
1745
1746         // for_all_existing_mdt
1747         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
1748                  if (test_bit(i,  fsdb->fsdb_mdt_index_map)) {
1749                         sprintf(mdt_index,"-MDT%04x",i);
1750                         name_create(&logname, mti->mti_fsname, mdt_index);
1751                         name_create(&lovname, logname, "-mdtlov");
1752                         mgs_write_log_osc_to_lov(obd, fsdb, mti, logname,
1753                                                  mdt_index, lovname,
1754                                                  &sec_conf_mdt, flags);
1755                         name_destroy(&logname);
1756                         name_destroy(&lovname);
1757                 }
1758         }
1759     
1760         /* Append ost info to the client log */
1761         name_create(&logname, mti->mti_fsname, "-client");
1762         mgs_write_log_osc_to_lov(obd, fsdb, mti, logname, "",
1763                                  fsdb->fsdb_clilov, &sec_conf_cli, 0);
1764         name_destroy(&logname);
1765         
1766         RETURN(rc);
1767 }
1768
1769 /* Add additional failnids to an existing log.  
1770    The mdc/osc must have been added to logs first */
1771 /* tcp nids must be in dotted-quad ascii -
1772    we can't resolve hostnames from the kernel. */
1773 static int mgs_write_log_add_failnid(struct obd_device *obd, struct fs_db *fsdb,
1774                                      struct mgs_target_info *mti)
1775 {
1776         char *logname, *cliname;
1777         struct llog_handle *llh = NULL;
1778         int rc;
1779         ENTRY;
1780
1781         /* FIXME how do we delete a failnid? Currently --writeconf is the
1782            only way.  Maybe make --erase-params pass a flag to really 
1783            erase all params from logs - except it can't erase the failnids
1784            given when a target first registers, since they aren't processed
1785            as params... */
1786
1787         /* Verify that we know about this target */
1788         if (mgs_log_is_empty(obd, mti->mti_svname)) {
1789                 LCONSOLE_ERROR_MSG(0x142, "The target %s has not registered "
1790                                    "yet. It must be started before failnids "
1791                                    "can be added.\n", mti->mti_svname);
1792                 RETURN(-ENOENT);
1793         }
1794
1795         /* Create mdc/osc client name (e.g. lustre-OST0001-osc) */
1796         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
1797                 name_create(&cliname, mti->mti_svname, "-mdc");
1798         } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1799                 name_create(&cliname, mti->mti_svname, "-osc");
1800         } else {
1801                 RETURN(-EINVAL);
1802         }
1803         
1804         /* Add failover nids to client log */
1805         name_create(&logname, mti->mti_fsname, "-client");
1806         rc = record_start_log(obd, &llh, logname);
1807         if (!rc) { 
1808                 /* FIXME this fn should be a single journal transaction */
1809                 rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,
1810                                    "add failnid");
1811                 rc = mgs_write_log_failnids(obd, mti, llh, cliname);
1812                 rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname,
1813                                    "add failnid"); 
1814                 rc = record_end_log(obd, &llh);
1815         }
1816         name_destroy(&logname);
1817
1818         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1819                 /* Add OST failover nids to the MDT log as well */
1820                 name_create(&logname, mti->mti_fsname, "-MDT0000");
1821                 rc = record_start_log(obd, &llh, logname);
1822                 if (!rc) {
1823                         rc = record_marker(obd, llh, fsdb, CM_START, 
1824                                            mti->mti_svname, "add failnid");
1825                         rc = mgs_write_log_failnids(obd, mti, llh, cliname);
1826                         rc = record_marker(obd, llh, fsdb, CM_END, 
1827                                            mti->mti_svname, "add failnid"); 
1828                         rc = record_end_log(obd, &llh);
1829                 }
1830                 name_destroy(&logname);
1831         }
1832
1833         name_destroy(&cliname);
1834         RETURN(rc);
1835 }
1836
1837 static int mgs_wlp_lcfg(struct obd_device *obd, struct fs_db *fsdb, 
1838                         struct mgs_target_info *mti,
1839                         char *logname, struct lustre_cfg_bufs *bufs,
1840                         char *tgtname, char *ptr)
1841 {
1842         char comment[MTI_NAME_MAXLEN];
1843         char *tmp;
1844         struct lustre_cfg *lcfg;
1845         int rc;
1846         
1847         /* Erase any old settings of this same parameter */
1848         memcpy(comment, ptr, MTI_NAME_MAXLEN);
1849         comment[MTI_NAME_MAXLEN - 1] = 0;
1850         /* But don't try to match the value. */
1851         if ((tmp = strchr(comment, '=')))
1852             *tmp = 0;
1853         /* FIXME we should skip settings that are the same as old values */
1854         rc = mgs_modify(obd, fsdb, mti, logname, tgtname, comment, CM_SKIP);
1855         LCONSOLE_INFO("%sing parameter %s.%s in log %s\n", rc ?
1856                       "Sett" : "Modify", tgtname, comment, logname);
1857
1858         lustre_cfg_bufs_reset(bufs, tgtname);
1859         lustre_cfg_bufs_set_string(bufs, 1, ptr);
1860         lcfg = lustre_cfg_new(LCFG_PARAM, bufs);
1861         if (!lcfg) 
1862                 return -ENOMEM;
1863         rc = mgs_write_log_direct(obd, fsdb, logname, lcfg, tgtname, comment);
1864         lustre_cfg_free(lcfg);
1865         return rc;
1866 }
1867
1868 static int mgs_write_log_params(struct obd_device *obd, struct fs_db *fsdb,
1869                                 struct mgs_target_info *mti)
1870 {
1871         struct lustre_cfg_bufs bufs;
1872         struct lustre_cfg *lcfg;
1873         char *logname;
1874         char *ptr = mti->mti_params;
1875         char *endptr, *tmp;
1876         int rc = 0;
1877         ENTRY;
1878
1879         if (!mti->mti_params) 
1880                 RETURN(0);
1881
1882         /* For various parameter settings, we have to figure out which logs
1883            care about them (e.g. both mdt and client for lov settings) */
1884         while (ptr) {
1885                 while (*ptr == ' ') 
1886                         ptr++;
1887                 if (*ptr == '\0')
1888                         break;
1889                 endptr = strchr(ptr, ' ');
1890                 if (endptr) 
1891                         *endptr = '\0';
1892                 CDEBUG(D_MGS, "next param '%s'\n", ptr);
1893
1894                 /* The params are stored in MOUNT_DATA_FILE and modified 
1895                    via tunefs.lustre */
1896
1897                 /* Processed in lustre_start_mgc */
1898                 if (class_match_param(ptr, PARAM_MGSNODE, NULL) == 0) 
1899                         GOTO(end_while, rc);
1900
1901                 /* Processed in mgs_write_log_ost */
1902                 if (class_match_param(ptr, PARAM_FAILMODE, NULL) == 0) {
1903                         if (mti->mti_flags & LDD_F_PARAM) {
1904                                 LCONSOLE_ERROR_MSG(0x169, "%s can only be "
1905                                                    "changed with tunefs.lustre"
1906                                                    "and --writeconf\n", ptr);
1907                                 rc = -EPERM;
1908                         }
1909                         GOTO(end_while, rc);
1910                 }
1911                 /* Processed in mgs_write_log_mdt/mgs_write_log_ost */
1912                 if (class_match_param(ptr, PARAM_SEC_RPC_MDT, NULL) == 0 ||
1913                     class_match_param(ptr, PARAM_SEC_RPC_CLI, NULL) == 0)
1914                         GOTO(end_while, rc);
1915
1916                 if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
1917                         /* Add a failover nidlist */
1918                         rc = 0;
1919                         /* We already processed failovers params for new
1920                            targets in mgs_write_log_target */
1921                         if (mti->mti_flags & LDD_F_PARAM) {
1922                                 CDEBUG(D_MGS, "Adding failnode\n");
1923                                 rc = mgs_write_log_add_failnid(obd, fsdb, mti);
1924                         }
1925                         GOTO(end_while, rc);
1926                 }
1927
1928                 if (class_match_param(ptr, PARAM_SYS_TIMEOUT, &tmp) == 0) {
1929                         /* Change obd timeout */
1930                         int timeout;
1931                         timeout = simple_strtoul(tmp, NULL, 0);
1932
1933                         CDEBUG(D_MGS, "obd timeout %d\n", timeout);
1934                         lustre_cfg_bufs_reset(&bufs, NULL);
1935                         lcfg = lustre_cfg_new(LCFG_SET_TIMEOUT, &bufs);
1936                         lcfg->lcfg_num = timeout;
1937                         /* modify all servers and clients */
1938                         rc = mgs_write_log_direct_all(obd, fsdb, mti, lcfg,
1939                                                       mti->mti_fsname,
1940                                                       "timeout"); 
1941                         lustre_cfg_free(lcfg);
1942                         GOTO(end_while, rc);
1943                 }
1944
1945                 if (class_match_param(ptr, PARAM_OSC""PARAM_ACTIVE, &tmp) == 0) { 
1946                         /* active=0 means off, anything else means on */
1947                         char mdt_index[16];
1948                         int flag = (*tmp == '0') ? CM_EXCLUDE : 0;
1949                         int i;
1950
1951                         if (!(mti->mti_flags & LDD_F_SV_TYPE_OST)) {
1952                                 LCONSOLE_ERROR_MSG(0x144, "%s: Only OSCs can "
1953                                                    "be (de)activated.\n",
1954                                                    mti->mti_svname);
1955                                 rc = -EINVAL;
1956                                 goto end_while;
1957                         }
1958                         LCONSOLE_WARN("Permanently %sactivating %s\n",
1959                                       flag ? "de": "re", mti->mti_svname);
1960                         /* Modify clilov */
1961                         name_create(&logname, mti->mti_fsname, "-client");
1962                         rc = mgs_modify(obd, fsdb, mti, logname, 
1963                                         mti->mti_svname, "add osc", flag);
1964                         name_destroy(&logname);
1965                         if (rc) 
1966                                 goto active_err;
1967                         /* Modify mdtlov */
1968                         /* FIXME add to all MDT logs for CMD */
1969                         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
1970                                 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
1971                                         continue;
1972                                 sprintf(mdt_index,"-MDT%04x", i);
1973                                 name_create(&logname, mti->mti_fsname, mdt_index);
1974                                 rc = mgs_modify(obd, fsdb, mti, logname, 
1975                                                 mti->mti_svname, "add osc", flag);
1976                                 name_destroy(&logname);
1977                                 if (rc)
1978                                         goto active_err;
1979                         }
1980 active_err:
1981                         if (rc) {
1982                                 LCONSOLE_ERROR_MSG(0x145, "Couldn't find %s in"
1983                                                    "log (%d). No permanent "
1984                                                    "changes were made to the "
1985                                                    "config log.\n",
1986                                                    mti->mti_svname, rc);
1987                                 if (fsdb->fsdb_flags & FSDB_OLDLOG14) 
1988                                         LCONSOLE_ERROR_MSG(0x146, "This may be"
1989                                                            " because the log "
1990                                                            "is in the old 1.4"
1991                                                            "style. Consider "
1992                                                            " --writeconf to "
1993                                                            "update the logs.\n");
1994                                 goto end_while;
1995                         }
1996                         /* Fall through to osc proc for deactivating 
1997                            live OSC on running MDT / clients. */
1998                 }
1999                 /* Below here, let obd's XXX_process_config methods handle it */
2000  
2001                 /* All lov. in proc */
2002                 if (class_match_param(ptr, PARAM_LOV, NULL) == 0) {
2003                         char mdt_index[16];
2004                         char *mdtlovname;
2005                         
2006                         CDEBUG(D_MGS, "lov param %s\n", ptr);
2007                         if (!(mti->mti_flags & LDD_F_SV_TYPE_MDT)) {
2008                                 LCONSOLE_ERROR_MSG(0x147, "LOV params must be "
2009                                                    "set on the MDT, not %s. "
2010                                                    "Ignoring.\n", 
2011                                                    mti->mti_svname);
2012                                 rc = 0;
2013                                 goto end_while;
2014                         }
2015
2016                         /* Modify mdtlov */
2017                         if (mgs_log_is_empty(obd, mti->mti_svname))
2018                                 GOTO(end_while, rc = -ENODEV);
2019
2020                         sprintf(mdt_index,"-MDT%04x", mti->mti_stripe_index);
2021                         name_create(&logname, mti->mti_fsname, mdt_index);
2022                         name_create(&mdtlovname, logname, "-mdtlov");
2023                         rc = mgs_wlp_lcfg(obd, fsdb, mti, mti->mti_svname, 
2024                                           &bufs, mdtlovname, ptr);
2025                         name_destroy(&logname);
2026                         name_destroy(&mdtlovname);
2027                         if (rc)
2028                                 GOTO(end_while, rc);
2029
2030                         /* Modify clilov */
2031                         name_create(&logname, mti->mti_fsname, "-client");
2032                         rc = mgs_wlp_lcfg(obd, fsdb, mti, logname, &bufs,
2033                                           fsdb->fsdb_clilov, ptr);
2034                         name_destroy(&logname);
2035                         GOTO(end_while, rc);
2036                 }
2037
2038                 /* All osc., mdc., llite. params in proc */
2039                 if ((class_match_param(ptr, PARAM_OSC, NULL) == 0) || 
2040                     (class_match_param(ptr, PARAM_MDC, NULL) == 0) ||
2041                     (class_match_param(ptr, PARAM_LLITE, NULL) == 0)) {
2042                         char *cname;
2043                         if (memcmp(ptr, PARAM_LLITE, strlen(PARAM_LLITE)) == 0) {
2044                                 name_create(&cname, mti->mti_fsname, "-client");
2045                         /* Add the client type to match the obdname 
2046                            in class_config_llog_handler */
2047                         } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
2048                                 /* COMPAT_146 */
2049                                 if (fsdb->fsdb_mdc)
2050                                         name_create(&cname, fsdb->fsdb_mdc, "");
2051                                 else
2052                                         name_create(&cname, mti->mti_svname,
2053                                                     "-mdc");
2054                         } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
2055                                 /* COMPAT_146 */
2056                                 if (fsdb->fsdb_flags & FSDB_OLDLOG14) {
2057                                         LCONSOLE_ERROR_MSG(0x148, "Upgraded "
2058                                                            "client logs for %s"
2059                                                            " cannot be "
2060                                                            "modified. Consider"
2061                                                            " updating the "
2062                                                            "configuration with"
2063                                                            " --writeconf\n",
2064                                                            mti->mti_svname);
2065                                         /* We don't know the names of all the
2066                                            old oscs*/
2067                                         rc = -EINVAL;
2068                                         goto end_while;
2069                                 }
2070                                 name_create(&cname, mti->mti_svname, "-osc");
2071                         } else {       
2072                                 rc = -EINVAL;
2073                                 goto end_while;
2074                         }
2075
2076                         CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
2077                         
2078                         /* Modify client */
2079                         name_create(&logname, mti->mti_fsname, "-client");
2080                         rc = mgs_wlp_lcfg(obd, fsdb, mti, logname, &bufs,
2081                                           cname, ptr);
2082
2083                         /* osc params affect the MDT as well */
2084                         if (!rc && (mti->mti_flags & LDD_F_SV_TYPE_OST)) {
2085                                 char mdt_index[16];
2086                                 int i;
2087
2088                                 for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
2089                                         if (!test_bit(i, fsdb->fsdb_mdt_index_map))
2090                                                 continue;
2091                                         name_destroy(&cname);
2092                                         sprintf(mdt_index, "-osc-MDT%04x", i);
2093                                         name_create(&cname, mti->mti_svname,
2094                                                     mdt_index);
2095                                         name_destroy(&logname);
2096                                         sprintf(mdt_index, "-MDT%04x", i);
2097                                         name_create(&logname, mti->mti_fsname,
2098                                                     mdt_index);
2099                                         if (!mgs_log_is_empty(obd, logname))
2100                                                 rc = mgs_wlp_lcfg(obd, fsdb,
2101                                                                   mti, logname,
2102                                                                   &bufs, cname,
2103                                                                   ptr);
2104                                         if (rc)
2105                                                 break;
2106                                 }
2107                         }
2108                         name_destroy(&logname);
2109                         name_destroy(&cname);
2110                         GOTO(end_while, rc);
2111                 }
2112
2113                 /* All mdt., ost. params in proc */
2114                 if ((class_match_param(ptr, PARAM_MDT, NULL) == 0) || 
2115                     (class_match_param(ptr, PARAM_OST, NULL) == 0)) {
2116                         CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
2117                         if (mgs_log_is_empty(obd, mti->mti_svname)) {
2118                                 rc = -ENODEV;
2119                                 goto end_while;
2120                         }
2121                         rc = mgs_wlp_lcfg(obd, fsdb, mti, mti->mti_svname,
2122                                           &bufs, mti->mti_svname, ptr);
2123                         GOTO(end_while, rc);
2124                 }
2125
2126                 LCONSOLE_WARN("Ignoring unrecognized param '%s'\n", ptr);
2127
2128 end_while:
2129                 if (rc) {
2130                         CERROR("err %d on param '%s\n", rc, ptr);
2131                         break;
2132                 }
2133                 
2134                 if (!endptr)
2135                         /* last param */
2136                         break;
2137                  
2138                 *endptr = ' ';
2139                 ptr = endptr + 1;
2140         }
2141
2142         RETURN(rc);
2143 }
2144
2145 /* Not implementing automatic failover nid addition at this time. */
2146 int mgs_check_failnid(struct obd_device *obd, struct mgs_target_info *mti)
2147 {
2148 #if 0
2149         struct fs_db *fsdb;
2150         int rc;
2151         ENTRY;
2152
2153         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb); 
2154         if (rc) 
2155                 RETURN(rc);
2156
2157         if (mgs_log_is_empty(obd, mti->mti_svname)) 
2158                 /* should never happen */
2159                 RETURN(-ENOENT);
2160
2161         CDEBUG(D_MGS, "Checking for new failnids for %s\n", mti->mti_svname);
2162
2163         /* FIXME We can just check mti->params to see if we're already in
2164            the failover list.  Modify mti->params for rewriting back at 
2165            server_register_target(). */
2166         
2167         down(&fsdb->fsdb_sem);
2168         rc = mgs_write_log_add_failnid(obd, fsdb, mti);
2169         up(&fsdb->fsdb_sem);
2170
2171         RETURN(rc);
2172 #endif
2173         return 0;
2174 }
2175
2176 int mgs_write_log_target(struct obd_device *obd,
2177                          struct mgs_target_info *mti)
2178 {
2179         struct fs_db *fsdb;
2180         int rc = -EINVAL;
2181         ENTRY;
2182
2183         /* set/check the new target index */
2184         rc = mgs_set_index(obd, mti);
2185         if (rc < 0) {
2186                 CERROR("Can't get index (%d)\n", rc);
2187                 RETURN(rc);
2188         }
2189
2190         /* COMPAT_146 */
2191         if (mti->mti_flags & LDD_F_UPGRADE14) {
2192                 if (rc == EALREADY) {
2193                         LCONSOLE_INFO("Found index %d for %s 1.4 log, "
2194                                       "upgrading\n", mti->mti_stripe_index, 
2195                                       mti->mti_svname);
2196                 } else {
2197                         LCONSOLE_ERROR_MSG(0x149, "Failed to find %s in the old"
2198                                            " client log. Apparently it is not "
2199                                            "part of this filesystem, or the old"
2200                                            " log is wrong.\nUse 'writeconf' on "
2201                                            "the MDT to force log regeneration."
2202                                            "\n", mti->mti_svname);
2203                         /* Not in client log?  Upgrade anyhow...*/
2204                         /* Argument against upgrading: reformat MDT,
2205                            upgrade OST, then OST will start but will be SKIPped
2206                            in client logs.  Maybe error now is better. */
2207                         /* RETURN(-EINVAL); */
2208                 }
2209                 /* end COMPAT_146 */
2210         } else {
2211                 if (rc == EALREADY) {
2212                         LCONSOLE_WARN("Found index %d for %s, updating log\n", 
2213                                       mti->mti_stripe_index, mti->mti_svname);
2214                         /* We would like to mark old log sections as invalid 
2215                            and add new log sections in the client and mdt logs.
2216                            But if we add new sections, then live clients will
2217                            get repeat setup instructions for already running
2218                            osc's. So don't update the client/mdt logs. */
2219                         mti->mti_flags &= ~LDD_F_UPDATE;
2220                 }
2221         }
2222
2223         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb); 
2224         if (rc) {
2225                 CERROR("Can't get db for %s\n", mti->mti_fsname);
2226                 RETURN(rc);
2227         }
2228
2229         down(&fsdb->fsdb_sem);
2230
2231         if (mti->mti_flags & 
2232             (LDD_F_VIRGIN | LDD_F_UPGRADE14 | LDD_F_WRITECONF)) {
2233                 /* Generate a log from scratch */
2234                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
2235                         rc = mgs_write_log_mdt(obd, fsdb, mti);
2236                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
2237                         rc = mgs_write_log_ost(obd, fsdb, mti);
2238                 } else {
2239                         CERROR("Unknown target type %#x, can't create log for "
2240                                "%s\n", mti->mti_flags, mti->mti_svname);
2241                 }
2242                 if (rc) {
2243                         CERROR("Can't write logs for %s (%d)\n",
2244                                mti->mti_svname, rc);
2245                         GOTO(out_up, rc);
2246                 }
2247         } else {
2248                 /* Just update the params from tunefs in mgs_write_log_params */
2249                 CDEBUG(D_MGS, "Update params for %s\n", mti->mti_svname);
2250                 mti->mti_flags |= LDD_F_PARAM;
2251         }
2252         
2253         rc = mgs_write_log_params(obd, fsdb, mti);
2254
2255 out_up:
2256         up(&fsdb->fsdb_sem);
2257         RETURN(rc);
2258 }
2259
2260 /* COMPAT_146 */
2261 /* verify that we can handle the old config logs */ 
2262 int mgs_upgrade_sv_14(struct obd_device *obd, struct mgs_target_info *mti)
2263 {
2264         struct fs_db *fsdb;
2265         int rc = 0;
2266         ENTRY;
2267
2268         /* Create ost log normally, as servers register.  Servers 
2269            register with their old uuids (from last_rcvd), so old
2270            (MDT and client) logs should work.
2271          - new MDT won't know about old OSTs, only the ones that have 
2272            registered, so we need the old MDT log to get the LOV right 
2273            in order for old clients to work. 
2274          - Old clients connect to the MDT, not the MGS, for their logs, and 
2275            will therefore receive the old client log from the MDT /LOGS dir. 
2276          - Old clients can continue to use and connect to old or new OSTs
2277          - New clients will contact the MGS for their log 
2278         */
2279
2280         LCONSOLE_INFO("upgrading server %s from pre-1.6\n", mti->mti_svname); 
2281         server_mti_print("upgrade", mti);
2282         
2283         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb);
2284         if (rc) 
2285                 RETURN(rc);
2286
2287         if (fsdb->fsdb_flags & FSDB_LOG_EMPTY) {
2288                 LCONSOLE_ERROR_MSG(0x14a, "The old client log %s-client is "
2289                                    "missing.  Was tunefs.lustre successful?\n",
2290                                    mti->mti_fsname);
2291                 RETURN(-ENOENT);
2292         }
2293
2294         if (fsdb->fsdb_gen == 0) {
2295                 /* There were no markers in the client log, meaning we have 
2296                    not updated the logs for this fs */
2297                 CDEBUG(D_MGS, "found old, unupdated client log\n");
2298         }
2299
2300         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
2301                 if (mgs_log_is_empty(obd, mti->mti_svname)) {
2302                         LCONSOLE_ERROR_MSG(0x14b, "The old MDT log %s is "
2303                                            "missing. Was tunefs.lustre "
2304                                            "successful?\n",
2305                                            mti->mti_svname);
2306                         RETURN(-ENOENT);
2307                 }
2308                 /* We're starting with an old uuid.  Assume old name for lov
2309                    as well since the lov entry already exists in the log. */
2310                 CDEBUG(D_MGS, "old mds uuid %s\n", mti->mti_uuid);
2311                 if (strncmp(mti->mti_uuid, fsdb->fsdb_mdtlov + 4, 
2312                             strlen(fsdb->fsdb_mdtlov) - 4) != 0) {
2313                         CERROR("old mds uuid %s doesn't match log %s (%s)\n",
2314                                mti->mti_uuid, fsdb->fsdb_mdtlov, 
2315                                fsdb->fsdb_mdtlov + 4);
2316                         RETURN(-EINVAL);
2317                 }
2318         }
2319
2320         if (!(fsdb->fsdb_flags & FSDB_OLDLOG14)) {
2321                 LCONSOLE_ERROR_MSG(0x14c, "%s-client is supposedly an old "
2322                                    "log, but no old LOV or MDT was found. "
2323                                    "Consider updating the configuration with"
2324                                    " --writeconf.\n", mti->mti_fsname);
2325         }
2326
2327         RETURN(rc);
2328 }
2329 /* end COMPAT_146 */
2330
2331 int mgs_erase_log(struct obd_device *obd, char *name)
2332 {
2333         struct lvfs_run_ctxt saved;
2334         struct llog_handle *llh;
2335         int rc = 0;
2336
2337         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2338         rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
2339                          &llh, NULL, name);
2340         if (rc == 0) {
2341                 llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
2342                 rc = llog_destroy(llh);
2343                 llog_free_handle(llh);
2344         }
2345         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2346
2347         if (rc)
2348                 CERROR("failed to clear log %s: %d\n", name, rc);
2349
2350         return(rc);
2351 }
2352
2353 /* erase all logs for the given fs */
2354 int mgs_erase_logs(struct obd_device *obd, char *fsname)
2355 {
2356         struct mgs_obd *mgs = &obd->u.mgs;
2357         static struct fs_db *fsdb;
2358         struct list_head dentry_list;
2359         struct l_linux_dirent *dirent, *n;
2360         int rc, len = strlen(fsname);
2361         ENTRY;
2362         
2363         /* Find all the logs in the CONFIGS directory */
2364         rc = class_dentry_readdir(obd, mgs->mgs_configs_dir,
2365                                   mgs->mgs_vfsmnt, &dentry_list);
2366         if (rc) {
2367                 CERROR("Can't read %s dir\n", MOUNT_CONFIGS_DIR);
2368                 RETURN(rc);
2369         }
2370                                                                                 
2371         down(&mgs->mgs_sem);
2372         
2373         /* Delete the fs db */
2374         fsdb = mgs_find_fsdb(obd, fsname);
2375         if (fsdb) 
2376                 mgs_free_fsdb(obd, fsdb);
2377
2378         list_for_each_entry_safe(dirent, n, &dentry_list, lld_list) {
2379                 list_del(&dirent->lld_list);
2380                 if (strncmp(fsname, dirent->lld_name, len) == 0) {
2381                         CDEBUG(D_MGS, "Removing log %s\n", dirent->lld_name);
2382                         mgs_erase_log(obd, dirent->lld_name);
2383                 }
2384                 OBD_FREE(dirent, sizeof(*dirent));
2385         }
2386         
2387         up(&mgs->mgs_sem);
2388
2389         RETURN(rc);
2390 }
2391
2392 /* from llog_swab */
2393 static void print_lustre_cfg(struct lustre_cfg *lcfg)
2394 {
2395         int i;
2396         ENTRY;
2397
2398         CDEBUG(D_MGS, "lustre_cfg: %p\n", lcfg);
2399         CDEBUG(D_MGS, "\tlcfg->lcfg_version: %#x\n", lcfg->lcfg_version);
2400
2401         CDEBUG(D_MGS, "\tlcfg->lcfg_command: %#x\n", lcfg->lcfg_command);
2402         CDEBUG(D_MGS, "\tlcfg->lcfg_num: %#x\n", lcfg->lcfg_num);
2403         CDEBUG(D_MGS, "\tlcfg->lcfg_flags: %#x\n", lcfg->lcfg_flags);
2404         CDEBUG(D_MGS, "\tlcfg->lcfg_nid: %s\n", libcfs_nid2str(lcfg->lcfg_nid));
2405
2406         CDEBUG(D_MGS, "\tlcfg->lcfg_bufcount: %d\n", lcfg->lcfg_bufcount);
2407         if (lcfg->lcfg_bufcount < LUSTRE_CFG_MAX_BUFCOUNT)
2408                 for (i = 0; i < lcfg->lcfg_bufcount; i++) {
2409                         CDEBUG(D_MGS, "\tlcfg->lcfg_buflens[%d]: %d %s\n",
2410                                i, lcfg->lcfg_buflens[i], 
2411                                lustre_cfg_string(lcfg, i));
2412                 }
2413         EXIT;
2414 }
2415
2416 /* Set a permanent (config log) param for a target or fs */
2417 int mgs_setparam(struct obd_device *obd, struct lustre_cfg *lcfg, char *fsname)
2418 {
2419         struct fs_db *fsdb;
2420         struct mgs_target_info *mti;
2421         char *devname, *param;
2422         char *ptr, *tmp;
2423         __u32 index;
2424         int rc = 0;
2425         ENTRY;
2426
2427         print_lustre_cfg(lcfg);
2428         
2429         /* lustre, lustre-mdtlov, lustre-client, lustre-MDT0000 */
2430         devname = lustre_cfg_string(lcfg, 0);
2431         param = lustre_cfg_string(lcfg, 1);
2432         if (!devname) {
2433                 /* Assume device name embedded in param:
2434                    lustre-OST0000.osc.max_dirty_mb=32 */
2435                 ptr = strchr(param, '.');
2436                 if (ptr) {
2437                         devname = param;
2438                         *ptr = 0;
2439                         param = ptr + 1;
2440                 }
2441         }
2442         if (!devname) {
2443                 LCONSOLE_ERROR_MSG(0x14d, "No target specified: %s\n", param);
2444                 RETURN(-ENOSYS);
2445         }
2446
2447         /* Extract fsname */
2448         ptr = strrchr(devname, '-');
2449         memset(fsname, 0, MTI_NAME_MAXLEN);
2450         if (ptr && (server_name2index(ptr, &index, NULL) >= 0)) {
2451                 strncpy(fsname, devname, ptr - devname);
2452         } else {
2453                 /* assume devname is the fsname */
2454                 strncpy(fsname, devname, MTI_NAME_MAXLEN);
2455         }
2456         fsname[MTI_NAME_MAXLEN - 1] = 0;
2457         CDEBUG(D_MGS, "setparam on fs %s device %s\n", fsname, devname);
2458
2459         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb); 
2460         if (rc) 
2461                 RETURN(rc);
2462         if (fsdb->fsdb_flags & FSDB_LOG_EMPTY) {
2463                 CERROR("No filesystem targets for %s.  cfg_device from lctl "
2464                        "is '%s'\n", fsname, devname);
2465                 mgs_free_fsdb(obd, fsdb);
2466                 RETURN(-EINVAL);
2467         }
2468
2469         /* Create a fake mti to hold everything */
2470         OBD_ALLOC_PTR(mti);
2471         if (!mti) 
2472                 GOTO(out, rc = -ENOMEM);
2473         strncpy(mti->mti_fsname, fsname, MTI_NAME_MAXLEN);
2474         strncpy(mti->mti_svname, devname, MTI_NAME_MAXLEN);
2475         strncpy(mti->mti_params, param, sizeof(mti->mti_params));
2476         rc = server_name2index(mti->mti_svname, &mti->mti_stripe_index, &tmp);
2477         if (rc < 0) 
2478                 /* Not a valid server; may be only fsname */
2479                 rc = 0;
2480         else
2481                 /* Strip -osc or -mdc suffix from svname */
2482                 if (server_make_name(rc, mti->mti_stripe_index, mti->mti_fsname, 
2483                                      mti->mti_svname)) 
2484                         GOTO(out, rc = -EINVAL);
2485
2486         mti->mti_flags = rc | LDD_F_PARAM;
2487
2488         down(&fsdb->fsdb_sem);
2489         rc = mgs_write_log_params(obd, fsdb, mti); 
2490         up(&fsdb->fsdb_sem);
2491
2492 out:
2493         OBD_FREE_PTR(mti);
2494         RETURN(rc);
2495 }
2496
2497 #if 0
2498 /******************** unused *********************/
2499 static int mgs_backup_llog(struct obd_device *obd, char* fsname)
2500 {
2501         struct file *filp, *bak_filp;
2502         struct lvfs_run_ctxt saved;
2503         char *logname, *buf;
2504         loff_t soff = 0 , doff = 0;
2505         int count = 4096, len;
2506         int rc = 0;
2507
2508         OBD_ALLOC(logname, PATH_MAX);
2509         if (logname == NULL)
2510                 return -ENOMEM;
2511
2512         OBD_ALLOC(buf, count);
2513         if (!buf)
2514                 GOTO(out , rc = -ENOMEM);
2515
2516         len = snprintf(logname, PATH_MAX, "%s/%s.bak",
2517                        MOUNT_CONFIGS_DIR, fsname);
2518
2519         if (len >= PATH_MAX - 1) {
2520                 GOTO(out, -ENAMETOOLONG);
2521         } 
2522
2523         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2524                 
2525         bak_filp = l_filp_open(logname, O_RDWR|O_CREAT|O_TRUNC, 0660);
2526         if (IS_ERR(bak_filp)) {
2527                 rc = PTR_ERR(bak_filp);
2528                 CERROR("backup logfile open %s: %d\n", logname, rc);
2529                 GOTO(pop, rc);
2530         }
2531         sprintf(logname, "%s/%s", MOUNT_CONFIGS_DIR, fsname);
2532         filp = l_filp_open(logname, O_RDONLY, 0);
2533         if (IS_ERR(filp)) {
2534                 rc = PTR_ERR(filp);
2535                 CERROR("logfile open %s: %d\n", logname, rc);
2536                 GOTO(close1f, rc);
2537         }
2538
2539         while ((rc = lustre_fread(filp, buf, count, &soff)) > 0) {
2540                 rc = lustre_fwrite(bak_filp, buf, count, &doff);
2541                 break;
2542         }
2543
2544         filp_close(filp, 0);
2545 close1f:
2546         filp_close(bak_filp, 0);
2547 pop:
2548         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2549 out:
2550         if (buf)
2551                 OBD_FREE(buf, count);
2552         OBD_FREE(logname, PATH_MAX);
2553         return rc;
2554 }
2555
2556 #endif