Whamcloud - gitweb
land b1_5 onto 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 "mgs_internal.h"
49
50 /******************** Class functions *********************/
51
52 /* Caller must list_del and OBD_FREE each dentry from the list */
53 int class_dentry_readdir(struct obd_device *obd, struct dentry *dir,
54                          struct vfsmount *inmnt, 
55                          struct list_head *dentry_list){
56         /* see mds_cleanup_pending */
57         struct lvfs_run_ctxt saved;
58         struct file *file;
59         struct dentry *dentry;
60         struct vfsmount *mnt;
61         int rc = 0;
62         ENTRY;
63
64         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
65         dentry = dget(dir);
66         if (IS_ERR(dentry))
67                 GOTO(out_pop, rc = PTR_ERR(dentry));
68         mnt = mntget(inmnt);
69         if (IS_ERR(mnt)) {
70                 l_dput(dentry);
71                 GOTO(out_pop, rc = PTR_ERR(mnt));
72         }
73
74         file = dentry_open(dentry, mnt, O_RDONLY);
75         if (IS_ERR(file))
76                 /* dentry_open_it() drops the dentry, mnt refs */
77                 GOTO(out_pop, rc = PTR_ERR(file));
78
79         INIT_LIST_HEAD(dentry_list);
80         rc = l_readdir(file, dentry_list);
81         filp_close(file, 0);
82         /*  filp_close->fput() drops the dentry, mnt refs */
83
84 out_pop:
85         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
86         RETURN(rc);
87 }
88
89 /******************** DB functions *********************/
90
91 static inline int name_create(char **newname, char *prefix, char *suffix)
92 {
93         LASSERT(newname);
94         OBD_ALLOC(*newname, strlen(prefix) + strlen(suffix) + 1);
95         if (!*newname) 
96                 return -ENOMEM;
97         sprintf(*newname, "%s%s", prefix, suffix);
98         return 0;
99 }
100
101 static inline void name_destroy(char **name)
102 {        
103         if (*name)
104                 OBD_FREE(*name, strlen(*name) + 1);
105         *name = NULL;
106 }
107
108 /* from the (client) config log, figure out:
109         1. which ost's/mdt's are configured (by index)
110         2. what the last config step is
111         3. COMPAT_146 lov name
112         4. COMPAT_146 mdt lov name
113         5. COMPAT_146 mdc name 
114 */
115 /* It might be better to have a separate db file, instead of parsing the info
116    out of the client log.  This is slow and potentially error-prone. */
117 static int mgs_fsdb_handler(struct llog_handle *llh, struct llog_rec_hdr *rec, 
118                             void *data)
119 {
120         struct fs_db *fsdb = (struct fs_db *)data;
121         int cfg_len = rec->lrh_len;
122         char *cfg_buf = (char*) (rec + 1);
123         struct lustre_cfg *lcfg;
124         __u32 index;
125         int rc = 0;
126         ENTRY;
127
128         if (rec->lrh_type != OBD_CFG_REC) {
129                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
130                 RETURN(-EINVAL);
131         }
132
133         rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
134         if (rc) {
135                 CERROR("Insane cfg\n");
136                 RETURN(rc);
137         }
138
139         lcfg = (struct lustre_cfg *)cfg_buf;
140
141         CDEBUG(D_INFO, "cmd %x %s %s\n", lcfg->lcfg_command, 
142                lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
143
144         /* Figure out ost indicies */ 
145         /* lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1 */
146         if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD ||
147             lcfg->lcfg_command == LCFG_LOV_DEL_OBD) {
148                 index = simple_strtoul(lustre_cfg_string(lcfg, 2),
149                                        NULL, 10);
150                 CDEBUG(D_MGS, "OST index for %s is %u (%s)\n",
151                        lustre_cfg_string(lcfg, 1), index, 
152                        lustre_cfg_string(lcfg, 2));
153                 set_bit(index, fsdb->fsdb_ost_index_map);
154         }
155         
156         /* Figure out mdt indicies */
157         /* attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f */
158         if ((lcfg->lcfg_command == LCFG_ATTACH) &&
159             (strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_MDC_NAME) == 0)) {
160                 rc = server_name2index(lustre_cfg_string(lcfg, 0),
161                                        &index, NULL);
162                 if (rc != LDD_F_SV_TYPE_MDT) {
163                         CWARN("Unparsable MDC name %s, assuming index 0\n",
164                               lustre_cfg_string(lcfg, 0));
165                         index = 0;
166                 }
167                 rc = 0;
168                 CDEBUG(D_MGS, "MDT index is %u\n", index);
169                 set_bit(index, fsdb->fsdb_mdt_index_map);
170         }
171
172         /* COMPAT_146 */
173         /* figure out the old LOV name. fsdb_gen = 0 means old log */
174         /* #01 L attach 0:lov_mdsA 1:lov 2:cdbe9_lov_mdsA_dc8cf7f3bb */
175         if ((fsdb->fsdb_gen == 0) && (lcfg->lcfg_command == LCFG_ATTACH) &&
176             (strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_LOV_NAME) == 0)) {
177                 fsdb->fsdb_flags |= FSDB_OLDLOG14;
178                 name_destroy(&fsdb->fsdb_clilov);
179                 rc = name_create(&fsdb->fsdb_clilov, 
180                                  lustre_cfg_string(lcfg, 0), "");
181                 if (rc) 
182                         RETURN(rc);
183                 CDEBUG(D_MGS, "client lov name is %s\n", fsdb->fsdb_clilov);
184         }
185
186         /* figure out the old MDT lov name from the MDT uuid */
187         if ((fsdb->fsdb_gen == 0) && (lcfg->lcfg_command == LCFG_SETUP) &&
188             (strncmp(lustre_cfg_string(lcfg, 0), "MDC_", 4) == 0)) {
189                 char *ptr;
190                 fsdb->fsdb_flags |= FSDB_OLDLOG14;
191                 ptr = strstr(lustre_cfg_string(lcfg, 1), "_UUID");
192                 if (!ptr) {
193                         CERROR("Can't parse MDT uuid %s\n", 
194                                lustre_cfg_string(lcfg, 1));
195                         RETURN(-EINVAL);
196                 }
197                 *ptr = '\0';
198                 name_destroy(&fsdb->fsdb_mdtlov);
199                 rc = name_create(&fsdb->fsdb_mdtlov, 
200                                  "lov_", lustre_cfg_string(lcfg, 1));
201                 if (rc) 
202                         RETURN(rc);
203                 name_destroy(&fsdb->fsdb_mdc);
204                 rc = name_create(&fsdb->fsdb_mdc, 
205                                  lustre_cfg_string(lcfg, 0), "");
206                 if (rc) 
207                         RETURN(rc);
208                 CDEBUG(D_MGS, "MDT lov name is %s\n", fsdb->fsdb_mdtlov);
209         }
210         /* end COMPAT_146 */
211
212         /* Keep track of the latest marker step */
213         if (lcfg->lcfg_command == LCFG_MARKER) {
214                 struct cfg_marker *marker;
215                 marker = lustre_cfg_buf(lcfg, 1);
216                 fsdb->fsdb_gen = max(fsdb->fsdb_gen, marker->cm_step);
217         }
218
219         RETURN(rc);
220 }
221
222 static int mgs_get_fsdb_from_llog(struct obd_device *obd, struct fs_db *fsdb)
223 {
224         char *logname;
225         struct llog_handle *loghandle;
226         struct lvfs_run_ctxt saved;
227         int rc, rc2;
228         ENTRY;
229
230         name_create(&logname, fsdb->fsdb_name, "-client");
231         down(&fsdb->fsdb_sem);
232         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
233         
234         rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
235                          &loghandle, NULL, logname);
236         if (rc)
237                 GOTO(out_pop, rc);
238
239         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
240         if (rc)
241                 GOTO(out_close, rc);
242
243         if (llog_get_size(loghandle) <= 1)
244                 fsdb->fsdb_flags |= FSDB_LOG_EMPTY;
245
246         rc = llog_process(loghandle, mgs_fsdb_handler, (void *)fsdb, NULL);
247         CDEBUG(D_INFO, "get_db = %d\n", rc);
248 out_close:
249         rc2 = llog_close(loghandle);
250         if (!rc)
251                 rc = rc2;
252
253 out_pop:
254         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
255         up(&fsdb->fsdb_sem);
256         name_destroy(&logname);
257
258         RETURN(rc);
259 }
260
261 static struct fs_db *mgs_find_fsdb(struct obd_device *obd, char *fsname)
262 {
263         struct mgs_obd *mgs = &obd->u.mgs;
264         struct fs_db *fsdb;
265         struct list_head *tmp;
266
267         list_for_each(tmp, &mgs->mgs_fs_db_list) {
268                 fsdb = list_entry(tmp, struct fs_db, fsdb_list);
269                 if (strcmp(fsdb->fsdb_name, fsname) == 0)
270                         return fsdb;
271         }
272         return NULL;
273 }
274
275 /* caller must hold the mgs->mgs_fs_db_lock */
276 static struct fs_db *mgs_new_fsdb(struct obd_device *obd, char *fsname)
277 {
278         struct mgs_obd *mgs = &obd->u.mgs;
279         struct fs_db *fsdb;
280         int rc;
281         ENTRY;
282         
283         OBD_ALLOC_PTR(fsdb);
284         if (!fsdb) 
285                 RETURN(NULL);
286
287         OBD_ALLOC(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
288         OBD_ALLOC(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
289         if (!fsdb->fsdb_ost_index_map || !fsdb->fsdb_mdt_index_map) {
290                 CERROR("No memory for index maps\n");
291                 GOTO(err, 0);
292         }
293         
294         strncpy(fsdb->fsdb_name, fsname, sizeof(fsdb->fsdb_name));
295         rc = name_create(&fsdb->fsdb_mdtlov, fsname, "-mdtlov");
296         if (rc) 
297                 GOTO(err, rc);
298         rc = name_create(&fsdb->fsdb_clilov, fsname, "-clilov");
299         if (rc) 
300                 GOTO(err, rc);
301
302         sema_init(&fsdb->fsdb_sem, 1);
303         list_add(&fsdb->fsdb_list, &mgs->mgs_fs_db_list);
304         lproc_mgs_add_live(obd, fsdb);
305
306         RETURN(fsdb);
307 err:
308         if (fsdb->fsdb_ost_index_map) 
309                 OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
310         if (fsdb->fsdb_mdt_index_map) 
311                 OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
312         name_destroy(&fsdb->fsdb_clilov); 
313         name_destroy(&fsdb->fsdb_mdtlov); 
314         OBD_FREE_PTR(fsdb);
315         RETURN(NULL);
316 }
317
318 static void mgs_free_fsdb(struct obd_device *obd, struct fs_db *fsdb)
319 {
320         /* wait for anyone with the sem */
321         down(&fsdb->fsdb_sem);
322         lproc_mgs_del_live(obd, fsdb);
323         list_del(&fsdb->fsdb_list);
324         OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
325         OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
326         name_destroy(&fsdb->fsdb_clilov); 
327         name_destroy(&fsdb->fsdb_mdtlov); 
328         name_destroy(&fsdb->fsdb_mdc); 
329         OBD_FREE_PTR(fsdb);
330 }
331
332 int mgs_init_fsdb_list(struct obd_device *obd)
333 {
334         struct mgs_obd *mgs = &obd->u.mgs;
335         INIT_LIST_HEAD(&mgs->mgs_fs_db_list);
336         return 0;
337 }
338
339 int mgs_cleanup_fsdb_list(struct obd_device *obd)
340 {
341         struct mgs_obd *mgs = &obd->u.mgs;
342         struct fs_db *fsdb;
343         struct list_head *tmp, *tmp2;
344         down(&mgs->mgs_sem);
345         list_for_each_safe(tmp, tmp2, &mgs->mgs_fs_db_list) {
346                 fsdb = list_entry(tmp, struct fs_db, fsdb_list);
347                 mgs_free_fsdb(obd, fsdb);
348         }
349         up(&mgs->mgs_sem);
350         return 0;
351 }
352
353 static int mgs_find_or_make_fsdb(struct obd_device *obd, char *name, 
354                                struct fs_db **dbh)
355 {
356         struct mgs_obd *mgs = &obd->u.mgs;
357         struct fs_db *fsdb;
358         int rc = 0;
359
360         down(&mgs->mgs_sem);
361         fsdb = mgs_find_fsdb(obd, name);
362         if (fsdb) {
363                 up(&mgs->mgs_sem);
364                 *dbh = fsdb;
365                 return 0;
366         }
367
368         CDEBUG(D_MGS, "Creating new db\n");
369         fsdb = mgs_new_fsdb(obd, name);
370         up(&mgs->mgs_sem);
371         if (!fsdb) 
372                 return -ENOMEM;
373
374         /* populate the db from the client llog */
375         rc = mgs_get_fsdb_from_llog(obd, fsdb);
376         if (rc) {
377                 CERROR("Can't get db from client log %d\n", rc);
378                 mgs_free_fsdb(obd, fsdb);
379                 return rc;
380         }
381
382         *dbh = fsdb;
383         
384         return 0;
385 }
386
387 /* 1 = index in use
388    0 = index unused 
389    -1= empty client log */
390 int mgs_check_index(struct obd_device *obd, struct mgs_target_info *mti)
391 {
392         struct fs_db *fsdb;
393         void *imap;
394         int rc = 0;
395         ENTRY;
396
397         LASSERT(!(mti->mti_flags & LDD_F_NEED_INDEX));
398
399         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb); 
400         if (rc) {
401                 CERROR("Can't get db for %s\n", mti->mti_fsname);
402                 RETURN(rc);
403         }
404
405         if (fsdb->fsdb_flags & FSDB_LOG_EMPTY) 
406                 RETURN(-1);
407
408         if (mti->mti_flags & LDD_F_SV_TYPE_OST) 
409                 imap = fsdb->fsdb_ost_index_map;
410         else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) 
411                 imap = fsdb->fsdb_mdt_index_map;
412         else
413                 RETURN(-EINVAL);
414
415         if (test_bit(mti->mti_stripe_index, imap)) 
416                 RETURN(1);
417         RETURN(0);
418 }
419
420 static __inline__ int next_index(void *index_map, int map_len)
421 {
422         int i;
423         for (i = 0; i < map_len * 8; i++)
424                  if (!test_bit(i, index_map)) {
425                          return i;
426                  }
427         CERROR("max index %d exceeded.\n", i);
428         return -1;
429 }
430
431 /* Return codes:
432         0  newly marked as in use
433         <0 err
434         +EALREADY for update of an old index */
435 int mgs_set_index(struct obd_device *obd, struct mgs_target_info *mti)
436 {
437         struct fs_db *fsdb;
438         void *imap;
439         int rc = 0;
440         ENTRY;
441
442         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb); 
443         if (rc) {
444                 CERROR("Can't get db for %s\n", mti->mti_fsname);
445                 RETURN(rc);
446         }
447
448         if (mti->mti_flags & LDD_F_SV_TYPE_OST) 
449                 imap = fsdb->fsdb_ost_index_map;
450         else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) 
451                 imap = fsdb->fsdb_mdt_index_map;
452         else
453                 RETURN(-EINVAL);
454
455         if (mti->mti_flags & LDD_F_NEED_INDEX) {
456                 rc = next_index(imap, INDEX_MAP_SIZE);
457                 if (rc == -1)
458                         RETURN(-ERANGE);
459                 mti->mti_stripe_index = rc;
460         }
461
462         /* Remove after CMD */
463         if ((mti->mti_flags & LDD_F_SV_TYPE_MDT) && 
464             (mti->mti_stripe_index > 0)) {
465                 LCONSOLE_ERROR("MDT index must = 0 (until Clustered MetaData "
466                                "feature is ready.)\n");
467                 mti->mti_stripe_index = 0;
468         }
469
470         if (mti->mti_stripe_index >= INDEX_MAP_SIZE * 8) {
471                 LCONSOLE_ERROR("Server %s requested index %d, but the"
472                                "max index is %d.\n", 
473                                mti->mti_svname, mti->mti_stripe_index,
474                                INDEX_MAP_SIZE * 8);
475                 RETURN(-ERANGE);
476         }
477          
478         if (test_bit(mti->mti_stripe_index, imap)) {
479                 if (mti->mti_flags & LDD_F_VIRGIN) {
480                         LCONSOLE_ERROR("Server %s requested index %d, but that "
481                                        "index is already in use\n",
482                                        mti->mti_svname, mti->mti_stripe_index);
483                         RETURN(-EADDRINUSE);
484                 } else {
485                         CDEBUG(D_MGS, "Server %s updating index %d\n",
486                                mti->mti_svname, mti->mti_stripe_index);
487                         RETURN(EALREADY);
488                 }
489         }
490
491         set_bit(mti->mti_stripe_index, imap);
492         fsdb->fsdb_flags &= ~FSDB_LOG_EMPTY;
493         server_make_name(mti->mti_flags, mti->mti_stripe_index,
494                          mti->mti_fsname, mti->mti_svname);
495
496         CDEBUG(D_MGS, "Set index for %s to %d\n", mti->mti_svname, 
497                mti->mti_stripe_index);
498
499         RETURN(0);
500 }
501
502 struct mgs_modify_lookup {
503         struct cfg_marker mml_marker;
504         int               mml_modified;
505 };
506
507 static int mgs_modify_handler(struct llog_handle *llh, struct llog_rec_hdr *rec, 
508                               void *data)
509 {
510         struct mgs_modify_lookup *mml = (struct mgs_modify_lookup *)data;
511         struct cfg_marker *marker;
512         struct lustre_cfg *lcfg = (struct lustre_cfg *)(rec + 1);
513         int cfg_len = rec->lrh_len - sizeof(struct llog_rec_hdr) - 
514                 sizeof(struct llog_rec_tail);
515         int rc;
516         ENTRY;
517
518         if (rec->lrh_type != OBD_CFG_REC) {
519                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
520                 RETURN(-EINVAL);
521         }
522
523         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
524         if (rc) {
525                 CERROR("Insane cfg\n");
526                 RETURN(rc);
527         }
528
529         /* We only care about markers */
530         if (lcfg->lcfg_command != LCFG_MARKER)
531                 RETURN(0); 
532         
533         marker = lustre_cfg_buf(lcfg, 1);
534         if ((strcmp(mml->mml_marker.cm_comment, marker->cm_comment) == 0) && 
535             (strcmp(mml->mml_marker.cm_tgtname, marker->cm_tgtname) == 0) &&
536             !(marker->cm_flags & CM_SKIP)) {
537                 /* Found a non-skipped marker match */
538                 CDEBUG(D_MGS, "Changing rec %u marker %d %x->%x: %s %s\n",
539                        rec->lrh_index, marker->cm_step, 
540                        marker->cm_flags, mml->mml_marker.cm_flags,
541                        marker->cm_tgtname, marker->cm_comment);
542                 /* Overwrite the old marker llog entry */
543                 marker->cm_flags &= ~CM_EXCLUDE; /* in case we're unexcluding */
544                 marker->cm_flags |= mml->mml_marker.cm_flags;
545                 marker->cm_canceltime = mml->mml_marker.cm_canceltime;
546                 /* Header and tail are added back to lrh_len in 
547                    llog_lvfs_write_rec */
548                 rec->lrh_len = cfg_len; 
549                 rc = llog_write_rec(llh, rec, NULL, 0, (void *)lcfg, 
550                                     rec->lrh_index);
551                 if (!rc) 
552                          mml->mml_modified++;
553         }
554
555         RETURN(rc);
556 }
557
558 /* Modify an existing config log record (for CM_SKIP or CM_EXCLUDE) */
559 static int mgs_modify(struct obd_device *obd, struct fs_db *fsdb,
560                       struct mgs_target_info *mti, char *logname, 
561                       char *devname, char *comment, int flags)
562 {
563         struct llog_handle *loghandle;
564         struct lvfs_run_ctxt saved;
565         struct mgs_modify_lookup *mml;
566         int rc, rc2;
567         ENTRY;
568
569         CDEBUG(D_MGS, "modify %s/%s/%s\n", logname, devname, comment);
570
571         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
572         
573         rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
574                          &loghandle, NULL, logname);
575         if (rc)
576                 GOTO(out_pop, rc);
577
578         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
579         if (rc)
580                 GOTO(out_close, rc);
581
582         if (llog_get_size(loghandle) <= 1)
583                 GOTO(out_close, rc = 0);
584
585         OBD_ALLOC_PTR(mml);
586         if (!mml) 
587                 GOTO(out_close, rc = -ENOMEM);
588         strcpy(mml->mml_marker.cm_comment, comment);
589         strcpy(mml->mml_marker.cm_tgtname, devname);
590         /* Modify mostly means cancel */
591         mml->mml_marker.cm_flags = flags;
592         mml->mml_marker.cm_canceltime = flags ? cfs_time_current_sec() : 0;
593         mml->mml_modified = 0;
594         rc = llog_process(loghandle, mgs_modify_handler, (void *)mml, NULL);
595         if (!rc && !mml->mml_modified) 
596                 rc = -ENODEV;
597         OBD_FREE_PTR(mml);
598
599 out_close:
600         rc2 = llog_close(loghandle);
601         if (!rc)
602                 rc = rc2;
603
604 out_pop:
605         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
606         if (rc && rc != -ENODEV) 
607                 CERROR("modify %s/%s failed %d\n",
608                        mti->mti_svname, comment, rc);
609
610         RETURN(rc);
611 }
612
613                            
614 /******************** config log recording functions *********************/
615
616 static int record_lcfg(struct obd_device *obd, struct llog_handle *llh,
617                          struct lustre_cfg *lcfg)
618 {
619         struct lvfs_run_ctxt   saved;
620         struct llog_rec_hdr    rec;
621         int buflen, rc;
622
623         if (!lcfg || !llh) 
624                 return -ENOMEM;
625
626         LASSERT(llh->lgh_ctxt);        
627
628         buflen = lustre_cfg_len(lcfg->lcfg_bufcount,
629                                 lcfg->lcfg_buflens);
630         rec.lrh_len = llog_data_len(buflen);
631         rec.lrh_type = OBD_CFG_REC;
632         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
633         /* idx = -1 means append */
634         rc = llog_write_rec(llh, &rec, NULL, 0, (void *)lcfg, -1);
635         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
636         if (rc) 
637                 CERROR("failed %d\n", rc);
638         return rc;
639 }
640
641 static int record_base(struct obd_device *obd, struct llog_handle *llh,
642                      char *cfgname, lnet_nid_t nid, int cmd,
643                      char *s1, char *s2, char *s3, char *s4)
644 {
645         struct lustre_cfg_bufs bufs;
646         struct lustre_cfg     *lcfg;
647         int rc;
648                
649         CDEBUG(D_MGS, "lcfg %s %#x %s %s %s %s\n", cfgname,
650                cmd, s1, s2, s3, s4); 
651
652         lustre_cfg_bufs_reset(&bufs, cfgname);
653         if (s1) 
654                 lustre_cfg_bufs_set_string(&bufs, 1, s1);
655         if (s2) 
656                 lustre_cfg_bufs_set_string(&bufs, 2, s2);
657         if (s3) 
658                 lustre_cfg_bufs_set_string(&bufs, 3, s3);
659         if (s4) 
660                 lustre_cfg_bufs_set_string(&bufs, 4, s4);
661
662         lcfg = lustre_cfg_new(cmd, &bufs);
663         if (!lcfg) 
664                 return -ENOMEM;
665         lcfg->lcfg_nid = nid;
666
667         rc = record_lcfg(obd, llh, lcfg);
668         
669         lustre_cfg_free(lcfg);
670         
671         if (rc) {
672                 CERROR("error %d: lcfg %s %#x %s %s %s %s\n", rc, cfgname,
673                        cmd, s1, s2, s3, s4); 
674         }
675         return(rc);
676 }
677
678
679 static inline int record_add_uuid(struct obd_device *obd, 
680                                   struct llog_handle *llh, 
681                                   uint64_t nid, char *uuid)
682 {
683         return record_base(obd,llh,NULL,nid,LCFG_ADD_UUID,uuid,0,0,0);
684
685 }
686
687 static inline int record_add_conn(struct obd_device *obd, 
688                                   struct llog_handle *llh,
689                                   char *devname,
690                                   char *uuid)
691 {
692         return record_base(obd,llh,devname,0,LCFG_ADD_CONN,uuid,0,0,0);
693 }
694
695 static inline int record_attach(struct obd_device *obd, struct llog_handle *llh,
696                                 char *devname, char *type, char *uuid)
697 {
698         return record_base(obd,llh,devname,0,LCFG_ATTACH,type,uuid,0,0);
699 }
700
701 static inline int record_setup(struct obd_device *obd, struct llog_handle *llh,
702                                char *devname, 
703                                char *s1, char *s2, char *s3, char *s4)
704 {
705         return record_base(obd,llh,devname,0,LCFG_SETUP,s1,s2,s3,s4);
706 }
707
708 static int record_lov_setup(struct obd_device *obd, struct llog_handle *llh,
709                             char *devname, struct lov_desc *desc)
710 {
711         struct lustre_cfg_bufs bufs;
712         struct lustre_cfg *lcfg;
713         int rc;
714
715         lustre_cfg_bufs_reset(&bufs, devname);
716         lustre_cfg_bufs_set(&bufs, 1, desc, sizeof(*desc));
717         lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
718         if (!lcfg) 
719                 return -ENOMEM;
720         rc = record_lcfg(obd, llh, lcfg);
721
722         lustre_cfg_free(lcfg);
723         return rc;
724 }
725
726 static inline int record_lov_add(struct obd_device *obd,
727                                  struct llog_handle *llh,
728                                  char *lov_name, char *ost_uuid,
729                                  char *index, char *gen)
730 {
731         return record_base(obd,llh,lov_name,0,LCFG_LOV_ADD_OBD,
732                            ost_uuid,index,gen,0);
733 }                                  
734
735 static inline int record_mount_opt(struct obd_device *obd, 
736                                    struct llog_handle *llh,
737                                    char *profile, char *lov_name,
738                                    char *mdc_name)
739 {
740         return record_base(obd,llh,NULL,0,LCFG_MOUNTOPT,
741                            profile,lov_name,mdc_name,0);
742 }                
743
744 static int record_marker(struct obd_device *obd, struct llog_handle *llh,
745                          struct fs_db *fsdb, __u32 flags,
746                          char *tgtname, char *comment)
747 {
748         struct cfg_marker marker;
749         struct lustre_cfg_bufs bufs;
750         struct lustre_cfg *lcfg;
751         int rc;
752
753         if (flags & CM_START) 
754                 fsdb->fsdb_gen++;
755         marker.cm_step = fsdb->fsdb_gen;
756         marker.cm_flags = flags;
757         marker.cm_vers = LUSTRE_VERSION_CODE;
758         strncpy(marker.cm_tgtname, tgtname, sizeof(marker.cm_tgtname)); 
759         strncpy(marker.cm_comment, comment, sizeof(marker.cm_comment)); 
760         marker.cm_createtime = cfs_time_current_sec();
761         marker.cm_canceltime = 0;
762         lustre_cfg_bufs_reset(&bufs, NULL);
763         lustre_cfg_bufs_set(&bufs, 1, &marker, sizeof(marker));
764         lcfg = lustre_cfg_new(LCFG_MARKER, &bufs);
765         if (!lcfg) 
766                 return -ENOMEM;
767         rc = record_lcfg(obd, llh, lcfg);
768
769         lustre_cfg_free(lcfg);
770         return rc;
771 }
772
773 static int record_start_log(struct obd_device *obd, 
774                             struct llog_handle **llh, char *name)
775 {
776         static struct obd_uuid cfg_uuid = { .uuid = "config_uuid" };
777         struct lvfs_run_ctxt saved;
778         int rc = 0;
779         
780         if (*llh) {
781                 GOTO(out, rc = -EBUSY);
782         }
783
784         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
785
786         rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
787                          llh, NULL, name);
788         if (rc == 0)
789                 llog_init_handle(*llh, LLOG_F_IS_PLAIN, &cfg_uuid);
790         else
791                 *llh = NULL;
792
793         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
794
795 out:
796         if (rc) {
797                 CERROR("Can't start log %s: %d\n", name, rc);
798         }
799         RETURN(rc);
800 }
801
802 static int record_end_log(struct obd_device *obd, struct llog_handle **llh)
803 {
804         struct lvfs_run_ctxt saved;
805         int rc = 0;
806
807         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
808         
809         rc = llog_close(*llh);
810         *llh = NULL;
811         
812         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
813         RETURN(rc);
814 }
815
816 static int mgs_log_is_empty(struct obd_device *obd, char *name)
817 {
818         struct lvfs_run_ctxt saved;
819         struct llog_handle *llh;
820         int rc = 0;
821
822         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
823         rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
824                          &llh, NULL, name);
825         if (rc == 0) {
826                 llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
827                 rc = llog_get_size(llh);
828                 llog_close(llh);
829         }
830         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
831         /* header is record 1 */
832         return(rc <= 1);
833 }
834
835 /******************** config "macros" *********************/
836
837 /* write an lcfg directly into a log (with markers) */
838 static int mgs_write_log_direct(struct obd_device *obd, struct fs_db *fsdb,
839                                 char *logname, struct lustre_cfg *lcfg, 
840                                 char *devname, char *comment)
841 {
842         struct llog_handle *llh = NULL;
843         int rc;
844         ENTRY;
845
846         if (!lcfg) 
847                 RETURN(-ENOMEM);
848
849         rc = record_start_log(obd, &llh, logname);
850         if (rc) 
851                 RETURN(rc);
852         
853         /* FIXME These should be a single journal transaction */
854         rc = record_marker(obd, llh, fsdb, CM_START, devname, comment); 
855         
856         rc = record_lcfg(obd, llh, lcfg);
857
858         rc = record_marker(obd, llh, fsdb, CM_END, devname, comment); 
859         rc = record_end_log(obd, &llh);
860         
861         RETURN(rc);
862 }
863
864 /* write the lcfg in all logs for the given fs */
865 int mgs_write_log_direct_all(struct obd_device *obd, struct fs_db *fsdb,
866                              struct mgs_target_info *mti, 
867                              struct lustre_cfg *lcfg,
868                              char *devname, char *comment)
869 {
870         struct mgs_obd *mgs = &obd->u.mgs;
871         struct list_head dentry_list;
872         struct l_linux_dirent *dirent, *n;
873         char *fsname = mti->mti_fsname;
874         char *logname;
875         int rc = 0, len = strlen(fsname);
876         ENTRY;
877         
878         /* We need to set params for any future logs 
879            as well. FIXME Append this file to every new log. 
880            Actually, we should store as params (text), not llogs.  Or
881            in a database. */
882         name_create(&logname, fsname, "-params");
883         if (mgs_log_is_empty(obd, logname)) {
884                 struct llog_handle *llh = NULL;
885                 rc = record_start_log(obd, &llh, logname);
886                 record_end_log(obd, &llh);
887         }
888         name_destroy(&logname);
889         if (rc) 
890                 RETURN(rc);
891
892         /* Find all the logs in the CONFIGS directory */
893         rc = class_dentry_readdir(obd, mgs->mgs_configs_dir,
894                                   mgs->mgs_vfsmnt, &dentry_list);
895         if (rc) {
896                 CERROR("Can't read %s dir\n", MOUNT_CONFIGS_DIR);
897                 RETURN(rc);
898         }
899                                                                                 
900         /* Could use fsdb index maps instead of directory listing */
901         list_for_each_entry_safe(dirent, n, &dentry_list, lld_list) {
902                 list_del(&dirent->lld_list);
903                 if (strncmp(fsname, dirent->lld_name, len) == 0) {
904                         CDEBUG(D_MGS, "Changing log %s\n", dirent->lld_name);
905                         /* Erase any old settings of this same parameter */
906                         mgs_modify(obd, fsdb, mti, dirent->lld_name, devname, 
907                                    comment, CM_SKIP);
908                         /* Write the new one */
909                         rc = mgs_write_log_direct(obd, fsdb, dirent->lld_name,
910                                                   lcfg, devname, comment);
911                         if (rc)
912                                 CERROR("err %d writing log %s\n", rc, 
913                                        dirent->lld_name);
914                 }
915                 OBD_FREE(dirent, sizeof(*dirent));
916         }
917         
918         RETURN(rc);
919 }
920
921 /* lov is the first thing in the mdt and client logs */
922 static int mgs_write_log_lov(struct obd_device *obd, struct fs_db *fsdb, 
923                              struct mgs_target_info *mti,
924                              char *logname, char *lovname)
925 {
926         struct llog_handle *llh = NULL;
927         struct lov_desc *lovdesc;
928         char *uuid;
929         int rc = 0;
930         ENTRY;
931
932         CDEBUG(D_MGS, "Writing log %s\n", logname);
933
934         /*
935         #01 L attach   0:lov_mdsA  1:lov  2:71ccb_lov_mdsA_19f961a9e1
936         #02 L lov_setup 0:lov_mdsA 1:(struct lov_desc)
937               uuid=lov1_UUID, stripe count=1, size=1048576, offset=0, pattern=0
938         */
939
940         /* FIXME just make lov_setup accept empty desc (put uuid in buf 2) */
941         OBD_ALLOC(lovdesc, sizeof(*lovdesc));
942         if (lovdesc == NULL)
943                 RETURN(-ENOMEM);
944         lovdesc->ld_magic = LOV_DESC_MAGIC;
945         lovdesc->ld_tgt_count = 0;
946         /* Defaults.  Can be changed later by lcfg config_param */ 
947         lovdesc->ld_default_stripe_count = 1;
948         lovdesc->ld_pattern = LOV_PATTERN_RAID0;
949         lovdesc->ld_default_stripe_size = 1024 * 1024;
950         lovdesc->ld_default_stripe_offset = 0;
951         lovdesc->ld_qos_maxage = QOS_DEFAULT_MAXAGE;
952         sprintf((char*)lovdesc->ld_uuid.uuid, "%s_UUID", lovname);
953         /* can these be the same? */
954         uuid = (char *)lovdesc->ld_uuid.uuid;
955
956         /* This should always be the first entry in a log.
957         rc = mgs_clear_log(obd, logname); */
958         rc = record_start_log(obd, &llh, logname);
959         if (rc) 
960                 GOTO(out, rc);
961         /* FIXME these should be a single journal transaction */
962         rc = record_marker(obd, llh, fsdb, CM_START, lovname, "lov setup"); 
963         rc = record_attach(obd, llh, lovname, "lov", uuid);
964         rc = record_lov_setup(obd, llh, lovname, lovdesc);
965         rc = record_marker(obd, llh, fsdb, CM_END, lovname, "lov setup"); 
966         rc = record_end_log(obd, &llh);
967 out:        
968         OBD_FREE(lovdesc, sizeof(*lovdesc));
969         RETURN(rc);
970 }
971
972 /* add failnids to open log */
973 static int mgs_write_log_failnids(struct obd_device *obd,
974                                   struct mgs_target_info *mti,
975                                   struct llog_handle *llh,
976                                   char *cliname)
977 {
978         char *failnodeuuid = NULL;
979         char *ptr = mti->mti_params;
980         lnet_nid_t nid;
981         int rc = 0;
982
983         /*
984         #03 L add_uuid  nid=uml1@tcp(0x20000c0a80201) nal=90 0:  1:uml1_UUID
985         #04 L add_uuid  nid=1@elan(0x1000000000001)   nal=90 0:  1:uml1_UUID
986         #05 L setup    0:OSC_uml1_ost1_mdsA  1:ost1_UUID  2:uml1_UUID
987         #06 L add_uuid  nid=uml2@tcp(0x20000c0a80202) nal=90 0:  1:uml2_UUID
988         #0x L add_uuid  nid=2@elan(0x1000000000002)   nal=90 0:  1:uml2_UUID
989         #07 L add_conn 0:OSC_uml1_ost1_mdsA  1:uml2_UUID
990         */
991
992         /* Pull failnid info out of params string */
993         while (class_find_param(ptr, PARAM_FAILNODE, &ptr) == 0) {
994                 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
995                         if (failnodeuuid == NULL) {
996                                 /* We don't know the failover node name, 
997                                    so just use the first nid as the uuid */
998                                 rc = name_create(&failnodeuuid,
999                                                  libcfs_nid2str(nid), "");
1000                                 if (rc) 
1001                                         return rc;
1002                         }
1003                         CDEBUG(D_MGS, "add nid %s for failover uuid %s, "
1004                                "client %s\n", libcfs_nid2str(nid),
1005                                failnodeuuid, cliname);
1006                         rc = record_add_uuid(obd, llh, nid, failnodeuuid);
1007                 }
1008                 if (failnodeuuid) {
1009                         rc = record_add_conn(obd, llh, cliname, failnodeuuid);
1010                         name_destroy(&failnodeuuid);
1011                         failnodeuuid = NULL;
1012                 }
1013         }
1014
1015         return rc;
1016 }
1017
1018 static int mgs_write_log_mdt(struct obd_device *obd, struct fs_db *fsdb,
1019                              struct mgs_target_info *mti)
1020 {
1021         struct llog_handle *llh = NULL;
1022         char *cliname, *mdcname, *nodeuuid, *mdcuuid;
1023         int rc, i, first_log = 0;
1024         ENTRY;
1025
1026         CDEBUG(D_MGS, "writing new mdt %s\n", mti->mti_svname);
1027
1028         /* COMPAT_146 */
1029         if (mti->mti_flags & LDD_F_UPGRADE14) {
1030                 /* We're starting with an old uuid.  Assume old name for lov
1031                    as well since the lov entry already exists in the log. */
1032                 CDEBUG(D_MGS, "old mds uuid %s\n", mti->mti_uuid);
1033                 if (strncmp(mti->mti_uuid, fsdb->fsdb_mdtlov + 4, 
1034                             strlen(fsdb->fsdb_mdtlov) - 4) != 0) {
1035                         CERROR("old mds uuid %s doesn't match log %s (%s)\n",
1036                                mti->mti_uuid, fsdb->fsdb_mdtlov, 
1037                                fsdb->fsdb_mdtlov + 4);
1038                         RETURN(-EINVAL);
1039                 }
1040         }
1041         /* end COMPAT_146 */
1042         
1043         if (mti->mti_uuid[0] == '\0') {
1044                 /* Make up our own uuid */
1045                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
1046                          "%s_UUID", mti->mti_svname);
1047         }
1048
1049         /* Append mdt info to mdt log */
1050         if (mgs_log_is_empty(obd, mti->mti_svname)) {
1051                 /* This is the first time for all logs for this fs, 
1052                    since any ost should have already started the mdt log. */
1053                 first_log++;
1054                 rc = mgs_write_log_lov(obd, fsdb, mti, mti->mti_svname,
1055                                        fsdb->fsdb_mdtlov);
1056         } 
1057         /* else there's already some ost entries in the mdt log. */
1058
1059         /* We added the lov, maybe some osc's, now for the mdt.
1060            We might add more ost's after this. Note that during the parsing
1061            of this log, this is when the mdt will start. (This was not 
1062            formerly part of the old mds log, it was directly executed by
1063            lconf.) */ 
1064         /*
1065         mount_option 0:  1:mdsA  2:lov_mdsA
1066         attach mds mdsA mdsA_UUID
1067         setup /dev/loop2 ldiskfs mdsA errors=remount-ro,user_xattr
1068         */
1069         rc = record_start_log(obd, &llh, mti->mti_svname);
1070         if (rc) 
1071                 RETURN(rc);
1072         /* FIXME this whole fn should be a single journal transaction */
1073         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,"add mdt"); 
1074         rc = record_mount_opt(obd, llh, mti->mti_svname, fsdb->fsdb_mdtlov, 0);
1075         rc = record_attach(obd, llh, mti->mti_svname, LUSTRE_MDS_NAME, 
1076                            mti->mti_uuid);
1077         rc = record_setup(obd, llh, mti->mti_svname,
1078                           "dev"/*ignored*/, "type"/*ignored*/,
1079                           mti->mti_svname, 0/*options*/);
1080         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname, "add mdt"); 
1081         rc = record_end_log(obd, &llh);
1082
1083         /* Append the mdt info to the client log */
1084         name_create(&cliname, mti->mti_fsname, "-client");
1085         if (first_log) { 
1086                 /* Start client log */
1087                 rc = mgs_write_log_lov(obd, fsdb, mti, cliname,
1088                                        fsdb->fsdb_clilov);
1089         }
1090
1091         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]),/*"_UUID"*/"");
1092         name_create(&mdcname, mti->mti_svname, "-mdc");
1093         name_create(&mdcuuid, mdcname, "_UUID");
1094         /* 
1095         #09 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
1096         #10 L attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f
1097         #11 L setup    0:MDC_uml1_mdsA_MNT_client  1:mdsA_UUID  2:uml1_UUID
1098         #12 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
1099         #13 L add_conn 0:MDC_uml1_mdsA_MNT_client  1:uml2_UUID
1100         #14 L mount_option 0:  1:client  2:lov1  3:MDC_uml1_mdsA_MNT_client
1101         */
1102         rc = record_start_log(obd, &llh, cliname);
1103         if (rc) 
1104                 GOTO(out, rc);
1105         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,"add mdc");
1106         /* COMPAT_146 */
1107         if (mti->mti_flags & LDD_F_UPGRADE14) { 
1108                 /* Old client log already has MDC entry, but needs mount opt 
1109                    for new client name (lustre-client) */
1110                 /* FIXME Old MDT log already has an old mount opt 
1111                    which we should remove (currently handled by
1112                    class_del_profiles()) */
1113                 rc = record_mount_opt(obd, llh, cliname, fsdb->fsdb_clilov,
1114                                       fsdb->fsdb_mdc);
1115                 /* end COMPAT_146 */
1116         } else {
1117                 for (i = 0; i < mti->mti_nid_count; i++) {
1118                         CDEBUG(D_MGS, "add nid %s\n",
1119                                libcfs_nid2str(mti->mti_nids[i]));
1120                         rc = record_add_uuid(obd, llh, mti->mti_nids[i],
1121                                              nodeuuid);
1122                 }
1123                 rc = record_attach(obd, llh, mdcname, LUSTRE_MDC_NAME, mdcuuid);
1124                 rc = record_setup(obd, llh, mdcname, mti->mti_uuid,nodeuuid,
1125                                   0, 0);
1126                 rc = mgs_write_log_failnids(obd, mti, llh, mdcname);
1127                 rc = record_mount_opt(obd, llh, cliname, fsdb->fsdb_clilov,
1128                                       mdcname);
1129         }
1130         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname, "add mdc"); 
1131         rc = record_end_log(obd, &llh);
1132 out:
1133         name_destroy(&mdcuuid);
1134         name_destroy(&mdcname);
1135         name_destroy(&nodeuuid);
1136         name_destroy(&cliname);
1137         RETURN(rc);
1138 }
1139
1140 /* Add the ost info to the client/mdt lov */
1141 static int mgs_write_log_osc(struct obd_device *obd, struct fs_db *fsdb,
1142                              struct mgs_target_info *mti,
1143                              char *logname, char *lovname, int flags)
1144 {
1145         struct llog_handle *llh = NULL;
1146         char *nodeuuid, *oscname, *oscuuid, *lovuuid;
1147         char index[5];
1148         int i, rc;
1149
1150         if (mgs_log_is_empty(obd, logname)) {
1151                 /* The first item in the log must be the lov, so we have
1152                    somewhere to add our osc. */
1153                 rc = mgs_write_log_lov(obd, fsdb, mti, logname, lovname);
1154         }
1155   
1156         CDEBUG(D_MGS, "adding osc for %s to log %s\n",
1157                mti->mti_svname, logname);
1158
1159         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
1160         name_create(&oscname, mti->mti_svname, "-osc");
1161         name_create(&oscuuid, oscname, "_UUID");
1162         name_create(&lovuuid, lovname, "_UUID");
1163
1164         /*
1165         #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
1166         multihomed (#4)
1167         #04 L add_uuid  nid=1@elan(0x1000000000001)  nal=90 0:  1:uml1_UUID
1168         #04 L attach   0:OSC_uml1_ost1_MNT_client  1:osc  2:89070_lov1_a41dff51a
1169         #05 L setup    0:OSC_uml1_ost1_MNT_client  1:ost1_UUID  2:uml1_UUID
1170         failover (#6,7)
1171         #06 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
1172         #07 L add_conn 0:OSC_uml1_ost1_MNT_client  1:uml2_UUID
1173         #08 L lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1
1174         */
1175         rc = record_start_log(obd, &llh, logname);
1176         if (rc) 
1177                 GOTO(out, rc);
1178         /* FIXME these should be a single journal transaction */
1179         rc = record_marker(obd, llh, fsdb, CM_START | flags, mti->mti_svname,
1180                            "add osc"); 
1181         for (i = 0; i < mti->mti_nid_count; i++) {
1182                 CDEBUG(D_MGS, "add nid %s\n", libcfs_nid2str(mti->mti_nids[i]));
1183                 rc = record_add_uuid(obd, llh, mti->mti_nids[i], nodeuuid);
1184         }
1185         rc = record_attach(obd, llh, oscname, LUSTRE_OSC_NAME, lovuuid);
1186         rc = record_setup(obd, llh, oscname, mti->mti_uuid, nodeuuid, 0, 0);
1187         rc = mgs_write_log_failnids(obd, mti, llh, oscname);
1188         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
1189         rc = record_lov_add(obd, llh, lovname, mti->mti_uuid, index, "1");
1190         rc = record_marker(obd, llh, fsdb, CM_END | flags, mti->mti_svname,
1191                            "add osc"); 
1192         rc = record_end_log(obd, &llh);
1193 out:        
1194         name_destroy(&lovuuid);
1195         name_destroy(&oscuuid);
1196         name_destroy(&oscname);
1197         name_destroy(&nodeuuid);
1198         return rc;
1199 }
1200
1201 static int mgs_write_log_ost(struct obd_device *obd, struct fs_db *fsdb,
1202                              struct mgs_target_info *mti)
1203 {
1204         struct llog_handle *llh = NULL;
1205         char *logname;
1206         char *ptr = mti->mti_params;
1207         int rc, flags = 0, failout = 0;
1208         ENTRY;
1209         
1210         CDEBUG(D_MGS, "writing new ost %s\n", mti->mti_svname);
1211
1212         /* The ost startup log */
1213
1214         /* If the ost log already exists, that means that someone reformatted
1215            the ost and it called target_add again. */
1216         if (!mgs_log_is_empty(obd, mti->mti_svname)) {
1217                 LCONSOLE_ERROR("The config log for %s already exists, yet the "
1218                                "server claims it never registered.  It may have"
1219                                " been reformatted, or the index changed. "
1220                                "writeconf the MDT to regenerate all logs.\n", 
1221                                mti->mti_svname);
1222                 RETURN(-EALREADY);
1223         }
1224         /*
1225         attach obdfilter ost1 ost1_UUID
1226         setup /dev/loop2 ldiskfs f|n errors=remount-ro,user_xattr
1227         */
1228         if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0) 
1229                 failout = (strncmp(ptr, "failout", 7) == 0);
1230         rc = record_start_log(obd, &llh, mti->mti_svname);
1231         if (rc) 
1232                 RETURN(rc);
1233         /* FIXME these should be a single journal transaction */
1234         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,"add ost"); 
1235         if (*mti->mti_uuid == '\0') 
1236                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
1237                          "%s_UUID", mti->mti_svname);
1238         rc = record_attach(obd, llh, mti->mti_svname,
1239                            "obdfilter"/*LUSTRE_OST_NAME*/, mti->mti_uuid);
1240         rc = record_setup(obd, llh, mti->mti_svname,
1241                           "dev"/*ignored*/, "type"/*ignored*/,
1242                           failout ? "n" : "f", 0/*options*/);
1243         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname, "add ost"); 
1244         rc = record_end_log(obd, &llh);
1245
1246         /* We also have to update the other logs where this osc is part of 
1247            the lov */
1248
1249         if (mti->mti_flags & LDD_F_UPGRADE14) {
1250                 /* If we're upgrading, the old mdt log already has our
1251                    entry. Let's do a fake one for fun. */
1252                 flags = CM_SKIP | CM_UPGRADE146;
1253         } else if ((mti->mti_flags & LDD_F_UPDATE) != LDD_F_UPDATE) {
1254                 /* If the update flag isn't set, don't really update
1255                    client/mdt logs. */
1256                 flags |= CM_SKIP;
1257                 LCONSOLE_WARN("Client log for %s was not updated; writeconf "
1258                               "the MDT first to regenerate it.\n",
1259                               mti->mti_svname);
1260         }
1261         
1262         /* Append ost info to mdt log */
1263         /* FIXME add to all MDT logs for CMD */
1264         /* FIXME need real MDT name, but MDT may not have registered yet! */
1265         name_create(&logname, mti->mti_fsname, "-MDT0000");
1266         rc = mgs_write_log_osc(obd, fsdb, mti, logname, fsdb->fsdb_mdtlov,
1267                                flags);
1268         name_destroy(&logname);
1269         
1270         /* Append ost info to the client log */
1271         name_create(&logname, mti->mti_fsname, "-client");
1272         rc = mgs_write_log_osc(obd, fsdb, mti, logname, fsdb->fsdb_clilov, 
1273                                flags);
1274         name_destroy(&logname);
1275         
1276         RETURN(rc);
1277 }
1278
1279 /* Add additional failnids to an existing log.  
1280    The mdc/osc must have been added to logs first */
1281 /* tcp nids must be in dotted-quad ascii -
1282    we can't resolve hostnames from the kernel. */
1283 static int mgs_write_log_add_failnid(struct obd_device *obd, struct fs_db *fsdb,
1284                                      struct mgs_target_info *mti)
1285 {
1286         char *logname, *cliname;
1287         struct llog_handle *llh = NULL;
1288         int rc;
1289         ENTRY;
1290
1291         /* Verify that we know about this target */
1292         if (mgs_log_is_empty(obd, mti->mti_svname)) {
1293                 LCONSOLE_ERROR("The target %s has not registered yet. "
1294                                "It must be started before failnids can "
1295                                "be added.\n", mti->mti_svname);
1296                 RETURN(-ENOENT);
1297         }
1298
1299         /* Create mdc/osc client name (e.g. lustre-OST0001-osc) */
1300         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
1301                 name_create(&cliname, mti->mti_svname, "-mdc");
1302         } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1303                 name_create(&cliname, mti->mti_svname, "-osc");
1304         } else {
1305                 RETURN(-EINVAL);
1306         }
1307         
1308         /* Add failover nids to client log */
1309         name_create(&logname, mti->mti_fsname, "-client");
1310         rc = record_start_log(obd, &llh, logname);
1311         if (!rc) { 
1312                 /* FIXME this fn should be a single journal transaction */
1313                 rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,
1314                                    "add failnid");
1315                 rc = mgs_write_log_failnids(obd, mti, llh, cliname);
1316                 rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname,
1317                                    "add failnid"); 
1318                 rc = record_end_log(obd, &llh);
1319         }
1320         name_destroy(&logname);
1321
1322         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1323                 /* Add OST failover nids to the MDT log as well */
1324                 name_create(&logname, mti->mti_fsname, "-MDT0000");
1325                 rc = record_start_log(obd, &llh, logname);
1326                 if (!rc) {
1327                         rc = record_marker(obd, llh, fsdb, CM_START, 
1328                                            mti->mti_svname, "add failnid");
1329                         rc = mgs_write_log_failnids(obd, mti, llh, cliname);
1330                         rc = record_marker(obd, llh, fsdb, CM_END, 
1331                                            mti->mti_svname, "add failnid"); 
1332                         rc = record_end_log(obd, &llh);
1333                 }
1334                 name_destroy(&logname);
1335         }
1336
1337         name_destroy(&cliname);
1338         RETURN(rc);
1339 }
1340
1341 static int mgs_wlp_lcfg(struct obd_device *obd, struct fs_db *fsdb, 
1342                         struct mgs_target_info *mti,
1343                         char *logname, struct lustre_cfg_bufs *bufs,
1344                         char *tgtname, char *ptr)
1345 {
1346         char comment[MTI_NAME_MAXLEN];
1347         char *tmp;
1348         struct lustre_cfg *lcfg;
1349         int rc;
1350         
1351         /* Erase any old settings of this same parameter */
1352         memcpy(comment, ptr, MTI_NAME_MAXLEN);
1353         comment[MTI_NAME_MAXLEN - 1] = 0;
1354         /* But don't try to match the value. */
1355         if ((tmp = strchr(comment, '=')))
1356             *tmp = 0;
1357         rc = mgs_modify(obd, fsdb, mti, logname, tgtname, comment, CM_SKIP);
1358         LCONSOLE_INFO("%sing parameter %s.%s in log %s\n", rc ?
1359                       "Sett" : "Modify", tgtname, comment, logname);
1360
1361         lustre_cfg_bufs_reset(bufs, tgtname);
1362         lustre_cfg_bufs_set_string(bufs, 1, ptr);
1363         lcfg = lustre_cfg_new(LCFG_PARAM, bufs);
1364         if (!lcfg) 
1365                 return -ENOMEM;
1366         rc = mgs_write_log_direct(obd, fsdb, logname, lcfg, tgtname, comment);
1367         lustre_cfg_free(lcfg);
1368         return rc;
1369 }
1370
1371 static int mgs_write_log_params(struct obd_device *obd, struct fs_db *fsdb,
1372                                 struct mgs_target_info *mti)
1373 {
1374         struct lustre_cfg_bufs bufs;
1375         struct lustre_cfg *lcfg;
1376         char *logname;
1377         char *ptr = mti->mti_params;
1378         char *endptr, *tmp;
1379         int rc = 0;
1380         ENTRY;
1381
1382         if (!mti->mti_params) 
1383                 RETURN(0);
1384
1385         /* FIXME we should cancel out old settings of the same parameters,
1386            and skip settings that are the same as old values */
1387
1388         /* For various parameter settings, we have to figure out which logs
1389            care about them (e.g. both mdt and client for lov settings) */
1390         while (ptr) {
1391                 while (*ptr == ' ') 
1392                         ptr++;
1393                 if (*ptr == '\0')
1394                         break;
1395                 endptr = strchr(ptr, ' ');
1396                 if (endptr) 
1397                         *endptr = '\0';
1398                 CDEBUG(D_MGS, "next param '%s'\n", ptr);
1399
1400                 /* The params are stored in MOUNT_DATA_FILE and modified 
1401                    via tunefs.lustre */
1402
1403                 /* Processed in lustre_start_mgc */
1404                 if (class_match_param(ptr, PARAM_MGSNODE, NULL) == 0) 
1405                         goto end_while;
1406
1407                 /* Processed in mgs_write_log_ost */
1408                 if (class_match_param(ptr, PARAM_FAILMODE, NULL) == 0) 
1409                         goto end_while;
1410
1411                 if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
1412                         /* Add a failover nidlist */
1413                         rc = 0;
1414                         /* We already processed failovers params for new
1415                            targets in mgs_write_log_target */
1416                         if (mti->mti_flags & LDD_F_PARAM_FNID) {
1417                                 CDEBUG(D_MGS, "Adding failnode\n");
1418                                 rc = mgs_write_log_add_failnid(obd, fsdb, mti);
1419                         }
1420                         goto end_while;
1421                 }
1422
1423                 if (class_match_param(ptr, PARAM_SYS_TIMEOUT, &tmp) == 0) {
1424                         /* Change obd timeout */
1425                         int timeout;
1426                         timeout = simple_strtoul(tmp, NULL, 0);
1427
1428                         CDEBUG(D_MGS, "obd timeout %d\n", timeout);
1429                         
1430                         lustre_cfg_bufs_reset(&bufs, NULL);
1431                         lcfg = lustre_cfg_new(LCFG_SET_TIMEOUT, &bufs);
1432                         lcfg->lcfg_num = timeout;
1433                         /* modify all servers and clients */
1434                         rc = mgs_write_log_direct_all(obd, fsdb, mti, lcfg,
1435                                                       mti->mti_fsname,
1436                                                       "timeout"); 
1437                         lustre_cfg_free(lcfg);
1438                         goto end_while;
1439                 }
1440
1441                 if (class_match_param(ptr, PARAM_OSC""PARAM_ACTIVE, &tmp) == 0){ 
1442                         /* active=0 means off, anything else means on */
1443                         int flag = (*tmp == '0') ? CM_EXCLUDE : 0;
1444                         if (!(mti->mti_flags & LDD_F_SV_TYPE_OST)) {
1445                                 LCONSOLE_ERROR("%s: Only OSCs can be (de)activ"
1446                                                "ated.\n", mti->mti_svname);
1447                                 rc = -EINVAL;
1448                                 goto end_while;
1449                         }
1450                         LCONSOLE_WARN("Permanently %sactivating %s\n",
1451                                       flag ? "de": "re", mti->mti_svname);
1452                         /* Modify clilov */
1453                         name_create(&logname, mti->mti_fsname, "-client");
1454                         rc = mgs_modify(obd, fsdb, mti, logname, 
1455                                         mti->mti_svname, "add osc", flag);
1456                         name_destroy(&logname);
1457                         if (rc) 
1458                                 goto active_err;
1459                         /* Modify mdtlov */
1460                         /* FIXME add to all MDT logs for CMD */
1461                         name_create(&logname, mti->mti_fsname, "-MDT0000");
1462                         rc = mgs_modify(obd, fsdb, mti, logname, 
1463                                         mti->mti_svname, "add osc", flag);
1464                         name_destroy(&logname);
1465 active_err:
1466                         if (rc) {
1467                                 LCONSOLE_ERROR("Couldn't find %s in log (%d). "
1468                                    "No permanent changes were made to the "
1469                                    "config log.\n", mti->mti_svname, rc);
1470                                 if (fsdb->fsdb_flags & FSDB_OLDLOG14) 
1471                                         LCONSOLE_ERROR("This may be because the"
1472                                         " log is in the old 1.4 style. Consider"
1473                                         " --writeconf to update the logs.\n");
1474                                 goto end_while;
1475                         }
1476                         /* Fall through to osc proc for deactivating 
1477                            live OSC on running MDT / clients. */
1478                 }
1479
1480                 /* Below here, let obd's XXX_process_config methods handle it */
1481
1482                 /* All lov. in proc */
1483                 if (class_match_param(ptr, PARAM_LOV, NULL) == 0) {
1484                         CDEBUG(D_MGS, "lov param %s\n", ptr);
1485                         if (!(mti->mti_flags & LDD_F_SV_TYPE_MDT)) {
1486                                 LCONSOLE_ERROR("LOV params must be set on the "
1487                                                "MDT, not %s. Ignoring.\n",
1488                                                mti->mti_svname);
1489                                 rc = 0;
1490                                 goto end_while;
1491                         }
1492
1493                         /* Modify mdtlov */
1494                         if (mgs_log_is_empty(obd, mti->mti_svname)) {
1495                                 rc = -ENODEV;
1496                                 goto end_while;
1497                         }
1498                         rc = mgs_wlp_lcfg(obd, fsdb, mti, mti->mti_svname, 
1499                                           &bufs, fsdb->fsdb_mdtlov, ptr);
1500                         if (rc) 
1501                                 goto end_while;
1502
1503                         /* Modify clilov */
1504                         name_create(&logname, mti->mti_fsname, "-client");
1505                         rc = mgs_wlp_lcfg(obd, fsdb, mti, logname, &bufs,
1506                                           fsdb->fsdb_clilov, ptr);
1507                         name_destroy(&logname);
1508                         goto end_while;
1509                 }
1510
1511                 /* All osc., mdc., llite. params in proc */
1512                 if ((class_match_param(ptr, PARAM_OSC, NULL) == 0) || 
1513                     (class_match_param(ptr, PARAM_MDC, NULL) == 0) || 
1514                     (class_match_param(ptr, PARAM_LLITE, NULL) == 0)) {
1515                         char *cname;
1516                         if (memcmp(ptr, PARAM_LLITE, strlen(PARAM_LLITE)) == 0) {
1517                                 name_create(&cname, mti->mti_fsname, "-client");
1518                         /* Add the client type to match the obdname 
1519                            in class_config_llog_handler */
1520                         } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
1521                                 name_create(&cname, mti->mti_svname, "-mdc");
1522                         } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1523                                 name_create(&cname, mti->mti_svname, "-osc");
1524                         } else {       
1525                                 rc = -EINVAL;
1526                                 goto end_while;
1527                         }
1528
1529                         CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
1530                         
1531                         /* Modify client */
1532                         name_create(&logname, mti->mti_fsname, "-client");
1533                         rc = mgs_wlp_lcfg(obd, fsdb, mti, logname, &bufs, 
1534                                           cname, ptr);
1535                         name_destroy(&logname);
1536                         
1537                         /* osc params affect the MDT as well */
1538                         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1539                                 /* FIXME add to all MDT logs for CMD */
1540                                 name_create(&logname, mti->mti_fsname,
1541                                             "-MDT0000");
1542                                 if (!mgs_log_is_empty(obd, logname))
1543                                         rc = mgs_wlp_lcfg(obd, fsdb, mti,
1544                                                           logname, &bufs, 
1545                                                           cname, ptr);
1546                                 name_destroy(&logname);
1547                         }
1548                         name_destroy(&cname);
1549                         goto end_while;
1550                 }
1551
1552                 /* All mdt., ost. params in proc */
1553                 if ((class_match_param(ptr, PARAM_MDT, NULL) == 0) || 
1554                     (class_match_param(ptr, PARAM_OST, NULL) == 0)) {
1555                         CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
1556                         if (mgs_log_is_empty(obd, mti->mti_svname)) {
1557                                 rc = -ENODEV;
1558                                 goto end_while;
1559                         }
1560                         rc = mgs_wlp_lcfg(obd, fsdb, mti, mti->mti_svname,
1561                                           &bufs, mti->mti_svname, ptr);
1562                         goto end_while;
1563                 }
1564
1565                 LCONSOLE_WARN("Ignoring unrecognized param '%s'\n", ptr);
1566
1567 end_while:
1568                 if (rc) {
1569                         CERROR("err %d on param '%s\n", rc, ptr);
1570                         break;
1571                 }
1572                 
1573                 if (!endptr)
1574                         /* last param */
1575                         break;
1576                  
1577                 *endptr = ' ';
1578                 ptr = endptr + 1;
1579         }
1580
1581         RETURN(rc);
1582 }
1583
1584 int mgs_check_failnid(struct obd_device *obd, struct mgs_target_info *mti)
1585 {
1586         /* Not implementing automatic failover nid addition at this time. */
1587         return 0;
1588 #if 0
1589         struct fs_db *fsdb;
1590         int rc;
1591         ENTRY;
1592
1593         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb); 
1594         if (rc) 
1595                 RETURN(rc);
1596
1597         if (mgs_log_is_empty(obd, mti->mti_svname)) 
1598                 /* should never happen */
1599                 RETURN(-ENOENT);
1600
1601         CDEBUG(D_MGS, "Checking for new failnids for %s\n", mti->mti_svname);
1602
1603         /* FIXME We can just check mti->params to see if we're already in
1604            the failover list.  Modify mti->params for rewriting back at 
1605            server_register_target(). */
1606         
1607         down(&fsdb->fsdb_sem);
1608         rc = mgs_write_log_add_failnid(obd, fsdb, mti);
1609         up(&fsdb->fsdb_sem);
1610
1611         RETURN(rc);
1612 #endif
1613 }
1614
1615 int mgs_write_log_target(struct obd_device *obd,
1616                          struct mgs_target_info *mti)
1617 {
1618         struct fs_db *fsdb;
1619         int rc = -EINVAL;
1620         ENTRY;
1621
1622         /* set/check the new target index */
1623         rc = mgs_set_index(obd, mti);
1624         if (rc < 0) {
1625                 CERROR("Can't get index (%d)\n", rc);
1626                 RETURN(rc);
1627         }
1628         /* COMPAT_146 */
1629         if (mti->mti_flags & LDD_F_UPGRADE14) {
1630                 if (rc == EALREADY) {
1631                         LCONSOLE_INFO("Found index %d for %s 1.4 log, "
1632                                       "upgrading\n", mti->mti_stripe_index, 
1633                                       mti->mti_svname);
1634                 } else {
1635                         LCONSOLE_ERROR("Failed to find %s in the old client "
1636                                        "log. Apparently it is not part of this "
1637                                        "filesystem, or the old log is wrong.\n"
1638                                        "Use 'writeconf' on the MDT to force log"
1639                                        " regeneration.\n", mti->mti_svname);
1640                         /* Not in client log?  Upgrade anyhow...*/
1641                         /* Argument against upgrading: reformat MDT,
1642                            upgrade OST, then OST will start but will be SKIPped
1643                            in client logs.  Maybe error now is better. */
1644                         /* RETURN(-EINVAL); */
1645                 }
1646                 /* end COMPAT_146 */
1647         } else {
1648                 if (rc == EALREADY) {
1649                         /* This might be a params update, or a 
1650                            local writeconf. (For "full" writeconf, the client
1651                            log won't have an entry for this target, so we 
1652                            won't get here.) */
1653                         LCONSOLE_WARN("Found index %d for %s, updating log\n", 
1654                                       mti->mti_stripe_index, mti->mti_svname);
1655                         /* We would like to mark old log sections as invalid 
1656                            and add new log sections in the client and mdt logs.
1657                            But if we add new sections, then live clients will
1658                            get repeat setup instructions for already running
1659                            osc's. So don't update the client/mdt logs. */
1660                         mti->mti_flags &= ~LDD_F_UPDATE;
1661                 }
1662         }
1663
1664         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb); 
1665         if (rc) {
1666                 CERROR("Can't get db for %s\n", mti->mti_fsname);
1667                 RETURN(rc);
1668         }
1669
1670         down(&fsdb->fsdb_sem);
1671
1672         if (mti->mti_flags & 
1673             (LDD_F_VIRGIN | LDD_F_UPGRADE14 | LDD_F_WRITECONF)) {
1674                 /* Generate a log from scratch */
1675                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
1676                         rc = mgs_write_log_mdt(obd, fsdb, mti);
1677                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1678                         rc = mgs_write_log_ost(obd, fsdb, mti);
1679                 } else {
1680                         CERROR("Unknown target type %#x, can't create log for "
1681                                "%s\n", mti->mti_flags, mti->mti_svname);
1682                 }
1683                 if (rc) {
1684                         CERROR("Can't write logs for %s (%d)\n",
1685                                mti->mti_svname, rc);
1686                         GOTO(out_up, rc);
1687                 }
1688         } else {
1689                 /* Just update the params from tunefs in mgs_write_log_params */
1690                 CDEBUG(D_MGS, "Update params for %s\n", mti->mti_svname);
1691                 mti->mti_flags |= LDD_F_PARAM_FNID;
1692         }
1693         
1694         rc = mgs_write_log_params(obd, fsdb, mti);
1695
1696 out_up:
1697         up(&fsdb->fsdb_sem);
1698         RETURN(rc);
1699 }
1700
1701 /* COMPAT_146 */
1702 /* upgrade pre-mountconf logs to mountconf at first connect */ 
1703 int mgs_upgrade_sv_14(struct obd_device *obd, struct mgs_target_info *mti)
1704 {
1705         struct fs_db *fsdb;
1706         int rc = 0;
1707         ENTRY;
1708
1709         /* Create ost log normally, as servers register.  Servers 
1710            register with their old uuids (from last_rcvd), so old
1711            (MDT and client) logs should work.
1712          - new MDT won't know about old OSTs, only the ones that have 
1713            registered, so we need the old MDT log to get the LOV right 
1714            in order for old clients to work. 
1715          - Old clients connect to the MDT, not the MGS, for their logs, and 
1716            will therefore receive the old client log from the MDT /LOGS dir. 
1717          - Old clients can continue to use and connect to old or new OSTs
1718          - New clients will contact the MGS for their log 
1719         */
1720
1721         LCONSOLE_INFO("upgrading server %s from pre-1.6\n", mti->mti_svname); 
1722         server_mti_print("upgrade", mti);
1723         
1724         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb);
1725         if (rc) 
1726                 RETURN(rc);
1727
1728         if (fsdb->fsdb_flags & FSDB_LOG_EMPTY) {
1729                 LCONSOLE_ERROR("The old client log %s-client is missing.  Was "
1730                                "tunefs.lustre successful?\n",
1731                                mti->mti_fsname);
1732                 RETURN(-ENOENT);
1733         }
1734
1735         if (fsdb->fsdb_gen == 0) {
1736                 /* There were no markers in the client log, meaning we have 
1737                    not updated the logs for this fs */
1738                 CDEBUG(D_MGS, "found old, unupdated client log\n");
1739         }
1740
1741         if ((mti->mti_flags & LDD_F_SV_TYPE_MDT) && 
1742             mgs_log_is_empty(obd, mti->mti_svname)) {
1743                 LCONSOLE_ERROR("The old MDT log %s is missing.  Was "
1744                                "tunefs.lustre successful?\n",
1745                                mti->mti_svname);
1746                 RETURN(-ENOENT);
1747         }
1748
1749         rc = mgs_write_log_target(obd, mti);
1750         RETURN(rc);
1751 }
1752 /* end COMPAT_146 */
1753
1754 int mgs_erase_log(struct obd_device *obd, char *name)
1755 {
1756         struct lvfs_run_ctxt saved;
1757         struct llog_handle *llh;
1758         int rc = 0;
1759
1760         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
1761         rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
1762                          &llh, NULL, name);
1763         if (rc == 0) {
1764                 llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
1765                 rc = llog_destroy(llh);
1766                 llog_free_handle(llh);
1767         }
1768         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
1769
1770         if (rc)
1771                 CERROR("failed to clear log %s: %d\n", name, rc);
1772
1773         return(rc);
1774 }
1775
1776 /* erase all logs for the given fs */
1777 int mgs_erase_logs(struct obd_device *obd, char *fsname)
1778 {
1779         struct mgs_obd *mgs = &obd->u.mgs;
1780         static struct fs_db *fsdb;
1781         struct list_head dentry_list;
1782         struct l_linux_dirent *dirent, *n;
1783         int rc, len = strlen(fsname);
1784         ENTRY;
1785         
1786         /* Find all the logs in the CONFIGS directory */
1787         rc = class_dentry_readdir(obd, mgs->mgs_configs_dir,
1788                                   mgs->mgs_vfsmnt, &dentry_list);
1789         if (rc) {
1790                 CERROR("Can't read %s dir\n", MOUNT_CONFIGS_DIR);
1791                 RETURN(rc);
1792         }
1793                                                                                 
1794         down(&mgs->mgs_sem);
1795         
1796         /* Delete the fs db */
1797         fsdb = mgs_find_fsdb(obd, fsname);
1798         if (fsdb) 
1799                 mgs_free_fsdb(obd, fsdb);
1800
1801         list_for_each_entry_safe(dirent, n, &dentry_list, lld_list) {
1802                 list_del(&dirent->lld_list);
1803                 if (strncmp(fsname, dirent->lld_name, len) == 0) {
1804                         CDEBUG(D_MGS, "Removing log %s\n", dirent->lld_name);
1805                         mgs_erase_log(obd, dirent->lld_name);
1806                 }
1807                 OBD_FREE(dirent, sizeof(*dirent));
1808         }
1809         
1810         up(&mgs->mgs_sem);
1811
1812         RETURN(rc);
1813 }
1814
1815 /* from llog_swab */
1816 static void print_lustre_cfg(struct lustre_cfg *lcfg)
1817 {
1818         int i;
1819         ENTRY;
1820
1821         CDEBUG(D_MGS, "lustre_cfg: %p\n", lcfg);
1822         CDEBUG(D_MGS, "\tlcfg->lcfg_version: %#x\n", lcfg->lcfg_version);
1823
1824         CDEBUG(D_MGS, "\tlcfg->lcfg_command: %#x\n", lcfg->lcfg_command);
1825         CDEBUG(D_MGS, "\tlcfg->lcfg_num: %#x\n", lcfg->lcfg_num);
1826         CDEBUG(D_MGS, "\tlcfg->lcfg_flags: %#x\n", lcfg->lcfg_flags);
1827         CDEBUG(D_MGS, "\tlcfg->lcfg_nid: %s\n", libcfs_nid2str(lcfg->lcfg_nid));
1828
1829         CDEBUG(D_MGS, "\tlcfg->lcfg_bufcount: %d\n", lcfg->lcfg_bufcount);
1830         if (lcfg->lcfg_bufcount < LUSTRE_CFG_MAX_BUFCOUNT)
1831                 for (i = 0; i < lcfg->lcfg_bufcount; i++) {
1832                         CDEBUG(D_MGS, "\tlcfg->lcfg_buflens[%d]: %d %s\n",
1833                                i, lcfg->lcfg_buflens[i], 
1834                                lustre_cfg_string(lcfg, i));
1835                 }
1836         EXIT;
1837 }
1838
1839 /* Set a permanent (config log) param for a target or fs */
1840 int mgs_setparam(struct obd_device *obd, struct lustre_cfg *lcfg, char *fsname)
1841 {
1842         struct fs_db *fsdb;
1843         struct mgs_target_info *mti;
1844         char *devname, *param;
1845         char *ptr, *tmp;
1846         int rc = 0;
1847         ENTRY;
1848
1849         print_lustre_cfg(lcfg);
1850         
1851         /* lustre, lustre-mdtlov, lustre-client, lustre-MDT0000 */
1852         devname = lustre_cfg_string(lcfg, 0);
1853         param = lustre_cfg_string(lcfg, 1);
1854         if (!devname) {
1855                 /* Assume device name embedded in param:
1856                    lustre-OST0000.osc.max_dirty_mb=32 */
1857                 ptr = strchr(param, '.');
1858                 if (ptr) {
1859                         devname = param;
1860                         *ptr = 0;
1861                         param = ptr + 1;
1862                 }
1863         }
1864         if (!devname) {
1865                 LCONSOLE_ERROR("No target specified: %s\n", param);
1866                 RETURN(-ENOSYS);
1867         }
1868
1869         /* Extract fsname */
1870         ptr = strchr(devname, '-');
1871         memset(fsname, 0, MTI_NAME_MAXLEN);
1872         if (!ptr) {
1873                 /* assume devname is the fsname */
1874                 strncpy(fsname, devname, MTI_NAME_MAXLEN);
1875         } else {  
1876                 strncpy(fsname, devname, ptr - devname);
1877         }
1878         fsname[MTI_NAME_MAXLEN] = 0;
1879         CDEBUG(D_MGS, "setparam on fs %s device %s\n", fsname, devname);
1880
1881         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb); 
1882         if (rc) 
1883                 RETURN(rc);
1884         if (fsdb->fsdb_flags & FSDB_LOG_EMPTY) {
1885                 CERROR("No filesystem targets for %s\n", fsname);
1886                 RETURN(-EINVAL);
1887         }
1888
1889         /* Create a fake mti to hold everything */
1890         OBD_ALLOC_PTR(mti);
1891         if (!mti) 
1892                 GOTO(out, rc = -ENOMEM);
1893         strncpy(mti->mti_fsname, fsname, MTI_NAME_MAXLEN);
1894         strncpy(mti->mti_svname, devname, MTI_NAME_MAXLEN);
1895         strncpy(mti->mti_params, param, sizeof(mti->mti_params));
1896         rc = server_name2index(mti->mti_svname, &mti->mti_stripe_index, &tmp);
1897         if (rc < 0) 
1898                 /* Not a valid server; may be only fsname */
1899                 rc = 0;
1900         else
1901                 /* Strip -osc or -mdc suffix from svname */
1902                 if (server_make_name(rc, mti->mti_stripe_index, mti->mti_fsname, 
1903                                      mti->mti_svname)) 
1904                         GOTO(out, rc = -EINVAL);
1905
1906         mti->mti_flags = rc | LDD_F_PARAM_FNID;
1907
1908         down(&fsdb->fsdb_sem);
1909         rc = mgs_write_log_params(obd, fsdb, mti); 
1910         up(&fsdb->fsdb_sem);
1911
1912 out:
1913         OBD_FREE_PTR(mti);
1914         RETURN(rc);
1915 }
1916
1917
1918 #if 0
1919 /******************** unused *********************/
1920 static int mgs_backup_llog(struct obd_device *obd, char* fsname)
1921 {
1922         struct file *filp, *bak_filp;
1923         struct lvfs_run_ctxt saved;
1924         char *logname, *buf;
1925         loff_t soff = 0 , doff = 0;
1926         int count = 4096, len;
1927         int rc = 0;
1928
1929         OBD_ALLOC(logname, PATH_MAX);
1930         if (logname == NULL)
1931                 return -ENOMEM;
1932
1933         OBD_ALLOC(buf, count);
1934         if (!buf)
1935                 GOTO(out , rc = -ENOMEM);
1936
1937         len = snprintf(logname, PATH_MAX, "%s/%s.bak",
1938                        MOUNT_CONFIGS_DIR, fsname);
1939
1940         if (len >= PATH_MAX - 1) {
1941                 GOTO(out, -ENAMETOOLONG);
1942         } 
1943
1944         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
1945                 
1946         bak_filp = l_filp_open(logname, O_RDWR|O_CREAT|O_TRUNC, 0660);
1947         if (IS_ERR(bak_filp)) {
1948                 rc = PTR_ERR(bak_filp);
1949                 CERROR("backup logfile open %s: %d\n", logname, rc);
1950                 GOTO(pop, rc);
1951         }
1952         sprintf(logname, "%s/%s", MOUNT_CONFIGS_DIR, fsname);
1953         filp = l_filp_open(logname, O_RDONLY, 0);
1954         if (IS_ERR(filp)) {
1955                 rc = PTR_ERR(filp);
1956                 CERROR("logfile open %s: %d\n", logname, rc);
1957                 GOTO(close1f, rc);
1958         }
1959
1960         while ((rc = lustre_fread(filp, buf, count, &soff)) > 0) {
1961                 rc = lustre_fwrite(bak_filp, buf, count, &doff);
1962                 break;
1963         }
1964
1965         filp_close(filp, 0);
1966 close1f:
1967         filp_close(bak_filp, 0);
1968 pop:
1969         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
1970 out:
1971         if (buf)
1972                 OBD_FREE(buf, count);
1973         OBD_FREE(logname, PATH_MAX);
1974         return rc;
1975 }
1976
1977
1978
1979 #endif