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