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