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