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