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