Whamcloud - gitweb
806c273620d754ee51686c8d9bd3f1fa8571c536
[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 #ifndef EXPORT_SYMTAB
44 #define EXPORT_SYMTAB
45 #endif
46 #define DEBUG_SUBSYSTEM S_MGS
47 #define D_MGS D_CONFIG
48
49 #ifdef __KERNEL__
50 #include <linux/module.h>
51 #include <linux/pagemap.h>
52 #include <linux/fs.h>
53 #endif
54
55 #include <obd.h>
56 #include <obd_lov.h>
57 #include <obd_class.h>
58 #include <lustre_log.h>
59 #include <obd_ost.h>
60 #include <libcfs/list.h>
61 #include <linux/lvfs.h>
62 #include <lustre_fsfilt.h>
63 #include <lustre_disk.h>
64 #include <lustre_param.h>
65 #include <lustre_sec.h>
66 #include "mgs_internal.h"
67
68 /********************** Class functions ********************/
69
70 /* Caller must list_del and OBD_FREE each dentry from the list */
71 int class_dentry_readdir(struct obd_device *obd, struct dentry *dir,
72                                 struct vfsmount *inmnt,
73                                 cfs_list_t *dentry_list){
74         /* see mds_cleanup_pending */
75         struct lvfs_run_ctxt saved;
76         struct file *file;
77         struct dentry *dentry;
78         struct vfsmount *mnt;
79         int rc = 0;
80         ENTRY;
81
82         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
83         dentry = dget(dir);
84         if (IS_ERR(dentry))
85                 GOTO(out_pop, rc = PTR_ERR(dentry));
86         mnt = mntget(inmnt);
87         if (IS_ERR(mnt)) {
88                 l_dput(dentry);
89                 GOTO(out_pop, rc = PTR_ERR(mnt));
90         }
91
92         file = ll_dentry_open(dentry, mnt, O_RDONLY, current_cred());
93         if (IS_ERR(file))
94                 /* dentry_open_it() drops the dentry, mnt refs */
95                 GOTO(out_pop, rc = PTR_ERR(file));
96
97         CFS_INIT_LIST_HEAD(dentry_list);
98         rc = l_readdir(file, dentry_list);
99         filp_close(file, 0);
100         /*  filp_close->fput() drops the dentry, mnt refs */
101
102 out_pop:
103         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
104         RETURN(rc);
105 }
106
107 /******************** DB functions *********************/
108
109 static inline int name_create(char **newname, char *prefix, char *suffix)
110 {
111         LASSERT(newname);
112         OBD_ALLOC(*newname, strlen(prefix) + strlen(suffix) + 1);
113         if (!*newname)
114                 return -ENOMEM;
115         sprintf(*newname, "%s%s", prefix, suffix);
116         return 0;
117 }
118
119 static inline void name_destroy(char **name)
120 {
121         if (*name)
122                 OBD_FREE(*name, strlen(*name) + 1);
123         *name = NULL;
124 }
125
126 struct mgs_fsdb_handler_data
127 {
128         struct fs_db   *fsdb;
129         __u32           ver;
130 };
131
132 /* from the (client) config log, figure out:
133         1. which ost's/mdt's are configured (by index)
134         2. what the last config step is
135         3. COMPAT_146 lov name
136         4. COMPAT_146 mdt lov name
137         5. COMPAT_146 mdc name
138         6. COMPAT_18 osc name
139 */
140 /* It might be better to have a separate db file, instead of parsing the info
141    out of the client log.  This is slow and potentially error-prone. */
142 static int mgs_fsdb_handler(struct llog_handle *llh, struct llog_rec_hdr *rec,
143                             void *data)
144 {
145         struct mgs_fsdb_handler_data *d = (struct mgs_fsdb_handler_data *) data;
146         struct fs_db *fsdb = d->fsdb;
147         int cfg_len = rec->lrh_len;
148         char *cfg_buf = (char*) (rec + 1);
149         struct lustre_cfg *lcfg;
150         __u32 index;
151         int rc = 0;
152         ENTRY;
153
154         if (rec->lrh_type != OBD_CFG_REC) {
155                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
156                 RETURN(-EINVAL);
157         }
158
159         rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
160         if (rc) {
161                 CERROR("Insane cfg\n");
162                 RETURN(rc);
163         }
164
165         lcfg = (struct lustre_cfg *)cfg_buf;
166
167         CDEBUG(D_INFO, "cmd %x %s %s\n", lcfg->lcfg_command,
168                lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
169
170         /* Figure out ost indicies */
171         /* lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1 */
172         if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD ||
173             lcfg->lcfg_command == LCFG_LOV_DEL_OBD) {
174                 index = simple_strtoul(lustre_cfg_string(lcfg, 2),
175                                        NULL, 10);
176                 CDEBUG(D_MGS, "OST index for %s is %u (%s)\n",
177                        lustre_cfg_string(lcfg, 1), index,
178                        lustre_cfg_string(lcfg, 2));
179                 cfs_set_bit(index, fsdb->fsdb_ost_index_map);
180         }
181
182         /* Figure out mdt indicies */
183         /* attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f */
184         if ((lcfg->lcfg_command == LCFG_ATTACH) &&
185             (strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_MDC_NAME) == 0)) {
186                 rc = server_name2index(lustre_cfg_string(lcfg, 0),
187                                        &index, NULL);
188                 if (rc != LDD_F_SV_TYPE_MDT) {
189                         CWARN("Unparsable MDC name %s, assuming index 0\n",
190                               lustre_cfg_string(lcfg, 0));
191                         index = 0;
192                 }
193                 rc = 0;
194                 CDEBUG(D_MGS, "MDT index is %u\n", index);
195                 cfs_set_bit(index, fsdb->fsdb_mdt_index_map);
196                 fsdb->fsdb_mdt_count ++;
197         }
198
199         /* COMPAT_146 */
200         /* figure out the old LOV name. fsdb_gen = 0 means old log */
201         /* #01 L attach 0:lov_mdsA 1:lov 2:cdbe9_lov_mdsA_dc8cf7f3bb */
202         if ((fsdb->fsdb_gen == 0) && (lcfg->lcfg_command == LCFG_ATTACH) &&
203             (strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_LOV_NAME) == 0)) {
204                 cfs_set_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags);
205                 name_destroy(&fsdb->fsdb_clilov);
206                 rc = name_create(&fsdb->fsdb_clilov,
207                                  lustre_cfg_string(lcfg, 0), "");
208                 if (rc)
209                         RETURN(rc);
210                 CDEBUG(D_MGS, "client lov name is %s\n", fsdb->fsdb_clilov);
211         }
212
213         /* figure out the old MDT lov name from the MDT uuid */
214         if ((fsdb->fsdb_gen == 0) && (lcfg->lcfg_command == LCFG_SETUP) &&
215             (strncmp(lustre_cfg_string(lcfg, 0), "MDC_", 4) == 0)) {
216                 char *ptr;
217                 cfs_set_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags);
218                 ptr = strstr(lustre_cfg_string(lcfg, 1), "_UUID");
219                 if (!ptr) {
220                         CERROR("Can't parse MDT uuid %s\n",
221                                lustre_cfg_string(lcfg, 1));
222                         RETURN(-EINVAL);
223                 }
224                 *ptr = '\0';
225                 name_destroy(&fsdb->fsdb_mdtlov);
226                 rc = name_create(&fsdb->fsdb_mdtlov,
227                                  "lov_", lustre_cfg_string(lcfg, 1));
228                 if (rc)
229                         RETURN(rc);
230                 name_destroy(&fsdb->fsdb_mdc);
231                 rc = name_create(&fsdb->fsdb_mdc,
232                                  lustre_cfg_string(lcfg, 0), "");
233                 if (rc)
234                         RETURN(rc);
235                 CDEBUG(D_MGS, "MDT lov name is %s\n", fsdb->fsdb_mdtlov);
236         }
237         /* end COMPAT_146 */
238
239         /*
240          * compat to 1.8, check osc name used by MDT0 to OSTs, bz18548.
241          */
242         if (!cfs_test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags) &&
243             lcfg->lcfg_command == LCFG_ATTACH &&
244             strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_OSC_NAME) == 0) {
245                 if (OBD_OCD_VERSION_MAJOR(d->ver) == 1 &&
246                     OBD_OCD_VERSION_MINOR(d->ver) <= 8) {
247                         CWARN("MDT using 1.8 OSC name scheme\n");
248                         cfs_set_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags);
249                 }
250         }
251
252         if (lcfg->lcfg_command == LCFG_MARKER) {
253                 struct cfg_marker *marker;
254                 marker = lustre_cfg_buf(lcfg, 1);
255
256                 d->ver = marker->cm_vers;
257
258                 /* Keep track of the latest marker step */
259                 fsdb->fsdb_gen = max(fsdb->fsdb_gen, marker->cm_step);
260         }
261
262         RETURN(rc);
263 }
264
265 /* fsdb->fsdb_mutex is already held  in mgs_find_or_make_fsdb*/
266 static int mgs_get_fsdb_from_llog(struct obd_device *obd, struct fs_db *fsdb)
267 {
268         char *logname;
269         struct llog_handle *loghandle;
270         struct lvfs_run_ctxt saved;
271         struct llog_ctxt *ctxt;
272         struct mgs_fsdb_handler_data d = { fsdb, 0 };
273         int rc, rc2;
274         ENTRY;
275
276         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
277         LASSERT(ctxt != NULL);
278         name_create(&logname, fsdb->fsdb_name, "-client");
279         cfs_mutex_lock(&fsdb->fsdb_mutex);
280         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
281         rc = llog_create(ctxt, &loghandle, NULL, logname);
282         if (rc)
283                 GOTO(out_pop, rc);
284
285         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
286         if (rc)
287                 GOTO(out_close, rc);
288
289         if (llog_get_size(loghandle) <= 1)
290                 cfs_set_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags);
291
292         rc = llog_process(loghandle, mgs_fsdb_handler, (void *) &d, NULL);
293         CDEBUG(D_INFO, "get_db = %d\n", rc);
294 out_close:
295         rc2 = llog_close(loghandle);
296         if (!rc)
297                 rc = rc2;
298 out_pop:
299         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
300         cfs_mutex_unlock(&fsdb->fsdb_mutex);
301         name_destroy(&logname);
302         llog_ctxt_put(ctxt);
303
304         RETURN(rc);
305 }
306
307 static void mgs_free_fsdb_srpc(struct fs_db *fsdb)
308 {
309         struct mgs_tgt_srpc_conf *tgtconf;
310
311         /* free target-specific rules */
312         while (fsdb->fsdb_srpc_tgt) {
313                 tgtconf = fsdb->fsdb_srpc_tgt;
314                 fsdb->fsdb_srpc_tgt = tgtconf->mtsc_next;
315
316                 LASSERT(tgtconf->mtsc_tgt);
317
318                 sptlrpc_rule_set_free(&tgtconf->mtsc_rset);
319                 OBD_FREE(tgtconf->mtsc_tgt, strlen(tgtconf->mtsc_tgt) + 1);
320                 OBD_FREE_PTR(tgtconf);
321         }
322
323         /* free general rules */
324         sptlrpc_rule_set_free(&fsdb->fsdb_srpc_gen);
325 }
326
327 struct fs_db *mgs_find_fsdb(struct obd_device *obd, char *fsname)
328 {
329         struct mgs_obd *mgs = &obd->u.mgs;
330         struct fs_db *fsdb;
331         cfs_list_t *tmp;
332
333         cfs_list_for_each(tmp, &mgs->mgs_fs_db_list) {
334                 fsdb = cfs_list_entry(tmp, struct fs_db, fsdb_list);
335                 if (strcmp(fsdb->fsdb_name, fsname) == 0)
336                         return fsdb;
337         }
338         return NULL;
339 }
340
341 /* caller must hold the mgs->mgs_fs_db_lock */
342 static struct fs_db *mgs_new_fsdb(struct obd_device *obd, char *fsname)
343 {
344         struct mgs_obd *mgs = &obd->u.mgs;
345         struct fs_db *fsdb;
346         int rc;
347         ENTRY;
348
349         if (strlen(fsname) >= sizeof(fsdb->fsdb_name)) {
350                 CERROR("fsname %s is too long\n", fsname);
351                 RETURN(NULL);
352         }
353
354         OBD_ALLOC_PTR(fsdb);
355         if (!fsdb)
356                 RETURN(NULL);
357
358         strcpy(fsdb->fsdb_name, fsname);
359         cfs_mutex_init(&fsdb->fsdb_mutex);
360         cfs_set_bit(FSDB_UDESC, &fsdb->fsdb_flags);
361
362         if (strcmp(fsname, MGSSELF_NAME) == 0) {
363                 cfs_set_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags);
364         } else {
365                 OBD_ALLOC(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
366                 OBD_ALLOC(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
367                 if (!fsdb->fsdb_ost_index_map || !fsdb->fsdb_mdt_index_map) {
368                         CERROR("No memory for index maps\n");
369                         GOTO(err, 0);
370                 }
371
372                 rc = name_create(&fsdb->fsdb_mdtlov, fsname, "-mdtlov");
373                 if (rc)
374                         GOTO(err, rc);
375                 rc = name_create(&fsdb->fsdb_mdtlmv, fsname, "-mdtlmv");
376                 if (rc)
377                         GOTO(err, rc);
378                 rc = name_create(&fsdb->fsdb_clilov, fsname, "-clilov");
379                 if (rc)
380                         GOTO(err, rc);
381                 rc = name_create(&fsdb->fsdb_clilmv, fsname, "-clilmv");
382                 if (rc)
383                         GOTO(err, rc);
384
385                 /* initialise data for NID table */
386                 mgs_ir_init_fs(obd, fsdb);
387
388                 lproc_mgs_add_live(obd, fsdb);
389         }
390
391         cfs_list_add(&fsdb->fsdb_list, &mgs->mgs_fs_db_list);
392
393         RETURN(fsdb);
394 err:
395         if (fsdb->fsdb_ost_index_map)
396                 OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
397         if (fsdb->fsdb_mdt_index_map)
398                 OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
399         name_destroy(&fsdb->fsdb_clilov);
400         name_destroy(&fsdb->fsdb_clilmv);
401         name_destroy(&fsdb->fsdb_mdtlov);
402         name_destroy(&fsdb->fsdb_mdtlmv);
403         OBD_FREE_PTR(fsdb);
404         RETURN(NULL);
405 }
406
407 static void mgs_free_fsdb(struct obd_device *obd, struct fs_db *fsdb)
408 {
409         /* wait for anyone with the sem */
410         cfs_mutex_lock(&fsdb->fsdb_mutex);
411         lproc_mgs_del_live(obd, fsdb);
412         cfs_list_del(&fsdb->fsdb_list);
413
414         /* deinitialize fsr */
415         mgs_ir_fini_fs(obd, fsdb);
416
417         if (fsdb->fsdb_ost_index_map)
418                 OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
419         if (fsdb->fsdb_mdt_index_map)
420                 OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
421         name_destroy(&fsdb->fsdb_clilov);
422         name_destroy(&fsdb->fsdb_clilmv);
423         name_destroy(&fsdb->fsdb_mdtlov);
424         name_destroy(&fsdb->fsdb_mdtlmv);
425         name_destroy(&fsdb->fsdb_mdc);
426         mgs_free_fsdb_srpc(fsdb);
427         cfs_mutex_unlock(&fsdb->fsdb_mutex);
428         OBD_FREE_PTR(fsdb);
429 }
430
431 int mgs_init_fsdb_list(struct obd_device *obd)
432 {
433         struct mgs_obd *mgs = &obd->u.mgs;
434         CFS_INIT_LIST_HEAD(&mgs->mgs_fs_db_list);
435         return 0;
436 }
437
438 int mgs_cleanup_fsdb_list(struct obd_device *obd)
439 {
440         struct mgs_obd *mgs = &obd->u.mgs;
441         struct fs_db *fsdb;
442         cfs_list_t *tmp, *tmp2;
443         cfs_mutex_lock(&mgs->mgs_mutex);
444         cfs_list_for_each_safe(tmp, tmp2, &mgs->mgs_fs_db_list) {
445                 fsdb = cfs_list_entry(tmp, struct fs_db, fsdb_list);
446                 mgs_free_fsdb(obd, fsdb);
447         }
448         cfs_mutex_unlock(&mgs->mgs_mutex);
449         return 0;
450 }
451
452 int mgs_find_or_make_fsdb(struct obd_device *obd, char *name,
453                           struct fs_db **dbh)
454 {
455         struct mgs_obd *mgs = &obd->u.mgs;
456         struct fs_db *fsdb;
457         int rc = 0;
458
459         cfs_mutex_lock(&mgs->mgs_mutex);
460         fsdb = mgs_find_fsdb(obd, name);
461         if (fsdb) {
462                 cfs_mutex_unlock(&mgs->mgs_mutex);
463                 *dbh = fsdb;
464                 return 0;
465         }
466
467         CDEBUG(D_MGS, "Creating new db\n");
468         fsdb = mgs_new_fsdb(obd, name);
469         cfs_mutex_unlock(&mgs->mgs_mutex);
470         if (!fsdb)
471                 return -ENOMEM;
472
473         if (!cfs_test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
474                 /* populate the db from the client llog */
475                 rc = mgs_get_fsdb_from_llog(obd, fsdb);
476                 if (rc) {
477                         CERROR("Can't get db from client log %d\n", rc);
478                         mgs_free_fsdb(obd, fsdb);
479                         return rc;
480                 }
481         }
482
483         /* populate srpc rules from params llog */
484         rc = mgs_get_fsdb_srpc_from_llog(obd, fsdb);
485         if (rc) {
486                 CERROR("Can't get db from params log %d\n", rc);
487                 mgs_free_fsdb(obd, fsdb);
488                 return rc;
489         }
490
491         *dbh = fsdb;
492
493         return 0;
494 }
495
496 /* 1 = index in use
497    0 = index unused
498    -1= empty client log */
499 int mgs_check_index(struct obd_device *obd, struct mgs_target_info *mti)
500 {
501         struct fs_db *fsdb;
502         void *imap;
503         int rc = 0;
504         ENTRY;
505
506         LASSERT(!(mti->mti_flags & LDD_F_NEED_INDEX));
507
508         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb);
509         if (rc) {
510                 CERROR("Can't get db for %s\n", mti->mti_fsname);
511                 RETURN(rc);
512         }
513
514         if (cfs_test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags))
515                 RETURN(-1);
516
517         if (mti->mti_flags & LDD_F_SV_TYPE_OST)
518                 imap = fsdb->fsdb_ost_index_map;
519         else if (mti->mti_flags & LDD_F_SV_TYPE_MDT)
520                 imap = fsdb->fsdb_mdt_index_map;
521         else
522                 RETURN(-EINVAL);
523
524         if (cfs_test_bit(mti->mti_stripe_index, imap))
525                 RETURN(1);
526         RETURN(0);
527 }
528
529 static __inline__ int next_index(void *index_map, int map_len)
530 {
531         int i;
532         for (i = 0; i < map_len * 8; i++)
533                  if (!cfs_test_bit(i, index_map)) {
534                          return i;
535                  }
536         CERROR("max index %d exceeded.\n", i);
537         return -1;
538 }
539
540 /* Return codes:
541         0  newly marked as in use
542         <0 err
543         +EALREADY for update of an old index */
544 static int mgs_set_index(struct obd_device *obd, struct mgs_target_info *mti)
545 {
546         struct fs_db *fsdb;
547         void *imap;
548         int rc = 0;
549         ENTRY;
550
551         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb);
552         if (rc) {
553                 CERROR("Can't get db for %s\n", mti->mti_fsname);
554                 RETURN(rc);
555         }
556
557         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
558                 imap = fsdb->fsdb_ost_index_map;
559         } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
560                 imap = fsdb->fsdb_mdt_index_map;
561                 if (fsdb->fsdb_mdt_count >= MAX_MDT_COUNT) {
562                         LCONSOLE_ERROR_MSG(0x13f, "The max mdt count"
563                                            "is %d\n", (int)MAX_MDT_COUNT);
564                         RETURN(-ERANGE);
565                 }
566         } else {
567                 RETURN(-EINVAL);
568         }
569
570         if (mti->mti_flags & LDD_F_NEED_INDEX) {
571                 rc = next_index(imap, INDEX_MAP_SIZE);
572                 if (rc == -1)
573                         RETURN(-ERANGE);
574                 mti->mti_stripe_index = rc;
575                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT)
576                         fsdb->fsdb_mdt_count ++;
577         }
578
579         if (mti->mti_stripe_index >= INDEX_MAP_SIZE * 8) {
580                 LCONSOLE_ERROR_MSG(0x13f, "Server %s requested index %d, "
581                                    "but the max index is %d.\n",
582                                    mti->mti_svname, mti->mti_stripe_index,
583                                    INDEX_MAP_SIZE * 8);
584                 RETURN(-ERANGE);
585         }
586
587         if (cfs_test_bit(mti->mti_stripe_index, imap)) {
588                 if ((mti->mti_flags & LDD_F_VIRGIN) &&
589                     !(mti->mti_flags & LDD_F_WRITECONF)) {
590                         LCONSOLE_ERROR_MSG(0x140, "Server %s requested index "
591                                            "%d, but that index is already in "
592                                            "use. Use --writeconf to force\n",
593                                            mti->mti_svname,
594                                            mti->mti_stripe_index);
595                         RETURN(-EADDRINUSE);
596                 } else {
597                         CDEBUG(D_MGS, "Server %s updating index %d\n",
598                                mti->mti_svname, mti->mti_stripe_index);
599                         RETURN(EALREADY);
600                 }
601         }
602
603         cfs_set_bit(mti->mti_stripe_index, imap);
604         cfs_clear_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags);
605         server_make_name(mti->mti_flags, mti->mti_stripe_index,
606                          mti->mti_fsname, mti->mti_svname);
607
608         CDEBUG(D_MGS, "Set index for %s to %d\n", mti->mti_svname,
609                mti->mti_stripe_index);
610
611         RETURN(0);
612 }
613
614 struct mgs_modify_lookup {
615         struct cfg_marker mml_marker;
616         int               mml_modified;
617 };
618
619 static int mgs_modify_handler(struct llog_handle *llh, struct llog_rec_hdr *rec,
620                               void *data)
621 {
622         struct mgs_modify_lookup *mml = (struct mgs_modify_lookup *)data;
623         struct cfg_marker *marker;
624         struct lustre_cfg *lcfg = (struct lustre_cfg *)(rec + 1);
625         int cfg_len = rec->lrh_len - sizeof(struct llog_rec_hdr) -
626                 sizeof(struct llog_rec_tail);
627         int rc;
628         ENTRY;
629
630         if (rec->lrh_type != OBD_CFG_REC) {
631                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
632                 RETURN(-EINVAL);
633         }
634
635         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
636         if (rc) {
637                 CERROR("Insane cfg\n");
638                 RETURN(rc);
639         }
640
641         /* We only care about markers */
642         if (lcfg->lcfg_command != LCFG_MARKER)
643                 RETURN(0);
644
645         marker = lustre_cfg_buf(lcfg, 1);
646         if ((strcmp(mml->mml_marker.cm_comment, marker->cm_comment) == 0) &&
647             (strcmp(mml->mml_marker.cm_tgtname, marker->cm_tgtname) == 0) &&
648             !(marker->cm_flags & CM_SKIP)) {
649                 /* Found a non-skipped marker match */
650                 CDEBUG(D_MGS, "Changing rec %u marker %d %x->%x: %s %s\n",
651                        rec->lrh_index, marker->cm_step,
652                        marker->cm_flags, mml->mml_marker.cm_flags,
653                        marker->cm_tgtname, marker->cm_comment);
654                 /* Overwrite the old marker llog entry */
655                 marker->cm_flags &= ~CM_EXCLUDE; /* in case we're unexcluding */
656                 marker->cm_flags |= mml->mml_marker.cm_flags;
657                 marker->cm_canceltime = mml->mml_marker.cm_canceltime;
658                 /* Header and tail are added back to lrh_len in
659                    llog_lvfs_write_rec */
660                 rec->lrh_len = cfg_len;
661                 rc = llog_write_rec(llh, rec, NULL, 0, (void *)lcfg,
662                                     rec->lrh_index);
663                 if (!rc)
664                          mml->mml_modified++;
665         }
666
667         RETURN(rc);
668 }
669
670 /* Modify an existing config log record (for CM_SKIP or CM_EXCLUDE) */
671 static int mgs_modify(struct obd_device *obd, struct fs_db *fsdb,
672                       struct mgs_target_info *mti, char *logname,
673                       char *devname, char *comment, int flags)
674 {
675         struct llog_handle *loghandle;
676         struct lvfs_run_ctxt saved;
677         struct llog_ctxt *ctxt;
678         struct mgs_modify_lookup *mml;
679         int rc, rc2;
680         ENTRY;
681
682         CDEBUG(D_MGS, "modify %s/%s/%s fl=%x\n", logname, devname, comment,
683                flags);
684
685         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
686
687         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
688         LASSERT(ctxt != NULL);
689         rc = llog_create(ctxt, &loghandle, NULL, logname);
690         if (rc)
691                 GOTO(out_pop, rc);
692
693         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
694         if (rc)
695                 GOTO(out_close, rc);
696
697         if (llog_get_size(loghandle) <= 1)
698                 GOTO(out_close, rc = 0);
699
700         OBD_ALLOC_PTR(mml);
701         if (!mml)
702                 GOTO(out_close, rc = -ENOMEM);
703         strcpy(mml->mml_marker.cm_comment, comment);
704         strcpy(mml->mml_marker.cm_tgtname, devname);
705         /* Modify mostly means cancel */
706         mml->mml_marker.cm_flags = flags;
707         mml->mml_marker.cm_canceltime = flags ? cfs_time_current_sec() : 0;
708         mml->mml_modified = 0;
709         rc = llog_process(loghandle, mgs_modify_handler, (void *)mml, NULL);
710         if (!rc && !mml->mml_modified)
711                 rc = -ENODEV;
712         OBD_FREE_PTR(mml);
713
714 out_close:
715         rc2 = llog_close(loghandle);
716         if (!rc)
717                 rc = rc2;
718 out_pop:
719         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
720         if (rc && rc != -ENODEV)
721                 CERROR("modify %s/%s failed %d\n",
722                        mti->mti_svname, comment, rc);
723         llog_ctxt_put(ctxt);
724         RETURN(rc);
725 }
726
727 /******************** config log recording functions *********************/
728
729 static int record_lcfg(struct obd_device *obd, struct llog_handle *llh,
730                          struct lustre_cfg *lcfg)
731 {
732         struct lvfs_run_ctxt   saved;
733         struct llog_rec_hdr    rec;
734         int buflen, rc;
735
736         if (!lcfg || !llh)
737                 return -ENOMEM;
738
739         LASSERT(llh->lgh_ctxt);
740
741         buflen = lustre_cfg_len(lcfg->lcfg_bufcount,
742                                 lcfg->lcfg_buflens);
743         rec.lrh_len = llog_data_len(buflen);
744         rec.lrh_type = OBD_CFG_REC;
745
746         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
747         /* idx = -1 means append */
748         rc = llog_write_rec(llh, &rec, NULL, 0, (void *)lcfg, -1);
749         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
750         if (rc)
751                 CERROR("failed %d\n", rc);
752         return rc;
753 }
754
755 static int record_base(struct obd_device *obd, struct llog_handle *llh,
756                      char *cfgname, lnet_nid_t nid, int cmd,
757                      char *s1, char *s2, char *s3, char *s4)
758 {
759         struct lustre_cfg_bufs bufs;
760         struct lustre_cfg     *lcfg;
761         int rc;
762
763         CDEBUG(D_MGS, "lcfg %s %#x %s %s %s %s\n", cfgname,
764                cmd, s1, s2, s3, s4);
765
766         lustre_cfg_bufs_reset(&bufs, cfgname);
767         if (s1)
768                 lustre_cfg_bufs_set_string(&bufs, 1, s1);
769         if (s2)
770                 lustre_cfg_bufs_set_string(&bufs, 2, s2);
771         if (s3)
772                 lustre_cfg_bufs_set_string(&bufs, 3, s3);
773         if (s4)
774                 lustre_cfg_bufs_set_string(&bufs, 4, s4);
775
776         lcfg = lustre_cfg_new(cmd, &bufs);
777         if (!lcfg)
778                 return -ENOMEM;
779         lcfg->lcfg_nid = nid;
780
781         rc = record_lcfg(obd, llh, lcfg);
782
783         lustre_cfg_free(lcfg);
784
785         if (rc) {
786                 CERROR("error %d: lcfg %s %#x %s %s %s %s\n", rc, cfgname,
787                        cmd, s1, s2, s3, s4);
788         }
789         return(rc);
790 }
791
792
793 static inline int record_add_uuid(struct obd_device *obd,
794                                   struct llog_handle *llh,
795                                   uint64_t nid, char *uuid)
796 {
797         return record_base(obd,llh,NULL,nid,LCFG_ADD_UUID,uuid,0,0,0);
798
799 }
800
801 static inline int record_add_conn(struct obd_device *obd,
802                                   struct llog_handle *llh,
803                                   char *devname,
804                                   char *uuid)
805 {
806         return record_base(obd,llh,devname,0,LCFG_ADD_CONN,uuid,0,0,0);
807 }
808
809 static inline int record_attach(struct obd_device *obd, struct llog_handle *llh,
810                                 char *devname, char *type, char *uuid)
811 {
812         return record_base(obd,llh,devname,0,LCFG_ATTACH,type,uuid,0,0);
813 }
814
815 static inline int record_setup(struct obd_device *obd, struct llog_handle *llh,
816                                char *devname,
817                                char *s1, char *s2, char *s3, char *s4)
818 {
819         return record_base(obd,llh,devname,0,LCFG_SETUP,s1,s2,s3,s4);
820 }
821
822 static int record_lov_setup(struct obd_device *obd, struct llog_handle *llh,
823                             char *devname, struct lov_desc *desc)
824 {
825         struct lustre_cfg_bufs bufs;
826         struct lustre_cfg *lcfg;
827         int rc;
828
829         lustre_cfg_bufs_reset(&bufs, devname);
830         lustre_cfg_bufs_set(&bufs, 1, desc, sizeof(*desc));
831         lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
832         if (!lcfg)
833                 return -ENOMEM;
834         rc = record_lcfg(obd, llh, lcfg);
835
836         lustre_cfg_free(lcfg);
837         return rc;
838 }
839
840 static int record_lmv_setup(struct obd_device *obd, struct llog_handle *llh,
841                             char *devname, struct lmv_desc *desc)
842 {
843         struct lustre_cfg_bufs bufs;
844         struct lustre_cfg *lcfg;
845         int rc;
846
847         lustre_cfg_bufs_reset(&bufs, devname);
848         lustre_cfg_bufs_set(&bufs, 1, desc, sizeof(*desc));
849         lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
850
851         rc = record_lcfg(obd, llh, lcfg);
852
853         lustre_cfg_free(lcfg);
854         return rc;
855 }
856
857 static inline int record_mdc_add(struct obd_device *obd,
858                                  struct llog_handle *llh,
859                                  char *logname, char *mdcuuid,
860                                  char *mdtuuid, char *index,
861                                  char *gen)
862 {
863         return record_base(obd,llh,logname,0,LCFG_ADD_MDC,
864                            mdtuuid,index,gen,mdcuuid);
865 }
866
867 static inline int record_lov_add(struct obd_device *obd,
868                                  struct llog_handle *llh,
869                                  char *lov_name, char *ost_uuid,
870                                  char *index, char *gen)
871 {
872         return record_base(obd,llh,lov_name,0,LCFG_LOV_ADD_OBD,
873                            ost_uuid,index,gen,0);
874 }
875
876 static inline int record_mount_opt(struct obd_device *obd,
877                                    struct llog_handle *llh,
878                                    char *profile, char *lov_name,
879                                    char *mdc_name)
880 {
881         return record_base(obd,llh,NULL,0,LCFG_MOUNTOPT,
882                            profile,lov_name,mdc_name,0);
883 }
884
885 static int record_marker(struct obd_device *obd, struct llog_handle *llh,
886                          struct fs_db *fsdb, __u32 flags,
887                          char *tgtname, char *comment)
888 {
889         struct cfg_marker marker;
890         struct lustre_cfg_bufs bufs;
891         struct lustre_cfg *lcfg;
892         int rc;
893
894         if (flags & CM_START)
895                 fsdb->fsdb_gen++;
896         marker.cm_step = fsdb->fsdb_gen;
897         marker.cm_flags = flags;
898         marker.cm_vers = LUSTRE_VERSION_CODE;
899         strncpy(marker.cm_tgtname, tgtname, sizeof(marker.cm_tgtname));
900         strncpy(marker.cm_comment, comment, sizeof(marker.cm_comment));
901         marker.cm_createtime = cfs_time_current_sec();
902         marker.cm_canceltime = 0;
903         lustre_cfg_bufs_reset(&bufs, NULL);
904         lustre_cfg_bufs_set(&bufs, 1, &marker, sizeof(marker));
905         lcfg = lustre_cfg_new(LCFG_MARKER, &bufs);
906         if (!lcfg)
907                 return -ENOMEM;
908         rc = record_lcfg(obd, llh, lcfg);
909
910         lustre_cfg_free(lcfg);
911         return rc;
912 }
913
914 static int record_start_log(struct obd_device *obd,
915                             struct llog_handle **llh, char *name)
916 {
917         static struct obd_uuid cfg_uuid = { .uuid = "config_uuid" };
918         struct lvfs_run_ctxt saved;
919         struct llog_ctxt *ctxt;
920         int rc = 0;
921
922         if (*llh)
923                 GOTO(out, rc = -EBUSY);
924
925         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
926         if (!ctxt)
927                 GOTO(out, rc = -ENODEV);
928
929         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
930         rc = llog_create(ctxt, llh, NULL, name);
931         if (rc == 0)
932                 llog_init_handle(*llh, LLOG_F_IS_PLAIN, &cfg_uuid);
933         else
934                 *llh = NULL;
935
936         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
937         llog_ctxt_put(ctxt);
938
939 out:
940         if (rc) {
941                 CERROR("Can't start log %s: %d\n", name, rc);
942         }
943         RETURN(rc);
944 }
945
946 static int record_end_log(struct obd_device *obd, struct llog_handle **llh)
947 {
948         struct lvfs_run_ctxt saved;
949         int rc = 0;
950
951         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
952
953         rc = llog_close(*llh);
954         *llh = NULL;
955
956         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
957         RETURN(rc);
958 }
959
960 static int mgs_log_is_empty(struct obd_device *obd, char *name)
961 {
962         struct lvfs_run_ctxt saved;
963         struct llog_handle *llh;
964         struct llog_ctxt *ctxt;
965         int rc = 0;
966
967         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
968         LASSERT(ctxt != NULL);
969         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
970         rc = llog_create(ctxt, &llh, NULL, name);
971         if (rc == 0) {
972                 llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
973                 rc = llog_get_size(llh);
974                 llog_close(llh);
975         }
976         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
977         llog_ctxt_put(ctxt);
978         /* header is record 1 */
979         return(rc <= 1);
980 }
981
982 /******************** config "macros" *********************/
983
984 /* write an lcfg directly into a log (with markers) */
985 static int mgs_write_log_direct(struct obd_device *obd, struct fs_db *fsdb,
986                                 char *logname, struct lustre_cfg *lcfg,
987                                 char *devname, char *comment)
988 {
989         struct llog_handle *llh = NULL;
990         int rc;
991         ENTRY;
992
993         if (!lcfg)
994                 RETURN(-ENOMEM);
995
996         rc = record_start_log(obd, &llh, logname);
997         if (rc)
998                 RETURN(rc);
999
1000         /* FIXME These should be a single journal transaction */
1001         rc = record_marker(obd, llh, fsdb, CM_START, devname, comment);
1002
1003         rc = record_lcfg(obd, llh, lcfg);
1004
1005         rc = record_marker(obd, llh, fsdb, CM_END, devname, comment);
1006         rc = record_end_log(obd, &llh);
1007
1008         RETURN(rc);
1009 }
1010
1011 /* write the lcfg in all logs for the given fs */
1012 int mgs_write_log_direct_all(struct obd_device *obd, struct fs_db *fsdb,
1013                              struct mgs_target_info *mti,
1014                              struct lustre_cfg *lcfg,
1015                              char *devname, char *comment)
1016 {
1017         struct mgs_obd *mgs = &obd->u.mgs;
1018         cfs_list_t dentry_list;
1019         struct l_linux_dirent *dirent, *n;
1020         char *fsname = mti->mti_fsname;
1021         char *logname;
1022         int rc = 0, len = strlen(fsname);
1023         ENTRY;
1024
1025         /* We need to set params for any future logs
1026            as well. FIXME Append this file to every new log.
1027            Actually, we should store as params (text), not llogs.  Or
1028            in a database. */
1029         name_create(&logname, fsname, "-params");
1030         if (mgs_log_is_empty(obd, logname)) {
1031                 struct llog_handle *llh = NULL;
1032                 rc = record_start_log(obd, &llh, logname);
1033                 record_end_log(obd, &llh);
1034         }
1035         name_destroy(&logname);
1036         if (rc)
1037                 RETURN(rc);
1038
1039         /* Find all the logs in the CONFIGS directory */
1040         rc = class_dentry_readdir(obd, mgs->mgs_configs_dir,
1041                                   mgs->mgs_vfsmnt, &dentry_list);
1042         if (rc) {
1043                 CERROR("Can't read %s dir\n", MOUNT_CONFIGS_DIR);
1044                 RETURN(rc);
1045         }
1046
1047         /* Could use fsdb index maps instead of directory listing */
1048         cfs_list_for_each_entry_safe(dirent, n, &dentry_list, lld_list) {
1049                 cfs_list_del(&dirent->lld_list);
1050                 /* don't write to sptlrpc rule log */
1051                 if (strncmp(fsname, dirent->lld_name, len) == 0 &&
1052                     strstr(dirent->lld_name, "-sptlrpc") == NULL) {
1053                         CDEBUG(D_MGS, "Changing log %s\n", dirent->lld_name);
1054                         /* Erase any old settings of this same parameter */
1055                         mgs_modify(obd, fsdb, mti, dirent->lld_name, devname,
1056                                    comment, CM_SKIP);
1057                         /* Write the new one */
1058                         if (lcfg) {
1059                                 rc = mgs_write_log_direct(obd, fsdb,
1060                                                           dirent->lld_name,
1061                                                           lcfg, devname,
1062                                                           comment);
1063                                 if (rc)
1064                                         CERROR("err %d writing log %s\n", rc,
1065                                                dirent->lld_name);
1066                         }
1067                 }
1068                 OBD_FREE(dirent, sizeof(*dirent));
1069         }
1070
1071         RETURN(rc);
1072 }
1073
1074 struct temp_comp
1075 {
1076         struct mgs_target_info   *comp_tmti;
1077         struct mgs_target_info   *comp_mti;
1078         struct fs_db             *comp_fsdb;
1079         struct obd_device        *comp_obd;
1080 };
1081
1082 static int mgs_write_log_mdc_to_mdt(struct obd_device *, struct fs_db *,
1083                                     struct mgs_target_info *, char *);
1084 static int mgs_write_log_osc_to_lov(struct obd_device *obd, struct fs_db *fsdb,
1085                                     struct mgs_target_info *mti,
1086                                     char *logname, char *suffix, char *lovname,
1087                                     enum lustre_sec_part sec_part, int flags);
1088 static void name_create_mdt_and_lov(char **logname, char **lovname,
1089                                     struct fs_db *fsdb, int i);
1090
1091 static int mgs_steal_llog_handler(struct llog_handle *llh,
1092                                   struct llog_rec_hdr *rec,
1093                                   void *data)
1094 {
1095         struct obd_device * obd;
1096         struct mgs_target_info *mti, *tmti;
1097         struct fs_db *fsdb;
1098         int cfg_len = rec->lrh_len;
1099         char *cfg_buf = (char*) (rec + 1);
1100         struct lustre_cfg *lcfg;
1101         int rc = 0;
1102         struct llog_handle *mdt_llh = NULL;
1103         static int got_an_osc_or_mdc = 0;
1104         /* 0: not found any osc/mdc;
1105            1: found osc;
1106            2: found mdc;
1107         */
1108         static int last_step = -1;
1109
1110         ENTRY;
1111
1112         mti = ((struct temp_comp*)data)->comp_mti;
1113         tmti = ((struct temp_comp*)data)->comp_tmti;
1114         fsdb = ((struct temp_comp*)data)->comp_fsdb;
1115         obd = ((struct temp_comp*)data)->comp_obd;
1116
1117         if (rec->lrh_type != OBD_CFG_REC) {
1118                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
1119                 RETURN(-EINVAL);
1120         }
1121
1122         rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
1123         if (rc) {
1124                 CERROR("Insane cfg\n");
1125                 RETURN(rc);
1126         }
1127
1128         lcfg = (struct lustre_cfg *)cfg_buf;
1129
1130         if (lcfg->lcfg_command == LCFG_MARKER) {
1131                 struct cfg_marker *marker;
1132                 marker = lustre_cfg_buf(lcfg, 1);
1133                 if (!strncmp(marker->cm_comment,"add osc",7) &&
1134                     (marker->cm_flags & CM_START)){
1135                         got_an_osc_or_mdc = 1;
1136                         strncpy(tmti->mti_svname, marker->cm_tgtname,
1137                                 sizeof(tmti->mti_svname));
1138                         rc = record_start_log(obd, &mdt_llh, mti->mti_svname);
1139                         rc = record_marker(obd, mdt_llh, fsdb, CM_START,
1140                                            mti->mti_svname,"add osc(copied)");
1141                         rc = record_end_log(obd, &mdt_llh);
1142                         last_step = marker->cm_step;
1143                         RETURN(rc);
1144                 }
1145                 if (!strncmp(marker->cm_comment,"add osc",7) &&
1146                     (marker->cm_flags & CM_END)){
1147                         LASSERT(last_step == marker->cm_step);
1148                         last_step = -1;
1149                         got_an_osc_or_mdc = 0;
1150                         rc = record_start_log(obd, &mdt_llh, mti->mti_svname);
1151                         rc = record_marker(obd, mdt_llh, fsdb, CM_END,
1152                                            mti->mti_svname,"add osc(copied)");
1153                         rc = record_end_log(obd, &mdt_llh);
1154                         RETURN(rc);
1155                 }
1156                 if (!strncmp(marker->cm_comment,"add mdc",7) &&
1157                     (marker->cm_flags & CM_START)){
1158                         got_an_osc_or_mdc = 2;
1159                         last_step = marker->cm_step;
1160                         memcpy(tmti->mti_svname, marker->cm_tgtname,
1161                                strlen(marker->cm_tgtname));
1162
1163                         RETURN(rc);
1164                 }
1165                 if (!strncmp(marker->cm_comment,"add mdc",7) &&
1166                     (marker->cm_flags & CM_END)){
1167                         LASSERT(last_step == marker->cm_step);
1168                         last_step = -1;
1169                         got_an_osc_or_mdc = 0;
1170                         RETURN(rc);
1171                 }
1172         }
1173
1174         if (got_an_osc_or_mdc == 0 || last_step < 0)
1175                 RETURN(rc);
1176
1177         if (lcfg->lcfg_command == LCFG_ADD_UUID) {
1178                 uint64_t nodenid;
1179                 nodenid = lcfg->lcfg_nid;
1180
1181                 tmti->mti_nids[tmti->mti_nid_count] = nodenid;
1182                 tmti->mti_nid_count++;
1183
1184                 RETURN(rc);
1185         }
1186
1187         if (lcfg->lcfg_command == LCFG_SETUP) {
1188                 char *target;
1189
1190                 target = lustre_cfg_string(lcfg, 1);
1191                 memcpy(tmti->mti_uuid, target, strlen(target));
1192                 RETURN(rc);
1193         }
1194
1195         /* ignore client side sptlrpc_conf_log */
1196         if (lcfg->lcfg_command == LCFG_SPTLRPC_CONF)
1197                 RETURN(rc);
1198
1199         if (lcfg->lcfg_command == LCFG_ADD_MDC) {
1200                 int index;
1201
1202                 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1)
1203                         RETURN (-EINVAL);
1204
1205                 memcpy(tmti->mti_fsname, mti->mti_fsname,
1206                        strlen(mti->mti_fsname));
1207                 tmti->mti_stripe_index = index;
1208
1209                 mgs_write_log_mdc_to_mdt(obd, fsdb, tmti, mti->mti_svname);
1210                 memset(tmti, 0, sizeof(*tmti));
1211                 RETURN(rc);
1212         }
1213
1214         if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD) {
1215                 int index;
1216                 char mdt_index[9];
1217                 char *logname, *lovname;
1218
1219                 name_create_mdt_and_lov(&logname, &lovname, fsdb,
1220                                         mti->mti_stripe_index);
1221                 sprintf(mdt_index, "-MDT%04x", mti->mti_stripe_index);
1222
1223                 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1) {
1224                         name_destroy(&logname);
1225                         name_destroy(&lovname);
1226                         RETURN(-EINVAL);
1227                 }
1228
1229                 tmti->mti_stripe_index = index;
1230                 mgs_write_log_osc_to_lov(obd, fsdb, tmti, logname,
1231                                          mdt_index, lovname,
1232                                          LUSTRE_SP_MDT, 0);
1233                 name_destroy(&logname);
1234                 name_destroy(&lovname);
1235                 RETURN(rc);
1236         }
1237         RETURN(rc);
1238 }
1239
1240 /* fsdb->fsdb_mutex is already held  in mgs_write_log_target*/
1241 /* stealed from mgs_get_fsdb_from_llog*/
1242 static int mgs_steal_llog_for_mdt_from_client(struct obd_device *obd,
1243                                               char *client_name,
1244                                               struct temp_comp* comp)
1245 {
1246         struct llog_handle *loghandle;
1247         struct lvfs_run_ctxt saved;
1248         struct mgs_target_info *tmti;
1249         struct llog_ctxt *ctxt;
1250         int rc, rc2;
1251         ENTRY;
1252
1253         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
1254         LASSERT(ctxt != NULL);
1255
1256         OBD_ALLOC_PTR(tmti);
1257         if (tmti == NULL)
1258                 RETURN(-ENOMEM);
1259
1260         comp->comp_tmti = tmti;
1261         comp->comp_obd = obd;
1262
1263         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
1264
1265         rc = llog_create(ctxt, &loghandle, NULL, client_name);
1266         if (rc)
1267                 GOTO(out_pop, rc);
1268
1269         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
1270         if (rc)
1271                 GOTO(out_close, rc);
1272
1273         rc = llog_process(loghandle, mgs_steal_llog_handler, (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;
2012         char sep;
2013         int cmd, val;
2014         int rc;
2015
2016         if (class_match_param(ptr, PARAM_TIMEOUT, &tmp) == 0)
2017                 cmd = LCFG_SET_TIMEOUT;
2018         else if (class_match_param(ptr, PARAM_LDLM_TIMEOUT, &tmp) == 0)
2019                 cmd = LCFG_SET_LDLM_TIMEOUT;
2020         /* Check for known params here so we can return error to lctl */
2021         else if ((class_match_param(ptr, PARAM_AT_MIN, &tmp) == 0)
2022                  || (class_match_param(ptr, PARAM_AT_MAX, &tmp) == 0)
2023                  || (class_match_param(ptr, PARAM_AT_EXTRA, &tmp) == 0)
2024                  || (class_match_param(ptr, PARAM_AT_EARLY_MARGIN, &tmp) == 0)
2025                  || (class_match_param(ptr, PARAM_AT_HISTORY, &tmp) == 0))
2026                 cmd = LCFG_PARAM;
2027         else
2028                 return -EINVAL;
2029
2030         /* separate the value */
2031         val = simple_strtoul(tmp, NULL, 0);
2032         if (*tmp == '\0')
2033                 CDEBUG(D_MGS, "global '%s' removed\n", sys);
2034         else
2035                 CDEBUG(D_MGS, "global '%s' val=%d\n", sys, val);
2036
2037         lustre_cfg_bufs_reset(&bufs, NULL);
2038         lustre_cfg_bufs_set_string(&bufs, 1, sys);
2039         lcfg = lustre_cfg_new(cmd, &bufs);
2040         lcfg->lcfg_num = val;
2041         /* truncate the comment to the parameter name */
2042         ptr = tmp - 1;
2043         sep = *ptr;
2044         *ptr = '\0';
2045         /* modify all servers and clients */
2046         rc = mgs_write_log_direct_all(obd, fsdb, mti,
2047                                       *tmp == '\0' ? NULL : lcfg,
2048                                       mti->mti_fsname, sys);
2049         *ptr = sep;
2050         lustre_cfg_free(lcfg);
2051         return rc;
2052 }
2053
2054 static int mgs_srpc_set_param_disk(struct obd_device *obd,
2055                                    struct fs_db *fsdb,
2056                                    struct mgs_target_info *mti,
2057                                    char *param)
2058 {
2059         struct llog_handle     *llh = NULL;
2060         char                   *logname;
2061         char                   *comment, *ptr;
2062         struct lustre_cfg_bufs  bufs;
2063         struct lustre_cfg      *lcfg;
2064         int                     rc, len;
2065         ENTRY;
2066
2067         /* get comment */
2068         ptr = strchr(param, '=');
2069         LASSERT(ptr);
2070         len = ptr - param;
2071
2072         OBD_ALLOC(comment, len + 1);
2073         if (comment == NULL)
2074                 RETURN(-ENOMEM);
2075         strncpy(comment, param, len);
2076         comment[len] = '\0';
2077
2078         /* prepare lcfg */
2079         lustre_cfg_bufs_reset(&bufs, mti->mti_svname);
2080         lustre_cfg_bufs_set_string(&bufs, 1, param);
2081         lcfg = lustre_cfg_new(LCFG_SPTLRPC_CONF, &bufs);
2082         if (lcfg == NULL)
2083                 GOTO(out_comment, rc = -ENOMEM);
2084
2085         /* construct log name */
2086         rc = name_create(&logname, mti->mti_fsname, "-sptlrpc");
2087         if (rc)
2088                 GOTO(out_lcfg, rc);
2089
2090         if (mgs_log_is_empty(obd, logname)) {
2091                 rc = record_start_log(obd, &llh, logname);
2092                 record_end_log(obd, &llh);
2093                 if (rc)
2094                         GOTO(out, rc);
2095         }
2096
2097         /* obsolete old one */
2098         mgs_modify(obd, fsdb, mti, logname, mti->mti_svname, comment, CM_SKIP);
2099
2100         /* write the new one */
2101         rc = mgs_write_log_direct(obd, fsdb, logname, lcfg,
2102                                   mti->mti_svname, comment);
2103         if (rc)
2104                 CERROR("err %d writing log %s\n", rc, logname);
2105
2106 out:
2107         name_destroy(&logname);
2108 out_lcfg:
2109         lustre_cfg_free(lcfg);
2110 out_comment:
2111         OBD_FREE(comment, len + 1);
2112         RETURN(rc);
2113 }
2114
2115 static int mgs_srpc_set_param_udesc_mem(struct fs_db *fsdb,
2116                                         char *param)
2117 {
2118         char    *ptr;
2119
2120         /* disable the adjustable udesc parameter for now, i.e. use default
2121          * setting that client always ship udesc to MDT if possible. to enable
2122          * it simply remove the following line */
2123         goto error_out;
2124
2125         ptr = strchr(param, '=');
2126         if (ptr == NULL)
2127                 goto error_out;
2128         *ptr++ = '\0';
2129
2130         if (strcmp(param, PARAM_SRPC_UDESC))
2131                 goto error_out;
2132
2133         if (strcmp(ptr, "yes") == 0) {
2134                 cfs_set_bit(FSDB_UDESC, &fsdb->fsdb_flags);
2135                 CWARN("Enable user descriptor shipping from client to MDT\n");
2136         } else if (strcmp(ptr, "no") == 0) {
2137                 cfs_clear_bit(FSDB_UDESC, &fsdb->fsdb_flags);
2138                 CWARN("Disable user descriptor shipping from client to MDT\n");
2139         } else {
2140                 *(ptr - 1) = '=';
2141                 goto error_out;
2142         }
2143         return 0;
2144
2145 error_out:
2146         CERROR("Invalid param: %s\n", param);
2147         return -EINVAL;
2148 }
2149
2150 static int mgs_srpc_set_param_mem(struct fs_db *fsdb,
2151                                   const char *svname,
2152                                   char *param)
2153 {
2154         struct sptlrpc_rule      rule;
2155         struct sptlrpc_rule_set *rset;
2156         int                      rc;
2157         ENTRY;
2158
2159         if (strncmp(param, PARAM_SRPC, sizeof(PARAM_SRPC) - 1) != 0) {
2160                 CERROR("Invalid sptlrpc parameter: %s\n", param);
2161                 RETURN(-EINVAL);
2162         }
2163
2164         if (strncmp(param, PARAM_SRPC_UDESC,
2165                     sizeof(PARAM_SRPC_UDESC) - 1) == 0) {
2166                 RETURN(mgs_srpc_set_param_udesc_mem(fsdb, param));
2167         }
2168
2169         if (strncmp(param, PARAM_SRPC_FLVR, sizeof(PARAM_SRPC_FLVR) - 1) != 0) {
2170                 CERROR("Invalid sptlrpc flavor parameter: %s\n", param);
2171                 RETURN(-EINVAL);
2172         }
2173
2174         param += sizeof(PARAM_SRPC_FLVR) - 1;
2175
2176         rc = sptlrpc_parse_rule(param, &rule);
2177         if (rc)
2178                 RETURN(rc);
2179
2180         /* mgs rules implies must be mgc->mgs */
2181         if (cfs_test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
2182                 if ((rule.sr_from != LUSTRE_SP_MGC &&
2183                      rule.sr_from != LUSTRE_SP_ANY) ||
2184                     (rule.sr_to != LUSTRE_SP_MGS &&
2185                      rule.sr_to != LUSTRE_SP_ANY))
2186                         RETURN(-EINVAL);
2187         }
2188
2189         /* preapre room for this coming rule. svcname format should be:
2190          * - fsname: general rule
2191          * - fsname-tgtname: target-specific rule
2192          */
2193         if (strchr(svname, '-')) {
2194                 struct mgs_tgt_srpc_conf *tgtconf;
2195                 int                       found = 0;
2196
2197                 for (tgtconf = fsdb->fsdb_srpc_tgt; tgtconf != NULL;
2198                      tgtconf = tgtconf->mtsc_next) {
2199                         if (!strcmp(tgtconf->mtsc_tgt, svname)) {
2200                                 found = 1;
2201                                 break;
2202                         }
2203                 }
2204
2205                 if (!found) {
2206                         int name_len;
2207
2208                         OBD_ALLOC_PTR(tgtconf);
2209                         if (tgtconf == NULL)
2210                                 RETURN(-ENOMEM);
2211
2212                         name_len = strlen(svname);
2213
2214                         OBD_ALLOC(tgtconf->mtsc_tgt, name_len + 1);
2215                         if (tgtconf->mtsc_tgt == NULL) {
2216                                 OBD_FREE_PTR(tgtconf);
2217                                 RETURN(-ENOMEM);
2218                         }
2219                         memcpy(tgtconf->mtsc_tgt, svname, name_len);
2220
2221                         tgtconf->mtsc_next = fsdb->fsdb_srpc_tgt;
2222                         fsdb->fsdb_srpc_tgt = tgtconf;
2223                 }
2224
2225                 rset = &tgtconf->mtsc_rset;
2226         } else {
2227                 rset = &fsdb->fsdb_srpc_gen;
2228         }
2229
2230         rc = sptlrpc_rule_set_merge(rset, &rule);
2231
2232         RETURN(rc);
2233 }
2234
2235 static int mgs_srpc_set_param(struct obd_device *obd,
2236                               struct fs_db *fsdb,
2237                               struct mgs_target_info *mti,
2238                               char *param)
2239 {
2240         char                   *copy;
2241         int                     rc, copy_size;
2242         ENTRY;
2243
2244 #ifndef HAVE_GSS
2245         RETURN(-EINVAL);
2246 #endif
2247         /* keep a copy of original param, which could be destroied
2248          * during parsing */
2249         copy_size = strlen(param) + 1;
2250         OBD_ALLOC(copy, copy_size);
2251         if (copy == NULL)
2252                 return -ENOMEM;
2253         memcpy(copy, param, copy_size);
2254
2255         rc = mgs_srpc_set_param_mem(fsdb, mti->mti_svname, param);
2256         if (rc)
2257                 goto out_free;
2258
2259         /* previous steps guaranteed the syntax is correct */
2260         rc = mgs_srpc_set_param_disk(obd, fsdb, mti, copy);
2261         if (rc)
2262                 goto out_free;
2263
2264         if (cfs_test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
2265                 /*
2266                  * for mgs rules, make them effective immediately.
2267                  */
2268                 LASSERT(fsdb->fsdb_srpc_tgt == NULL);
2269                 sptlrpc_target_update_exp_flavor(obd, &fsdb->fsdb_srpc_gen);
2270         }
2271
2272 out_free:
2273         OBD_FREE(copy, copy_size);
2274         RETURN(rc);
2275 }
2276
2277 struct mgs_srpc_read_data {
2278         struct fs_db   *msrd_fsdb;
2279         int             msrd_skip;
2280 };
2281
2282 static int mgs_srpc_read_handler(struct llog_handle *llh,
2283                                  struct llog_rec_hdr *rec,
2284                                  void *data)
2285 {
2286         struct mgs_srpc_read_data *msrd = (struct mgs_srpc_read_data *) data;
2287         struct cfg_marker         *marker;
2288         struct lustre_cfg         *lcfg = (struct lustre_cfg *)(rec + 1);
2289         char                      *svname, *param;
2290         int                        cfg_len, rc;
2291         ENTRY;
2292
2293         if (rec->lrh_type != OBD_CFG_REC) {
2294                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
2295                 RETURN(-EINVAL);
2296         }
2297
2298         cfg_len = rec->lrh_len - sizeof(struct llog_rec_hdr) -
2299                   sizeof(struct llog_rec_tail);
2300
2301         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
2302         if (rc) {
2303                 CERROR("Insane cfg\n");
2304                 RETURN(rc);
2305         }
2306
2307         if (lcfg->lcfg_command == LCFG_MARKER) {
2308                 marker = lustre_cfg_buf(lcfg, 1);
2309
2310                 if (marker->cm_flags & CM_START &&
2311                     marker->cm_flags & CM_SKIP)
2312                         msrd->msrd_skip = 1;
2313                 if (marker->cm_flags & CM_END)
2314                         msrd->msrd_skip = 0;
2315
2316                 RETURN(0);
2317         }
2318
2319         if (msrd->msrd_skip)
2320                 RETURN(0);
2321
2322         if (lcfg->lcfg_command != LCFG_SPTLRPC_CONF) {
2323                 CERROR("invalid command (%x)\n", lcfg->lcfg_command);
2324                 RETURN(0);
2325         }
2326
2327         svname = lustre_cfg_string(lcfg, 0);
2328         if (svname == NULL) {
2329                 CERROR("svname is empty\n");
2330                 RETURN(0);
2331         }
2332
2333         param = lustre_cfg_string(lcfg, 1);
2334         if (param == NULL) {
2335                 CERROR("param is empty\n");
2336                 RETURN(0);
2337         }
2338
2339         rc = mgs_srpc_set_param_mem(msrd->msrd_fsdb, svname, param);
2340         if (rc)
2341                 CERROR("read sptlrpc record error (%d): %s\n", rc, param);
2342
2343         RETURN(0);
2344 }
2345
2346 int mgs_get_fsdb_srpc_from_llog(struct obd_device *obd,
2347                                 struct fs_db *fsdb)
2348 {
2349         struct llog_handle        *llh = NULL;
2350         struct lvfs_run_ctxt       saved;
2351         struct llog_ctxt          *ctxt;
2352         char                      *logname;
2353         struct mgs_srpc_read_data  msrd;
2354         int                        rc;
2355         ENTRY;
2356
2357         /* construct log name */
2358         rc = name_create(&logname, fsdb->fsdb_name, "-sptlrpc");
2359         if (rc)
2360                 RETURN(rc);
2361
2362         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
2363         LASSERT(ctxt != NULL);
2364
2365         if (mgs_log_is_empty(obd, logname))
2366                 GOTO(out, rc = 0);
2367
2368         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2369
2370         rc = llog_create(ctxt, &llh, NULL, logname);
2371         if (rc)
2372                 GOTO(out_pop, rc);
2373
2374         rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
2375         if (rc)
2376                 GOTO(out_close, rc);
2377
2378         if (llog_get_size(llh) <= 1)
2379                 GOTO(out_close, rc = 0);
2380
2381         msrd.msrd_fsdb = fsdb;
2382         msrd.msrd_skip = 0;
2383
2384         rc = llog_process(llh, mgs_srpc_read_handler, (void *) &msrd, NULL);
2385
2386 out_close:
2387         llog_close(llh);
2388 out_pop:
2389         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2390 out:
2391         llog_ctxt_put(ctxt);
2392         name_destroy(&logname);
2393
2394         if (rc)
2395                 CERROR("failed to read sptlrpc config database: %d\n", rc);
2396         RETURN(rc);
2397 }
2398
2399 /* Permanent settings of all parameters by writing into the appropriate
2400  * configuration logs.
2401  * A parameter with null value ("<param>='\0'") means to erase it out of
2402  * the logs.
2403  */
2404 static int mgs_write_log_param(struct obd_device *obd, struct fs_db *fsdb,
2405                                struct mgs_target_info *mti, char *ptr)
2406 {
2407         struct lustre_cfg_bufs bufs;
2408         char *logname;
2409         char *tmp;
2410         int rc = 0, rc2 = 0;
2411         ENTRY;
2412
2413         /* For various parameter settings, we have to figure out which logs
2414            care about them (e.g. both mdt and client for lov settings) */
2415         CDEBUG(D_MGS, "next param '%s'\n", ptr);
2416
2417         /* The params are stored in MOUNT_DATA_FILE and modified via
2418            tunefs.lustre, or set using lctl conf_param */
2419
2420         /* Processed in lustre_start_mgc */
2421         if (class_match_param(ptr, PARAM_MGSNODE, NULL) == 0)
2422                 GOTO(end, rc);
2423
2424         /* Processed in ost/mdt */
2425         if (class_match_param(ptr, PARAM_NETWORK, NULL) == 0)
2426                 GOTO(end, rc);
2427
2428         /* Processed in mgs_write_log_ost */
2429         if (class_match_param(ptr, PARAM_FAILMODE, NULL) == 0) {
2430                 if (mti->mti_flags & LDD_F_PARAM) {
2431                         LCONSOLE_ERROR_MSG(0x169, "%s can only be "
2432                                            "changed with tunefs.lustre"
2433                                            "and --writeconf\n", ptr);
2434                         rc = -EPERM;
2435                 }
2436                 GOTO(end, rc);
2437         }
2438
2439         if (class_match_param(ptr, PARAM_SRPC, NULL) == 0) {
2440                 rc = mgs_srpc_set_param(obd, fsdb, mti, ptr);
2441                 GOTO(end, rc);
2442         }
2443
2444         if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
2445                 /* Add a failover nidlist */
2446                 rc = 0;
2447                 /* We already processed failovers params for new
2448                    targets in mgs_write_log_target */
2449                 if (mti->mti_flags & LDD_F_PARAM) {
2450                         CDEBUG(D_MGS, "Adding failnode\n");
2451                         rc = mgs_write_log_add_failnid(obd, fsdb, mti);
2452                 }
2453                 GOTO(end, rc);
2454         }
2455
2456         if (class_match_param(ptr, PARAM_SYS, &tmp) == 0) {
2457                 rc = mgs_write_log_sys(obd, fsdb, mti, ptr, tmp);
2458                 GOTO(end, rc);
2459         }
2460
2461         if (class_match_param(ptr, PARAM_OSC""PARAM_ACTIVE, &tmp) == 0) {
2462                 /* active=0 means off, anything else means on */
2463                 int flag = (*tmp == '0') ? CM_EXCLUDE : 0;
2464                 int i;
2465
2466                 if (!(mti->mti_flags & LDD_F_SV_TYPE_OST)) {
2467                         LCONSOLE_ERROR_MSG(0x144, "%s: Only OSCs can "
2468                                            "be (de)activated.\n",
2469                                            mti->mti_svname);
2470                         GOTO(end, rc = -EINVAL);
2471                 }
2472                 LCONSOLE_WARN("Permanently %sactivating %s\n",
2473                               flag ? "de": "re", mti->mti_svname);
2474                 /* Modify clilov */
2475                 name_create(&logname, mti->mti_fsname, "-client");
2476                 rc = mgs_modify(obd, fsdb, mti, logname,
2477                                 mti->mti_svname, "add osc", flag);
2478                 name_destroy(&logname);
2479                 if (rc)
2480                         goto active_err;
2481                 /* Modify mdtlov */
2482                 /* Add to all MDT logs for CMD */
2483                 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
2484                         if (!cfs_test_bit(i, fsdb->fsdb_mdt_index_map))
2485                                 continue;
2486                         name_create_mdt(&logname, mti->mti_fsname, i);
2487                         rc = mgs_modify(obd, fsdb, mti, logname,
2488                                         mti->mti_svname, "add osc", flag);
2489                         name_destroy(&logname);
2490                         if (rc)
2491                                 goto active_err;
2492                 }
2493         active_err:
2494                 if (rc) {
2495                         LCONSOLE_ERROR_MSG(0x145, "Couldn't find %s in"
2496                                            "log (%d). No permanent "
2497                                            "changes were made to the "
2498                                            "config log.\n",
2499                                            mti->mti_svname, rc);
2500                         if (cfs_test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags))
2501                                 LCONSOLE_ERROR_MSG(0x146, "This may be"
2502                                                    " because the log"
2503                                                    "is in the old 1.4"
2504                                                    "style. Consider "
2505                                                    " --writeconf to "
2506                                                    "update the logs.\n");
2507                         GOTO(end, rc);
2508                 }
2509                 /* Fall through to osc proc for deactivating live OSC
2510                    on running MDT / clients. */
2511         }
2512         /* Below here, let obd's XXX_process_config methods handle it */
2513
2514         /* All lov. in proc */
2515         if (class_match_param(ptr, PARAM_LOV, NULL) == 0) {
2516                 char *mdtlovname;
2517
2518                 CDEBUG(D_MGS, "lov param %s\n", ptr);
2519                 if (!(mti->mti_flags & LDD_F_SV_TYPE_MDT)) {
2520                         LCONSOLE_ERROR_MSG(0x147, "LOV params must be "
2521                                            "set on the MDT, not %s. "
2522                                            "Ignoring.\n",
2523                                            mti->mti_svname);
2524                         GOTO(end, rc = 0);
2525                 }
2526
2527                 /* Modify mdtlov */
2528                 if (mgs_log_is_empty(obd, mti->mti_svname))
2529                         GOTO(end, rc = -ENODEV);
2530
2531                 name_create_mdt_and_lov(&logname, &mdtlovname, fsdb,
2532                                         mti->mti_stripe_index);
2533                 rc = mgs_wlp_lcfg(obd, fsdb, mti, mti->mti_svname,
2534                                   &bufs, mdtlovname, ptr);
2535                 name_destroy(&logname);
2536                 name_destroy(&mdtlovname);
2537                 if (rc)
2538                         GOTO(end, rc);
2539
2540                 /* Modify clilov */
2541                 name_create(&logname, mti->mti_fsname, "-client");
2542                 rc = mgs_wlp_lcfg(obd, fsdb, mti, logname, &bufs,
2543                                   fsdb->fsdb_clilov, ptr);
2544                 name_destroy(&logname);
2545                 GOTO(end, rc);
2546         }
2547
2548         /* All osc., mdc., llite. params in proc */
2549         if ((class_match_param(ptr, PARAM_OSC, NULL) == 0) ||
2550             (class_match_param(ptr, PARAM_MDC, NULL) == 0) ||
2551             (class_match_param(ptr, PARAM_LLITE, NULL) == 0)) {
2552                 char *cname;
2553                 if (memcmp(ptr, PARAM_LLITE, strlen(PARAM_LLITE)) == 0) {
2554                         name_create(&cname, mti->mti_fsname, "-client");
2555                         /* Add the client type to match the obdname in
2556                            class_config_llog_handler */
2557                 } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
2558                         /* COMPAT_146 */
2559                         if (fsdb->fsdb_mdc)
2560                                 name_create(&cname, fsdb->fsdb_mdc, "");
2561                         else
2562                                 name_create(&cname, mti->mti_svname,
2563                                             "-mdc");
2564                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
2565                         /* COMPAT_146 */
2566                         if (cfs_test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
2567                                 LCONSOLE_ERROR_MSG(0x148, "Upgraded "
2568                                                    "client logs for %s"
2569                                                    " cannot be "
2570                                                    "modified. Consider"
2571                                                    " updating the "
2572                                                    "configuration with"
2573                                                    " --writeconf\n",
2574                                                    mti->mti_svname);
2575                                 /* We don't know the names of all the
2576                                    old oscs*/
2577                                 GOTO(end, rc = -EINVAL);
2578                         }
2579                         name_create(&cname, mti->mti_svname, "-osc");
2580                 } else {
2581                         GOTO(end, rc = -EINVAL);
2582                 }
2583
2584                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
2585
2586                 /* Modify client */
2587                 name_create(&logname, mti->mti_fsname, "-client");
2588                 rc = mgs_wlp_lcfg(obd, fsdb, mti, logname, &bufs,
2589                                   cname, ptr);
2590
2591                 /* osc params affect the MDT as well */
2592                 if (!rc && (mti->mti_flags & LDD_F_SV_TYPE_OST)) {
2593                         int i;
2594
2595                         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
2596                                 if (!cfs_test_bit(i, fsdb->fsdb_mdt_index_map))
2597                                         continue;
2598                                 name_destroy(&cname);
2599                                 name_create_mdt_osc(&cname, mti->mti_svname,
2600                                                     fsdb, i);
2601                                 name_destroy(&logname);
2602                                 name_create_mdt(&logname, mti->mti_fsname, i);
2603                                 if (!mgs_log_is_empty(obd, logname))
2604                                         rc = mgs_wlp_lcfg(obd, fsdb,mti,logname,
2605                                                           &bufs, cname, ptr);
2606                                 if (rc)
2607                                         break;
2608                         }
2609                 }
2610                 name_destroy(&logname);
2611                 name_destroy(&cname);
2612                 GOTO(end, rc);
2613         }
2614
2615         /* All mdt. params in proc */
2616         if (class_match_param(ptr, PARAM_MDT, NULL) == 0) {
2617                 int i;
2618                 __u32 idx;
2619
2620                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
2621                 if (strncmp(mti->mti_svname, mti->mti_fsname,
2622                             MTI_NAME_MAXLEN) == 0)
2623                         /* device is unspecified completely? */
2624                         rc = LDD_F_SV_TYPE_MDT | LDD_F_SV_ALL;
2625                 else
2626                         rc = server_name2index(mti->mti_svname, &idx, NULL);
2627                 if (rc < 0)
2628                         goto active_err;
2629                 if ((rc & LDD_F_SV_TYPE_MDT) == 0)
2630                         goto active_err;
2631                 if (rc & LDD_F_SV_ALL) {
2632                         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
2633                                 if (!cfs_test_bit(i,
2634                                                   fsdb->fsdb_mdt_index_map))
2635                                         continue;
2636                                 name_create_mdt(&logname, mti->mti_fsname, i);
2637                                 rc = mgs_wlp_lcfg(obd, fsdb, mti,
2638                                                   logname, &bufs,
2639                                                   logname, ptr);
2640                                 name_destroy(&logname);
2641                                 if (rc)
2642                                         goto active_err;
2643                         }
2644                 } else {
2645                         rc = mgs_wlp_lcfg(obd, fsdb, mti,
2646                                           mti->mti_svname, &bufs,
2647                                           mti->mti_svname, ptr);
2648                         if (rc)
2649                                 goto active_err;
2650                 }
2651                 GOTO(end, rc);
2652         }
2653
2654         /* All mdd., ost. params in proc */
2655         if ((class_match_param(ptr, PARAM_MDD, NULL) == 0) ||
2656             (class_match_param(ptr, PARAM_OST, NULL) == 0)) {
2657                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
2658                 if (mgs_log_is_empty(obd, mti->mti_svname))
2659                         GOTO(end, rc = -ENODEV);
2660
2661                 rc = mgs_wlp_lcfg(obd, fsdb, mti, mti->mti_svname,
2662                                   &bufs, mti->mti_svname, ptr);
2663                 GOTO(end, rc);
2664         }
2665
2666         LCONSOLE_WARN("Ignoring unrecognized param '%s'\n", ptr);
2667         rc2 = -ENOSYS;
2668
2669 end:
2670         if (rc)
2671                 CERROR("err %d on param '%s'\n", rc, ptr);
2672
2673         RETURN(rc ?: rc2);
2674 }
2675
2676 /* Not implementing automatic failover nid addition at this time. */
2677 int mgs_check_failnid(struct obd_device *obd, struct mgs_target_info *mti)
2678 {
2679 #if 0
2680         struct fs_db *fsdb;
2681         int rc;
2682         ENTRY;
2683
2684         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb);
2685         if (rc)
2686                 RETURN(rc);
2687
2688         if (mgs_log_is_empty(obd, mti->mti_svname))
2689                 /* should never happen */
2690                 RETURN(-ENOENT);
2691
2692         CDEBUG(D_MGS, "Checking for new failnids for %s\n", mti->mti_svname);
2693
2694         /* FIXME We can just check mti->params to see if we're already in
2695            the failover list.  Modify mti->params for rewriting back at
2696            server_register_target(). */
2697
2698         cfs_mutex_lock(&fsdb->fsdb_mutex);
2699         rc = mgs_write_log_add_failnid(obd, fsdb, mti);
2700         cfs_mutex_unlock(&fsdb->fsdb_mutex);
2701
2702         RETURN(rc);
2703 #endif
2704         return 0;
2705 }
2706
2707 int mgs_write_log_target(struct obd_device *obd,
2708                          struct mgs_target_info *mti,
2709                          struct fs_db *fsdb)
2710 {
2711         int rc = -EINVAL;
2712         char *buf, *params;
2713         ENTRY;
2714
2715         /* set/check the new target index */
2716         rc = mgs_set_index(obd, mti);
2717         if (rc < 0) {
2718                 CERROR("Can't get index (%d)\n", rc);
2719                 RETURN(rc);
2720         }
2721
2722         /* COMPAT_146 */
2723         if (mti->mti_flags & LDD_F_UPGRADE14) {
2724                 if (rc == EALREADY) {
2725                         LCONSOLE_INFO("Found index %d for %s 1.4 log, "
2726                                       "upgrading\n", mti->mti_stripe_index,
2727                                       mti->mti_svname);
2728                 } else {
2729                         LCONSOLE_ERROR_MSG(0x149, "Failed to find %s in the old"
2730                                            " client log. Apparently it is not "
2731                                            "part of this filesystem, or the old"
2732                                            " log is wrong.\nUse 'writeconf' on "
2733                                            "the MDT to force log regeneration."
2734                                            "\n", mti->mti_svname);
2735                         /* Not in client log?  Upgrade anyhow...*/
2736                         /* Argument against upgrading: reformat MDT,
2737                            upgrade OST, then OST will start but will be SKIPped
2738                            in client logs.  Maybe error now is better. */
2739                         /* RETURN(-EINVAL); */
2740                 }
2741                 /* end COMPAT_146 */
2742         } else {
2743                 if (rc == EALREADY) {
2744                         LCONSOLE_WARN("Found index %d for %s, updating log\n",
2745                                       mti->mti_stripe_index, mti->mti_svname);
2746                         /* We would like to mark old log sections as invalid
2747                            and add new log sections in the client and mdt logs.
2748                            But if we add new sections, then live clients will
2749                            get repeat setup instructions for already running
2750                            osc's. So don't update the client/mdt logs. */
2751                         mti->mti_flags &= ~LDD_F_UPDATE;
2752                 }
2753         }
2754
2755         cfs_mutex_lock(&fsdb->fsdb_mutex);
2756
2757         if (mti->mti_flags &
2758             (LDD_F_VIRGIN | LDD_F_UPGRADE14 | LDD_F_WRITECONF)) {
2759                 /* Generate a log from scratch */
2760                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
2761                         rc = mgs_write_log_mdt(obd, fsdb, mti);
2762                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
2763                         rc = mgs_write_log_ost(obd, fsdb, mti);
2764                 } else {
2765                         CERROR("Unknown target type %#x, can't create log for "
2766                                "%s\n", mti->mti_flags, mti->mti_svname);
2767                 }
2768                 if (rc) {
2769                         CERROR("Can't write logs for %s (%d)\n",
2770                                mti->mti_svname, rc);
2771                         GOTO(out_up, rc);
2772                 }
2773         } else {
2774                 /* Just update the params from tunefs in mgs_write_log_params */
2775                 CDEBUG(D_MGS, "Update params for %s\n", mti->mti_svname);
2776                 mti->mti_flags |= LDD_F_PARAM;
2777         }
2778
2779         /* allocate temporary buffer, where class_get_next_param will
2780            make copy of a current  parameter */
2781         OBD_ALLOC(buf, strlen(mti->mti_params) + 1);
2782         if (buf == NULL)
2783                 GOTO(out_up, rc = -ENOMEM);
2784         params = mti->mti_params;
2785         while (params != NULL) {
2786                 rc = class_get_next_param(&params, buf);
2787                 if (rc) {
2788                         if (rc == 1)
2789                                 /* there is no next parameter, that is
2790                                    not an error */
2791                                 rc = 0;
2792                         break;
2793                 }
2794                 CDEBUG(D_MGS, "remaining string: '%s', param: '%s'\n",
2795                        params, buf);
2796                 rc = mgs_write_log_param(obd, fsdb, mti, buf);
2797                 if (rc)
2798                         break;
2799         }
2800
2801         OBD_FREE(buf, strlen(mti->mti_params) + 1);
2802
2803 out_up:
2804         cfs_mutex_unlock(&fsdb->fsdb_mutex);
2805         RETURN(rc);
2806 }
2807
2808 /* COMPAT_146 */
2809 /* verify that we can handle the old config logs */
2810 int mgs_upgrade_sv_14(struct obd_device *obd, struct mgs_target_info *mti,
2811                       struct fs_db *fsdb)
2812 {
2813         int rc = 0;
2814         ENTRY;
2815
2816         /* Create ost log normally, as servers register.  Servers
2817            register with their old uuids (from last_rcvd), so old
2818            (MDT and client) logs should work.
2819          - new MDT won't know about old OSTs, only the ones that have
2820            registered, so we need the old MDT log to get the LOV right
2821            in order for old clients to work.
2822          - Old clients connect to the MDT, not the MGS, for their logs, and
2823            will therefore receive the old client log from the MDT /LOGS dir.
2824          - Old clients can continue to use and connect to old or new OSTs
2825          - New clients will contact the MGS for their log
2826         */
2827
2828         LCONSOLE_INFO("upgrading server %s from pre-1.6\n", mti->mti_svname);
2829         server_mti_print("upgrade", mti);
2830
2831         if (cfs_test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
2832                 LCONSOLE_ERROR_MSG(0x14a, "The old client log %s-client is "
2833                                    "missing.  Was tunefs.lustre successful?\n",
2834                                    mti->mti_fsname);
2835                 RETURN(-ENOENT);
2836         }
2837
2838         if (fsdb->fsdb_gen == 0) {
2839                 /* There were no markers in the client log, meaning we have
2840                    not updated the logs for this fs */
2841                 CDEBUG(D_MGS, "found old, unupdated client log\n");
2842         }
2843
2844         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
2845                 if (mgs_log_is_empty(obd, mti->mti_svname)) {
2846                         LCONSOLE_ERROR_MSG(0x14b, "The old MDT log %s is "
2847                                            "missing. Was tunefs.lustre "
2848                                            "successful?\n",
2849                                            mti->mti_svname);
2850                         RETURN(-ENOENT);
2851                 }
2852                 /* We're starting with an old uuid.  Assume old name for lov
2853                    as well since the lov entry already exists in the log. */
2854                 CDEBUG(D_MGS, "old mds uuid %s\n", mti->mti_uuid);
2855                 if (strncmp(mti->mti_uuid, fsdb->fsdb_mdtlov + 4,
2856                             strlen(fsdb->fsdb_mdtlov) - 4) != 0) {
2857                         CERROR("old mds uuid %s doesn't match log %s (%s)\n",
2858                                mti->mti_uuid, fsdb->fsdb_mdtlov,
2859                                fsdb->fsdb_mdtlov + 4);
2860                         RETURN(-EINVAL);
2861                 }
2862         }
2863
2864         if (!cfs_test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
2865                 LCONSOLE_ERROR_MSG(0x14c, "%s-client is supposedly an old "
2866                                    "log, but no old LOV or MDT was found. "
2867                                    "Consider updating the configuration with"
2868                                    " --writeconf.\n", mti->mti_fsname);
2869         }
2870
2871         RETURN(rc);
2872 }
2873 /* end COMPAT_146 */
2874
2875 int mgs_erase_log(struct obd_device *obd, char *name)
2876 {
2877         struct lvfs_run_ctxt saved;
2878         struct llog_ctxt *ctxt;
2879         struct llog_handle *llh;
2880         int rc = 0;
2881
2882         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
2883         LASSERT(ctxt != NULL);
2884
2885         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2886         rc = llog_create(ctxt, &llh, NULL, name);
2887         if (rc == 0) {
2888                 llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
2889                 rc = llog_destroy(llh);
2890                 llog_free_handle(llh);
2891         }
2892         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2893         llog_ctxt_put(ctxt);
2894
2895         if (rc)
2896                 CERROR("failed to clear log %s: %d\n", name, rc);
2897
2898         return(rc);
2899 }
2900
2901 /* erase all logs for the given fs */
2902 int mgs_erase_logs(struct obd_device *obd, char *fsname)
2903 {
2904         struct mgs_obd *mgs = &obd->u.mgs;
2905         struct fs_db *fsdb;
2906         cfs_list_t dentry_list;
2907         struct l_linux_dirent *dirent, *n;
2908         int rc, len = strlen(fsname);
2909         char *suffix;
2910         ENTRY;
2911
2912         /* Find all the logs in the CONFIGS directory */
2913         rc = class_dentry_readdir(obd, mgs->mgs_configs_dir,
2914                                   mgs->mgs_vfsmnt, &dentry_list);
2915         if (rc) {
2916                 CERROR("Can't read %s dir\n", MOUNT_CONFIGS_DIR);
2917                 RETURN(rc);
2918         }
2919
2920         cfs_mutex_lock(&mgs->mgs_mutex);
2921
2922         /* Delete the fs db */
2923         fsdb = mgs_find_fsdb(obd, fsname);
2924         if (fsdb)
2925                 mgs_free_fsdb(obd, fsdb);
2926
2927         cfs_list_for_each_entry_safe(dirent, n, &dentry_list, lld_list) {
2928                 cfs_list_del(&dirent->lld_list);
2929                 suffix = strrchr(dirent->lld_name, '-');
2930                 if (suffix != NULL) {
2931                         if ((len == suffix - dirent->lld_name) &&
2932                             (strncmp(fsname, dirent->lld_name, len) == 0)) {
2933                                 CDEBUG(D_MGS, "Removing log %s\n",
2934                                        dirent->lld_name);
2935                                 mgs_erase_log(obd, dirent->lld_name);
2936                         }
2937                 }
2938                 OBD_FREE(dirent, sizeof(*dirent));
2939         }
2940
2941         cfs_mutex_unlock(&mgs->mgs_mutex);
2942
2943         RETURN(rc);
2944 }
2945
2946 /* from llog_swab */
2947 static void print_lustre_cfg(struct lustre_cfg *lcfg)
2948 {
2949         int i;
2950         ENTRY;
2951
2952         CDEBUG(D_MGS, "lustre_cfg: %p\n", lcfg);
2953         CDEBUG(D_MGS, "\tlcfg->lcfg_version: %#x\n", lcfg->lcfg_version);
2954
2955         CDEBUG(D_MGS, "\tlcfg->lcfg_command: %#x\n", lcfg->lcfg_command);
2956         CDEBUG(D_MGS, "\tlcfg->lcfg_num: %#x\n", lcfg->lcfg_num);
2957         CDEBUG(D_MGS, "\tlcfg->lcfg_flags: %#x\n", lcfg->lcfg_flags);
2958         CDEBUG(D_MGS, "\tlcfg->lcfg_nid: %s\n", libcfs_nid2str(lcfg->lcfg_nid));
2959
2960         CDEBUG(D_MGS, "\tlcfg->lcfg_bufcount: %d\n", lcfg->lcfg_bufcount);
2961         if (lcfg->lcfg_bufcount < LUSTRE_CFG_MAX_BUFCOUNT)
2962                 for (i = 0; i < lcfg->lcfg_bufcount; i++) {
2963                         CDEBUG(D_MGS, "\tlcfg->lcfg_buflens[%d]: %d %s\n",
2964                                i, lcfg->lcfg_buflens[i],
2965                                lustre_cfg_string(lcfg, i));
2966                 }
2967         EXIT;
2968 }
2969
2970 /* Set a permanent (config log) param for a target or fs
2971  * \param lcfg buf0 may contain the device (testfs-MDT0000) name
2972  *             buf1 contains the single parameter
2973  */
2974 int mgs_setparam(struct obd_device *obd, struct lustre_cfg *lcfg, char *fsname)
2975 {
2976         struct fs_db *fsdb;
2977         struct mgs_target_info *mti;
2978         char *devname, *param;
2979         char *ptr, *tmp;
2980         __u32 index;
2981         int rc = 0;
2982         ENTRY;
2983
2984         print_lustre_cfg(lcfg);
2985
2986         /* lustre, lustre-mdtlov, lustre-client, lustre-MDT0000 */
2987         devname = lustre_cfg_string(lcfg, 0);
2988         param = lustre_cfg_string(lcfg, 1);
2989         if (!devname) {
2990                 /* Assume device name embedded in param:
2991                    lustre-OST0000.osc.max_dirty_mb=32 */
2992                 ptr = strchr(param, '.');
2993                 if (ptr) {
2994                         devname = param;
2995                         *ptr = 0;
2996                         param = ptr + 1;
2997                 }
2998         }
2999         if (!devname) {
3000                 LCONSOLE_ERROR_MSG(0x14d, "No target specified: %s\n", param);
3001                 RETURN(-ENOSYS);
3002         }
3003
3004         /* Extract fsname */
3005         ptr = strrchr(devname, '-');
3006         memset(fsname, 0, MTI_NAME_MAXLEN);
3007         if (ptr && (server_name2index(ptr, &index, NULL) >= 0)) {
3008                 /* param related to llite isn't allowed to set by OST or MDT */
3009                 if (strncmp(param, PARAM_LLITE, sizeof(PARAM_LLITE)) == 0)
3010                         RETURN(-EINVAL);
3011
3012                 strncpy(fsname, devname, ptr - devname);
3013         } else {
3014                 /* assume devname is the fsname */
3015                 strncpy(fsname, devname, MTI_NAME_MAXLEN);
3016         }
3017         fsname[MTI_NAME_MAXLEN - 1] = 0;
3018         CDEBUG(D_MGS, "setparam fs='%s' device='%s'\n", fsname, devname);
3019
3020         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb);
3021         if (rc)
3022                 RETURN(rc);
3023         if (!cfs_test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags) &&
3024             cfs_test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
3025                 CERROR("No filesystem targets for %s.  cfg_device from lctl "
3026                        "is '%s'\n", fsname, devname);
3027                 mgs_free_fsdb(obd, fsdb);
3028                 RETURN(-EINVAL);
3029         }
3030
3031         /* Create a fake mti to hold everything */
3032         OBD_ALLOC_PTR(mti);
3033         if (!mti)
3034                 GOTO(out, rc = -ENOMEM);
3035         strncpy(mti->mti_fsname, fsname, MTI_NAME_MAXLEN);
3036         strncpy(mti->mti_svname, devname, MTI_NAME_MAXLEN);
3037         strncpy(mti->mti_params, param, sizeof(mti->mti_params));
3038         rc = server_name2index(mti->mti_svname, &mti->mti_stripe_index, &tmp);
3039         if (rc < 0)
3040                 /* Not a valid server; may be only fsname */
3041                 rc = 0;
3042         else
3043                 /* Strip -osc or -mdc suffix from svname */
3044                 if (server_make_name(rc, mti->mti_stripe_index, mti->mti_fsname,
3045                                      mti->mti_svname))
3046                         GOTO(out, rc = -EINVAL);
3047
3048         mti->mti_flags = rc | LDD_F_PARAM;
3049
3050         cfs_mutex_lock(&fsdb->fsdb_mutex);
3051         rc = mgs_write_log_param(obd, fsdb, mti, mti->mti_params);
3052         cfs_mutex_unlock(&fsdb->fsdb_mutex);
3053
3054         /*
3055          * Revoke lock so everyone updates.  Should be alright if
3056          * someone was already reading while we were updating the logs,
3057          * so we don't really need to hold the lock while we're
3058          * writing (above).
3059          */
3060         mgs_revoke_lock(obd, fsdb, CONFIG_T_CONFIG);
3061 out:
3062         OBD_FREE_PTR(mti);
3063         RETURN(rc);
3064 }
3065
3066 static int mgs_write_log_pool(struct obd_device *obd, char *logname,
3067                               struct fs_db *fsdb, char *lovname,
3068                               enum lcfg_command_type cmd,
3069                               char *poolname, char *fsname,
3070                               char *ostname, char *comment)
3071 {
3072         struct llog_handle *llh = NULL;
3073         int rc;
3074
3075         rc = record_start_log(obd, &llh, logname);
3076         if (rc)
3077                 return rc;
3078         rc = record_marker(obd, llh, fsdb, CM_START, lovname, comment);
3079         record_base(obd, llh, lovname, 0, cmd, poolname, fsname, ostname, 0);
3080         rc = record_marker(obd, llh, fsdb, CM_END, lovname, comment);
3081         rc = record_end_log(obd, &llh);
3082
3083         return rc;
3084 }
3085
3086 int mgs_pool_cmd(struct obd_device *obd, enum lcfg_command_type cmd,
3087                  char *fsname, char *poolname, char *ostname)
3088 {
3089         struct fs_db *fsdb;
3090         char *lovname;
3091         char *logname;
3092         char *label = NULL, *canceled_label = NULL;
3093         int label_sz;
3094         struct mgs_target_info *mti = NULL;
3095         int rc, i;
3096         ENTRY;
3097
3098         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb);
3099         if (rc) {
3100                 CERROR("Can't get db for %s\n", fsname);
3101                 RETURN(rc);
3102         }
3103         if (cfs_test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
3104                 CERROR("%s is not defined\n", fsname);
3105                 mgs_free_fsdb(obd, fsdb);
3106                 RETURN(-EINVAL);
3107         }
3108
3109         label_sz = 10 + strlen(fsname) + strlen(poolname);
3110
3111         /* check if ostname match fsname */
3112         if (ostname != NULL) {
3113                 char *ptr;
3114
3115                 ptr = strrchr(ostname, '-');
3116                 if ((ptr == NULL) ||
3117                     (strncmp(fsname, ostname, ptr-ostname) != 0))
3118                         RETURN(-EINVAL);
3119                 label_sz += strlen(ostname);
3120         }
3121
3122         OBD_ALLOC(label, label_sz);
3123         if (label == NULL)
3124                 GOTO(out, rc = -ENOMEM);
3125
3126         switch(cmd) {
3127         case LCFG_POOL_NEW: {
3128                 sprintf(label,
3129                         "new %s.%s", fsname, poolname);
3130                 break;
3131         }
3132         case LCFG_POOL_ADD: {
3133                 sprintf(label,
3134                         "add %s.%s.%s", fsname, poolname, ostname);
3135                 break;
3136         }
3137         case LCFG_POOL_REM: {
3138                 OBD_ALLOC(canceled_label, label_sz);
3139                 if (canceled_label == NULL)
3140                          GOTO(out, rc = -ENOMEM);
3141                 sprintf(label,
3142                         "rem %s.%s.%s", fsname, poolname, ostname);
3143                 sprintf(canceled_label,
3144                         "add %s.%s.%s", fsname, poolname, ostname);
3145                 break;
3146         }
3147         case LCFG_POOL_DEL: {
3148                 OBD_ALLOC(canceled_label, label_sz);
3149                 if (canceled_label == NULL)
3150                          GOTO(out, rc = -ENOMEM);
3151                 sprintf(label,
3152                         "del %s.%s", fsname, poolname);
3153                 sprintf(canceled_label,
3154                         "new %s.%s", fsname, poolname);
3155                 break;
3156         }
3157         default: {
3158                 break;
3159         }
3160         }
3161
3162         cfs_mutex_lock(&fsdb->fsdb_mutex);
3163
3164         if (canceled_label != NULL) {
3165                 OBD_ALLOC_PTR(mti);
3166                 if (mti == NULL)
3167                         GOTO(out, rc = -ENOMEM);
3168         }
3169
3170         /* write pool def to all MDT logs */
3171         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
3172                  if (cfs_test_bit(i,  fsdb->fsdb_mdt_index_map)) {
3173                         name_create_mdt_and_lov(&logname, &lovname, fsdb, i);
3174
3175                         if (canceled_label != NULL) {
3176                                 strcpy(mti->mti_svname, "lov pool");
3177                                 mgs_modify(obd, fsdb, mti, logname, lovname,
3178                                            canceled_label, CM_SKIP);
3179                         }
3180
3181                         mgs_write_log_pool(obd, logname, fsdb, lovname,
3182                                            cmd, fsname, poolname, ostname,
3183                                            label);
3184                         name_destroy(&logname);
3185                         name_destroy(&lovname);
3186                 }
3187         }
3188
3189         name_create(&logname, fsname, "-client");
3190         if (canceled_label != NULL)
3191                 mgs_modify(obd, fsdb, mti, logname, fsdb->fsdb_clilov,
3192                            canceled_label, CM_SKIP);
3193
3194         mgs_write_log_pool(obd, logname, fsdb, fsdb->fsdb_clilov,
3195                            cmd, fsname, poolname, ostname, label);
3196         name_destroy(&logname);
3197
3198         cfs_mutex_unlock(&fsdb->fsdb_mutex);
3199         /* request for update */
3200         mgs_revoke_lock(obd, fsdb, CONFIG_T_CONFIG);
3201
3202         EXIT;
3203 out:
3204         if (label != NULL)
3205                 OBD_FREE(label, label_sz);
3206
3207         if (canceled_label != NULL)
3208                 OBD_FREE(canceled_label, label_sz);
3209
3210         if (mti != NULL)
3211                 OBD_FREE_PTR(mti);
3212
3213         return rc;
3214 }
3215
3216 #if 0
3217 /******************** unused *********************/
3218 static int mgs_backup_llog(struct obd_device *obd, char* fsname)
3219 {
3220         struct file *filp, *bak_filp;
3221         struct lvfs_run_ctxt saved;
3222         char *logname, *buf;
3223         loff_t soff = 0 , doff = 0;
3224         int count = 4096, len;
3225         int rc = 0;
3226
3227         OBD_ALLOC(logname, PATH_MAX);
3228         if (logname == NULL)
3229                 return -ENOMEM;
3230
3231         OBD_ALLOC(buf, count);
3232         if (!buf)
3233                 GOTO(out , rc = -ENOMEM);
3234
3235         len = snprintf(logname, PATH_MAX, "%s/%s.bak",
3236                        MOUNT_CONFIGS_DIR, fsname);
3237
3238         if (len >= PATH_MAX - 1) {
3239                 GOTO(out, -ENAMETOOLONG);
3240         }
3241
3242         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
3243
3244         bak_filp = l_filp_open(logname, O_RDWR|O_CREAT|O_TRUNC, 0660);
3245         if (IS_ERR(bak_filp)) {
3246                 rc = PTR_ERR(bak_filp);
3247                 CERROR("backup logfile open %s: %d\n", logname, rc);
3248                 GOTO(pop, rc);
3249         }
3250         sprintf(logname, "%s/%s", MOUNT_CONFIGS_DIR, fsname);
3251         filp = l_filp_open(logname, O_RDONLY, 0);
3252         if (IS_ERR(filp)) {
3253                 rc = PTR_ERR(filp);
3254                 CERROR("logfile open %s: %d\n", logname, rc);
3255                 GOTO(close1f, rc);
3256         }
3257
3258         while ((rc = lustre_fread(filp, buf, count, &soff)) > 0) {
3259                 rc = lustre_fwrite(bak_filp, buf, count, &doff);
3260                 break;
3261         }
3262
3263         filp_close(filp, 0);
3264 close1f:
3265         filp_close(bak_filp, 0);
3266 pop:
3267         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
3268 out:
3269         if (buf)
3270                 OBD_FREE(buf, count);
3271         OBD_FREE(logname, PATH_MAX);
3272         return rc;
3273 }
3274
3275 #endif