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