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