Whamcloud - gitweb
LU-350 fix bug in mgs to allow starting OST before MDT
[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 (c) 2007, 2010, Oracle and/or its affiliates. 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
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 <lustre_sec.h>
66 #include "mgs_internal.h"
67
68 /********************** Class functions ********************/
69
70 /* Caller must list_del and OBD_FREE each dentry from the list */
71 int class_dentry_readdir(struct obd_device *obd, struct dentry *dir,
72                                 struct vfsmount *inmnt,
73                                 cfs_list_t *dentry_list){
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 = ll_dentry_open(dentry, mnt, O_RDONLY, current_cred());
93         if (IS_ERR(file))
94                 /* dentry_open_it() drops the dentry, mnt refs */
95                 GOTO(out_pop, rc = PTR_ERR(file));
96
97         CFS_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 struct mgs_fsdb_handler_data
127 {
128         struct fs_db   *fsdb;
129         __u32           ver;
130 };
131
132 /* from the (client) config log, figure out:
133         1. which ost's/mdt's are configured (by index)
134         2. what the last config step is
135         3. COMPAT_146 lov name
136         4. COMPAT_146 mdt lov name
137         5. COMPAT_146 mdc name
138         6. COMPAT_18 osc name
139 */
140 /* It might be better to have a separate db file, instead of parsing the info
141    out of the client log.  This is slow and potentially error-prone. */
142 static int mgs_fsdb_handler(struct llog_handle *llh, struct llog_rec_hdr *rec,
143                             void *data)
144 {
145         struct mgs_fsdb_handler_data *d = (struct mgs_fsdb_handler_data *) data;
146         struct fs_db *fsdb = d->fsdb;
147         int cfg_len = rec->lrh_len;
148         char *cfg_buf = (char*) (rec + 1);
149         struct lustre_cfg *lcfg;
150         __u32 index;
151         int rc = 0;
152         ENTRY;
153
154         if (rec->lrh_type != OBD_CFG_REC) {
155                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
156                 RETURN(-EINVAL);
157         }
158
159         rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
160         if (rc) {
161                 CERROR("Insane cfg\n");
162                 RETURN(rc);
163         }
164
165         lcfg = (struct lustre_cfg *)cfg_buf;
166
167         CDEBUG(D_INFO, "cmd %x %s %s\n", lcfg->lcfg_command,
168                lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
169
170         /* Figure out ost indicies */
171         /* lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1 */
172         if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD ||
173             lcfg->lcfg_command == LCFG_LOV_DEL_OBD) {
174                 index = simple_strtoul(lustre_cfg_string(lcfg, 2),
175                                        NULL, 10);
176                 CDEBUG(D_MGS, "OST index for %s is %u (%s)\n",
177                        lustre_cfg_string(lcfg, 1), index,
178                        lustre_cfg_string(lcfg, 2));
179                 cfs_set_bit(index, fsdb->fsdb_ost_index_map);
180         }
181
182         /* Figure out mdt indicies */
183         /* attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f */
184         if ((lcfg->lcfg_command == LCFG_ATTACH) &&
185             (strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_MDC_NAME) == 0)) {
186                 rc = server_name2index(lustre_cfg_string(lcfg, 0),
187                                        &index, NULL);
188                 if (rc != LDD_F_SV_TYPE_MDT) {
189                         CWARN("Unparsable MDC name %s, assuming index 0\n",
190                               lustre_cfg_string(lcfg, 0));
191                         index = 0;
192                 }
193                 rc = 0;
194                 CDEBUG(D_MGS, "MDT index is %u\n", index);
195                 cfs_set_bit(index, fsdb->fsdb_mdt_index_map);
196                 fsdb->fsdb_mdt_count ++;
197         }
198
199         /* COMPAT_146 */
200         /* figure out the old LOV name. fsdb_gen = 0 means old log */
201         /* #01 L attach 0:lov_mdsA 1:lov 2:cdbe9_lov_mdsA_dc8cf7f3bb */
202         if ((fsdb->fsdb_gen == 0) && (lcfg->lcfg_command == LCFG_ATTACH) &&
203             (strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_LOV_NAME) == 0)) {
204                 cfs_set_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags);
205                 name_destroy(&fsdb->fsdb_clilov);
206                 rc = name_create(&fsdb->fsdb_clilov,
207                                  lustre_cfg_string(lcfg, 0), "");
208                 if (rc)
209                         RETURN(rc);
210                 CDEBUG(D_MGS, "client lov name is %s\n", fsdb->fsdb_clilov);
211         }
212
213         /* figure out the old MDT lov name from the MDT uuid */
214         if ((fsdb->fsdb_gen == 0) && (lcfg->lcfg_command == LCFG_SETUP) &&
215             (strncmp(lustre_cfg_string(lcfg, 0), "MDC_", 4) == 0)) {
216                 char *ptr;
217                 cfs_set_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags);
218                 ptr = strstr(lustre_cfg_string(lcfg, 1), "_UUID");
219                 if (!ptr) {
220                         CERROR("Can't parse MDT uuid %s\n",
221                                lustre_cfg_string(lcfg, 1));
222                         RETURN(-EINVAL);
223                 }
224                 *ptr = '\0';
225                 name_destroy(&fsdb->fsdb_mdtlov);
226                 rc = name_create(&fsdb->fsdb_mdtlov,
227                                  "lov_", lustre_cfg_string(lcfg, 1));
228                 if (rc)
229                         RETURN(rc);
230                 name_destroy(&fsdb->fsdb_mdc);
231                 rc = name_create(&fsdb->fsdb_mdc,
232                                  lustre_cfg_string(lcfg, 0), "");
233                 if (rc)
234                         RETURN(rc);
235                 CDEBUG(D_MGS, "MDT lov name is %s\n", fsdb->fsdb_mdtlov);
236         }
237         /* end COMPAT_146 */
238
239         /*
240          * compat to 1.8, check osc name used by MDT0 to OSTs, bz18548.
241          */
242         if (!cfs_test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags) &&
243             lcfg->lcfg_command == LCFG_ATTACH &&
244             strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_OSC_NAME) == 0) {
245                 if (OBD_OCD_VERSION_MAJOR(d->ver) == 1 &&
246                     OBD_OCD_VERSION_MINOR(d->ver) <= 8) {
247                         CWARN("MDT using 1.8 OSC name scheme\n");
248                         cfs_set_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags);
249                 }
250         }
251
252         if (lcfg->lcfg_command == LCFG_MARKER) {
253                 struct cfg_marker *marker;
254                 marker = lustre_cfg_buf(lcfg, 1);
255
256                 d->ver = marker->cm_vers;
257
258                 /* Keep track of the latest marker step */
259                 fsdb->fsdb_gen = max(fsdb->fsdb_gen, marker->cm_step);
260         }
261
262         RETURN(rc);
263 }
264
265 /* fsdb->fsdb_sem is already held  in mgs_find_or_make_fsdb*/
266 static int mgs_get_fsdb_from_llog(struct obd_device *obd, struct fs_db *fsdb)
267 {
268         char *logname;
269         struct llog_handle *loghandle;
270         struct lvfs_run_ctxt saved;
271         struct llog_ctxt *ctxt;
272         struct mgs_fsdb_handler_data d = { fsdb, 0 };
273         int rc, rc2;
274         ENTRY;
275
276         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
277         LASSERT(ctxt != NULL);
278         name_create(&logname, fsdb->fsdb_name, "-client");
279         cfs_down(&fsdb->fsdb_sem);
280         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
281         rc = llog_create(ctxt, &loghandle, NULL, logname);
282         if (rc)
283                 GOTO(out_pop, rc);
284
285         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
286         if (rc)
287                 GOTO(out_close, rc);
288
289         if (llog_get_size(loghandle) <= 1)
290                 cfs_set_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags);
291
292         rc = llog_process(loghandle, mgs_fsdb_handler, (void *) &d, NULL);
293         CDEBUG(D_INFO, "get_db = %d\n", rc);
294 out_close:
295         rc2 = llog_close(loghandle);
296         if (!rc)
297                 rc = rc2;
298 out_pop:
299         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
300         cfs_up(&fsdb->fsdb_sem);
301         name_destroy(&logname);
302         llog_ctxt_put(ctxt);
303
304         RETURN(rc);
305 }
306
307 static void mgs_free_fsdb_srpc(struct fs_db *fsdb)
308 {
309         struct mgs_tgt_srpc_conf *tgtconf;
310
311         /* free target-specific rules */
312         while (fsdb->fsdb_srpc_tgt) {
313                 tgtconf = fsdb->fsdb_srpc_tgt;
314                 fsdb->fsdb_srpc_tgt = tgtconf->mtsc_next;
315
316                 LASSERT(tgtconf->mtsc_tgt);
317
318                 sptlrpc_rule_set_free(&tgtconf->mtsc_rset);
319                 OBD_FREE(tgtconf->mtsc_tgt, strlen(tgtconf->mtsc_tgt) + 1);
320                 OBD_FREE_PTR(tgtconf);
321         }
322
323         /* free general rules */
324         sptlrpc_rule_set_free(&fsdb->fsdb_srpc_gen);
325 }
326
327 static struct fs_db *mgs_find_fsdb(struct obd_device *obd, char *fsname)
328 {
329         struct mgs_obd *mgs = &obd->u.mgs;
330         struct fs_db *fsdb;
331         cfs_list_t *tmp;
332
333         cfs_list_for_each(tmp, &mgs->mgs_fs_db_list) {
334                 fsdb = cfs_list_entry(tmp, struct fs_db, fsdb_list);
335                 if (strcmp(fsdb->fsdb_name, fsname) == 0)
336                         return fsdb;
337         }
338         return NULL;
339 }
340
341 /* caller must hold the mgs->mgs_fs_db_lock */
342 static struct fs_db *mgs_new_fsdb(struct obd_device *obd, char *fsname)
343 {
344         struct mgs_obd *mgs = &obd->u.mgs;
345         struct fs_db *fsdb;
346         int rc;
347         ENTRY;
348
349         if (strlen(fsname) >= sizeof(fsdb->fsdb_name)) {
350                 CERROR("fsname %s is too long\n", fsname);
351                 RETURN(NULL);
352         }
353
354         OBD_ALLOC_PTR(fsdb);
355         if (!fsdb)
356                 RETURN(NULL);
357
358         strcpy(fsdb->fsdb_name, fsname);
359         cfs_sema_init(&fsdb->fsdb_sem, 1);
360         cfs_set_bit(FSDB_UDESC, &fsdb->fsdb_flags);
361
362         if (strcmp(fsname, MGSSELF_NAME) == 0) {
363                 cfs_set_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags);
364         } else {
365                 OBD_ALLOC(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
366                 OBD_ALLOC(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
367                 if (!fsdb->fsdb_ost_index_map || !fsdb->fsdb_mdt_index_map) {
368                         CERROR("No memory for index maps\n");
369                         GOTO(err, 0);
370                 }
371
372                 rc = name_create(&fsdb->fsdb_mdtlov, fsname, "-mdtlov");
373                 if (rc)
374                         GOTO(err, rc);
375                 rc = name_create(&fsdb->fsdb_mdtlmv, fsname, "-mdtlmv");
376                 if (rc)
377                         GOTO(err, rc);
378                 rc = name_create(&fsdb->fsdb_clilov, fsname, "-clilov");
379                 if (rc)
380                         GOTO(err, rc);
381                 rc = name_create(&fsdb->fsdb_clilmv, fsname, "-clilmv");
382                 if (rc)
383                         GOTO(err, rc);
384
385                 lproc_mgs_add_live(obd, fsdb);
386         }
387
388         cfs_list_add(&fsdb->fsdb_list, &mgs->mgs_fs_db_list);
389
390         RETURN(fsdb);
391 err:
392         if (fsdb->fsdb_ost_index_map)
393                 OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
394         if (fsdb->fsdb_mdt_index_map)
395                 OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
396         name_destroy(&fsdb->fsdb_clilov);
397         name_destroy(&fsdb->fsdb_clilmv);
398         name_destroy(&fsdb->fsdb_mdtlov);
399         name_destroy(&fsdb->fsdb_mdtlmv);
400         OBD_FREE_PTR(fsdb);
401         RETURN(NULL);
402 }
403
404 static void mgs_free_fsdb(struct obd_device *obd, struct fs_db *fsdb)
405 {
406         /* wait for anyone with the sem */
407         cfs_down(&fsdb->fsdb_sem);
408         lproc_mgs_del_live(obd, fsdb);
409         cfs_list_del(&fsdb->fsdb_list);
410         if (fsdb->fsdb_ost_index_map)
411                 OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
412         if (fsdb->fsdb_mdt_index_map)
413                 OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
414         name_destroy(&fsdb->fsdb_clilov);
415         name_destroy(&fsdb->fsdb_clilmv);
416         name_destroy(&fsdb->fsdb_mdtlov);
417         name_destroy(&fsdb->fsdb_mdtlmv);
418         name_destroy(&fsdb->fsdb_mdc);
419         mgs_free_fsdb_srpc(fsdb);
420         OBD_FREE_PTR(fsdb);
421 }
422
423 int mgs_init_fsdb_list(struct obd_device *obd)
424 {
425         struct mgs_obd *mgs = &obd->u.mgs;
426         CFS_INIT_LIST_HEAD(&mgs->mgs_fs_db_list);
427         return 0;
428 }
429
430 int mgs_cleanup_fsdb_list(struct obd_device *obd)
431 {
432         struct mgs_obd *mgs = &obd->u.mgs;
433         struct fs_db *fsdb;
434         cfs_list_t *tmp, *tmp2;
435         cfs_down(&mgs->mgs_sem);
436         cfs_list_for_each_safe(tmp, tmp2, &mgs->mgs_fs_db_list) {
437                 fsdb = cfs_list_entry(tmp, struct fs_db, fsdb_list);
438                 mgs_free_fsdb(obd, fsdb);
439         }
440         cfs_up(&mgs->mgs_sem);
441         return 0;
442 }
443
444 int mgs_find_or_make_fsdb(struct obd_device *obd, char *name,
445                           struct fs_db **dbh)
446 {
447         struct mgs_obd *mgs = &obd->u.mgs;
448         struct fs_db *fsdb;
449         int rc = 0;
450
451         cfs_down(&mgs->mgs_sem);
452         fsdb = mgs_find_fsdb(obd, name);
453         if (fsdb) {
454                 cfs_up(&mgs->mgs_sem);
455                 *dbh = fsdb;
456                 return 0;
457         }
458
459         CDEBUG(D_MGS, "Creating new db\n");
460         fsdb = mgs_new_fsdb(obd, name);
461         cfs_up(&mgs->mgs_sem);
462         if (!fsdb)
463                 return -ENOMEM;
464
465         if (!cfs_test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
466                 /* populate the db from the client llog */
467                 rc = mgs_get_fsdb_from_llog(obd, fsdb);
468                 if (rc) {
469                         CERROR("Can't get db from client log %d\n", rc);
470                         mgs_free_fsdb(obd, fsdb);
471                         return rc;
472                 }
473         }
474
475         /* populate srpc rules from params llog */
476         rc = mgs_get_fsdb_srpc_from_llog(obd, fsdb);
477         if (rc) {
478                 CERROR("Can't get db from params log %d\n", rc);
479                 mgs_free_fsdb(obd, fsdb);
480                 return rc;
481         }
482
483         *dbh = fsdb;
484
485         return 0;
486 }
487
488 /* 1 = index in use
489    0 = index unused
490    -1= empty client log */
491 int mgs_check_index(struct obd_device *obd, struct mgs_target_info *mti)
492 {
493         struct fs_db *fsdb;
494         void *imap;
495         int rc = 0;
496         ENTRY;
497
498         LASSERT(!(mti->mti_flags & LDD_F_NEED_INDEX));
499
500         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb);
501         if (rc) {
502                 CERROR("Can't get db for %s\n", mti->mti_fsname);
503                 RETURN(rc);
504         }
505
506         if (cfs_test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags))
507                 RETURN(-1);
508
509         if (mti->mti_flags & LDD_F_SV_TYPE_OST)
510                 imap = fsdb->fsdb_ost_index_map;
511         else if (mti->mti_flags & LDD_F_SV_TYPE_MDT)
512                 imap = fsdb->fsdb_mdt_index_map;
513         else
514                 RETURN(-EINVAL);
515
516         if (cfs_test_bit(mti->mti_stripe_index, imap))
517                 RETURN(1);
518         RETURN(0);
519 }
520
521 static __inline__ int next_index(void *index_map, int map_len)
522 {
523         int i;
524         for (i = 0; i < map_len * 8; i++)
525                  if (!cfs_test_bit(i, index_map)) {
526                          return i;
527                  }
528         CERROR("max index %d exceeded.\n", i);
529         return -1;
530 }
531
532 /* Return codes:
533         0  newly marked as in use
534         <0 err
535         +EALREADY for update of an old index */
536 static int mgs_set_index(struct obd_device *obd, struct mgs_target_info *mti)
537 {
538         struct fs_db *fsdb;
539         void *imap;
540         int rc = 0;
541         ENTRY;
542
543         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb);
544         if (rc) {
545                 CERROR("Can't get db for %s\n", mti->mti_fsname);
546                 RETURN(rc);
547         }
548
549         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
550                 imap = fsdb->fsdb_ost_index_map;
551         } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
552                 imap = fsdb->fsdb_mdt_index_map;
553                 if (fsdb->fsdb_mdt_count >= MAX_MDT_COUNT) {
554                         LCONSOLE_ERROR_MSG(0x13f, "The max mdt count"
555                                            "is %d\n", (int)MAX_MDT_COUNT);
556                         RETURN(-ERANGE);
557                 }
558         } else {
559                 RETURN(-EINVAL);
560         }
561
562         if (mti->mti_flags & LDD_F_NEED_INDEX) {
563                 rc = next_index(imap, INDEX_MAP_SIZE);
564                 if (rc == -1)
565                         RETURN(-ERANGE);
566                 mti->mti_stripe_index = rc;
567                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT)
568                         fsdb->fsdb_mdt_count ++;
569         }
570
571         if (mti->mti_stripe_index >= INDEX_MAP_SIZE * 8) {
572                 LCONSOLE_ERROR_MSG(0x13f, "Server %s requested index %d, "
573                                    "but the max index is %d.\n",
574                                    mti->mti_svname, mti->mti_stripe_index,
575                                    INDEX_MAP_SIZE * 8);
576                 RETURN(-ERANGE);
577         }
578
579         if (cfs_test_bit(mti->mti_stripe_index, imap)) {
580                 if ((mti->mti_flags & LDD_F_VIRGIN) &&
581                     !(mti->mti_flags & LDD_F_WRITECONF)) {
582                         LCONSOLE_ERROR_MSG(0x140, "Server %s requested index "
583                                            "%d, but that index is already in "
584                                            "use. Use --writeconf to force\n",
585                                            mti->mti_svname,
586                                            mti->mti_stripe_index);
587                         RETURN(-EADDRINUSE);
588                 } else {
589                         CDEBUG(D_MGS, "Server %s updating index %d\n",
590                                mti->mti_svname, mti->mti_stripe_index);
591                         RETURN(EALREADY);
592                 }
593         }
594
595         cfs_set_bit(mti->mti_stripe_index, imap);
596         cfs_clear_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags);
597         server_make_name(mti->mti_flags, mti->mti_stripe_index,
598                          mti->mti_fsname, mti->mti_svname);
599
600         CDEBUG(D_MGS, "Set index for %s to %d\n", mti->mti_svname,
601                mti->mti_stripe_index);
602
603         RETURN(0);
604 }
605
606 struct mgs_modify_lookup {
607         struct cfg_marker mml_marker;
608         int               mml_modified;
609 };
610
611 static int mgs_modify_handler(struct llog_handle *llh, struct llog_rec_hdr *rec,
612                               void *data)
613 {
614         struct mgs_modify_lookup *mml = (struct mgs_modify_lookup *)data;
615         struct cfg_marker *marker;
616         struct lustre_cfg *lcfg = (struct lustre_cfg *)(rec + 1);
617         int cfg_len = rec->lrh_len - sizeof(struct llog_rec_hdr) -
618                 sizeof(struct llog_rec_tail);
619         int rc;
620         ENTRY;
621
622         if (rec->lrh_type != OBD_CFG_REC) {
623                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
624                 RETURN(-EINVAL);
625         }
626
627         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
628         if (rc) {
629                 CERROR("Insane cfg\n");
630                 RETURN(rc);
631         }
632
633         /* We only care about markers */
634         if (lcfg->lcfg_command != LCFG_MARKER)
635                 RETURN(0);
636
637         marker = lustre_cfg_buf(lcfg, 1);
638         if ((strcmp(mml->mml_marker.cm_comment, marker->cm_comment) == 0) &&
639             (strcmp(mml->mml_marker.cm_tgtname, marker->cm_tgtname) == 0) &&
640             !(marker->cm_flags & CM_SKIP)) {
641                 /* Found a non-skipped marker match */
642                 CDEBUG(D_MGS, "Changing rec %u marker %d %x->%x: %s %s\n",
643                        rec->lrh_index, marker->cm_step,
644                        marker->cm_flags, mml->mml_marker.cm_flags,
645                        marker->cm_tgtname, marker->cm_comment);
646                 /* Overwrite the old marker llog entry */
647                 marker->cm_flags &= ~CM_EXCLUDE; /* in case we're unexcluding */
648                 marker->cm_flags |= mml->mml_marker.cm_flags;
649                 marker->cm_canceltime = mml->mml_marker.cm_canceltime;
650                 /* Header and tail are added back to lrh_len in
651                    llog_lvfs_write_rec */
652                 rec->lrh_len = cfg_len;
653                 rc = llog_write_rec(llh, rec, NULL, 0, (void *)lcfg,
654                                     rec->lrh_index);
655                 if (!rc)
656                          mml->mml_modified++;
657         }
658
659         RETURN(rc);
660 }
661
662 /* Modify an existing config log record (for CM_SKIP or CM_EXCLUDE) */
663 static int mgs_modify(struct obd_device *obd, struct fs_db *fsdb,
664                       struct mgs_target_info *mti, char *logname,
665                       char *devname, char *comment, int flags)
666 {
667         struct llog_handle *loghandle;
668         struct lvfs_run_ctxt saved;
669         struct llog_ctxt *ctxt;
670         struct mgs_modify_lookup *mml;
671         int rc, rc2;
672         ENTRY;
673
674         CDEBUG(D_MGS, "modify %s/%s/%s fl=%x\n", logname, devname, comment,
675                flags);
676
677         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
678
679         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
680         LASSERT(ctxt != NULL);
681         rc = llog_create(ctxt, &loghandle, NULL, logname);
682         if (rc)
683                 GOTO(out_pop, rc);
684
685         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
686         if (rc)
687                 GOTO(out_close, rc);
688
689         if (llog_get_size(loghandle) <= 1)
690                 GOTO(out_close, rc = 0);
691
692         OBD_ALLOC_PTR(mml);
693         if (!mml)
694                 GOTO(out_close, rc = -ENOMEM);
695         strcpy(mml->mml_marker.cm_comment, comment);
696         strcpy(mml->mml_marker.cm_tgtname, devname);
697         /* Modify mostly means cancel */
698         mml->mml_marker.cm_flags = flags;
699         mml->mml_marker.cm_canceltime = flags ? cfs_time_current_sec() : 0;
700         mml->mml_modified = 0;
701         rc = llog_process(loghandle, mgs_modify_handler, (void *)mml, NULL);
702         if (!rc && !mml->mml_modified)
703                 rc = -ENODEV;
704         OBD_FREE_PTR(mml);
705
706 out_close:
707         rc2 = llog_close(loghandle);
708         if (!rc)
709                 rc = rc2;
710 out_pop:
711         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
712         if (rc && rc != -ENODEV)
713                 CERROR("modify %s/%s failed %d\n",
714                        mti->mti_svname, comment, rc);
715         llog_ctxt_put(ctxt);
716         RETURN(rc);
717 }
718
719 /******************** config log recording functions *********************/
720
721 static int record_lcfg(struct obd_device *obd, struct llog_handle *llh,
722                          struct lustre_cfg *lcfg)
723 {
724         struct lvfs_run_ctxt   saved;
725         struct llog_rec_hdr    rec;
726         int buflen, rc;
727
728         if (!lcfg || !llh)
729                 return -ENOMEM;
730
731         LASSERT(llh->lgh_ctxt);
732
733         buflen = lustre_cfg_len(lcfg->lcfg_bufcount,
734                                 lcfg->lcfg_buflens);
735         rec.lrh_len = llog_data_len(buflen);
736         rec.lrh_type = OBD_CFG_REC;
737
738         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
739         /* idx = -1 means append */
740         rc = llog_write_rec(llh, &rec, NULL, 0, (void *)lcfg, -1);
741         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
742         if (rc)
743                 CERROR("failed %d\n", rc);
744         return rc;
745 }
746
747 static int record_base(struct obd_device *obd, struct llog_handle *llh,
748                      char *cfgname, lnet_nid_t nid, int cmd,
749                      char *s1, char *s2, char *s3, char *s4)
750 {
751         struct lustre_cfg_bufs bufs;
752         struct lustre_cfg     *lcfg;
753         int rc;
754
755         CDEBUG(D_MGS, "lcfg %s %#x %s %s %s %s\n", cfgname,
756                cmd, s1, s2, s3, s4);
757
758         lustre_cfg_bufs_reset(&bufs, cfgname);
759         if (s1)
760                 lustre_cfg_bufs_set_string(&bufs, 1, s1);
761         if (s2)
762                 lustre_cfg_bufs_set_string(&bufs, 2, s2);
763         if (s3)
764                 lustre_cfg_bufs_set_string(&bufs, 3, s3);
765         if (s4)
766                 lustre_cfg_bufs_set_string(&bufs, 4, s4);
767
768         lcfg = lustre_cfg_new(cmd, &bufs);
769         if (!lcfg)
770                 return -ENOMEM;
771         lcfg->lcfg_nid = nid;
772
773         rc = record_lcfg(obd, llh, lcfg);
774
775         lustre_cfg_free(lcfg);
776
777         if (rc) {
778                 CERROR("error %d: lcfg %s %#x %s %s %s %s\n", rc, cfgname,
779                        cmd, s1, s2, s3, s4);
780         }
781         return(rc);
782 }
783
784
785 static inline int record_add_uuid(struct obd_device *obd,
786                                   struct llog_handle *llh,
787                                   uint64_t nid, char *uuid)
788 {
789         return record_base(obd,llh,NULL,nid,LCFG_ADD_UUID,uuid,0,0,0);
790
791 }
792
793 static inline int record_add_conn(struct obd_device *obd,
794                                   struct llog_handle *llh,
795                                   char *devname,
796                                   char *uuid)
797 {
798         return record_base(obd,llh,devname,0,LCFG_ADD_CONN,uuid,0,0,0);
799 }
800
801 static inline int record_attach(struct obd_device *obd, struct llog_handle *llh,
802                                 char *devname, char *type, char *uuid)
803 {
804         return record_base(obd,llh,devname,0,LCFG_ATTACH,type,uuid,0,0);
805 }
806
807 static inline int record_setup(struct obd_device *obd, struct llog_handle *llh,
808                                char *devname,
809                                char *s1, char *s2, char *s3, char *s4)
810 {
811         return record_base(obd,llh,devname,0,LCFG_SETUP,s1,s2,s3,s4);
812 }
813
814 static int record_lov_setup(struct obd_device *obd, struct llog_handle *llh,
815                             char *devname, struct lov_desc *desc)
816 {
817         struct lustre_cfg_bufs bufs;
818         struct lustre_cfg *lcfg;
819         int rc;
820
821         lustre_cfg_bufs_reset(&bufs, devname);
822         lustre_cfg_bufs_set(&bufs, 1, desc, sizeof(*desc));
823         lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
824         if (!lcfg)
825                 return -ENOMEM;
826         rc = record_lcfg(obd, llh, lcfg);
827
828         lustre_cfg_free(lcfg);
829         return rc;
830 }
831
832 static int record_lmv_setup(struct obd_device *obd, struct llog_handle *llh,
833                             char *devname, struct lmv_desc *desc)
834 {
835         struct lustre_cfg_bufs bufs;
836         struct lustre_cfg *lcfg;
837         int rc;
838
839         lustre_cfg_bufs_reset(&bufs, devname);
840         lustre_cfg_bufs_set(&bufs, 1, desc, sizeof(*desc));
841         lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
842
843         rc = record_lcfg(obd, llh, lcfg);
844
845         lustre_cfg_free(lcfg);
846         return rc;
847 }
848
849 static inline int record_mdc_add(struct obd_device *obd,
850                                  struct llog_handle *llh,
851                                  char *logname, char *mdcuuid,
852                                  char *mdtuuid, char *index,
853                                  char *gen)
854 {
855         return record_base(obd,llh,logname,0,LCFG_ADD_MDC,
856                            mdtuuid,index,gen,mdcuuid);
857 }
858
859 static inline int record_lov_add(struct obd_device *obd,
860                                  struct llog_handle *llh,
861                                  char *lov_name, char *ost_uuid,
862                                  char *index, char *gen)
863 {
864         return record_base(obd,llh,lov_name,0,LCFG_LOV_ADD_OBD,
865                            ost_uuid,index,gen,0);
866 }
867
868 static inline int record_mount_opt(struct obd_device *obd,
869                                    struct llog_handle *llh,
870                                    char *profile, char *lov_name,
871                                    char *mdc_name)
872 {
873         return record_base(obd,llh,NULL,0,LCFG_MOUNTOPT,
874                            profile,lov_name,mdc_name,0);
875 }
876
877 static int record_marker(struct obd_device *obd, struct llog_handle *llh,
878                          struct fs_db *fsdb, __u32 flags,
879                          char *tgtname, char *comment)
880 {
881         struct cfg_marker marker;
882         struct lustre_cfg_bufs bufs;
883         struct lustre_cfg *lcfg;
884         int rc;
885
886         if (flags & CM_START)
887                 fsdb->fsdb_gen++;
888         marker.cm_step = fsdb->fsdb_gen;
889         marker.cm_flags = flags;
890         marker.cm_vers = LUSTRE_VERSION_CODE;
891         strncpy(marker.cm_tgtname, tgtname, sizeof(marker.cm_tgtname));
892         strncpy(marker.cm_comment, comment, sizeof(marker.cm_comment));
893         marker.cm_createtime = cfs_time_current_sec();
894         marker.cm_canceltime = 0;
895         lustre_cfg_bufs_reset(&bufs, NULL);
896         lustre_cfg_bufs_set(&bufs, 1, &marker, sizeof(marker));
897         lcfg = lustre_cfg_new(LCFG_MARKER, &bufs);
898         if (!lcfg)
899                 return -ENOMEM;
900         rc = record_lcfg(obd, llh, lcfg);
901
902         lustre_cfg_free(lcfg);
903         return rc;
904 }
905
906 static int record_start_log(struct obd_device *obd,
907                             struct llog_handle **llh, char *name)
908 {
909         static struct obd_uuid cfg_uuid = { .uuid = "config_uuid" };
910         struct lvfs_run_ctxt saved;
911         struct llog_ctxt *ctxt;
912         int rc = 0;
913
914         if (*llh)
915                 GOTO(out, rc = -EBUSY);
916
917         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
918         if (!ctxt)
919                 GOTO(out, rc = -ENODEV);
920
921         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
922         rc = llog_create(ctxt, llh, NULL, name);
923         if (rc == 0)
924                 llog_init_handle(*llh, LLOG_F_IS_PLAIN, &cfg_uuid);
925         else
926                 *llh = NULL;
927
928         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
929         llog_ctxt_put(ctxt);
930
931 out:
932         if (rc) {
933                 CERROR("Can't start log %s: %d\n", name, rc);
934         }
935         RETURN(rc);
936 }
937
938 static int record_end_log(struct obd_device *obd, struct llog_handle **llh)
939 {
940         struct lvfs_run_ctxt saved;
941         int rc = 0;
942
943         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
944
945         rc = llog_close(*llh);
946         *llh = NULL;
947
948         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
949         RETURN(rc);
950 }
951
952 static int mgs_log_is_empty(struct obd_device *obd, char *name)
953 {
954         struct lvfs_run_ctxt saved;
955         struct llog_handle *llh;
956         struct llog_ctxt *ctxt;
957         int rc = 0;
958
959         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
960         LASSERT(ctxt != NULL);
961         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
962         rc = llog_create(ctxt, &llh, NULL, name);
963         if (rc == 0) {
964                 llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
965                 rc = llog_get_size(llh);
966                 llog_close(llh);
967         }
968         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
969         llog_ctxt_put(ctxt);
970         /* header is record 1 */
971         return(rc <= 1);
972 }
973
974 /******************** config "macros" *********************/
975
976 /* write an lcfg directly into a log (with markers) */
977 static int mgs_write_log_direct(struct obd_device *obd, struct fs_db *fsdb,
978                                 char *logname, struct lustre_cfg *lcfg,
979                                 char *devname, char *comment)
980 {
981         struct llog_handle *llh = NULL;
982         int rc;
983         ENTRY;
984
985         if (!lcfg)
986                 RETURN(-ENOMEM);
987
988         rc = record_start_log(obd, &llh, logname);
989         if (rc)
990                 RETURN(rc);
991
992         /* FIXME These should be a single journal transaction */
993         rc = record_marker(obd, llh, fsdb, CM_START, devname, comment);
994
995         rc = record_lcfg(obd, llh, lcfg);
996
997         rc = record_marker(obd, llh, fsdb, CM_END, devname, comment);
998         rc = record_end_log(obd, &llh);
999
1000         RETURN(rc);
1001 }
1002
1003 /* write the lcfg in all logs for the given fs */
1004 int mgs_write_log_direct_all(struct obd_device *obd, struct fs_db *fsdb,
1005                              struct mgs_target_info *mti,
1006                              struct lustre_cfg *lcfg,
1007                              char *devname, char *comment)
1008 {
1009         struct mgs_obd *mgs = &obd->u.mgs;
1010         cfs_list_t dentry_list;
1011         struct l_linux_dirent *dirent, *n;
1012         char *fsname = mti->mti_fsname;
1013         char *logname;
1014         int rc = 0, len = strlen(fsname);
1015         ENTRY;
1016
1017         /* We need to set params for any future logs
1018            as well. FIXME Append this file to every new log.
1019            Actually, we should store as params (text), not llogs.  Or
1020            in a database. */
1021         name_create(&logname, fsname, "-params");
1022         if (mgs_log_is_empty(obd, logname)) {
1023                 struct llog_handle *llh = NULL;
1024                 rc = record_start_log(obd, &llh, logname);
1025                 record_end_log(obd, &llh);
1026         }
1027         name_destroy(&logname);
1028         if (rc)
1029                 RETURN(rc);
1030
1031         /* Find all the logs in the CONFIGS directory */
1032         rc = class_dentry_readdir(obd, mgs->mgs_configs_dir,
1033                                   mgs->mgs_vfsmnt, &dentry_list);
1034         if (rc) {
1035                 CERROR("Can't read %s dir\n", MOUNT_CONFIGS_DIR);
1036                 RETURN(rc);
1037         }
1038
1039         /* Could use fsdb index maps instead of directory listing */
1040         cfs_list_for_each_entry_safe(dirent, n, &dentry_list, lld_list) {
1041                 cfs_list_del(&dirent->lld_list);
1042                 /* don't write to sptlrpc rule log */
1043                 if (strncmp(fsname, dirent->lld_name, len) == 0 &&
1044                     strstr(dirent->lld_name, "-sptlrpc") == NULL) {
1045                         CDEBUG(D_MGS, "Changing log %s\n", dirent->lld_name);
1046                         /* Erase any old settings of this same parameter */
1047                         mgs_modify(obd, fsdb, mti, dirent->lld_name, devname,
1048                                    comment, CM_SKIP);
1049                         /* Write the new one */
1050                         if (lcfg) {
1051                                 rc = mgs_write_log_direct(obd, fsdb,
1052                                                           dirent->lld_name,
1053                                                           lcfg, devname,
1054                                                           comment);
1055                                 if (rc)
1056                                         CERROR("err %d writing log %s\n", rc,
1057                                                dirent->lld_name);
1058                         }
1059                 }
1060                 OBD_FREE(dirent, sizeof(*dirent));
1061         }
1062
1063         RETURN(rc);
1064 }
1065
1066 struct temp_comp
1067 {
1068         struct mgs_target_info   *comp_tmti;
1069         struct mgs_target_info   *comp_mti;
1070         struct fs_db             *comp_fsdb;
1071         struct obd_device        *comp_obd;
1072 };
1073
1074 static int mgs_write_log_mdc_to_mdt(struct obd_device *, struct fs_db *,
1075                                     struct mgs_target_info *, char *);
1076 static int mgs_write_log_osc_to_lov(struct obd_device *obd, struct fs_db *fsdb,
1077                                     struct mgs_target_info *mti,
1078                                     char *logname, char *suffix, char *lovname,
1079                                     enum lustre_sec_part sec_part, int flags);
1080 static void name_create_mdt_and_lov(char **logname, char **lovname,
1081                                     struct fs_db *fsdb, int i);
1082
1083 static int mgs_steal_llog_handler(struct llog_handle *llh,
1084                                   struct llog_rec_hdr *rec,
1085                                   void *data)
1086 {
1087         struct obd_device * obd;
1088         struct mgs_target_info *mti, *tmti;
1089         struct fs_db *fsdb;
1090         int cfg_len = rec->lrh_len;
1091         char *cfg_buf = (char*) (rec + 1);
1092         struct lustre_cfg *lcfg;
1093         int rc = 0;
1094         struct llog_handle *mdt_llh = NULL;
1095         static int got_an_osc_or_mdc = 0;
1096         /* 0: not found any osc/mdc;
1097            1: found osc;
1098            2: found mdc;
1099         */
1100         static int last_step = -1;
1101
1102         ENTRY;
1103
1104         mti = ((struct temp_comp*)data)->comp_mti;
1105         tmti = ((struct temp_comp*)data)->comp_tmti;
1106         fsdb = ((struct temp_comp*)data)->comp_fsdb;
1107         obd = ((struct temp_comp*)data)->comp_obd;
1108
1109         if (rec->lrh_type != OBD_CFG_REC) {
1110                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
1111                 RETURN(-EINVAL);
1112         }
1113
1114         rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
1115         if (rc) {
1116                 CERROR("Insane cfg\n");
1117                 RETURN(rc);
1118         }
1119
1120         lcfg = (struct lustre_cfg *)cfg_buf;
1121
1122         if (lcfg->lcfg_command == LCFG_MARKER) {
1123                 struct cfg_marker *marker;
1124                 marker = lustre_cfg_buf(lcfg, 1);
1125                 if (!strncmp(marker->cm_comment,"add osc",7) &&
1126                     (marker->cm_flags & CM_START)){
1127                         got_an_osc_or_mdc = 1;
1128                         strncpy(tmti->mti_svname, marker->cm_tgtname,
1129                                 sizeof(tmti->mti_svname));
1130                         rc = record_start_log(obd, &mdt_llh, mti->mti_svname);
1131                         rc = record_marker(obd, mdt_llh, fsdb, CM_START,
1132                                            mti->mti_svname,"add osc(copied)");
1133                         rc = record_end_log(obd, &mdt_llh);
1134                         last_step = marker->cm_step;
1135                         RETURN(rc);
1136                 }
1137                 if (!strncmp(marker->cm_comment,"add osc",7) &&
1138                     (marker->cm_flags & CM_END)){
1139                         LASSERT(last_step == marker->cm_step);
1140                         last_step = -1;
1141                         got_an_osc_or_mdc = 0;
1142                         rc = record_start_log(obd, &mdt_llh, mti->mti_svname);
1143                         rc = record_marker(obd, mdt_llh, fsdb, CM_END,
1144                                            mti->mti_svname,"add osc(copied)");
1145                         rc = record_end_log(obd, &mdt_llh);
1146                         RETURN(rc);
1147                 }
1148                 if (!strncmp(marker->cm_comment,"add mdc",7) &&
1149                     (marker->cm_flags & CM_START)){
1150                         got_an_osc_or_mdc = 2;
1151                         last_step = marker->cm_step;
1152                         memcpy(tmti->mti_svname, marker->cm_tgtname,
1153                                strlen(marker->cm_tgtname));
1154
1155                         RETURN(rc);
1156                 }
1157                 if (!strncmp(marker->cm_comment,"add mdc",7) &&
1158                     (marker->cm_flags & CM_END)){
1159                         LASSERT(last_step == marker->cm_step);
1160                         last_step = -1;
1161                         got_an_osc_or_mdc = 0;
1162                         RETURN(rc);
1163                 }
1164         }
1165
1166         if (got_an_osc_or_mdc == 0 || last_step < 0)
1167                 RETURN(rc);
1168
1169         if (lcfg->lcfg_command == LCFG_ADD_UUID) {
1170                 uint64_t nodenid;
1171                 nodenid = lcfg->lcfg_nid;
1172
1173                 tmti->mti_nids[tmti->mti_nid_count] = nodenid;
1174                 tmti->mti_nid_count++;
1175
1176                 RETURN(rc);
1177         }
1178
1179         if (lcfg->lcfg_command == LCFG_SETUP) {
1180                 char *target;
1181
1182                 target = lustre_cfg_string(lcfg, 1);
1183                 memcpy(tmti->mti_uuid, target, strlen(target));
1184                 RETURN(rc);
1185         }
1186
1187         /* ignore client side sptlrpc_conf_log */
1188         if (lcfg->lcfg_command == LCFG_SPTLRPC_CONF)
1189                 RETURN(rc);
1190
1191         if (lcfg->lcfg_command == LCFG_ADD_MDC) {
1192                 int index;
1193
1194                 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1)
1195                         RETURN (-EINVAL);
1196
1197                 memcpy(tmti->mti_fsname, mti->mti_fsname,
1198                        strlen(mti->mti_fsname));
1199                 tmti->mti_stripe_index = index;
1200
1201                 mgs_write_log_mdc_to_mdt(obd, fsdb, tmti, mti->mti_svname);
1202                 memset(tmti, 0, sizeof(*tmti));
1203                 RETURN(rc);
1204         }
1205
1206         if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD) {
1207                 int index;
1208                 char mdt_index[9];
1209                 char *logname, *lovname;
1210
1211                 name_create_mdt_and_lov(&logname, &lovname, fsdb,
1212                                         mti->mti_stripe_index);
1213                 sprintf(mdt_index, "-MDT%04x", mti->mti_stripe_index);
1214
1215                 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1) {
1216                         name_destroy(&logname);
1217                         name_destroy(&lovname);
1218                         RETURN(-EINVAL);
1219                 }
1220
1221                 tmti->mti_stripe_index = index;
1222                 mgs_write_log_osc_to_lov(obd, fsdb, tmti, logname,
1223                                          mdt_index, lovname,
1224                                          LUSTRE_SP_MDT, 0);
1225                 name_destroy(&logname);
1226                 name_destroy(&lovname);
1227                 RETURN(rc);
1228         }
1229         RETURN(rc);
1230 }
1231
1232 /* fsdb->fsdb_sem is already held  in mgs_write_log_target*/
1233 /* stealed from mgs_get_fsdb_from_llog*/
1234 static int mgs_steal_llog_for_mdt_from_client(struct obd_device *obd,
1235                                               char *client_name,
1236                                               struct temp_comp* comp)
1237 {
1238         struct llog_handle *loghandle;
1239         struct lvfs_run_ctxt saved;
1240         struct mgs_target_info *tmti;
1241         struct llog_ctxt *ctxt;
1242         int rc, rc2;
1243         ENTRY;
1244
1245         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
1246         LASSERT(ctxt != NULL);
1247
1248         OBD_ALLOC_PTR(tmti);
1249         if (tmti == NULL)
1250                 RETURN(-ENOMEM);
1251
1252         comp->comp_tmti = tmti;
1253         comp->comp_obd = obd;
1254
1255         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
1256
1257         rc = llog_create(ctxt, &loghandle, NULL, client_name);
1258         if (rc)
1259                 GOTO(out_pop, rc);
1260
1261         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
1262         if (rc)
1263                 GOTO(out_close, rc);
1264
1265         rc = llog_process(loghandle, mgs_steal_llog_handler, (void *)comp, NULL);
1266         CDEBUG(D_MGS, "steal llog re = %d\n", rc);
1267 out_close:
1268         rc2 = llog_close(loghandle);
1269         if (!rc)
1270                 rc = rc2;
1271 out_pop:
1272         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
1273         OBD_FREE_PTR(tmti);
1274         llog_ctxt_put(ctxt);
1275         RETURN(rc);
1276 }
1277
1278 /* lmv is the second thing for client logs */
1279 /* copied from mgs_write_log_lov. Please refer to that.  */
1280 static int mgs_write_log_lmv(struct obd_device *obd, struct fs_db *fsdb,
1281                              struct mgs_target_info *mti,
1282                              char *logname, char *lmvname)
1283 {
1284         struct llog_handle *llh = NULL;
1285         struct lmv_desc *lmvdesc;
1286         char *uuid;
1287         int rc = 0;
1288         ENTRY;
1289
1290         CDEBUG(D_MGS, "Writing lmv(%s) log for %s\n", lmvname,logname);
1291
1292         OBD_ALLOC_PTR(lmvdesc);
1293         if (lmvdesc == NULL)
1294                 RETURN(-ENOMEM);
1295         lmvdesc->ld_active_tgt_count = 0;
1296         lmvdesc->ld_tgt_count = 0;
1297         sprintf((char*)lmvdesc->ld_uuid.uuid, "%s_UUID", lmvname);
1298         uuid = (char *)lmvdesc->ld_uuid.uuid;
1299
1300         rc = record_start_log(obd, &llh, logname);
1301         rc = record_marker(obd, llh, fsdb, CM_START, lmvname, "lmv setup");
1302         rc = record_attach(obd, llh, lmvname, "lmv", uuid);
1303         rc = record_lmv_setup(obd, llh, lmvname, lmvdesc);
1304         rc = record_marker(obd, llh, fsdb, CM_END, lmvname, "lmv setup");
1305         rc = record_end_log(obd, &llh);
1306
1307         OBD_FREE_PTR(lmvdesc);
1308         RETURN(rc);
1309 }
1310
1311 /* lov is the first thing in the mdt and client logs */
1312 static int mgs_write_log_lov(struct obd_device *obd, struct fs_db *fsdb,
1313                              struct mgs_target_info *mti,
1314                              char *logname, char *lovname)
1315 {
1316         struct llog_handle *llh = NULL;
1317         struct lov_desc *lovdesc;
1318         char *uuid;
1319         int rc = 0;
1320         ENTRY;
1321
1322         CDEBUG(D_MGS, "Writing lov(%s) log for %s\n", lovname, logname);
1323
1324         /*
1325         #01 L attach   0:lov_mdsA  1:lov  2:71ccb_lov_mdsA_19f961a9e1
1326         #02 L lov_setup 0:lov_mdsA 1:(struct lov_desc)
1327               uuid=lov1_UUID, stripe count=1, size=1048576, offset=0, pattern=0
1328         */
1329
1330         /* FIXME just make lov_setup accept empty desc (put uuid in buf 2) */
1331         OBD_ALLOC_PTR(lovdesc);
1332         if (lovdesc == NULL)
1333                 RETURN(-ENOMEM);
1334         lovdesc->ld_magic = LOV_DESC_MAGIC;
1335         lovdesc->ld_tgt_count = 0;
1336         /* Defaults.  Can be changed later by lcfg config_param */
1337         lovdesc->ld_default_stripe_count = 1;
1338         lovdesc->ld_pattern = LOV_PATTERN_RAID0;
1339         lovdesc->ld_default_stripe_size = 1024 * 1024;
1340         lovdesc->ld_default_stripe_offset = -1;
1341         lovdesc->ld_qos_maxage = QOS_DEFAULT_MAXAGE;
1342         sprintf((char*)lovdesc->ld_uuid.uuid, "%s_UUID", lovname);
1343         /* can these be the same? */
1344         uuid = (char *)lovdesc->ld_uuid.uuid;
1345
1346         /* This should always be the first entry in a log.
1347         rc = mgs_clear_log(obd, logname); */
1348         rc = record_start_log(obd, &llh, logname);
1349         if (rc)
1350                 GOTO(out, rc);
1351         /* FIXME these should be a single journal transaction */
1352         rc = record_marker(obd, llh, fsdb, CM_START, lovname, "lov setup");
1353         rc = record_attach(obd, llh, lovname, "lov", uuid);
1354         rc = record_lov_setup(obd, llh, lovname, lovdesc);
1355         rc = record_marker(obd, llh, fsdb, CM_END, lovname, "lov setup");
1356         rc = record_end_log(obd, &llh);
1357
1358         EXIT;
1359 out:
1360         OBD_FREE_PTR(lovdesc);
1361         return rc;
1362 }
1363
1364 /* add failnids to open log */
1365 static int mgs_write_log_failnids(struct obd_device *obd,
1366                                   struct mgs_target_info *mti,
1367                                   struct llog_handle *llh,
1368                                   char *cliname)
1369 {
1370         char *failnodeuuid = NULL;
1371         char *ptr = mti->mti_params;
1372         lnet_nid_t nid;
1373         int rc = 0;
1374
1375         /*
1376         #03 L add_uuid  nid=uml1@tcp(0x20000c0a80201) nal=90 0:  1:uml1_UUID
1377         #04 L add_uuid  nid=1@elan(0x1000000000001)   nal=90 0:  1:uml1_UUID
1378         #05 L setup    0:OSC_uml1_ost1_mdsA  1:ost1_UUID  2:uml1_UUID
1379         #06 L add_uuid  nid=uml2@tcp(0x20000c0a80202) nal=90 0:  1:uml2_UUID
1380         #0x L add_uuid  nid=2@elan(0x1000000000002)   nal=90 0:  1:uml2_UUID
1381         #07 L add_conn 0:OSC_uml1_ost1_mdsA  1:uml2_UUID
1382         */
1383
1384         /* Pull failnid info out of params string */
1385         while (class_find_param(ptr, PARAM_FAILNODE, &ptr) == 0) {
1386                 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
1387                         if (failnodeuuid == NULL) {
1388                                 /* We don't know the failover node name,
1389                                    so just use the first nid as the uuid */
1390                                 rc = name_create(&failnodeuuid,
1391                                                  libcfs_nid2str(nid), "");
1392                                 if (rc)
1393                                         return rc;
1394                         }
1395                         CDEBUG(D_MGS, "add nid %s for failover uuid %s, "
1396                                "client %s\n", libcfs_nid2str(nid),
1397                                failnodeuuid, cliname);
1398                         rc = record_add_uuid(obd, llh, nid, failnodeuuid);
1399                 }
1400                 if (failnodeuuid) {
1401                         rc = record_add_conn(obd, llh, cliname, failnodeuuid);
1402                         name_destroy(&failnodeuuid);
1403                         failnodeuuid = NULL;
1404                 }
1405         }
1406
1407         return rc;
1408 }
1409
1410 static int mgs_write_log_mdc_to_lmv(struct obd_device *obd, struct fs_db *fsdb,
1411                                     struct mgs_target_info *mti,
1412                                     char *logname, char *lmvname)
1413 {
1414         struct llog_handle *llh = NULL;
1415         char *mdcname, *nodeuuid, *mdcuuid, *lmvuuid;
1416         char index[6];
1417         int i, rc;
1418         ENTRY;
1419
1420         if (mgs_log_is_empty(obd, logname)) {
1421                 CERROR("log is empty! Logical error\n");
1422                 RETURN(-EINVAL);
1423         }
1424
1425         CDEBUG(D_MGS, "adding mdc for %s to log %s:lmv(%s)\n",
1426                mti->mti_svname, logname, lmvname);
1427
1428         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
1429         name_create(&mdcname, mti->mti_svname, "-mdc");
1430         name_create(&mdcuuid, mdcname, "_UUID");
1431         name_create(&lmvuuid, lmvname, "_UUID");
1432
1433         rc = record_start_log(obd, &llh, logname);
1434         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,
1435                            "add mdc");
1436
1437         for (i = 0; i < mti->mti_nid_count; i++) {
1438                 CDEBUG(D_MGS, "add nid %s for mdt\n",
1439                        libcfs_nid2str(mti->mti_nids[i]));
1440
1441                 rc = record_add_uuid(obd, llh, mti->mti_nids[i], nodeuuid);
1442         }
1443
1444         rc = record_attach(obd, llh, mdcname, LUSTRE_MDC_NAME, lmvuuid);
1445         rc = record_setup(obd, llh, mdcname, mti->mti_uuid, nodeuuid, 0, 0);
1446         rc = mgs_write_log_failnids(obd, mti, llh, mdcname);
1447         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
1448         rc = record_mdc_add(obd, llh, lmvname, mdcuuid, mti->mti_uuid,
1449                             index, "1");
1450         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname,
1451                            "add mdc");
1452         rc = record_end_log(obd, &llh);
1453
1454         name_destroy(&lmvuuid);
1455         name_destroy(&mdcuuid);
1456         name_destroy(&mdcname);
1457         name_destroy(&nodeuuid);
1458         RETURN(rc);
1459 }
1460
1461 /* add new mdc to already existent MDS */
1462 static int mgs_write_log_mdc_to_mdt(struct obd_device *obd, struct fs_db *fsdb,
1463                                     struct mgs_target_info *mti, char *logname)
1464 {
1465         struct llog_handle *llh = NULL;
1466         char *nodeuuid, *mdcname, *mdcuuid, *mdtuuid;
1467         int idx = mti->mti_stripe_index;
1468         char index[9];
1469         int i, rc;
1470
1471         ENTRY;
1472         if (mgs_log_is_empty(obd, logname)) {
1473                 CERROR("log is empty! Logical error\n");
1474                 RETURN (-EINVAL);
1475         }
1476
1477         CDEBUG(D_MGS, "adding mdc index %d to %s\n", idx, logname);
1478
1479         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
1480         snprintf(index, sizeof(index), "-mdc%04x", idx);
1481         name_create(&mdcname, logname, index);
1482         name_create(&mdcuuid, mdcname, "_UUID");
1483         name_create(&mdtuuid, logname, "_UUID");
1484
1485         rc = record_start_log(obd, &llh, logname);
1486         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname, "add mdc");
1487         for (i = 0; i < mti->mti_nid_count; i++) {
1488                 CDEBUG(D_MGS, "add nid %s for mdt\n",
1489                        libcfs_nid2str(mti->mti_nids[i]));
1490                 rc = record_add_uuid(obd, llh, mti->mti_nids[i], nodeuuid);
1491         }
1492         rc = record_attach(obd, llh, mdcname, LUSTRE_MDC_NAME, mdcuuid);
1493         rc = record_setup(obd, llh, mdcname, mti->mti_uuid, nodeuuid, 0, 0);
1494         rc = mgs_write_log_failnids(obd, mti, llh, mdcname);
1495         snprintf(index, sizeof(index), "%d", idx);
1496
1497         rc = record_mdc_add(obd, llh, logname, mdcuuid, mti->mti_uuid,
1498                             index, "1");
1499         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname, "add mdc");
1500         rc = record_end_log(obd, &llh);
1501
1502         name_destroy(&mdcuuid);
1503         name_destroy(&mdcname);
1504         name_destroy(&nodeuuid);
1505         name_destroy(&mdtuuid);
1506         RETURN(rc);
1507 }
1508
1509 static int mgs_write_log_mdt0(struct obd_device *obd, struct fs_db *fsdb,
1510                               struct mgs_target_info *mti)
1511 {
1512         char *log = mti->mti_svname;
1513         struct llog_handle *llh = NULL;
1514         char *uuid, *lovname;
1515         char mdt_index[6];
1516         char *ptr = mti->mti_params;
1517         int rc = 0, failout = 0;
1518         ENTRY;
1519
1520         OBD_ALLOC(uuid, sizeof(struct obd_uuid));
1521         if (uuid == NULL)
1522                 RETURN(-ENOMEM);
1523
1524         if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
1525                 failout = (strncmp(ptr, "failout", 7) == 0);
1526
1527         name_create(&lovname, log, "-mdtlov");
1528         if (mgs_log_is_empty(obd, log))
1529                 rc = mgs_write_log_lov(obd, fsdb, mti, log, lovname);
1530
1531         sprintf(uuid, "%s_UUID", log);
1532         sprintf(mdt_index, "%d", mti->mti_stripe_index);
1533
1534         /* add MDT itself */
1535         rc = record_start_log(obd, &llh, log);
1536         if (rc)
1537                 GOTO(out, rc);
1538
1539         /* FIXME this whole fn should be a single journal transaction */
1540         rc = record_marker(obd, llh, fsdb, CM_START, log, "add mdt");
1541         rc = record_attach(obd, llh, log, LUSTRE_MDT_NAME, uuid);
1542         rc = record_mount_opt(obd, llh, log, lovname, NULL);
1543         rc = record_setup(obd, llh, log, uuid, mdt_index, lovname,
1544                         failout ? "n" : "f");
1545         rc = record_marker(obd, llh, fsdb, CM_END, log, "add mdt");
1546         rc = record_end_log(obd, &llh);
1547 out:
1548         name_destroy(&lovname);
1549         OBD_FREE(uuid, sizeof(struct obd_uuid));
1550         RETURN(rc);
1551 }
1552
1553 static inline void name_create_mdt(char **logname, char *fsname, int i)
1554 {
1555         char mdt_index[9];
1556
1557         sprintf(mdt_index, "-MDT%04x", i);
1558         name_create(logname, fsname, mdt_index);
1559 }
1560
1561 static void name_create_mdt_and_lov(char **logname, char **lovname,
1562                                     struct fs_db *fsdb, int i)
1563 {
1564         name_create_mdt(logname, fsdb->fsdb_name, i);
1565         /* COMPAT_180 */
1566         if (i == 0 && cfs_test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
1567                 name_create(lovname, fsdb->fsdb_name, "-mdtlov");
1568         else
1569                 name_create(lovname, *logname, "-mdtlov");
1570 }
1571
1572 static inline void name_create_mdt_osc(char **oscname, char *ostname,
1573                                        struct fs_db *fsdb, int i)
1574 {
1575         char suffix[16];
1576
1577         if (i == 0 && cfs_test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
1578                 sprintf(suffix, "-osc");
1579         else
1580                 sprintf(suffix, "-osc-MDT%04x", i);
1581         name_create(oscname, ostname, suffix);
1582 }
1583
1584 /* envelope method for all layers log */
1585 static int mgs_write_log_mdt(struct obd_device *obd, struct fs_db *fsdb,
1586                               struct mgs_target_info *mti)
1587 {
1588         struct llog_handle *llh = NULL;
1589         char *cliname;
1590         struct temp_comp comp = { 0 };
1591         int rc, i = 0;
1592         ENTRY;
1593
1594         CDEBUG(D_MGS, "writing new mdt %s\n", mti->mti_svname);
1595
1596 #if 0
1597         /* COMPAT_146 */
1598         if (mti->mti_flags & LDD_F_UPGRADE14) {
1599                 /* We're starting with an old uuid.  Assume old name for lov
1600                    as well since the lov entry already exists in the log. */
1601                 CDEBUG(D_MGS, "old mds uuid %s\n", mti->mti_uuid);
1602                 if (strncmp(mti->mti_uuid, fsdb->fsdb_mdtlov + 4,
1603                             strlen(fsdb->fsdb_mdtlov) - 4) != 0) {
1604                         CERROR("old mds uuid %s doesn't match log %s (%s)\n",
1605                                mti->mti_uuid, fsdb->fsdb_mdtlov,
1606                                fsdb->fsdb_mdtlov + 4);
1607                         RETURN(-EINVAL);
1608                 }
1609         }
1610         /* end COMPAT_146 */
1611 #endif
1612         if (mti->mti_uuid[0] == '\0') {
1613                 /* Make up our own uuid */
1614                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
1615                          "%s_UUID", mti->mti_svname);
1616         }
1617
1618         /* add mdt */
1619         rc = mgs_write_log_mdt0(obd, fsdb, mti);
1620
1621         /* Append the mdt info to the client log */
1622         name_create(&cliname, mti->mti_fsname, "-client");
1623
1624         if (mgs_log_is_empty(obd, cliname)) {
1625                 /* Start client log */
1626                 rc = mgs_write_log_lov(obd, fsdb, mti, cliname,
1627                                        fsdb->fsdb_clilov);
1628                 rc = mgs_write_log_lmv(obd, fsdb, mti, cliname,
1629                                        fsdb->fsdb_clilmv);
1630         }
1631
1632         /*
1633         #09 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
1634         #10 L attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f
1635         #11 L setup    0:MDC_uml1_mdsA_MNT_client  1:mdsA_UUID  2:uml1_UUID
1636         #12 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
1637         #13 L add_conn 0:MDC_uml1_mdsA_MNT_client  1:uml2_UUID
1638         #14 L mount_option 0:  1:client  2:lov1  3:MDC_uml1_mdsA_MNT_client
1639         */
1640
1641 #if 0
1642         /* COMPAT_146 */
1643         if (mti->mti_flags & LDD_F_UPGRADE14) {
1644                 rc = record_start_log(obd, &llh, cliname);
1645                 if (rc)
1646                         GOTO(out, rc);
1647
1648                 rc = record_marker(obd, llh, fsdb, CM_START,
1649                                    mti->mti_svname,"add mdc");
1650
1651                 /* Old client log already has MDC entry, but needs mount opt
1652                    for new client name (lustre-client) */
1653                 /* FIXME Old MDT log already has an old mount opt
1654                    which we should remove (currently handled by
1655                    class_del_profiles()) */
1656                 rc = record_mount_opt(obd, llh, cliname, fsdb->fsdb_clilov,
1657                                       fsdb->fsdb_mdc);
1658                 /* end COMPAT_146 */
1659
1660                 rc = record_marker(obd, llh, fsdb, CM_END,
1661                                    mti->mti_svname, "add mdc");
1662         } else
1663 #endif
1664         {
1665                 /* copy client info about lov/lmv */
1666                 comp.comp_mti = mti;
1667                 comp.comp_fsdb = fsdb;
1668
1669                 rc = mgs_steal_llog_for_mdt_from_client(obd, cliname,
1670                                                         &comp);
1671
1672                 rc = mgs_write_log_mdc_to_lmv(obd, fsdb, mti, cliname,
1673                                               fsdb->fsdb_clilmv);
1674                 /* add mountopts */
1675                 rc = record_start_log(obd, &llh, cliname);
1676                 if (rc)
1677                         GOTO(out, rc);
1678
1679                 rc = record_marker(obd, llh, fsdb, CM_START, cliname,
1680                                    "mount opts");
1681                 rc = record_mount_opt(obd, llh, cliname, fsdb->fsdb_clilov,
1682                                       fsdb->fsdb_clilmv);
1683                 rc = record_marker(obd, llh, fsdb, CM_END, cliname,
1684                                    "mount opts");
1685         }
1686
1687         rc = record_end_log(obd, &llh);
1688 out:
1689         name_destroy(&cliname);
1690
1691         // for_all_existing_mdt except current one
1692         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
1693                 char *mdtname;
1694                 if (i !=  mti->mti_stripe_index &&
1695                     cfs_test_bit(i,  fsdb->fsdb_mdt_index_map)) {
1696                         name_create_mdt(&mdtname, mti->mti_fsname, i);
1697                         rc = mgs_write_log_mdc_to_mdt(obd, fsdb, mti, mdtname);
1698                         name_destroy(&mdtname);
1699                 }
1700         }
1701
1702         RETURN(rc);
1703 }
1704
1705 /* Add the ost info to the client/mdt lov */
1706 static int mgs_write_log_osc_to_lov(struct obd_device *obd, struct fs_db *fsdb,
1707                                     struct mgs_target_info *mti,
1708                                     char *logname, char *suffix, char *lovname,
1709                                     enum lustre_sec_part sec_part, int flags)
1710 {
1711         struct llog_handle *llh = NULL;
1712         char *nodeuuid, *oscname, *oscuuid, *lovuuid, *svname;
1713         char index[6];
1714         int i, rc;
1715
1716         ENTRY;
1717         CDEBUG(D_INFO, "adding osc for %s to log %s\n",
1718                mti->mti_svname, logname);
1719
1720         if (mgs_log_is_empty(obd, logname)) {
1721                 CERROR("log is empty! Logical error\n");
1722                 RETURN (-EINVAL);
1723         }
1724
1725         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
1726         name_create(&svname, mti->mti_svname, "-osc");
1727         name_create(&oscname, svname, suffix);
1728         name_create(&oscuuid, oscname, "_UUID");
1729         name_create(&lovuuid, lovname, "_UUID");
1730
1731         /*
1732         #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
1733         multihomed (#4)
1734         #04 L add_uuid  nid=1@elan(0x1000000000001)  nal=90 0:  1:uml1_UUID
1735         #04 L attach   0:OSC_uml1_ost1_MNT_client  1:osc  2:89070_lov1_a41dff51a
1736         #05 L setup    0:OSC_uml1_ost1_MNT_client  1:ost1_UUID  2:uml1_UUID
1737         failover (#6,7)
1738         #06 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
1739         #07 L add_conn 0:OSC_uml1_ost1_MNT_client  1:uml2_UUID
1740         #08 L lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1
1741         */
1742
1743         rc = record_start_log(obd, &llh, logname);
1744         if (rc)
1745                 GOTO(out, rc);
1746         /* FIXME these should be a single journal transaction */
1747         rc = record_marker(obd, llh, fsdb, CM_START | flags, mti->mti_svname,
1748                            "add osc");
1749         for (i = 0; i < mti->mti_nid_count; i++) {
1750                 CDEBUG(D_MGS, "add nid %s\n", libcfs_nid2str(mti->mti_nids[i]));
1751                 rc = record_add_uuid(obd, llh, mti->mti_nids[i], nodeuuid);
1752         }
1753         rc = record_attach(obd, llh, oscname, LUSTRE_OSC_NAME, lovuuid);
1754         rc = record_setup(obd, llh, oscname, mti->mti_uuid, nodeuuid, 0, 0);
1755         rc = mgs_write_log_failnids(obd, mti, llh, oscname);
1756         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
1757         rc = record_lov_add(obd, llh, lovname, mti->mti_uuid, index, "1");
1758         rc = record_marker(obd, llh, fsdb, CM_END | flags, mti->mti_svname,
1759                            "add osc");
1760         rc = record_end_log(obd, &llh);
1761 out:
1762         name_destroy(&lovuuid);
1763         name_destroy(&oscuuid);
1764         name_destroy(&oscname);
1765         name_destroy(&svname);
1766         name_destroy(&nodeuuid);
1767         RETURN(rc);
1768 }
1769
1770 static int mgs_write_log_ost(struct obd_device *obd, struct fs_db *fsdb,
1771                              struct mgs_target_info *mti)
1772 {
1773         struct llog_handle *llh = NULL;
1774         char *logname, *lovname;
1775         char *ptr = mti->mti_params;
1776         int rc, flags = 0, failout = 0, i;
1777         ENTRY;
1778
1779         CDEBUG(D_MGS, "writing new ost %s\n", mti->mti_svname);
1780
1781         /* The ost startup log */
1782
1783         /* If the ost log already exists, that means that someone reformatted
1784            the ost and it called target_add again. */
1785         if (!mgs_log_is_empty(obd, mti->mti_svname)) {
1786                 LCONSOLE_ERROR_MSG(0x141, "The config log for %s already "
1787                                    "exists, yet the server claims it never "
1788                                    "registered. It may have been reformatted, "
1789                                    "or the index changed. writeconf the MDT to "
1790                                    "regenerate all logs.\n", mti->mti_svname);
1791                 RETURN(-EALREADY);
1792         }
1793
1794         /*
1795         attach obdfilter ost1 ost1_UUID
1796         setup /dev/loop2 ldiskfs f|n errors=remount-ro,user_xattr
1797         */
1798         if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
1799                 failout = (strncmp(ptr, "failout", 7) == 0);
1800         rc = record_start_log(obd, &llh, mti->mti_svname);
1801         if (rc)
1802                 RETURN(rc);
1803         /* FIXME these should be a single journal transaction */
1804         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,"add ost");
1805         if (*mti->mti_uuid == '\0')
1806                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
1807                          "%s_UUID", mti->mti_svname);
1808         rc = record_attach(obd, llh, mti->mti_svname,
1809                            "obdfilter"/*LUSTRE_OST_NAME*/, mti->mti_uuid);
1810         rc = record_setup(obd, llh, mti->mti_svname,
1811                           "dev"/*ignored*/, "type"/*ignored*/,
1812                           failout ? "n" : "f", 0/*options*/);
1813         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname, "add ost");
1814         rc = record_end_log(obd, &llh);
1815
1816         /* We also have to update the other logs where this osc is part of
1817            the lov */
1818
1819         if (cfs_test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
1820                 /* If we're upgrading, the old mdt log already has our
1821                    entry. Let's do a fake one for fun. */
1822                 /* Note that we can't add any new failnids, since we don't
1823                    know the old osc names. */
1824                 flags = CM_SKIP | CM_UPGRADE146;
1825
1826         } else if ((mti->mti_flags & LDD_F_UPDATE) != LDD_F_UPDATE) {
1827                 /* If the update flag isn't set, don't update client/mdt
1828                    logs. */
1829                 flags |= CM_SKIP;
1830                 LCONSOLE_WARN("Client log for %s was not updated; writeconf "
1831                               "the MDT first to regenerate it.\n",
1832                               mti->mti_svname);
1833         }
1834
1835         /* Add ost to all MDT lov defs */
1836         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
1837                 if (cfs_test_bit(i, fsdb->fsdb_mdt_index_map)) {
1838                         char mdt_index[9];
1839
1840                         name_create_mdt_and_lov(&logname, &lovname, fsdb, i);
1841                         sprintf(mdt_index, "-MDT%04x", i);
1842                         mgs_write_log_osc_to_lov(obd, fsdb, mti, logname,
1843                                                  mdt_index, lovname,
1844                                                  LUSTRE_SP_MDT, flags);
1845                         name_destroy(&logname);
1846                         name_destroy(&lovname);
1847                 }
1848         }
1849
1850         /* Append ost info to the client log */
1851         name_create(&logname, mti->mti_fsname, "-client");
1852         if (mgs_log_is_empty(obd, logname)) {
1853                 /* Start client log */
1854                 rc = mgs_write_log_lov(obd, fsdb, mti, logname,
1855                                        fsdb->fsdb_clilov);
1856                 rc = mgs_write_log_lmv(obd, fsdb, mti, logname,
1857                                        fsdb->fsdb_clilmv);
1858         }
1859         mgs_write_log_osc_to_lov(obd, fsdb, mti, logname, "",
1860                                  fsdb->fsdb_clilov, LUSTRE_SP_CLI, flags);
1861         name_destroy(&logname);
1862         RETURN(rc);
1863 }
1864
1865 static __inline__ int mgs_param_empty(char *ptr)
1866 {
1867         char *tmp;
1868
1869         if ((tmp = strchr(ptr, '=')) && (*(++tmp) == '\0'))
1870                 return 1;
1871         return 0;
1872 }
1873
1874 static int mgs_write_log_failnid_internal(struct obd_device *obd,
1875                                           struct fs_db *fsdb,
1876                                           struct mgs_target_info *mti,
1877                                           char *logname, char *cliname)
1878 {
1879         int rc;
1880         struct llog_handle *llh = NULL;
1881
1882         if (mgs_param_empty(mti->mti_params)) {
1883                 /* Remove _all_ failnids */
1884                 rc = mgs_modify(obd, fsdb, mti, logname,
1885                                 mti->mti_svname, "add failnid", CM_SKIP);
1886                 return rc;
1887         }
1888
1889         /* Otherwise failover nids are additive */
1890         rc = record_start_log(obd, &llh, logname);
1891         if (!rc) {
1892                 /* FIXME this should be a single journal transaction */
1893                 rc = record_marker(obd, llh, fsdb, CM_START,
1894                                    mti->mti_svname, "add failnid");
1895                 rc = mgs_write_log_failnids(obd, mti, llh, cliname);
1896                 rc = record_marker(obd, llh, fsdb, CM_END,
1897                                    mti->mti_svname, "add failnid");
1898                 rc = record_end_log(obd, &llh);
1899         }
1900
1901         return rc;
1902 }
1903
1904
1905 /* Add additional failnids to an existing log.
1906    The mdc/osc must have been added to logs first */
1907 /* tcp nids must be in dotted-quad ascii -
1908    we can't resolve hostnames from the kernel. */
1909 static int mgs_write_log_add_failnid(struct obd_device *obd, struct fs_db *fsdb,
1910                                      struct mgs_target_info *mti)
1911 {
1912         char *logname, *cliname;
1913         int rc;
1914         ENTRY;
1915
1916         /* FIXME we currently can't erase the failnids
1917          * given when a target first registers, since they aren't part of
1918          * an "add uuid" stanza */
1919
1920         /* Verify that we know about this target */
1921         if (mgs_log_is_empty(obd, mti->mti_svname)) {
1922                 LCONSOLE_ERROR_MSG(0x142, "The target %s has not registered "
1923                                    "yet. It must be started before failnids "
1924                                    "can be added.\n", mti->mti_svname);
1925                 RETURN(-ENOENT);
1926         }
1927
1928         /* Create mdc/osc client name (e.g. lustre-OST0001-osc) */
1929         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
1930                 name_create(&cliname, mti->mti_svname, "-mdc");
1931         } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1932                 name_create(&cliname, mti->mti_svname, "-osc");
1933         } else {
1934                 RETURN(-EINVAL);
1935         }
1936
1937         /* Add failover nids to the client log */
1938         name_create(&logname, mti->mti_fsname, "-client");
1939         rc = mgs_write_log_failnid_internal(obd, fsdb, mti, logname, cliname);
1940         name_destroy(&logname);
1941         name_destroy(&cliname);
1942
1943         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1944                 /* Add OST failover nids to the MDT logs as well */
1945                 int i;
1946
1947                 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
1948                         if (!cfs_test_bit(i, fsdb->fsdb_mdt_index_map))
1949                                 continue;
1950                         name_create_mdt(&logname, mti->mti_fsname, i);
1951                         name_create_mdt_osc(&cliname, mti->mti_svname, fsdb, i);
1952                         rc = mgs_write_log_failnid_internal(obd, fsdb, mti,
1953                                                             logname, cliname);
1954                         name_destroy(&cliname);
1955                         name_destroy(&logname);
1956                 }
1957         }
1958
1959         RETURN(rc);
1960 }
1961
1962 static int mgs_wlp_lcfg(struct obd_device *obd, struct fs_db *fsdb,
1963                         struct mgs_target_info *mti,
1964                         char *logname, struct lustre_cfg_bufs *bufs,
1965                         char *tgtname, char *ptr)
1966 {
1967         char comment[MTI_NAME_MAXLEN];
1968         char *tmp;
1969         struct lustre_cfg *lcfg;
1970         int rc, del;
1971
1972         /* Erase any old settings of this same parameter */
1973         memcpy(comment, ptr, MTI_NAME_MAXLEN);
1974         comment[MTI_NAME_MAXLEN - 1] = 0;
1975         /* But don't try to match the value. */
1976         if ((tmp = strchr(comment, '=')))
1977             *tmp = 0;
1978         /* FIXME we should skip settings that are the same as old values */
1979         rc = mgs_modify(obd, fsdb, mti, logname, tgtname, comment, CM_SKIP);
1980         del = mgs_param_empty(ptr);
1981
1982         LCONSOLE_INFO("%sing parameter %s.%s in log %s\n", del ? "Disabl" : rc ?
1983                       "Sett" : "Modify", tgtname, comment, logname);
1984         if (del)
1985                 return rc;
1986
1987         lustre_cfg_bufs_reset(bufs, tgtname);
1988         lustre_cfg_bufs_set_string(bufs, 1, ptr);
1989         lcfg = lustre_cfg_new(LCFG_PARAM, bufs);
1990         if (!lcfg)
1991                 return -ENOMEM;
1992         rc = mgs_write_log_direct(obd, fsdb, logname, lcfg, tgtname, comment);
1993         lustre_cfg_free(lcfg);
1994         return rc;
1995 }
1996
1997 /* write global variable settings into log */
1998 static int mgs_write_log_sys(struct obd_device *obd, struct fs_db *fsdb,
1999                              struct mgs_target_info *mti, char *sys, char *ptr)
2000 {
2001         struct lustre_cfg_bufs bufs;
2002         struct lustre_cfg *lcfg;
2003         char *tmp;
2004         char sep;
2005         int cmd, val;
2006         int rc;
2007
2008         if (class_match_param(ptr, PARAM_TIMEOUT, &tmp) == 0)
2009                 cmd = LCFG_SET_TIMEOUT;
2010         else if (class_match_param(ptr, PARAM_LDLM_TIMEOUT, &tmp) == 0)
2011                 cmd = LCFG_SET_LDLM_TIMEOUT;
2012         /* Check for known params here so we can return error to lctl */
2013         else if ((class_match_param(ptr, PARAM_AT_MIN, &tmp) == 0)
2014                  || (class_match_param(ptr, PARAM_AT_MAX, &tmp) == 0)
2015                  || (class_match_param(ptr, PARAM_AT_EXTRA, &tmp) == 0)
2016                  || (class_match_param(ptr, PARAM_AT_EARLY_MARGIN, &tmp) == 0)
2017                  || (class_match_param(ptr, PARAM_AT_HISTORY, &tmp) == 0))
2018                 cmd = LCFG_PARAM;
2019         else
2020                 return -EINVAL;
2021
2022         /* separate the value */
2023         val = simple_strtoul(tmp, NULL, 0);
2024         if (*tmp == '\0')
2025                 CDEBUG(D_MGS, "global '%s' removed\n", sys);
2026         else
2027                 CDEBUG(D_MGS, "global '%s' val=%d\n", sys, val);
2028
2029         lustre_cfg_bufs_reset(&bufs, NULL);
2030         lustre_cfg_bufs_set_string(&bufs, 1, sys);
2031         lcfg = lustre_cfg_new(cmd, &bufs);
2032         lcfg->lcfg_num = val;
2033         /* truncate the comment to the parameter name */
2034         ptr = tmp - 1;
2035         sep = *ptr;
2036         *ptr = '\0';
2037         /* modify all servers and clients */
2038         rc = mgs_write_log_direct_all(obd, fsdb, mti,
2039                                       *tmp == '\0' ? NULL : lcfg,
2040                                       mti->mti_fsname, sys);
2041         *ptr = sep;
2042         lustre_cfg_free(lcfg);
2043         return rc;
2044 }
2045
2046 static int mgs_srpc_set_param_disk(struct obd_device *obd,
2047                                    struct fs_db *fsdb,
2048                                    struct mgs_target_info *mti,
2049                                    char *param)
2050 {
2051         struct llog_handle     *llh = NULL;
2052         char                   *logname;
2053         char                   *comment, *ptr;
2054         struct lustre_cfg_bufs  bufs;
2055         struct lustre_cfg      *lcfg;
2056         int                     rc, len;
2057         ENTRY;
2058
2059         /* get comment */
2060         ptr = strchr(param, '=');
2061         LASSERT(ptr);
2062         len = ptr - param;
2063
2064         OBD_ALLOC(comment, len + 1);
2065         if (comment == NULL)
2066                 RETURN(-ENOMEM);
2067         strncpy(comment, param, len);
2068         comment[len] = '\0';
2069
2070         /* prepare lcfg */
2071         lustre_cfg_bufs_reset(&bufs, mti->mti_svname);
2072         lustre_cfg_bufs_set_string(&bufs, 1, param);
2073         lcfg = lustre_cfg_new(LCFG_SPTLRPC_CONF, &bufs);
2074         if (lcfg == NULL)
2075                 GOTO(out_comment, rc = -ENOMEM);
2076
2077         /* construct log name */
2078         rc = name_create(&logname, mti->mti_fsname, "-sptlrpc");
2079         if (rc)
2080                 GOTO(out_lcfg, rc);
2081
2082         if (mgs_log_is_empty(obd, logname)) {
2083                 rc = record_start_log(obd, &llh, logname);
2084                 record_end_log(obd, &llh);
2085                 if (rc)
2086                         GOTO(out, rc);
2087         }
2088
2089         /* obsolete old one */
2090         mgs_modify(obd, fsdb, mti, logname, mti->mti_svname, comment, CM_SKIP);
2091
2092         /* write the new one */
2093         rc = mgs_write_log_direct(obd, fsdb, logname, lcfg,
2094                                   mti->mti_svname, comment);
2095         if (rc)
2096                 CERROR("err %d writing log %s\n", rc, logname);
2097
2098 out:
2099         name_destroy(&logname);
2100 out_lcfg:
2101         lustre_cfg_free(lcfg);
2102 out_comment:
2103         OBD_FREE(comment, len + 1);
2104         RETURN(rc);
2105 }
2106
2107 static int mgs_srpc_set_param_udesc_mem(struct fs_db *fsdb,
2108                                         char *param)
2109 {
2110         char    *ptr;
2111
2112         /* disable the adjustable udesc parameter for now, i.e. use default
2113          * setting that client always ship udesc to MDT if possible. to enable
2114          * it simply remove the following line */
2115         goto error_out;
2116
2117         ptr = strchr(param, '=');
2118         if (ptr == NULL)
2119                 goto error_out;
2120         *ptr++ = '\0';
2121
2122         if (strcmp(param, PARAM_SRPC_UDESC))
2123                 goto error_out;
2124
2125         if (strcmp(ptr, "yes") == 0) {
2126                 cfs_set_bit(FSDB_UDESC, &fsdb->fsdb_flags);
2127                 CWARN("Enable user descriptor shipping from client to MDT\n");
2128         } else if (strcmp(ptr, "no") == 0) {
2129                 cfs_clear_bit(FSDB_UDESC, &fsdb->fsdb_flags);
2130                 CWARN("Disable user descriptor shipping from client to MDT\n");
2131         } else {
2132                 *(ptr - 1) = '=';
2133                 goto error_out;
2134         }
2135         return 0;
2136
2137 error_out:
2138         CERROR("Invalid param: %s\n", param);
2139         return -EINVAL;
2140 }
2141
2142 static int mgs_srpc_set_param_mem(struct fs_db *fsdb,
2143                                   const char *svname,
2144                                   char *param)
2145 {
2146         struct sptlrpc_rule      rule;
2147         struct sptlrpc_rule_set *rset;
2148         int                      rc;
2149         ENTRY;
2150
2151         if (strncmp(param, PARAM_SRPC, sizeof(PARAM_SRPC) - 1) != 0) {
2152                 CERROR("Invalid sptlrpc parameter: %s\n", param);
2153                 RETURN(-EINVAL);
2154         }
2155
2156         if (strncmp(param, PARAM_SRPC_UDESC,
2157                     sizeof(PARAM_SRPC_UDESC) - 1) == 0) {
2158                 RETURN(mgs_srpc_set_param_udesc_mem(fsdb, param));
2159         }
2160
2161         if (strncmp(param, PARAM_SRPC_FLVR, sizeof(PARAM_SRPC_FLVR) - 1) != 0) {
2162                 CERROR("Invalid sptlrpc flavor parameter: %s\n", param);
2163                 RETURN(-EINVAL);
2164         }
2165
2166         param += sizeof(PARAM_SRPC_FLVR) - 1;
2167
2168         rc = sptlrpc_parse_rule(param, &rule);
2169         if (rc)
2170                 RETURN(rc);
2171
2172         /* mgs rules implies must be mgc->mgs */
2173         if (cfs_test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
2174                 if ((rule.sr_from != LUSTRE_SP_MGC &&
2175                      rule.sr_from != LUSTRE_SP_ANY) ||
2176                     (rule.sr_to != LUSTRE_SP_MGS &&
2177                      rule.sr_to != LUSTRE_SP_ANY))
2178                         RETURN(-EINVAL);
2179         }
2180
2181         /* preapre room for this coming rule. svcname format should be:
2182          * - fsname: general rule
2183          * - fsname-tgtname: target-specific rule
2184          */
2185         if (strchr(svname, '-')) {
2186                 struct mgs_tgt_srpc_conf *tgtconf;
2187                 int                       found = 0;
2188
2189                 for (tgtconf = fsdb->fsdb_srpc_tgt; tgtconf != NULL;
2190                      tgtconf = tgtconf->mtsc_next) {
2191                         if (!strcmp(tgtconf->mtsc_tgt, svname)) {
2192                                 found = 1;
2193                                 break;
2194                         }
2195                 }
2196
2197                 if (!found) {
2198                         int name_len;
2199
2200                         OBD_ALLOC_PTR(tgtconf);
2201                         if (tgtconf == NULL)
2202                                 RETURN(-ENOMEM);
2203
2204                         name_len = strlen(svname);
2205
2206                         OBD_ALLOC(tgtconf->mtsc_tgt, name_len + 1);
2207                         if (tgtconf->mtsc_tgt == NULL) {
2208                                 OBD_FREE_PTR(tgtconf);
2209                                 RETURN(-ENOMEM);
2210                         }
2211                         memcpy(tgtconf->mtsc_tgt, svname, name_len);
2212
2213                         tgtconf->mtsc_next = fsdb->fsdb_srpc_tgt;
2214                         fsdb->fsdb_srpc_tgt = tgtconf;
2215                 }
2216
2217                 rset = &tgtconf->mtsc_rset;
2218         } else {
2219                 rset = &fsdb->fsdb_srpc_gen;
2220         }
2221
2222         rc = sptlrpc_rule_set_merge(rset, &rule);
2223
2224         RETURN(rc);
2225 }
2226
2227 static int mgs_srpc_set_param(struct obd_device *obd,
2228                               struct fs_db *fsdb,
2229                               struct mgs_target_info *mti,
2230                               char *param)
2231 {
2232         char                   *copy;
2233         int                     rc, copy_size;
2234         ENTRY;
2235
2236 #ifndef HAVE_GSS
2237         RETURN(-EINVAL);
2238 #endif
2239         /* keep a copy of original param, which could be destroied
2240          * during parsing */
2241         copy_size = strlen(param) + 1;
2242         OBD_ALLOC(copy, copy_size);
2243         if (copy == NULL)
2244                 return -ENOMEM;
2245         memcpy(copy, param, copy_size);
2246
2247         rc = mgs_srpc_set_param_mem(fsdb, mti->mti_svname, param);
2248         if (rc)
2249                 goto out_free;
2250
2251         /* previous steps guaranteed the syntax is correct */
2252         rc = mgs_srpc_set_param_disk(obd, fsdb, mti, copy);
2253         if (rc)
2254                 goto out_free;
2255
2256         if (cfs_test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
2257                 /*
2258                  * for mgs rules, make them effective immediately.
2259                  */
2260                 LASSERT(fsdb->fsdb_srpc_tgt == NULL);
2261                 sptlrpc_target_update_exp_flavor(obd, &fsdb->fsdb_srpc_gen);
2262         }
2263
2264 out_free:
2265         OBD_FREE(copy, copy_size);
2266         RETURN(rc);
2267 }
2268
2269 struct mgs_srpc_read_data {
2270         struct fs_db   *msrd_fsdb;
2271         int             msrd_skip;
2272 };
2273
2274 static int mgs_srpc_read_handler(struct llog_handle *llh,
2275                                  struct llog_rec_hdr *rec,
2276                                  void *data)
2277 {
2278         struct mgs_srpc_read_data *msrd = (struct mgs_srpc_read_data *) data;
2279         struct cfg_marker         *marker;
2280         struct lustre_cfg         *lcfg = (struct lustre_cfg *)(rec + 1);
2281         char                      *svname, *param;
2282         int                        cfg_len, rc;
2283         ENTRY;
2284
2285         if (rec->lrh_type != OBD_CFG_REC) {
2286                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
2287                 RETURN(-EINVAL);
2288         }
2289
2290         cfg_len = rec->lrh_len - sizeof(struct llog_rec_hdr) -
2291                   sizeof(struct llog_rec_tail);
2292
2293         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
2294         if (rc) {
2295                 CERROR("Insane cfg\n");
2296                 RETURN(rc);
2297         }
2298
2299         if (lcfg->lcfg_command == LCFG_MARKER) {
2300                 marker = lustre_cfg_buf(lcfg, 1);
2301
2302                 if (marker->cm_flags & CM_START &&
2303                     marker->cm_flags & CM_SKIP)
2304                         msrd->msrd_skip = 1;
2305                 if (marker->cm_flags & CM_END)
2306                         msrd->msrd_skip = 0;
2307
2308                 RETURN(0);
2309         }
2310
2311         if (msrd->msrd_skip)
2312                 RETURN(0);
2313
2314         if (lcfg->lcfg_command != LCFG_SPTLRPC_CONF) {
2315                 CERROR("invalid command (%x)\n", lcfg->lcfg_command);
2316                 RETURN(0);
2317         }
2318
2319         svname = lustre_cfg_string(lcfg, 0);
2320         if (svname == NULL) {
2321                 CERROR("svname is empty\n");
2322                 RETURN(0);
2323         }
2324
2325         param = lustre_cfg_string(lcfg, 1);
2326         if (param == NULL) {
2327                 CERROR("param is empty\n");
2328                 RETURN(0);
2329         }
2330
2331         rc = mgs_srpc_set_param_mem(msrd->msrd_fsdb, svname, param);
2332         if (rc)
2333                 CERROR("read sptlrpc record error (%d): %s\n", rc, param);
2334
2335         RETURN(0);
2336 }
2337
2338 int mgs_get_fsdb_srpc_from_llog(struct obd_device *obd,
2339                                 struct fs_db *fsdb)
2340 {
2341         struct llog_handle        *llh = NULL;
2342         struct lvfs_run_ctxt       saved;
2343         struct llog_ctxt          *ctxt;
2344         char                      *logname;
2345         struct mgs_srpc_read_data  msrd;
2346         int                        rc;
2347         ENTRY;
2348
2349         /* construct log name */
2350         rc = name_create(&logname, fsdb->fsdb_name, "-sptlrpc");
2351         if (rc)
2352                 RETURN(rc);
2353
2354         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
2355         LASSERT(ctxt != NULL);
2356
2357         if (mgs_log_is_empty(obd, logname))
2358                 GOTO(out, rc = 0);
2359
2360         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2361
2362         rc = llog_create(ctxt, &llh, NULL, logname);
2363         if (rc)
2364                 GOTO(out_pop, rc);
2365
2366         rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
2367         if (rc)
2368                 GOTO(out_close, rc);
2369
2370         if (llog_get_size(llh) <= 1)
2371                 GOTO(out_close, rc = 0);
2372
2373         msrd.msrd_fsdb = fsdb;
2374         msrd.msrd_skip = 0;
2375
2376         rc = llog_process(llh, mgs_srpc_read_handler, (void *) &msrd, NULL);
2377
2378 out_close:
2379         llog_close(llh);
2380 out_pop:
2381         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2382 out:
2383         llog_ctxt_put(ctxt);
2384         name_destroy(&logname);
2385
2386         if (rc)
2387                 CERROR("failed to read sptlrpc config database: %d\n", rc);
2388         RETURN(rc);
2389 }
2390
2391 /* Permanent settings of all parameters by writing into the appropriate
2392  * configuration logs.
2393  * A parameter with null value ("<param>='\0'") means to erase it out of
2394  * the logs.
2395  */
2396 static int mgs_write_log_param(struct obd_device *obd, struct fs_db *fsdb,
2397                                struct mgs_target_info *mti, char *ptr)
2398 {
2399         struct lustre_cfg_bufs bufs;
2400         char *logname;
2401         char *tmp;
2402         int rc = 0, rc2 = 0;
2403         ENTRY;
2404
2405         /* For various parameter settings, we have to figure out which logs
2406            care about them (e.g. both mdt and client for lov settings) */
2407         CDEBUG(D_MGS, "next param '%s'\n", ptr);
2408
2409         /* The params are stored in MOUNT_DATA_FILE and modified via
2410            tunefs.lustre, or set using lctl conf_param */
2411
2412         /* Processed in lustre_start_mgc */
2413         if (class_match_param(ptr, PARAM_MGSNODE, NULL) == 0)
2414                 GOTO(end, rc);
2415
2416         /* Processed in ost/mdt */
2417         if (class_match_param(ptr, PARAM_NETWORK, NULL) == 0)
2418                 GOTO(end, rc);
2419
2420         /* Processed in mgs_write_log_ost */
2421         if (class_match_param(ptr, PARAM_FAILMODE, NULL) == 0) {
2422                 if (mti->mti_flags & LDD_F_PARAM) {
2423                         LCONSOLE_ERROR_MSG(0x169, "%s can only be "
2424                                            "changed with tunefs.lustre"
2425                                            "and --writeconf\n", ptr);
2426                         rc = -EPERM;
2427                 }
2428                 GOTO(end, rc);
2429         }
2430
2431         if (class_match_param(ptr, PARAM_SRPC, NULL) == 0) {
2432                 rc = mgs_srpc_set_param(obd, fsdb, mti, ptr);
2433                 GOTO(end, rc);
2434         }
2435
2436         if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
2437                 /* Add a failover nidlist */
2438                 rc = 0;
2439                 /* We already processed failovers params for new
2440                    targets in mgs_write_log_target */
2441                 if (mti->mti_flags & LDD_F_PARAM) {
2442                         CDEBUG(D_MGS, "Adding failnode\n");
2443                         rc = mgs_write_log_add_failnid(obd, fsdb, mti);
2444                 }
2445                 GOTO(end, rc);
2446         }
2447
2448         if (class_match_param(ptr, PARAM_SYS, &tmp) == 0) {
2449                 rc = mgs_write_log_sys(obd, fsdb, mti, ptr, tmp);
2450                 GOTO(end, rc);
2451         }
2452
2453         if (class_match_param(ptr, PARAM_OSC""PARAM_ACTIVE, &tmp) == 0) {
2454                 /* active=0 means off, anything else means on */
2455                 int flag = (*tmp == '0') ? CM_EXCLUDE : 0;
2456                 int i;
2457
2458                 if (!(mti->mti_flags & LDD_F_SV_TYPE_OST)) {
2459                         LCONSOLE_ERROR_MSG(0x144, "%s: Only OSCs can "
2460                                            "be (de)activated.\n",
2461                                            mti->mti_svname);
2462                         GOTO(end, rc = -EINVAL);
2463                 }
2464                 LCONSOLE_WARN("Permanently %sactivating %s\n",
2465                               flag ? "de": "re", mti->mti_svname);
2466                 /* Modify clilov */
2467                 name_create(&logname, mti->mti_fsname, "-client");
2468                 rc = mgs_modify(obd, fsdb, mti, logname,
2469                                 mti->mti_svname, "add osc", flag);
2470                 name_destroy(&logname);
2471                 if (rc)
2472                         goto active_err;
2473                 /* Modify mdtlov */
2474                 /* Add to all MDT logs for CMD */
2475                 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
2476                         if (!cfs_test_bit(i, fsdb->fsdb_mdt_index_map))
2477                                 continue;
2478                         name_create_mdt(&logname, mti->mti_fsname, i);
2479                         rc = mgs_modify(obd, fsdb, mti, logname,
2480                                         mti->mti_svname, "add osc", flag);
2481                         name_destroy(&logname);
2482                         if (rc)
2483                                 goto active_err;
2484                 }
2485         active_err:
2486                 if (rc) {
2487                         LCONSOLE_ERROR_MSG(0x145, "Couldn't find %s in"
2488                                            "log (%d). No permanent "
2489                                            "changes were made to the "
2490                                            "config log.\n",
2491                                            mti->mti_svname, rc);
2492                         if (cfs_test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags))
2493                                 LCONSOLE_ERROR_MSG(0x146, "This may be"
2494                                                    " because the log"
2495                                                    "is in the old 1.4"
2496                                                    "style. Consider "
2497                                                    " --writeconf to "
2498                                                    "update the logs.\n");
2499                         GOTO(end, rc);
2500                 }
2501                 /* Fall through to osc proc for deactivating live OSC
2502                    on running MDT / clients. */
2503         }
2504         /* Below here, let obd's XXX_process_config methods handle it */
2505
2506         /* All lov. in proc */
2507         if (class_match_param(ptr, PARAM_LOV, NULL) == 0) {
2508                 char *mdtlovname;
2509
2510                 CDEBUG(D_MGS, "lov param %s\n", ptr);
2511                 if (!(mti->mti_flags & LDD_F_SV_TYPE_MDT)) {
2512                         LCONSOLE_ERROR_MSG(0x147, "LOV params must be "
2513                                            "set on the MDT, not %s. "
2514                                            "Ignoring.\n",
2515                                            mti->mti_svname);
2516                         GOTO(end, rc = 0);
2517                 }
2518
2519                 /* Modify mdtlov */
2520                 if (mgs_log_is_empty(obd, mti->mti_svname))
2521                         GOTO(end, rc = -ENODEV);
2522
2523                 name_create_mdt_and_lov(&logname, &mdtlovname, fsdb,
2524                                         mti->mti_stripe_index);
2525                 rc = mgs_wlp_lcfg(obd, fsdb, mti, mti->mti_svname,
2526                                   &bufs, mdtlovname, ptr);
2527                 name_destroy(&logname);
2528                 name_destroy(&mdtlovname);
2529                 if (rc)
2530                         GOTO(end, rc);
2531
2532                 /* Modify clilov */
2533                 name_create(&logname, mti->mti_fsname, "-client");
2534                 rc = mgs_wlp_lcfg(obd, fsdb, mti, logname, &bufs,
2535                                   fsdb->fsdb_clilov, ptr);
2536                 name_destroy(&logname);
2537                 GOTO(end, rc);
2538         }
2539
2540         /* All osc., mdc., llite. params in proc */
2541         if ((class_match_param(ptr, PARAM_OSC, NULL) == 0) ||
2542             (class_match_param(ptr, PARAM_MDC, NULL) == 0) ||
2543             (class_match_param(ptr, PARAM_LLITE, NULL) == 0)) {
2544                 char *cname;
2545                 if (memcmp(ptr, PARAM_LLITE, strlen(PARAM_LLITE)) == 0) {
2546                         name_create(&cname, mti->mti_fsname, "-client");
2547                         /* Add the client type to match the obdname in
2548                            class_config_llog_handler */
2549                 } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
2550                         /* COMPAT_146 */
2551                         if (fsdb->fsdb_mdc)
2552                                 name_create(&cname, fsdb->fsdb_mdc, "");
2553                         else
2554                                 name_create(&cname, mti->mti_svname,
2555                                             "-mdc");
2556                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
2557                         /* COMPAT_146 */
2558                         if (cfs_test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
2559                                 LCONSOLE_ERROR_MSG(0x148, "Upgraded "
2560                                                    "client logs for %s"
2561                                                    " cannot be "
2562                                                    "modified. Consider"
2563                                                    " updating the "
2564                                                    "configuration with"
2565                                                    " --writeconf\n",
2566                                                    mti->mti_svname);
2567                                 /* We don't know the names of all the
2568                                    old oscs*/
2569                                 GOTO(end, rc = -EINVAL);
2570                         }
2571                         name_create(&cname, mti->mti_svname, "-osc");
2572                 } else {
2573                         GOTO(end, rc = -EINVAL);
2574                 }
2575
2576                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
2577
2578                 /* Modify client */
2579                 name_create(&logname, mti->mti_fsname, "-client");
2580                 rc = mgs_wlp_lcfg(obd, fsdb, mti, logname, &bufs,
2581                                   cname, ptr);
2582
2583                 /* osc params affect the MDT as well */
2584                 if (!rc && (mti->mti_flags & LDD_F_SV_TYPE_OST)) {
2585                         int i;
2586
2587                         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
2588                                 if (!cfs_test_bit(i, fsdb->fsdb_mdt_index_map))
2589                                         continue;
2590                                 name_destroy(&cname);
2591                                 name_create_mdt_osc(&cname, mti->mti_svname,
2592                                                     fsdb, i);
2593                                 name_destroy(&logname);
2594                                 name_create_mdt(&logname, mti->mti_fsname, i);
2595                                 if (!mgs_log_is_empty(obd, logname))
2596                                         rc = mgs_wlp_lcfg(obd, fsdb,mti,logname,
2597                                                           &bufs, cname, ptr);
2598                                 if (rc)
2599                                         break;
2600                         }
2601                 }
2602                 name_destroy(&logname);
2603                 name_destroy(&cname);
2604                 GOTO(end, rc);
2605         }
2606
2607         /* All mdt. params in proc */
2608         if (class_match_param(ptr, PARAM_MDT, NULL) == 0) {
2609                 int i;
2610                 __u32 idx;
2611
2612                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
2613                 if (strncmp(mti->mti_svname, mti->mti_fsname,
2614                             MTI_NAME_MAXLEN) == 0)
2615                         /* device is unspecified completely? */
2616                         rc = LDD_F_SV_TYPE_MDT | LDD_F_SV_ALL;
2617                 else
2618                         rc = server_name2index(mti->mti_svname, &idx, NULL);
2619                 if (rc < 0)
2620                         goto active_err;
2621                 if ((rc & LDD_F_SV_TYPE_MDT) == 0)
2622                         goto active_err;
2623                 if (rc & LDD_F_SV_ALL) {
2624                         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
2625                                 if (!cfs_test_bit(i,
2626                                                   fsdb->fsdb_mdt_index_map))
2627                                         continue;
2628                                 name_create_mdt(&logname, mti->mti_fsname, i);
2629                                 rc = mgs_wlp_lcfg(obd, fsdb, mti,
2630                                                   logname, &bufs,
2631                                                   logname, ptr);
2632                                 name_destroy(&logname);
2633                                 if (rc)
2634                                         goto active_err;
2635                         }
2636                 } else {
2637                         rc = mgs_wlp_lcfg(obd, fsdb, mti,
2638                                           mti->mti_svname, &bufs,
2639                                           mti->mti_svname, ptr);
2640                         if (rc)
2641                                 goto active_err;
2642                 }
2643                 GOTO(end, rc);
2644         }
2645
2646         /* All mdd., ost. params in proc */
2647         if ((class_match_param(ptr, PARAM_MDD, NULL) == 0) ||
2648             (class_match_param(ptr, PARAM_OST, NULL) == 0)) {
2649                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
2650                 if (mgs_log_is_empty(obd, mti->mti_svname))
2651                         GOTO(end, rc = -ENODEV);
2652
2653                 rc = mgs_wlp_lcfg(obd, fsdb, mti, mti->mti_svname,
2654                                   &bufs, mti->mti_svname, ptr);
2655                 GOTO(end, rc);
2656         }
2657
2658         LCONSOLE_WARN("Ignoring unrecognized param '%s'\n", ptr);
2659         rc2 = -ENOSYS;
2660
2661 end:
2662         if (rc)
2663                 CERROR("err %d on param '%s'\n", rc, ptr);
2664
2665         RETURN(rc ?: rc2);
2666 }
2667
2668 /* Not implementing automatic failover nid addition at this time. */
2669 int mgs_check_failnid(struct obd_device *obd, struct mgs_target_info *mti)
2670 {
2671 #if 0
2672         struct fs_db *fsdb;
2673         int rc;
2674         ENTRY;
2675
2676         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb);
2677         if (rc)
2678                 RETURN(rc);
2679
2680         if (mgs_log_is_empty(obd, mti->mti_svname))
2681                 /* should never happen */
2682                 RETURN(-ENOENT);
2683
2684         CDEBUG(D_MGS, "Checking for new failnids for %s\n", mti->mti_svname);
2685
2686         /* FIXME We can just check mti->params to see if we're already in
2687            the failover list.  Modify mti->params for rewriting back at
2688            server_register_target(). */
2689
2690         cfs_down(&fsdb->fsdb_sem);
2691         rc = mgs_write_log_add_failnid(obd, fsdb, mti);
2692         cfs_up(&fsdb->fsdb_sem);
2693
2694         RETURN(rc);
2695 #endif
2696         return 0;
2697 }
2698
2699 int mgs_write_log_target(struct obd_device *obd,
2700                          struct mgs_target_info *mti,
2701                          struct fs_db *fsdb)
2702 {
2703         int rc = -EINVAL;
2704         char *buf, *params;
2705         ENTRY;
2706
2707         /* set/check the new target index */
2708         rc = mgs_set_index(obd, mti);
2709         if (rc < 0) {
2710                 CERROR("Can't get index (%d)\n", rc);
2711                 RETURN(rc);
2712         }
2713
2714         /* COMPAT_146 */
2715         if (mti->mti_flags & LDD_F_UPGRADE14) {
2716                 if (rc == EALREADY) {
2717                         LCONSOLE_INFO("Found index %d for %s 1.4 log, "
2718                                       "upgrading\n", mti->mti_stripe_index,
2719                                       mti->mti_svname);
2720                 } else {
2721                         LCONSOLE_ERROR_MSG(0x149, "Failed to find %s in the old"
2722                                            " client log. Apparently it is not "
2723                                            "part of this filesystem, or the old"
2724                                            " log is wrong.\nUse 'writeconf' on "
2725                                            "the MDT to force log regeneration."
2726                                            "\n", mti->mti_svname);
2727                         /* Not in client log?  Upgrade anyhow...*/
2728                         /* Argument against upgrading: reformat MDT,
2729                            upgrade OST, then OST will start but will be SKIPped
2730                            in client logs.  Maybe error now is better. */
2731                         /* RETURN(-EINVAL); */
2732                 }
2733                 /* end COMPAT_146 */
2734         } else {
2735                 if (rc == EALREADY) {
2736                         LCONSOLE_WARN("Found index %d for %s, updating log\n",
2737                                       mti->mti_stripe_index, mti->mti_svname);
2738                         /* We would like to mark old log sections as invalid
2739                            and add new log sections in the client and mdt logs.
2740                            But if we add new sections, then live clients will
2741                            get repeat setup instructions for already running
2742                            osc's. So don't update the client/mdt logs. */
2743                         mti->mti_flags &= ~LDD_F_UPDATE;
2744                 }
2745         }
2746
2747         cfs_down(&fsdb->fsdb_sem);
2748
2749         if (mti->mti_flags &
2750             (LDD_F_VIRGIN | LDD_F_UPGRADE14 | LDD_F_WRITECONF)) {
2751                 /* Generate a log from scratch */
2752                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
2753                         rc = mgs_write_log_mdt(obd, fsdb, mti);
2754                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
2755                         rc = mgs_write_log_ost(obd, fsdb, mti);
2756                 } else {
2757                         CERROR("Unknown target type %#x, can't create log for "
2758                                "%s\n", mti->mti_flags, mti->mti_svname);
2759                 }
2760                 if (rc) {
2761                         CERROR("Can't write logs for %s (%d)\n",
2762                                mti->mti_svname, rc);
2763                         GOTO(out_up, rc);
2764                 }
2765         } else {
2766                 /* Just update the params from tunefs in mgs_write_log_params */
2767                 CDEBUG(D_MGS, "Update params for %s\n", mti->mti_svname);
2768                 mti->mti_flags |= LDD_F_PARAM;
2769         }
2770
2771         /* allocate temporary buffer, where class_get_next_param will
2772            make copy of a current  parameter */
2773         OBD_ALLOC(buf, strlen(mti->mti_params) + 1);
2774         if (buf == NULL)
2775                 GOTO(out_up, rc = -ENOMEM);
2776         params = mti->mti_params;
2777         while (params != NULL) {
2778                 rc = class_get_next_param(&params, buf);
2779                 if (rc) {
2780                         if (rc == 1)
2781                                 /* there is no next parameter, that is
2782                                    not an error */
2783                                 rc = 0;
2784                         break;
2785                 }
2786                 CDEBUG(D_MGS, "remaining string: '%s', param: '%s'\n",
2787                        params, buf);
2788                 rc = mgs_write_log_param(obd, fsdb, mti, buf);
2789                 if (rc)
2790                         break;
2791         }
2792
2793         OBD_FREE(buf, strlen(mti->mti_params) + 1);
2794
2795 out_up:
2796         cfs_up(&fsdb->fsdb_sem);
2797         RETURN(rc);
2798 }
2799
2800 /* COMPAT_146 */
2801 /* verify that we can handle the old config logs */
2802 int mgs_upgrade_sv_14(struct obd_device *obd, struct mgs_target_info *mti,
2803                       struct fs_db *fsdb)
2804 {
2805         int rc = 0;
2806         ENTRY;
2807
2808         /* Create ost log normally, as servers register.  Servers
2809            register with their old uuids (from last_rcvd), so old
2810            (MDT and client) logs should work.
2811          - new MDT won't know about old OSTs, only the ones that have
2812            registered, so we need the old MDT log to get the LOV right
2813            in order for old clients to work.
2814          - Old clients connect to the MDT, not the MGS, for their logs, and
2815            will therefore receive the old client log from the MDT /LOGS dir.
2816          - Old clients can continue to use and connect to old or new OSTs
2817          - New clients will contact the MGS for their log
2818         */
2819
2820         LCONSOLE_INFO("upgrading server %s from pre-1.6\n", mti->mti_svname);
2821         server_mti_print("upgrade", mti);
2822
2823         if (cfs_test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
2824                 LCONSOLE_ERROR_MSG(0x14a, "The old client log %s-client is "
2825                                    "missing.  Was tunefs.lustre successful?\n",
2826                                    mti->mti_fsname);
2827                 RETURN(-ENOENT);
2828         }
2829
2830         if (fsdb->fsdb_gen == 0) {
2831                 /* There were no markers in the client log, meaning we have
2832                    not updated the logs for this fs */
2833                 CDEBUG(D_MGS, "found old, unupdated client log\n");
2834         }
2835
2836         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
2837                 if (mgs_log_is_empty(obd, mti->mti_svname)) {
2838                         LCONSOLE_ERROR_MSG(0x14b, "The old MDT log %s is "
2839                                            "missing. Was tunefs.lustre "
2840                                            "successful?\n",
2841                                            mti->mti_svname);
2842                         RETURN(-ENOENT);
2843                 }
2844                 /* We're starting with an old uuid.  Assume old name for lov
2845                    as well since the lov entry already exists in the log. */
2846                 CDEBUG(D_MGS, "old mds uuid %s\n", mti->mti_uuid);
2847                 if (strncmp(mti->mti_uuid, fsdb->fsdb_mdtlov + 4,
2848                             strlen(fsdb->fsdb_mdtlov) - 4) != 0) {
2849                         CERROR("old mds uuid %s doesn't match log %s (%s)\n",
2850                                mti->mti_uuid, fsdb->fsdb_mdtlov,
2851                                fsdb->fsdb_mdtlov + 4);
2852                         RETURN(-EINVAL);
2853                 }
2854         }
2855
2856         if (!cfs_test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
2857                 LCONSOLE_ERROR_MSG(0x14c, "%s-client is supposedly an old "
2858                                    "log, but no old LOV or MDT was found. "
2859                                    "Consider updating the configuration with"
2860                                    " --writeconf.\n", mti->mti_fsname);
2861         }
2862
2863         RETURN(rc);
2864 }
2865 /* end COMPAT_146 */
2866
2867 int mgs_erase_log(struct obd_device *obd, char *name)
2868 {
2869         struct lvfs_run_ctxt saved;
2870         struct llog_ctxt *ctxt;
2871         struct llog_handle *llh;
2872         int rc = 0;
2873
2874         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
2875         LASSERT(ctxt != NULL);
2876
2877         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2878         rc = llog_create(ctxt, &llh, NULL, name);
2879         if (rc == 0) {
2880                 llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
2881                 rc = llog_destroy(llh);
2882                 llog_free_handle(llh);
2883         }
2884         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2885         llog_ctxt_put(ctxt);
2886
2887         if (rc)
2888                 CERROR("failed to clear log %s: %d\n", name, rc);
2889
2890         return(rc);
2891 }
2892
2893 /* erase all logs for the given fs */
2894 int mgs_erase_logs(struct obd_device *obd, char *fsname)
2895 {
2896         struct mgs_obd *mgs = &obd->u.mgs;
2897         static struct fs_db *fsdb;
2898         cfs_list_t dentry_list;
2899         struct l_linux_dirent *dirent, *n;
2900         int rc, len = strlen(fsname);
2901         char *suffix;
2902         ENTRY;
2903
2904         /* Find all the logs in the CONFIGS directory */
2905         rc = class_dentry_readdir(obd, mgs->mgs_configs_dir,
2906                                   mgs->mgs_vfsmnt, &dentry_list);
2907         if (rc) {
2908                 CERROR("Can't read %s dir\n", MOUNT_CONFIGS_DIR);
2909                 RETURN(rc);
2910         }
2911
2912         cfs_down(&mgs->mgs_sem);
2913
2914         /* Delete the fs db */
2915         fsdb = mgs_find_fsdb(obd, fsname);
2916         if (fsdb)
2917                 mgs_free_fsdb(obd, fsdb);
2918
2919         cfs_list_for_each_entry_safe(dirent, n, &dentry_list, lld_list) {
2920                 cfs_list_del(&dirent->lld_list);
2921                 suffix = strrchr(dirent->lld_name, '-');
2922                 if (suffix != NULL) {
2923                         if ((len == suffix - dirent->lld_name) &&
2924                             (strncmp(fsname, dirent->lld_name, len) == 0)) {
2925                                 CDEBUG(D_MGS, "Removing log %s\n",
2926                                        dirent->lld_name);
2927                                 mgs_erase_log(obd, dirent->lld_name);
2928                         }
2929                 }
2930                 OBD_FREE(dirent, sizeof(*dirent));
2931         }
2932
2933         cfs_up(&mgs->mgs_sem);
2934
2935         RETURN(rc);
2936 }
2937
2938 /* from llog_swab */
2939 static void print_lustre_cfg(struct lustre_cfg *lcfg)
2940 {
2941         int i;
2942         ENTRY;
2943
2944         CDEBUG(D_MGS, "lustre_cfg: %p\n", lcfg);
2945         CDEBUG(D_MGS, "\tlcfg->lcfg_version: %#x\n", lcfg->lcfg_version);
2946
2947         CDEBUG(D_MGS, "\tlcfg->lcfg_command: %#x\n", lcfg->lcfg_command);
2948         CDEBUG(D_MGS, "\tlcfg->lcfg_num: %#x\n", lcfg->lcfg_num);
2949         CDEBUG(D_MGS, "\tlcfg->lcfg_flags: %#x\n", lcfg->lcfg_flags);
2950         CDEBUG(D_MGS, "\tlcfg->lcfg_nid: %s\n", libcfs_nid2str(lcfg->lcfg_nid));
2951
2952         CDEBUG(D_MGS, "\tlcfg->lcfg_bufcount: %d\n", lcfg->lcfg_bufcount);
2953         if (lcfg->lcfg_bufcount < LUSTRE_CFG_MAX_BUFCOUNT)
2954                 for (i = 0; i < lcfg->lcfg_bufcount; i++) {
2955                         CDEBUG(D_MGS, "\tlcfg->lcfg_buflens[%d]: %d %s\n",
2956                                i, lcfg->lcfg_buflens[i],
2957                                lustre_cfg_string(lcfg, i));
2958                 }
2959         EXIT;
2960 }
2961
2962 /* Set a permanent (config log) param for a target or fs
2963  * \param lcfg buf0 may contain the device (testfs-MDT0000) name
2964  *             buf1 contains the single parameter
2965  */
2966 int mgs_setparam(struct obd_device *obd, struct lustre_cfg *lcfg, char *fsname)
2967 {
2968         struct fs_db *fsdb;
2969         struct mgs_target_info *mti;
2970         char *devname, *param;
2971         char *ptr, *tmp;
2972         __u32 index;
2973         int rc = 0;
2974         ENTRY;
2975
2976         print_lustre_cfg(lcfg);
2977
2978         /* lustre, lustre-mdtlov, lustre-client, lustre-MDT0000 */
2979         devname = lustre_cfg_string(lcfg, 0);
2980         param = lustre_cfg_string(lcfg, 1);
2981         if (!devname) {
2982                 /* Assume device name embedded in param:
2983                    lustre-OST0000.osc.max_dirty_mb=32 */
2984                 ptr = strchr(param, '.');
2985                 if (ptr) {
2986                         devname = param;
2987                         *ptr = 0;
2988                         param = ptr + 1;
2989                 }
2990         }
2991         if (!devname) {
2992                 LCONSOLE_ERROR_MSG(0x14d, "No target specified: %s\n", param);
2993                 RETURN(-ENOSYS);
2994         }
2995
2996         /* Extract fsname */
2997         ptr = strrchr(devname, '-');
2998         memset(fsname, 0, MTI_NAME_MAXLEN);
2999         if (ptr && (server_name2index(ptr, &index, NULL) >= 0)) {
3000                 /* param related to llite isn't allowed to set by OST or MDT */
3001                 if (strncmp(param, PARAM_LLITE, sizeof(PARAM_LLITE)) == 0)
3002                         RETURN(-EINVAL);
3003
3004                 strncpy(fsname, devname, ptr - devname);
3005         } else {
3006                 /* assume devname is the fsname */
3007                 strncpy(fsname, devname, MTI_NAME_MAXLEN);
3008         }
3009         fsname[MTI_NAME_MAXLEN - 1] = 0;
3010         CDEBUG(D_MGS, "setparam fs='%s' device='%s'\n", fsname, devname);
3011
3012         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb);
3013         if (rc)
3014                 RETURN(rc);
3015         if (!cfs_test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags) &&
3016             cfs_test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
3017                 CERROR("No filesystem targets for %s.  cfg_device from lctl "
3018                        "is '%s'\n", fsname, devname);
3019                 mgs_free_fsdb(obd, fsdb);
3020                 RETURN(-EINVAL);
3021         }
3022
3023         /* Create a fake mti to hold everything */
3024         OBD_ALLOC_PTR(mti);
3025         if (!mti)
3026                 GOTO(out, rc = -ENOMEM);
3027         strncpy(mti->mti_fsname, fsname, MTI_NAME_MAXLEN);
3028         strncpy(mti->mti_svname, devname, MTI_NAME_MAXLEN);
3029         strncpy(mti->mti_params, param, sizeof(mti->mti_params));
3030         rc = server_name2index(mti->mti_svname, &mti->mti_stripe_index, &tmp);
3031         if (rc < 0)
3032                 /* Not a valid server; may be only fsname */
3033                 rc = 0;
3034         else
3035                 /* Strip -osc or -mdc suffix from svname */
3036                 if (server_make_name(rc, mti->mti_stripe_index, mti->mti_fsname,
3037                                      mti->mti_svname))
3038                         GOTO(out, rc = -EINVAL);
3039
3040         mti->mti_flags = rc | LDD_F_PARAM;
3041
3042         cfs_down(&fsdb->fsdb_sem);
3043         rc = mgs_write_log_param(obd, fsdb, mti, mti->mti_params);
3044         cfs_up(&fsdb->fsdb_sem);
3045
3046         /*
3047          * Revoke lock so everyone updates.  Should be alright if
3048          * someone was already reading while we were updating the logs,
3049          * so we don't really need to hold the lock while we're
3050          * writing (above).
3051          */
3052         mgs_revoke_lock(obd, fsdb);
3053 out:
3054         OBD_FREE_PTR(mti);
3055         RETURN(rc);
3056 }
3057
3058 static int mgs_write_log_pool(struct obd_device *obd, char *logname,
3059                               struct fs_db *fsdb, char *lovname,
3060                               enum lcfg_command_type cmd,
3061                               char *poolname, char *fsname,
3062                               char *ostname, char *comment)
3063 {
3064         struct llog_handle *llh = NULL;
3065         int rc;
3066
3067         rc = record_start_log(obd, &llh, logname);
3068         if (rc)
3069                 return rc;
3070         rc = record_marker(obd, llh, fsdb, CM_START, lovname, comment);
3071         record_base(obd, llh, lovname, 0, cmd, poolname, fsname, ostname, 0);
3072         rc = record_marker(obd, llh, fsdb, CM_END, lovname, comment);
3073         rc = record_end_log(obd, &llh);
3074
3075         return rc;
3076 }
3077
3078 int mgs_pool_cmd(struct obd_device *obd, enum lcfg_command_type cmd,
3079                  char *fsname, char *poolname, char *ostname)
3080 {
3081         struct fs_db *fsdb;
3082         char *lovname;
3083         char *logname;
3084         char *label = NULL, *canceled_label = NULL;
3085         int label_sz;
3086         struct mgs_target_info *mti = NULL;
3087         int rc, i;
3088         ENTRY;
3089
3090         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb);
3091         if (rc) {
3092                 CERROR("Can't get db for %s\n", fsname);
3093                 RETURN(rc);
3094         }
3095         if (cfs_test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
3096                 CERROR("%s is not defined\n", fsname);
3097                 mgs_free_fsdb(obd, fsdb);
3098                 RETURN(-EINVAL);
3099         }
3100
3101         label_sz = 10 + strlen(fsname) + strlen(poolname);
3102
3103         /* check if ostname match fsname */
3104         if (ostname != NULL) {
3105                 char *ptr;
3106
3107                 ptr = strrchr(ostname, '-');
3108                 if ((ptr == NULL) ||
3109                     (strncmp(fsname, ostname, ptr-ostname) != 0))
3110                         RETURN(-EINVAL);
3111                 label_sz += strlen(ostname);
3112         }
3113
3114         OBD_ALLOC(label, label_sz);
3115         if (label == NULL)
3116                 GOTO(out, rc = -ENOMEM);
3117
3118         switch(cmd) {
3119         case LCFG_POOL_NEW: {
3120                 sprintf(label,
3121                         "new %s.%s", fsname, poolname);
3122                 break;
3123         }
3124         case LCFG_POOL_ADD: {
3125                 sprintf(label,
3126                         "add %s.%s.%s", fsname, poolname, ostname);
3127                 break;
3128         }
3129         case LCFG_POOL_REM: {
3130                 OBD_ALLOC(canceled_label, label_sz);
3131                 if (canceled_label == NULL)
3132                          GOTO(out, rc = -ENOMEM);
3133                 sprintf(label,
3134                         "rem %s.%s.%s", fsname, poolname, ostname);
3135                 sprintf(canceled_label,
3136                         "add %s.%s.%s", fsname, poolname, ostname);
3137                 break;
3138         }
3139         case LCFG_POOL_DEL: {
3140                 OBD_ALLOC(canceled_label, label_sz);
3141                 if (canceled_label == NULL)
3142                          GOTO(out, rc = -ENOMEM);
3143                 sprintf(label,
3144                         "del %s.%s", fsname, poolname);
3145                 sprintf(canceled_label,
3146                         "new %s.%s", fsname, poolname);
3147                 break;
3148         }
3149         default: {
3150                 break;
3151         }
3152         }
3153
3154         cfs_down(&fsdb->fsdb_sem);
3155
3156         if (canceled_label != NULL) {
3157                 OBD_ALLOC_PTR(mti);
3158                 if (mti == NULL)
3159                         GOTO(out, rc = -ENOMEM);
3160         }
3161
3162         /* write pool def to all MDT logs */
3163         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
3164                  if (cfs_test_bit(i,  fsdb->fsdb_mdt_index_map)) {
3165                         name_create_mdt_and_lov(&logname, &lovname, fsdb, i);
3166
3167                         if (canceled_label != NULL) {
3168                                 strcpy(mti->mti_svname, "lov pool");
3169                                 mgs_modify(obd, fsdb, mti, logname, lovname,
3170                                            canceled_label, CM_SKIP);
3171                         }
3172
3173                         mgs_write_log_pool(obd, logname, fsdb, lovname,
3174                                            cmd, fsname, poolname, ostname,
3175                                            label);
3176                         name_destroy(&logname);
3177                         name_destroy(&lovname);
3178                 }
3179         }
3180
3181         name_create(&logname, fsname, "-client");
3182         if (canceled_label != NULL)
3183                 mgs_modify(obd, fsdb, mti, logname, fsdb->fsdb_clilov,
3184                            canceled_label, CM_SKIP);
3185
3186         mgs_write_log_pool(obd, logname, fsdb, fsdb->fsdb_clilov,
3187                            cmd, fsname, poolname, ostname, label);
3188         name_destroy(&logname);
3189
3190         cfs_up(&fsdb->fsdb_sem);
3191         /* request for update */
3192         mgs_revoke_lock(obd, fsdb);
3193
3194         EXIT;
3195 out:
3196         if (label != NULL)
3197                 OBD_FREE(label, label_sz);
3198
3199         if (canceled_label != NULL)
3200                 OBD_FREE(canceled_label, label_sz);
3201
3202         if (mti != NULL)
3203                 OBD_FREE_PTR(mti);
3204
3205         return rc;
3206 }
3207
3208 #if 0
3209 /******************** unused *********************/
3210 static int mgs_backup_llog(struct obd_device *obd, char* fsname)
3211 {
3212         struct file *filp, *bak_filp;
3213         struct lvfs_run_ctxt saved;
3214         char *logname, *buf;
3215         loff_t soff = 0 , doff = 0;
3216         int count = 4096, len;
3217         int rc = 0;
3218
3219         OBD_ALLOC(logname, PATH_MAX);
3220         if (logname == NULL)
3221                 return -ENOMEM;
3222
3223         OBD_ALLOC(buf, count);
3224         if (!buf)
3225                 GOTO(out , rc = -ENOMEM);
3226
3227         len = snprintf(logname, PATH_MAX, "%s/%s.bak",
3228                        MOUNT_CONFIGS_DIR, fsname);
3229
3230         if (len >= PATH_MAX - 1) {
3231                 GOTO(out, -ENAMETOOLONG);
3232         }
3233
3234         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
3235
3236         bak_filp = l_filp_open(logname, O_RDWR|O_CREAT|O_TRUNC, 0660);
3237         if (IS_ERR(bak_filp)) {
3238                 rc = PTR_ERR(bak_filp);
3239                 CERROR("backup logfile open %s: %d\n", logname, rc);
3240                 GOTO(pop, rc);
3241         }
3242         sprintf(logname, "%s/%s", MOUNT_CONFIGS_DIR, fsname);
3243         filp = l_filp_open(logname, O_RDONLY, 0);
3244         if (IS_ERR(filp)) {
3245                 rc = PTR_ERR(filp);
3246                 CERROR("logfile open %s: %d\n", logname, rc);
3247                 GOTO(close1f, rc);
3248         }
3249
3250         while ((rc = lustre_fread(filp, buf, count, &soff)) > 0) {
3251                 rc = lustre_fwrite(bak_filp, buf, count, &doff);
3252                 break;
3253         }
3254
3255         filp_close(filp, 0);
3256 close1f:
3257         filp_close(bak_filp, 0);
3258 pop:
3259         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
3260 out:
3261         if (buf)
3262                 OBD_FREE(buf, count);
3263         OBD_FREE(logname, PATH_MAX);
3264         return rc;
3265 }
3266
3267 #endif