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