Whamcloud - gitweb
fb2e175b5026a18cca5b55406fa1b88bd6a389d0
[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.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2011, 2017, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  *
31  * lustre/mgs/mgs_llog.c
32  *
33  * Lustre Management Server (mgs) config llog creation
34  *
35  * Author: Nathan Rutman <nathan@clusterfs.com>
36  * Author: Alex Zhuravlev <bzzz@whamcloud.com>
37  * Author: Mikhail Pershin <tappro@whamcloud.com>
38  */
39
40 #define DEBUG_SUBSYSTEM S_MGS
41 #define D_MGS D_CONFIG
42
43 #include <obd.h>
44 #include <uapi/linux/lustre/lustre_ioctl.h>
45 #include <uapi/linux/lustre/lustre_param.h>
46 #include <lustre_sec.h>
47 #include <lustre_quota.h>
48 #include <lustre_sec.h>
49
50 #include "mgs_internal.h"
51
52 /********************** Class functions ********************/
53
54 /**
55  * Find all logs in CONFIG directory and link then into list.
56  *
57  * \param[in] env       pointer to the thread context
58  * \param[in] mgs       pointer to the mgs device
59  * \param[out] log_list the list to hold the found llog name entry
60  *
61  * \retval              0 for success
62  * \retval              negative error number on failure
63  **/
64 int class_dentry_readdir(const struct lu_env *env, struct mgs_device *mgs,
65                          struct list_head *log_list)
66 {
67         struct dt_object *dir = mgs->mgs_configs_dir;
68         const struct dt_it_ops *iops;
69         struct dt_it *it;
70         struct mgs_direntry *de;
71         char *key;
72         int rc, key_sz;
73
74         INIT_LIST_HEAD(log_list);
75
76         LASSERT(dir);
77         LASSERT(dir->do_index_ops);
78
79         iops = &dir->do_index_ops->dio_it;
80         it = iops->init(env, dir, LUDA_64BITHASH);
81         if (IS_ERR(it))
82                 RETURN(PTR_ERR(it));
83
84         rc = iops->load(env, it, 0);
85         if (rc <= 0)
86                 GOTO(fini, rc = 0);
87
88         /* main cycle */
89         do {
90                 key = (void *)iops->key(env, it);
91                 if (IS_ERR(key)) {
92                         CERROR("%s: key failed when listing %s: rc = %d\n",
93                                mgs->mgs_obd->obd_name, MOUNT_CONFIGS_DIR,
94                                (int) PTR_ERR(key));
95                         goto next;
96                 }
97                 key_sz = iops->key_size(env, it);
98                 LASSERT(key_sz > 0);
99
100                 /* filter out "." and ".." entries */
101                 if (key[0] == '.') {
102                         if (key_sz == 1)
103                                 goto next;
104                         if (key_sz == 2 && key[1] == '.')
105                                 goto next;
106                 }
107
108                 /* filter out backup files */
109                 if (lu_name_is_backup_file(key, key_sz, NULL)) {
110                         CDEBUG(D_MGS, "Skipping backup file %.*s\n",
111                                key_sz, key);
112                         goto next;
113                 }
114
115                 de = mgs_direntry_alloc(key_sz + 1);
116                 if (de == NULL) {
117                         rc = -ENOMEM;
118                         break;
119                 }
120
121                 memcpy(de->mde_name, key, key_sz);
122                 de->mde_name[key_sz] = 0;
123
124                 list_add(&de->mde_list, log_list);
125
126 next:
127                 rc = iops->next(env, it);
128         } while (rc == 0);
129         if (rc > 0)
130                 rc = 0;
131
132         iops->put(env, it);
133
134 fini:
135         iops->fini(env, it);
136         if (rc) {
137                 struct mgs_direntry *n;
138
139                 CERROR("%s: key failed when listing %s: rc = %d\n",
140                        mgs->mgs_obd->obd_name, MOUNT_CONFIGS_DIR, rc);
141
142                 list_for_each_entry_safe(de, n, log_list, mde_list) {
143                         list_del_init(&de->mde_list);
144                         mgs_direntry_free(de);
145                 }
146         }
147
148         RETURN(rc);
149 }
150
151 /******************** DB functions *********************/
152
153 static inline int name_create(char **newname, char *prefix, char *suffix)
154 {
155         LASSERT(newname);
156         OBD_ALLOC(*newname, strlen(prefix) + strlen(suffix) + 1);
157         if (!*newname)
158                 return -ENOMEM;
159         sprintf(*newname, "%s%s", prefix, suffix);
160         return 0;
161 }
162
163 static inline void name_destroy(char **name)
164 {
165         if (*name)
166                 OBD_FREE(*name, strlen(*name) + 1);
167         *name = NULL;
168 }
169
170 struct mgs_fsdb_handler_data
171 {
172         struct fs_db   *fsdb;
173         __u32           ver;
174 };
175
176 /* from the (client) config log, figure out:
177         1. which ost's/mdt's are configured (by index)
178         2. what the last config step is
179         3. COMPAT_18 osc name
180 */
181 /* It might be better to have a separate db file, instead of parsing the info
182    out of the client log.  This is slow and potentially error-prone. */
183 static int mgs_fsdb_handler(const struct lu_env *env, struct llog_handle *llh,
184                             struct llog_rec_hdr *rec, void *data)
185 {
186         struct mgs_fsdb_handler_data *d = data;
187         struct fs_db *fsdb = d->fsdb;
188         int cfg_len = rec->lrh_len;
189         char *cfg_buf = (char*) (rec + 1);
190         struct lustre_cfg *lcfg;
191         u32 index;
192         int rc = 0;
193         ENTRY;
194
195         if (rec->lrh_type != OBD_CFG_REC) {
196                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
197                 RETURN(-EINVAL);
198         }
199
200         rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
201         if (rc) {
202                 CERROR("Insane cfg\n");
203                 RETURN(rc);
204         }
205
206         lcfg = (struct lustre_cfg *)cfg_buf;
207
208         CDEBUG(D_INFO, "cmd %x %s %s\n", lcfg->lcfg_command,
209                lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
210
211         /* Figure out ost indicies */
212         /* lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1 */
213         if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD ||
214             lcfg->lcfg_command == LCFG_LOV_DEL_OBD) {
215                 rc = kstrtouint(lustre_cfg_string(lcfg, 2), 10, &index);
216                 if (rc)
217                         RETURN(rc);
218
219                 CDEBUG(D_MGS, "OST index for %s is %u (%s)\n",
220                        lustre_cfg_string(lcfg, 1), index,
221                        lustre_cfg_string(lcfg, 2));
222                 set_bit(index, fsdb->fsdb_ost_index_map);
223         }
224
225         /* Figure out mdt indicies */
226         /* attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f */
227         if ((lcfg->lcfg_command == LCFG_ATTACH) &&
228             (strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_MDC_NAME) == 0)) {
229                 rc = server_name2index(lustre_cfg_string(lcfg, 0),
230                                        &index, NULL);
231                 if (rc != LDD_F_SV_TYPE_MDT) {
232                         CWARN("Unparsable MDC name %s, assuming index 0\n",
233                               lustre_cfg_string(lcfg, 0));
234                         index = 0;
235                 }
236                 rc = 0;
237                 CDEBUG(D_MGS, "MDT index is %u\n", index);
238                 if (!test_bit(index, fsdb->fsdb_mdt_index_map)) {
239                         set_bit(index, fsdb->fsdb_mdt_index_map);
240                         fsdb->fsdb_mdt_count++;
241                 }
242         }
243
244         /**
245          * figure out the old config. fsdb_gen = 0 means old log
246          * It is obsoleted and not supported anymore
247          */
248         if (fsdb->fsdb_gen == 0) {
249                 CERROR("Old config format is not supported\n");
250                 RETURN(-EINVAL);
251         }
252
253         /*
254          * compat to 1.8, check osc name used by MDT0 to OSTs, bz18548.
255          */
256         if (!test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags) &&
257             lcfg->lcfg_command == LCFG_ATTACH &&
258             strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_OSC_NAME) == 0) {
259                 if (OBD_OCD_VERSION_MAJOR(d->ver) == 1 &&
260                     OBD_OCD_VERSION_MINOR(d->ver) <= 8) {
261                         CWARN("MDT using 1.8 OSC name scheme\n");
262                         set_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags);
263                 }
264         }
265
266         if (lcfg->lcfg_command == LCFG_MARKER) {
267                 struct cfg_marker *marker;
268                 marker = lustre_cfg_buf(lcfg, 1);
269
270                 d->ver = marker->cm_vers;
271
272                 /* Keep track of the latest marker step */
273                 fsdb->fsdb_gen = max(fsdb->fsdb_gen, marker->cm_step);
274         }
275
276         RETURN(rc);
277 }
278
279 /* fsdb->fsdb_mutex is already held  in mgs_find_or_make_fsdb*/
280 static int mgs_get_fsdb_from_llog(const struct lu_env *env,
281                                   struct mgs_device *mgs,
282                                   struct fs_db *fsdb)
283 {
284         char *logname;
285         struct llog_handle *loghandle;
286         struct llog_ctxt *ctxt;
287         struct mgs_fsdb_handler_data d = {
288                 .fsdb = fsdb,
289         };
290         int rc;
291
292         ENTRY;
293
294         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
295         LASSERT(ctxt != NULL);
296         rc = name_create(&logname, fsdb->fsdb_name, "-client");
297         if (rc)
298                 GOTO(out_put, rc);
299         rc = llog_open_create(env, ctxt, &loghandle, NULL, logname);
300         if (rc)
301                 GOTO(out_pop, rc);
302
303         rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
304         if (rc)
305                 GOTO(out_close, rc);
306
307         if (llog_get_size(loghandle) <= 1)
308                 set_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags);
309
310         rc = llog_process(env, loghandle, mgs_fsdb_handler, (void *)&d, NULL);
311         CDEBUG(D_INFO, "get_db = %d\n", rc);
312 out_close:
313         llog_close(env, loghandle);
314 out_pop:
315         name_destroy(&logname);
316 out_put:
317         llog_ctxt_put(ctxt);
318
319         RETURN(rc);
320 }
321
322 static void mgs_free_fsdb_srpc(struct fs_db *fsdb)
323 {
324         struct mgs_tgt_srpc_conf *tgtconf;
325
326         /* free target-specific rules */
327         while (fsdb->fsdb_srpc_tgt) {
328                 tgtconf = fsdb->fsdb_srpc_tgt;
329                 fsdb->fsdb_srpc_tgt = tgtconf->mtsc_next;
330
331                 LASSERT(tgtconf->mtsc_tgt);
332
333                 sptlrpc_rule_set_free(&tgtconf->mtsc_rset);
334                 OBD_FREE(tgtconf->mtsc_tgt, strlen(tgtconf->mtsc_tgt) + 1);
335                 OBD_FREE_PTR(tgtconf);
336         }
337
338         /* free general rules */
339         sptlrpc_rule_set_free(&fsdb->fsdb_srpc_gen);
340 }
341
342 static void mgs_unlink_fsdb(struct mgs_device *mgs, struct fs_db *fsdb)
343 {
344         mutex_lock(&mgs->mgs_mutex);
345         if (likely(!list_empty(&fsdb->fsdb_list))) {
346                 LASSERTF(atomic_read(&fsdb->fsdb_ref) >= 2,
347                          "Invalid ref %d on %s\n",
348                          atomic_read(&fsdb->fsdb_ref),
349                          fsdb->fsdb_name);
350
351                 list_del_init(&fsdb->fsdb_list);
352                 /* Drop the reference on the list.*/
353                 mgs_put_fsdb(mgs, fsdb);
354         }
355         mutex_unlock(&mgs->mgs_mutex);
356 }
357
358 /* The caller must hold mgs->mgs_mutex. */
359 static inline struct fs_db *
360 mgs_find_fsdb_noref(struct mgs_device *mgs, const char *fsname)
361 {
362         struct fs_db *fsdb;
363         struct list_head *tmp;
364
365         list_for_each(tmp, &mgs->mgs_fs_db_list) {
366                 fsdb = list_entry(tmp, struct fs_db, fsdb_list);
367                 if (strcmp(fsdb->fsdb_name, fsname) == 0)
368                         return fsdb;
369         }
370
371         return NULL;
372 }
373
374 /* The caller must hold mgs->mgs_mutex. */
375 static void mgs_remove_fsdb_by_name(struct mgs_device *mgs, const char *name)
376 {
377         struct fs_db *fsdb;
378
379         fsdb = mgs_find_fsdb_noref(mgs, name);
380         if (fsdb) {
381                 list_del_init(&fsdb->fsdb_list);
382                 /* Drop the reference on the list.*/
383                 mgs_put_fsdb(mgs, fsdb);
384         }
385 }
386
387 /* The caller must hold mgs->mgs_mutex. */
388 struct fs_db *mgs_find_fsdb(struct mgs_device *mgs, const char *fsname)
389 {
390         struct fs_db *fsdb;
391
392         fsdb = mgs_find_fsdb_noref(mgs, fsname);
393         if (fsdb)
394                 atomic_inc(&fsdb->fsdb_ref);
395
396         return fsdb;
397 }
398
399 /* The caller must hold mgs->mgs_mutex. */
400 static struct fs_db *mgs_new_fsdb(const struct lu_env *env,
401                                   struct mgs_device *mgs, char *fsname)
402 {
403         struct fs_db *fsdb;
404         int rc;
405         ENTRY;
406
407         if (strlen(fsname) >= sizeof(fsdb->fsdb_name)) {
408                 CERROR("fsname %s is too long\n", fsname);
409
410                 RETURN(ERR_PTR(-EINVAL));
411         }
412
413         OBD_ALLOC_PTR(fsdb);
414         if (!fsdb)
415                 RETURN(ERR_PTR(-ENOMEM));
416
417         strncpy(fsdb->fsdb_name, fsname, sizeof(fsdb->fsdb_name));
418         mutex_init(&fsdb->fsdb_mutex);
419         INIT_LIST_HEAD(&fsdb->fsdb_list);
420         set_bit(FSDB_UDESC, &fsdb->fsdb_flags);
421         fsdb->fsdb_gen = 1;
422         INIT_LIST_HEAD(&fsdb->fsdb_clients);
423         atomic_set(&fsdb->fsdb_notify_phase, 0);
424         init_waitqueue_head(&fsdb->fsdb_notify_waitq);
425         init_completion(&fsdb->fsdb_notify_comp);
426
427         if (strcmp(fsname, MGSSELF_NAME) == 0) {
428                 set_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags);
429                 fsdb->fsdb_mgs = mgs;
430                 if (logname_is_barrier(fsname))
431                         goto add;
432         } else {
433                 OBD_ALLOC(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
434                 if (!fsdb->fsdb_mdt_index_map) {
435                         CERROR("No memory for MDT index maps\n");
436
437                         GOTO(err, rc = -ENOMEM);
438                 }
439
440                 OBD_ALLOC(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
441                 if (!fsdb->fsdb_ost_index_map) {
442                         CERROR("No memory for OST index maps\n");
443
444                         GOTO(err, rc = -ENOMEM);
445                 }
446
447                 if (logname_is_barrier(fsname))
448                         goto add;
449
450                 rc = name_create(&fsdb->fsdb_clilov, fsname, "-clilov");
451                 if (rc)
452                         GOTO(err, rc);
453
454                 rc = name_create(&fsdb->fsdb_clilmv, fsname, "-clilmv");
455                 if (rc)
456                         GOTO(err, rc);
457
458                 /* initialise data for NID table */
459                 mgs_ir_init_fs(env, mgs, fsdb);
460                 lproc_mgs_add_live(mgs, fsdb);
461         }
462
463         if (!test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags) &&
464             strcmp(PARAMS_FILENAME, fsname) != 0) {
465                 /* populate the db from the client llog */
466                 rc = mgs_get_fsdb_from_llog(env, mgs, fsdb);
467                 if (rc) {
468                         CERROR("Can't get db from client log %d\n", rc);
469
470                         GOTO(err, rc);
471                 }
472         }
473
474         /* populate srpc rules from params llog */
475         rc = mgs_get_fsdb_srpc_from_llog(env, mgs, fsdb);
476         if (rc) {
477                 CERROR("Can't get db from params log %d\n", rc);
478
479                 GOTO(err, rc);
480         }
481
482 add:
483         /* One ref is for the fsdb on the list.
484          * The other ref is for the caller. */
485         atomic_set(&fsdb->fsdb_ref, 2);
486         list_add(&fsdb->fsdb_list, &mgs->mgs_fs_db_list);
487
488         RETURN(fsdb);
489
490 err:
491         atomic_set(&fsdb->fsdb_ref, 1);
492         mgs_put_fsdb(mgs, fsdb);
493
494         RETURN(ERR_PTR(rc));
495 }
496
497 static void mgs_free_fsdb(struct mgs_device *mgs, struct fs_db *fsdb)
498 {
499         LASSERT(list_empty(&fsdb->fsdb_list));
500
501         lproc_mgs_del_live(mgs, fsdb);
502
503         /* deinitialize fsr */
504         if (fsdb->fsdb_mgs)
505                 mgs_ir_fini_fs(mgs, fsdb);
506
507         if (fsdb->fsdb_ost_index_map)
508                 OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
509         if (fsdb->fsdb_mdt_index_map)
510                 OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
511         name_destroy(&fsdb->fsdb_clilov);
512         name_destroy(&fsdb->fsdb_clilmv);
513         mgs_free_fsdb_srpc(fsdb);
514         OBD_FREE_PTR(fsdb);
515 }
516
517 void mgs_put_fsdb(struct mgs_device *mgs, struct fs_db *fsdb)
518 {
519         if (atomic_dec_and_test(&fsdb->fsdb_ref))
520                 mgs_free_fsdb(mgs, fsdb);
521 }
522
523 int mgs_init_fsdb_list(struct mgs_device *mgs)
524 {
525         INIT_LIST_HEAD(&mgs->mgs_fs_db_list);
526         return 0;
527 }
528
529 int mgs_cleanup_fsdb_list(struct mgs_device *mgs)
530 {
531         struct fs_db *fsdb;
532         struct list_head *tmp, *tmp2;
533
534         mutex_lock(&mgs->mgs_mutex);
535         list_for_each_safe(tmp, tmp2, &mgs->mgs_fs_db_list) {
536                 fsdb = list_entry(tmp, struct fs_db, fsdb_list);
537                 list_del_init(&fsdb->fsdb_list);
538                 mgs_put_fsdb(mgs, fsdb);
539         }
540         mutex_unlock(&mgs->mgs_mutex);
541         return 0;
542 }
543
544 /* The caller must hold mgs->mgs_mutex. */
545 int mgs_find_or_make_fsdb_nolock(const struct lu_env *env,
546                                 struct mgs_device *mgs,
547                                 char *name, struct fs_db **dbh)
548 {
549         struct fs_db *fsdb;
550         int rc = 0;
551         ENTRY;
552
553         fsdb = mgs_find_fsdb(mgs, name);
554         if (!fsdb) {
555                 fsdb = mgs_new_fsdb(env, mgs, name);
556                 if (IS_ERR(fsdb))
557                         rc = PTR_ERR(fsdb);
558
559                 CDEBUG(D_MGS, "Created new db: rc = %d\n", rc);
560         }
561
562         if (!rc)
563                 *dbh = fsdb;
564
565         RETURN(rc);
566 }
567
568 int mgs_find_or_make_fsdb(const struct lu_env *env, struct mgs_device *mgs,
569                           char *name, struct fs_db **dbh)
570 {
571         int rc;
572         ENTRY;
573
574         mutex_lock(&mgs->mgs_mutex);
575         rc = mgs_find_or_make_fsdb_nolock(env, mgs, name, dbh);
576         mutex_unlock(&mgs->mgs_mutex);
577
578         RETURN(rc);
579 }
580
581 /* 1 = index in use
582    0 = index unused
583    -1= empty client log */
584 int mgs_check_index(const struct lu_env *env,
585                     struct mgs_device *mgs,
586                     struct mgs_target_info *mti)
587 {
588         struct fs_db *fsdb;
589         void *imap;
590         int rc = 0;
591         ENTRY;
592
593         LASSERT(!(mti->mti_flags & LDD_F_NEED_INDEX));
594
595         rc = mgs_find_or_make_fsdb(env, mgs, mti->mti_fsname, &fsdb);
596         if (rc) {
597                 CERROR("Can't get db for %s\n", mti->mti_fsname);
598                 RETURN(rc);
599         }
600
601         if (test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags))
602                 GOTO(out, rc = -1);
603
604         if (mti->mti_flags & LDD_F_SV_TYPE_OST)
605                 imap = fsdb->fsdb_ost_index_map;
606         else if (mti->mti_flags & LDD_F_SV_TYPE_MDT)
607                 imap = fsdb->fsdb_mdt_index_map;
608         else
609                 GOTO(out, rc = -EINVAL);
610
611         if (test_bit(mti->mti_stripe_index, imap))
612                 GOTO(out, rc = 1);
613
614         GOTO(out, rc = 0);
615
616 out:
617         mgs_put_fsdb(mgs, fsdb);
618         return rc;
619 }
620
621 static __inline__ int next_index(void *index_map, int map_len)
622 {
623         int i;
624         for (i = 0; i < map_len * 8; i++)
625                 if (!test_bit(i, index_map)) {
626                          return i;
627                  }
628         CERROR("max index %d exceeded.\n", i);
629         return -1;
630 }
631
632 /* Make the mdt/ost server obd name based on the filesystem name */
633 static bool server_make_name(u32 flags, u16 index, const char *fs,
634                              char *name_buf, size_t name_buf_size)
635 {
636         bool invalid_flag = false;
637
638         if (flags & (LDD_F_SV_TYPE_MDT | LDD_F_SV_TYPE_OST)) {
639                 if (!(flags & LDD_F_SV_ALL))
640                         snprintf(name_buf, name_buf_size, "%.8s%c%s%04x", fs,
641                                 (flags & LDD_F_VIRGIN) ? ':' :
642                                         ((flags & LDD_F_WRITECONF) ? '=' : '-'),
643                                 (flags & LDD_F_SV_TYPE_MDT) ? "MDT" : "OST",
644                                 index);
645         } else if (flags & LDD_F_SV_TYPE_MGS) {
646                 snprintf(name_buf, name_buf_size, "MGS");
647         } else {
648                 CERROR("unknown server type %#x\n", flags);
649                 invalid_flag = true;
650         }
651         return invalid_flag;
652 }
653
654 /* Return codes:
655         0  newly marked as in use
656         <0 err
657         +EALREADY for update of an old index */
658 static int mgs_set_index(const struct lu_env *env,
659                          struct mgs_device *mgs,
660                          struct mgs_target_info *mti)
661 {
662         struct fs_db *fsdb;
663         void *imap;
664         int rc = 0;
665         ENTRY;
666
667         rc = mgs_find_or_make_fsdb(env, mgs, mti->mti_fsname, &fsdb);
668         if (rc) {
669                 CERROR("Can't get db for %s\n", mti->mti_fsname);
670                 RETURN(rc);
671         }
672
673         mutex_lock(&fsdb->fsdb_mutex);
674         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
675                 imap = fsdb->fsdb_ost_index_map;
676         } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
677                 imap = fsdb->fsdb_mdt_index_map;
678         } else {
679                 GOTO(out_up, rc = -EINVAL);
680         }
681
682         if (mti->mti_flags & LDD_F_NEED_INDEX) {
683                 rc = next_index(imap, INDEX_MAP_SIZE);
684                 if (rc == -1)
685                         GOTO(out_up, rc = -ERANGE);
686                 mti->mti_stripe_index = rc;
687         }
688
689         /* the last index(0xffff) is reserved for default value. */
690         if (mti->mti_stripe_index >= INDEX_MAP_SIZE * 8 - 1) {
691                 LCONSOLE_ERROR_MSG(0x13f, "Server %s requested index %u, "
692                                    "but index must be less than %u.\n",
693                                    mti->mti_svname, mti->mti_stripe_index,
694                                    INDEX_MAP_SIZE * 8 - 1);
695                 GOTO(out_up, rc = -ERANGE);
696         }
697
698         if (test_bit(mti->mti_stripe_index, imap)) {
699                 if ((mti->mti_flags & LDD_F_VIRGIN) &&
700                     !(mti->mti_flags & LDD_F_WRITECONF)) {
701                         LCONSOLE_ERROR_MSG(0x140, "Server %s requested index "
702                                            "%d, but that index is already in "
703                                            "use. Use --writeconf to force\n",
704                                            mti->mti_svname,
705                                            mti->mti_stripe_index);
706                         GOTO(out_up, rc = -EADDRINUSE);
707                 } else {
708                         CDEBUG(D_MGS, "Server %s updating index %d\n",
709                                mti->mti_svname, mti->mti_stripe_index);
710                         GOTO(out_up, rc = EALREADY);
711                 }
712         } else {
713                 set_bit(mti->mti_stripe_index, imap);
714                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT)
715                         fsdb->fsdb_mdt_count++;
716         }
717
718         set_bit(mti->mti_stripe_index, imap);
719         clear_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags);
720         if (server_make_name(mti->mti_flags & ~(LDD_F_VIRGIN | LDD_F_WRITECONF),
721                              mti->mti_stripe_index, mti->mti_fsname,
722                              mti->mti_svname, sizeof(mti->mti_svname))) {
723                 CERROR("unknown server type %#x\n", mti->mti_flags);
724                 GOTO(out_up, rc = -EINVAL);
725         }
726
727         CDEBUG(D_MGS, "Set index for %s to %d\n", mti->mti_svname,
728                mti->mti_stripe_index);
729
730         GOTO(out_up, rc = 0);
731
732 out_up:
733         mutex_unlock(&fsdb->fsdb_mutex);
734         mgs_put_fsdb(mgs, fsdb);
735         return rc;
736 }
737
738 struct mgs_modify_lookup {
739         struct cfg_marker mml_marker;
740         int               mml_modified;
741 };
742
743 static int mgs_check_record_match(const struct lu_env *env,
744                                 struct llog_handle *llh,
745                                 struct llog_rec_hdr *rec, void *data)
746 {
747         struct cfg_marker *mc_marker = data;
748         struct cfg_marker *marker;
749         struct lustre_cfg *lcfg = REC_DATA(rec);
750         int cfg_len = REC_DATA_LEN(rec);
751         int rc;
752         ENTRY;
753
754
755         if (rec->lrh_type != OBD_CFG_REC) {
756                 CDEBUG(D_ERROR, "Unhandled lrh_type: %#x\n", rec->lrh_type);
757                 RETURN(-EINVAL);
758         }
759
760         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
761         if (rc) {
762                 CDEBUG(D_ERROR, "Insane cfg\n");
763                 RETURN(rc);
764         }
765
766         /* We only care about markers */
767         if (lcfg->lcfg_command != LCFG_MARKER)
768                 RETURN(0);
769
770         marker = lustre_cfg_buf(lcfg, 1);
771
772         if (marker->cm_flags & CM_SKIP)
773                 RETURN(0);
774
775         if ((strcmp(mc_marker->cm_comment, marker->cm_comment) == 0) &&
776                 (strcmp(mc_marker->cm_tgtname, marker->cm_tgtname) == 0)) {
777                 /* Found a non-skipped marker match */
778                 CDEBUG(D_MGS, "Matched rec %u marker %d flag %x %s %s\n",
779                         rec->lrh_index, marker->cm_step,
780                         marker->cm_flags, marker->cm_tgtname,
781                         marker->cm_comment);
782                 rc = LLOG_PROC_BREAK;
783         }
784
785         RETURN(rc);
786 }
787
788 /**
789  * Check an existing config log record with matching comment and device
790  * Return code:
791  * 0 - checked successfully,
792  * LLOG_PROC_BREAK - record matches
793  * negative - error
794  */
795 static int mgs_check_marker(const struct lu_env *env, struct mgs_device *mgs,
796                 struct fs_db *fsdb, struct mgs_target_info *mti,
797                 char *logname, char *devname, char *comment)
798 {
799         struct llog_handle *loghandle;
800         struct llog_ctxt *ctxt;
801         struct cfg_marker *mc_marker;
802         int rc;
803
804         ENTRY;
805
806         LASSERT(mutex_is_locked(&fsdb->fsdb_mutex));
807         CDEBUG(D_MGS, "mgs check %s/%s/%s\n", logname, devname, comment);
808
809         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
810         LASSERT(ctxt != NULL);
811         rc = llog_open(env, ctxt, &loghandle, NULL, logname, LLOG_OPEN_EXISTS);
812         if (rc < 0) {
813                 if (rc == -ENOENT)
814                         rc = 0;
815                 GOTO(out_pop, rc);
816         }
817
818         rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
819         if (rc)
820                 GOTO(out_close, rc);
821
822         if (llog_get_size(loghandle) <= 1)
823                 GOTO(out_close, rc = 0);
824
825         OBD_ALLOC_PTR(mc_marker);
826         if (!mc_marker)
827                 GOTO(out_close, rc = -ENOMEM);
828         if (strlcpy(mc_marker->cm_comment, comment,
829                 sizeof(mc_marker->cm_comment)) >=
830                 sizeof(mc_marker->cm_comment))
831                 GOTO(out_free, rc = -E2BIG);
832         if (strlcpy(mc_marker->cm_tgtname, devname,
833                 sizeof(mc_marker->cm_tgtname)) >=
834                 sizeof(mc_marker->cm_tgtname))
835                 GOTO(out_free, rc = -E2BIG);
836
837         rc = llog_process(env, loghandle, mgs_check_record_match,
838                         (void *)mc_marker, NULL);
839
840 out_free:
841         OBD_FREE_PTR(mc_marker);
842
843 out_close:
844         llog_close(env, loghandle);
845 out_pop:
846         if (rc && rc != LLOG_PROC_BREAK)
847                 CDEBUG(D_ERROR, "%s: mgs check %s/%s failed: rc = %d\n",
848                         mgs->mgs_obd->obd_name, mti->mti_svname, comment, rc);
849         llog_ctxt_put(ctxt);
850         RETURN(rc);
851 }
852
853 static int mgs_modify_handler(const struct lu_env *env,
854                               struct llog_handle *llh,
855                               struct llog_rec_hdr *rec, void *data)
856 {
857         struct mgs_modify_lookup *mml = data;
858         struct cfg_marker *marker;
859         struct lustre_cfg *lcfg = REC_DATA(rec);
860         int cfg_len = REC_DATA_LEN(rec);
861         int rc;
862         ENTRY;
863
864         if (rec->lrh_type != OBD_CFG_REC) {
865                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
866                 RETURN(-EINVAL);
867         }
868
869         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
870         if (rc) {
871                 CERROR("Insane cfg\n");
872                 RETURN(rc);
873         }
874
875         /* We only care about markers */
876         if (lcfg->lcfg_command != LCFG_MARKER)
877                 RETURN(0);
878
879         marker = lustre_cfg_buf(lcfg, 1);
880         if ((strcmp(mml->mml_marker.cm_comment, marker->cm_comment) == 0) &&
881             (strcmp(mml->mml_marker.cm_tgtname, marker->cm_tgtname) == 0) &&
882             !(marker->cm_flags & CM_SKIP)) {
883                 /* Found a non-skipped marker match */
884                 CDEBUG(D_MGS, "Changing rec %u marker %d %x->%x: %s %s\n",
885                        rec->lrh_index, marker->cm_step,
886                        marker->cm_flags, mml->mml_marker.cm_flags,
887                        marker->cm_tgtname, marker->cm_comment);
888                 /* Overwrite the old marker llog entry */
889                 marker->cm_flags &= ~CM_EXCLUDE; /* in case we're unexcluding */
890                 marker->cm_flags |= mml->mml_marker.cm_flags;
891                 marker->cm_canceltime = mml->mml_marker.cm_canceltime;
892                 rc = llog_write(env, llh, rec, rec->lrh_index);
893                 if (!rc)
894                          mml->mml_modified++;
895         }
896
897         RETURN(rc);
898 }
899
900 /**
901  * Modify an existing config log record (for CM_SKIP or CM_EXCLUDE)
902  * Return code:
903  * 0 - modified successfully,
904  * 1 - no modification was done
905  * negative - error
906  */
907 static int mgs_modify(const struct lu_env *env, struct mgs_device *mgs,
908                       struct fs_db *fsdb, struct mgs_target_info *mti,
909                       char *logname, char *devname, char *comment, int flags)
910 {
911         struct llog_handle *loghandle;
912         struct llog_ctxt *ctxt;
913         struct mgs_modify_lookup *mml;
914         int rc;
915
916         ENTRY;
917
918         LASSERT(mutex_is_locked(&fsdb->fsdb_mutex));
919         CDEBUG(D_MGS, "modify %s/%s/%s fl=%x\n", logname, devname, comment,
920                flags);
921
922         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
923         LASSERT(ctxt != NULL);
924         rc = llog_open(env, ctxt, &loghandle, NULL, logname, LLOG_OPEN_EXISTS);
925         if (rc < 0) {
926                 if (rc == -ENOENT)
927                         rc = 0;
928                 GOTO(out_pop, rc);
929         }
930
931         rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
932         if (rc)
933                 GOTO(out_close, rc);
934
935         if (llog_get_size(loghandle) <= 1)
936                 GOTO(out_close, rc = 0);
937
938         OBD_ALLOC_PTR(mml);
939         if (!mml)
940                 GOTO(out_close, rc = -ENOMEM);
941         if (strlcpy(mml->mml_marker.cm_comment, comment,
942                     sizeof(mml->mml_marker.cm_comment)) >=
943             sizeof(mml->mml_marker.cm_comment))
944                 GOTO(out_free, rc = -E2BIG);
945         if (strlcpy(mml->mml_marker.cm_tgtname, devname,
946                     sizeof(mml->mml_marker.cm_tgtname)) >=
947             sizeof(mml->mml_marker.cm_tgtname))
948                 GOTO(out_free, rc = -E2BIG);
949         /* Modify mostly means cancel */
950         mml->mml_marker.cm_flags = flags;
951         mml->mml_marker.cm_canceltime = flags ? ktime_get_real_seconds() : 0;
952         mml->mml_modified = 0;
953         rc = llog_process(env, loghandle, mgs_modify_handler, (void *)mml,
954                           NULL);
955         if (!rc && !mml->mml_modified)
956                 rc = 1;
957
958 out_free:
959         OBD_FREE_PTR(mml);
960
961 out_close:
962         llog_close(env, loghandle);
963 out_pop:
964         if (rc < 0)
965                 CERROR("%s: modify %s/%s failed: rc = %d\n",
966                        mgs->mgs_obd->obd_name, mti->mti_svname, comment, rc);
967         llog_ctxt_put(ctxt);
968         RETURN(rc);
969 }
970
971 enum replace_state {
972         REPLACE_COPY = 0,
973         REPLACE_SKIP,
974         REPLACE_DONE,
975         REPLACE_UUID,
976         REPLACE_SETUP
977 };
978
979 /** This structure is passed to mgs_replace_handler */
980 struct mgs_replace_data {
981         /* Nids are replaced for this target device */
982         struct mgs_target_info target;
983         /* Temporary modified llog */
984         struct llog_handle *temp_llh;
985         enum replace_state state;
986         char *failover;
987         char *nodeuuid;
988 };
989
990 /**
991  * Check: a) if block should be skipped
992  * b) is it target block
993  *
994  * \param[in] lcfg
995  * \param[in] mrd
996  *
997  * \retval 0 should not to be skipped
998  * \retval 1 should to be skipped
999  */
1000 static int check_markers(struct lustre_cfg *lcfg,
1001                          struct mgs_replace_data *mrd)
1002 {
1003          struct cfg_marker *marker;
1004
1005         /* Track markers. Find given device */
1006         if (lcfg->lcfg_command == LCFG_MARKER) {
1007                 marker = lustre_cfg_buf(lcfg, 1);
1008                 /* Clean llog from records marked as CM_SKIP.
1009                    CM_EXCLUDE records are used for "active" command
1010                    and can be restored if needed */
1011                 if ((marker->cm_flags & (CM_SKIP | CM_START)) ==
1012                     (CM_SKIP | CM_START)) {
1013                         mrd->state = REPLACE_SKIP;
1014                         return 1;
1015                 }
1016
1017                 if ((marker->cm_flags & (CM_SKIP | CM_END)) ==
1018                     (CM_SKIP | CM_END)) {
1019                         mrd->state = REPLACE_COPY;
1020                         return 1;
1021                 }
1022
1023                 if (strcmp(mrd->target.mti_svname, marker->cm_tgtname) == 0) {
1024                         LASSERT(!(marker->cm_flags & CM_START) ||
1025                                 !(marker->cm_flags & CM_END));
1026                         if (marker->cm_flags & CM_START) {
1027                                 if (!strncmp(marker->cm_comment,
1028                                              "add failnid", 11)) {
1029                                         mrd->state = REPLACE_SKIP;
1030                                 } else {
1031                                         mrd->state = REPLACE_UUID;
1032                                         mrd->failover = NULL;
1033                                 }
1034                         } else if (marker->cm_flags & CM_END)
1035                                 mrd->state = REPLACE_COPY;
1036
1037                         if (!strncmp(marker->cm_comment,
1038                                 "add failnid", 11))
1039                                 return 1;
1040                 }
1041         }
1042
1043         return 0;
1044 }
1045
1046 static int record_base(const struct lu_env *env, struct llog_handle *llh,
1047                      char *cfgname, lnet_nid_t nid, int cmd,
1048                      char *s1, char *s2, char *s3, char *s4)
1049 {
1050         struct mgs_thread_info  *mgi = mgs_env_info(env);
1051         struct llog_cfg_rec     *lcr;
1052         int rc;
1053
1054         CDEBUG(D_MGS, "lcfg %s %#x %s %s %s %s\n", cfgname,
1055                cmd, s1, s2, s3, s4);
1056
1057         lustre_cfg_bufs_reset(&mgi->mgi_bufs, cfgname);
1058         if (s1)
1059                 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, s1);
1060         if (s2)
1061                 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 2, s2);
1062         if (s3)
1063                 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 3, s3);
1064         if (s4)
1065                 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 4, s4);
1066
1067         lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
1068         if (lcr == NULL)
1069                 return -ENOMEM;
1070
1071         lcr->lcr_cfg.lcfg_nid = nid;
1072         rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1073
1074         lustre_cfg_rec_free(lcr);
1075
1076         if (rc < 0)
1077                 CDEBUG(D_MGS,
1078                        "failed to write lcfg %s %#x %s %s %s %s: rc = %d\n",
1079                        cfgname, cmd, s1, s2, s3, s4, rc);
1080         return rc;
1081 }
1082
1083 static inline int record_add_uuid(const struct lu_env *env,
1084                                   struct llog_handle *llh,
1085                                   uint64_t nid, char *uuid)
1086 {
1087         return record_base(env, llh, NULL, nid, LCFG_ADD_UUID, uuid,
1088                            NULL, NULL, NULL);
1089 }
1090
1091 static inline int record_add_conn(const struct lu_env *env,
1092                                   struct llog_handle *llh,
1093                                   char *devname, char *uuid)
1094 {
1095         return record_base(env, llh, devname, 0, LCFG_ADD_CONN, uuid,
1096                            NULL, NULL, NULL);
1097 }
1098
1099 static inline int record_attach(const struct lu_env *env,
1100                                 struct llog_handle *llh, char *devname,
1101                                 char *type, char *uuid)
1102 {
1103         return record_base(env, llh, devname, 0, LCFG_ATTACH, type, uuid,
1104                            NULL, NULL);
1105 }
1106
1107 static inline int record_setup(const struct lu_env *env,
1108                                struct llog_handle *llh, char *devname,
1109                                char *s1, char *s2, char *s3, char *s4)
1110 {
1111         return record_base(env, llh, devname, 0, LCFG_SETUP, s1, s2, s3, s4);
1112 }
1113
1114 /**
1115  * \retval <0 record processing error
1116  * \retval n record is processed. No need copy original one.
1117  * \retval 0 record is not processed.
1118  */
1119 static int process_command(const struct lu_env *env, struct lustre_cfg *lcfg,
1120                            struct mgs_replace_data *mrd)
1121 {
1122         int nids_added = 0;
1123         lnet_nid_t nid;
1124         char *ptr;
1125         int rc = 0;
1126
1127         if (mrd->state == REPLACE_UUID &&
1128             lcfg->lcfg_command == LCFG_ADD_UUID) {
1129                 /* LCFG_ADD_UUID command found. Let's skip original command
1130                    and add passed nids */
1131                 ptr = mrd->target.mti_params;
1132                 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
1133                         if (!mrd->nodeuuid) {
1134                                 rc = name_create(&mrd->nodeuuid,
1135                                                  libcfs_nid2str(nid), "");
1136                                 if (rc) {
1137                                         CERROR("Can't create uuid for "
1138                                                 "nid  %s, device %s\n",
1139                                                 libcfs_nid2str(nid),
1140                                                 mrd->target.mti_svname);
1141                                         return rc;
1142                                 }
1143                         }
1144                         CDEBUG(D_MGS, "add nid %s with uuid %s, "
1145                                "device %s\n", libcfs_nid2str(nid),
1146                                 mrd->target.mti_params,
1147                                 mrd->nodeuuid);
1148                         rc = record_add_uuid(env,
1149                                              mrd->temp_llh, nid,
1150                                              mrd->nodeuuid);
1151                         if (rc)
1152                                 CWARN("%s: Can't add nid %s for uuid %s :rc=%d\n",
1153                                         mrd->target.mti_svname,
1154                                         libcfs_nid2str(nid),
1155                                         mrd->nodeuuid, rc);
1156                         else
1157                                 nids_added++;
1158
1159                         if (*ptr == ':') {
1160                                 mrd->failover = ptr;
1161                                 break;
1162                         }
1163                 }
1164
1165                 if (nids_added == 0) {
1166                         CERROR("No new nids were added, nid %s with uuid %s, "
1167                                "device %s\n", libcfs_nid2str(nid),
1168                                mrd->nodeuuid ? mrd->nodeuuid : "NULL",
1169                                mrd->target.mti_svname);
1170                         name_destroy(&mrd->nodeuuid);
1171                         return -ENXIO;
1172                 } else {
1173                         mrd->state = REPLACE_SETUP;
1174                 }
1175
1176                 return nids_added;
1177         }
1178
1179         if (mrd->state == REPLACE_SETUP && lcfg->lcfg_command == LCFG_SETUP) {
1180                 /* LCFG_SETUP command found. UUID should be changed */
1181                 rc = record_setup(env,
1182                                   mrd->temp_llh,
1183                                   /* devname the same */
1184                                   lustre_cfg_string(lcfg, 0),
1185                                   /* s1 is not changed */
1186                                   lustre_cfg_string(lcfg, 1),
1187                                   mrd->nodeuuid,
1188                                   /* s3 is not changed */
1189                                   lustre_cfg_string(lcfg, 3),
1190                                   /* s4 is not changed */
1191                                   lustre_cfg_string(lcfg, 4));
1192
1193                 name_destroy(&mrd->nodeuuid);
1194                 if (rc)
1195                         return rc;
1196
1197                 if (mrd->failover) {
1198                         ptr = mrd->failover;
1199                         while (class_parse_nid(ptr, &nid, &ptr) == 0) {
1200                                 if (mrd->nodeuuid == NULL) {
1201                                         rc =  name_create(&mrd->nodeuuid,
1202                                                           libcfs_nid2str(nid),
1203                                                           "");
1204                                         if (rc)
1205                                                 return rc;
1206                                 }
1207
1208                                 CDEBUG(D_MGS, "add nid %s for failover %s\n",
1209                                        libcfs_nid2str(nid), mrd->nodeuuid);
1210                                 rc = record_add_uuid(env, mrd->temp_llh, nid,
1211                                                      mrd->nodeuuid);
1212                                 if (rc) {
1213                                         CWARN("%s: Can't add nid %s for failover %s :rc = %d\n",
1214                                                 mrd->target.mti_svname,
1215                                                 libcfs_nid2str(nid),
1216                                                 mrd->nodeuuid, rc);
1217                                         name_destroy(&mrd->nodeuuid);
1218                                         return rc;
1219                                 }
1220                                 if (*ptr == ':') {
1221                                         rc = record_add_conn(env,
1222                                                 mrd->temp_llh,
1223                                                 lustre_cfg_string(lcfg, 0),
1224                                                 mrd->nodeuuid);
1225                                         name_destroy(&mrd->nodeuuid);
1226                                         if (rc)
1227                                                 return rc;
1228                                 }
1229                         }
1230                         if (mrd->nodeuuid) {
1231                                 rc = record_add_conn(env, mrd->temp_llh,
1232                                                      lustre_cfg_string(lcfg, 0),
1233                                                      mrd->nodeuuid);
1234                                 name_destroy(&mrd->nodeuuid);
1235                                 if (rc)
1236                                         return rc;
1237                         }
1238                 }
1239                 mrd->state = REPLACE_DONE;
1240                 return rc ? rc : 1;
1241         }
1242
1243         /* All new UUID are added. Skip. */
1244         if (mrd->state == REPLACE_SETUP &&
1245                 lcfg->lcfg_command == LCFG_ADD_UUID)
1246                 return 1;
1247
1248         /* Another commands in target device block */
1249         return 0;
1250 }
1251
1252 /**
1253  * Handler that called for every record in llog.
1254  * Records are processed in order they placed in llog.
1255  *
1256  * \param[in] llh       log to be processed
1257  * \param[in] rec       current record
1258  * \param[in] data      mgs_replace_data structure
1259  *
1260  * \retval 0    success
1261  */
1262 static int mgs_replace_nids_handler(const struct lu_env *env,
1263                                     struct llog_handle *llh,
1264                                     struct llog_rec_hdr *rec,
1265                                     void *data)
1266 {
1267         struct mgs_replace_data *mrd;
1268         struct lustre_cfg *lcfg = REC_DATA(rec);
1269         int cfg_len = REC_DATA_LEN(rec);
1270         int rc;
1271         ENTRY;
1272
1273         mrd = (struct mgs_replace_data *)data;
1274
1275         if (rec->lrh_type != OBD_CFG_REC) {
1276                 CERROR("unhandled lrh_type: %#x, cmd %x %s %s\n",
1277                        rec->lrh_type, lcfg->lcfg_command,
1278                        lustre_cfg_string(lcfg, 0),
1279                        lustre_cfg_string(lcfg, 1));
1280                 RETURN(-EINVAL);
1281         }
1282
1283         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
1284         if (rc) {
1285                 /* Do not copy any invalidated records */
1286                 GOTO(skip_out, rc = 0);
1287         }
1288
1289         rc = check_markers(lcfg, mrd);
1290         if (rc || mrd->state == REPLACE_SKIP)
1291                 GOTO(skip_out, rc = 0);
1292
1293         /* Write to new log all commands outside target device block */
1294         if (mrd->state == REPLACE_COPY)
1295                 GOTO(copy_out, rc = 0);
1296
1297         if (mrd->state == REPLACE_DONE &&
1298             (lcfg->lcfg_command == LCFG_ADD_UUID ||
1299              lcfg->lcfg_command == LCFG_ADD_CONN)) {
1300                 if (!mrd->failover)
1301                         CWARN("Previous failover is deleted, but new one is "
1302                               "not set. This means you configure system "
1303                               "without failover or passed wrong replace_nids "
1304                               "command parameters. Device %s, passed nids %s\n",
1305                               mrd->target.mti_svname, mrd->target.mti_params);
1306                 GOTO(skip_out, rc = 0);
1307         }
1308
1309         rc = process_command(env, lcfg, mrd);
1310         if (rc < 0)
1311                 RETURN(rc);
1312
1313         if (rc)
1314                 RETURN(0);
1315 copy_out:
1316         /* Record is placed in temporary llog as is */
1317         rc = llog_write(env, mrd->temp_llh, rec, LLOG_NEXT_IDX);
1318
1319         CDEBUG(D_MGS, "Copied idx=%d, rc=%d, len=%d, cmd %x %s %s\n",
1320                rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
1321                lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
1322         RETURN(rc);
1323
1324 skip_out:
1325         CDEBUG(D_MGS, "Skipped idx=%d, rc=%d, len=%d, cmd %x %s %s\n",
1326                rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
1327                lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
1328         RETURN(rc);
1329 }
1330
1331 static int mgs_log_is_empty(const struct lu_env *env,
1332                             struct mgs_device *mgs, char *name)
1333 {
1334         struct llog_ctxt        *ctxt;
1335         int                      rc;
1336
1337         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
1338         LASSERT(ctxt != NULL);
1339
1340         rc = llog_is_empty(env, ctxt, name);
1341         llog_ctxt_put(ctxt);
1342         return rc;
1343 }
1344
1345 static int mgs_replace_log(const struct lu_env *env,
1346                            struct obd_device *mgs,
1347                            char *logname, char *devname,
1348                            llog_cb_t replace_handler, void *data)
1349 {
1350         struct llog_handle *orig_llh, *backup_llh;
1351         struct llog_ctxt *ctxt;
1352         struct mgs_replace_data *mrd;
1353         struct mgs_device *mgs_dev = lu2mgs_dev(mgs->obd_lu_dev);
1354         static struct obd_uuid   cfg_uuid = { .uuid = "config_uuid" };
1355         char *backup;
1356         int rc, rc2, buf_size;
1357         time64_t now;
1358         ENTRY;
1359
1360         ctxt = llog_get_context(mgs, LLOG_CONFIG_ORIG_CTXT);
1361         LASSERT(ctxt != NULL);
1362
1363         if (mgs_log_is_empty(env, mgs_dev, logname)) {
1364                 /* Log is empty. Nothing to replace */
1365                 GOTO(out_put, rc = 0);
1366         }
1367
1368         now = ktime_get_real_seconds();
1369
1370         /* max time64_t in decimal fits into 20 bytes long string */
1371         buf_size = strlen(logname) + 1 + 20 + 1 + strlen(".bak") + 1;
1372         OBD_ALLOC(backup, buf_size);
1373         if (backup == NULL)
1374                 GOTO(out_put, rc = -ENOMEM);
1375
1376         snprintf(backup, buf_size, "%s.%llu.bak", logname, now);
1377
1378         rc = llog_backup(env, mgs, ctxt, ctxt, logname, backup);
1379         if (rc == 0) {
1380                 /* Now erase original log file. Connections are not allowed.
1381                    Backup is already saved */
1382                 rc = llog_erase(env, ctxt, NULL, logname);
1383                 if (rc < 0)
1384                         GOTO(out_free, rc);
1385         } else if (rc != -ENOENT) {
1386                 CERROR("%s: can't make backup for %s: rc = %d\n",
1387                        mgs->obd_name, logname, rc);
1388                 GOTO(out_free,rc);
1389         }
1390
1391         /* open local log */
1392         rc = llog_open_create(env, ctxt, &orig_llh, NULL, logname);
1393         if (rc)
1394                 GOTO(out_restore, rc);
1395
1396         rc = llog_init_handle(env, orig_llh, LLOG_F_IS_PLAIN, &cfg_uuid);
1397         if (rc)
1398                 GOTO(out_closel, rc);
1399
1400         /* open backup llog */
1401         rc = llog_open(env, ctxt, &backup_llh, NULL, backup,
1402                        LLOG_OPEN_EXISTS);
1403         if (rc)
1404                 GOTO(out_closel, rc);
1405
1406         rc = llog_init_handle(env, backup_llh, LLOG_F_IS_PLAIN, NULL);
1407         if (rc)
1408                 GOTO(out_close, rc);
1409
1410         if (llog_get_size(backup_llh) <= 1)
1411                 GOTO(out_close, rc = 0);
1412
1413         OBD_ALLOC_PTR(mrd);
1414         if (!mrd)
1415                 GOTO(out_close, rc = -ENOMEM);
1416         /* devname is only needed information to replace UUID records */
1417         if (devname)
1418                 strlcpy(mrd->target.mti_svname, devname,
1419                         sizeof(mrd->target.mti_svname));
1420         /* data is parsed in llog callback */
1421         if (data)
1422                 strlcpy(mrd->target.mti_params, data,
1423                         sizeof(mrd->target.mti_params));
1424         /* Copy records to this temporary llog */
1425         mrd->temp_llh = orig_llh;
1426
1427         rc = llog_process(env, backup_llh, replace_handler,
1428                           (void *)mrd, NULL);
1429         OBD_FREE_PTR(mrd);
1430 out_close:
1431         rc2 = llog_close(NULL, backup_llh);
1432         if (!rc)
1433                 rc = rc2;
1434 out_closel:
1435         rc2 = llog_close(NULL, orig_llh);
1436         if (!rc)
1437                 rc = rc2;
1438
1439 out_restore:
1440         if (rc) {
1441                 CERROR("%s: llog should be restored: rc = %d\n",
1442                        mgs->obd_name, rc);
1443                 rc2 = llog_backup(env, mgs, ctxt, ctxt, backup,
1444                                   logname);
1445                 if (rc2 < 0)
1446                         CERROR("%s: can't restore backup %s: rc = %d\n",
1447                                mgs->obd_name, logname, rc2);
1448         }
1449
1450 out_free:
1451         OBD_FREE(backup, buf_size);
1452
1453 out_put:
1454         llog_ctxt_put(ctxt);
1455
1456         if (rc)
1457                 CERROR("%s: failed to replace log %s: rc = %d\n",
1458                        mgs->obd_name, logname, rc);
1459
1460         RETURN(rc);
1461 }
1462
1463 static int mgs_replace_nids_log(const struct lu_env *env,
1464                                 struct obd_device *obd,
1465                                 char *logname, char *devname, char *nids)
1466 {
1467         CDEBUG(D_MGS, "Replace NIDs for %s in %s\n", devname, logname);
1468         return mgs_replace_log(env, obd, logname, devname,
1469                                mgs_replace_nids_handler, nids);
1470 }
1471
1472 /**
1473  * Parse device name and get file system name and/or device index
1474  *
1475  * @devname     device name (ex. lustre-MDT0000)
1476  * @fsname      file system name extracted from @devname and returned
1477  *              to the caller (optional)
1478  * @index       device index extracted from @devname and returned to
1479  *              the caller (optional)
1480  *
1481  * RETURN       0                       success if we are only interested in
1482  *                                      extracting fsname from devname.
1483  *                                      i.e index is NULL
1484  *
1485  *              LDD_F_SV_TYPE_*         Besides extracting the fsname the
1486  *                                      user also wants the index. Report to
1487  *                                      the user the type of obd device the
1488  *                                      returned index belongs too.
1489  *
1490  *              -EINVAL                 The obd device name is improper so
1491  *                                      fsname could not be extracted.
1492  *
1493  *              -ENXIO                  Failed to extract the index out of
1494  *                                      the obd device name. Most likely an
1495  *                                      invalid obd device name
1496  */
1497 static int mgs_parse_devname(char *devname, char *fsname, u32 *index)
1498 {
1499         int rc = 0;
1500         ENTRY;
1501
1502         /* Extract fsname */
1503         if (fsname) {
1504                 rc = server_name2fsname(devname, fsname, NULL);
1505                 if (rc < 0) {
1506                         CDEBUG(D_MGS, "Device name %s without fsname\n",
1507                                devname);
1508                         RETURN(-EINVAL);
1509                 }
1510         }
1511
1512         if (index) {
1513                 rc = server_name2index(devname, index, NULL);
1514                 if (rc < 0) {
1515                         CDEBUG(D_MGS, "Device name %s with wrong index\n",
1516                                devname);
1517                         RETURN(-ENXIO);
1518                 }
1519         }
1520
1521         /* server_name2index can return LDD_F_SV_TYPE_* so always return rc */
1522         RETURN(rc);
1523 }
1524
1525 /* This is only called during replace_nids */
1526 static int only_mgs_is_running(struct obd_device *mgs_obd)
1527 {
1528         /* TDB: Is global variable with devices count exists? */
1529         int num_devices = get_devices_count();
1530         int num_exports = 0;
1531         struct obd_export *exp;
1532
1533         spin_lock(&mgs_obd->obd_dev_lock);
1534         list_for_each_entry(exp, &mgs_obd->obd_exports, exp_obd_chain) {
1535                 /* skip self export */
1536                 if (exp == mgs_obd->obd_self_export)
1537                         continue;
1538
1539                 ++num_exports;
1540
1541                 if (num_exports > 1)
1542                         CERROR("%s: node %s still connected during replace_nids connect_flags:%llx\n",
1543                                mgs_obd->obd_name,
1544                                libcfs_nid2str(exp->exp_nid_stats->nid),
1545                                exp_connect_flags(exp));
1546         }
1547         spin_unlock(&mgs_obd->obd_dev_lock);
1548
1549         /* osd, MGS and MGC + MGC export (nosvc starts MGC)
1550          *  (wc -l /proc/fs/lustre/devices <= 3) && (non self exports == 1)
1551          */
1552         return (num_devices <= 3) && (num_exports <= 1);
1553 }
1554
1555 static int name_create_mdt(char **logname, char *fsname, int mdt_idx)
1556 {
1557         char postfix[9];
1558
1559         if (mdt_idx > INDEX_MAP_MAX_VALUE)
1560                 return -E2BIG;
1561
1562         snprintf(postfix, sizeof(postfix), "-MDT%04x", mdt_idx);
1563         return name_create(logname, fsname, postfix);
1564 }
1565
1566 /**
1567  * Replace nids for \a device to \a nids values
1568  *
1569  * \param obd           MGS obd device
1570  * \param devname       nids need to be replaced for this device
1571  * (ex. lustre-OST0000)
1572  * \param nids          nids list (ex. nid1,nid2,nid3)
1573  *
1574  * \retval 0    success
1575  */
1576 int mgs_replace_nids(const struct lu_env *env,
1577                      struct mgs_device *mgs,
1578                      char *devname, char *nids)
1579 {
1580         /* Assume fsname is part of device name */
1581         char fsname[MTI_NAME_MAXLEN];
1582         int rc;
1583         __u32 index;
1584         char *logname;
1585         struct fs_db *fsdb = NULL;
1586         unsigned int i;
1587         int conn_state;
1588         struct obd_device *mgs_obd = mgs->mgs_obd;
1589         ENTRY;
1590
1591         /* We can only change NIDs if no other nodes are connected */
1592         spin_lock(&mgs_obd->obd_dev_lock);
1593         conn_state = mgs_obd->obd_no_conn;
1594         mgs_obd->obd_no_conn = 1;
1595         spin_unlock(&mgs_obd->obd_dev_lock);
1596
1597         /* We can not change nids if not only MGS is started */
1598         if (!only_mgs_is_running(mgs_obd)) {
1599                 CERROR("Only MGS is allowed to be started\n");
1600                 GOTO(out, rc = -EINPROGRESS);
1601         }
1602
1603         /* Get fsname and index */
1604         rc = mgs_parse_devname(devname, fsname, &index);
1605         if (rc < 0)
1606                 GOTO(out, rc);
1607
1608         rc = mgs_find_or_make_fsdb(env, mgs, fsname, &fsdb);
1609         if (rc) {
1610                 CERROR("%s: can't find fsdb: rc = %d\n", fsname, rc);
1611                 GOTO(out, rc);
1612         }
1613
1614         /* Process client llogs */
1615         rc = name_create(&logname, fsname, "-client");
1616         if (rc)
1617                 GOTO(out, rc);
1618         rc = mgs_replace_nids_log(env, mgs_obd, logname, devname, nids);
1619         name_destroy(&logname);
1620         if (rc) {
1621                 CERROR("%s: error while replacing NIDs for %s: rc = %d\n",
1622                        fsname, devname, rc);
1623                 GOTO(out, rc);
1624         }
1625
1626         /* Process MDT llogs */
1627         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
1628                 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
1629                         continue;
1630                 rc = name_create_mdt(&logname, fsname, i);
1631                 if (rc)
1632                         GOTO(out, rc);
1633                 rc = mgs_replace_nids_log(env, mgs_obd, logname, devname, nids);
1634                 name_destroy(&logname);
1635                 if (rc)
1636                         GOTO(out, rc);
1637         }
1638
1639 out:
1640         spin_lock(&mgs_obd->obd_dev_lock);
1641         mgs_obd->obd_no_conn = conn_state;
1642         spin_unlock(&mgs_obd->obd_dev_lock);
1643
1644         if (fsdb)
1645                 mgs_put_fsdb(mgs, fsdb);
1646
1647         RETURN(rc);
1648 }
1649
1650 /**
1651  * This is called for every record in llog. Some of records are
1652  * skipped, others are copied to new log as is.
1653  * Records to be skipped are
1654  *  marker records marked SKIP
1655  *  records enclosed between SKIP markers
1656  *
1657  * \param[in] llh       log to be processed
1658  * \param[in] rec       current record
1659  * \param[in] data      mgs_replace_data structure
1660  *
1661  * \retval 0    success
1662  **/
1663 static int mgs_clear_config_handler(const struct lu_env *env,
1664                                     struct llog_handle *llh,
1665                                     struct llog_rec_hdr *rec, void *data)
1666 {
1667         struct mgs_replace_data *mrd;
1668         struct lustre_cfg *lcfg = REC_DATA(rec);
1669         int cfg_len = REC_DATA_LEN(rec);
1670         int rc;
1671
1672         ENTRY;
1673
1674         mrd = (struct mgs_replace_data *)data;
1675
1676         if (rec->lrh_type != OBD_CFG_REC) {
1677                 CDEBUG(D_MGS, "Config llog Name=%s, Record Index=%u, "
1678                        "Unhandled Record Type=%#x\n", llh->lgh_name,
1679                        rec->lrh_index, rec->lrh_type);
1680                 RETURN(-EINVAL);
1681         }
1682
1683         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
1684         if (rc) {
1685                 CDEBUG(D_MGS, "Config llog Name=%s, Invalid config file.",
1686                        llh->lgh_name);
1687                 RETURN(-EINVAL);
1688         }
1689
1690         if (lcfg->lcfg_command == LCFG_MARKER) {
1691                 struct cfg_marker *marker;
1692
1693                 marker = lustre_cfg_buf(lcfg, 1);
1694                 if (marker->cm_flags & CM_SKIP) {
1695                         if (marker->cm_flags & CM_START)
1696                                 mrd->state = REPLACE_SKIP;
1697                         if (marker->cm_flags & CM_END)
1698                                 mrd->state = REPLACE_COPY;
1699                         /* SKIP section started or finished */
1700                         CDEBUG(D_MGS, "Skip idx=%d, rc=%d, len=%d, "
1701                                "cmd %x %s %s\n", rec->lrh_index, rc,
1702                                rec->lrh_len, lcfg->lcfg_command,
1703                                lustre_cfg_string(lcfg, 0),
1704                                lustre_cfg_string(lcfg, 1));
1705                         RETURN(0);
1706                 }
1707         } else {
1708                 if (mrd->state == REPLACE_SKIP) {
1709                         /* record enclosed between SKIP markers, skip it */
1710                         CDEBUG(D_MGS, "Skip idx=%d, rc=%d, len=%d, "
1711                                "cmd %x %s %s\n", rec->lrh_index, rc,
1712                                rec->lrh_len, lcfg->lcfg_command,
1713                                lustre_cfg_string(lcfg, 0),
1714                                lustre_cfg_string(lcfg, 1));
1715                         RETURN(0);
1716                 }
1717         }
1718
1719         /* Record is placed in temporary llog as is */
1720         rc = llog_write(env, mrd->temp_llh, rec, LLOG_NEXT_IDX);
1721
1722         CDEBUG(D_MGS, "Copied idx=%d, rc=%d, len=%d, cmd %x %s %s\n",
1723                rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
1724                lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
1725         RETURN(rc);
1726 }
1727
1728 /*
1729  * Directory CONFIGS/ may contain files which are not config logs to
1730  * be cleared. Skip any llogs with a non-alphanumeric character after
1731  * the last '-'. For example, fsname-MDT0000.sav, fsname-MDT0000.bak,
1732  * fsname-MDT0000.orig, fsname-MDT0000~, fsname-MDT0000.20150516, etc.
1733  */
1734 static bool config_to_clear(const char *logname)
1735 {
1736         int i;
1737         char *str;
1738
1739         str = strrchr(logname, '-');
1740         if (!str)
1741                 return 0;
1742
1743         i = 0;
1744         while (isalnum(str[++i]));
1745         return str[i] == '\0';
1746 }
1747
1748 /**
1749  * Clear config logs for \a name
1750  *
1751  * \param env
1752  * \param mgs           MGS device
1753  * \param name          name of device or of filesystem
1754  *                      (ex. lustre-OST0000 or lustre) in later case all logs
1755  *                      will be cleared
1756  *
1757  * \retval 0            success
1758  */
1759 int mgs_clear_configs(const struct lu_env *env,
1760                      struct mgs_device *mgs, const char *name)
1761 {
1762         struct list_head dentry_list;
1763         struct mgs_direntry *dirent, *n;
1764         char *namedash;
1765         int conn_state;
1766         struct obd_device *mgs_obd = mgs->mgs_obd;
1767         int rc;
1768
1769         ENTRY;
1770
1771         /* Prevent clients and servers from connecting to mgs */
1772         spin_lock(&mgs_obd->obd_dev_lock);
1773         conn_state = mgs_obd->obd_no_conn;
1774         mgs_obd->obd_no_conn = 1;
1775         spin_unlock(&mgs_obd->obd_dev_lock);
1776
1777         /*
1778          * config logs cannot be cleaned if anything other than
1779          * MGS is started
1780          */
1781         if (!only_mgs_is_running(mgs_obd)) {
1782                 CERROR("Only MGS is allowed to be started\n");
1783                 GOTO(out, rc = -EBUSY);
1784         }
1785
1786         /* Find all the logs in the CONFIGS directory */
1787         rc = class_dentry_readdir(env, mgs, &dentry_list);
1788         if (rc) {
1789                 CERROR("%s: cannot read config directory '%s': rc = %d\n",
1790                        mgs_obd->obd_name, MOUNT_CONFIGS_DIR, rc);
1791                 GOTO(out, rc);
1792         }
1793
1794         if (list_empty(&dentry_list)) {
1795                 CERROR("%s: list empty reading config dir '%s': rc = %d\n",
1796                         mgs_obd->obd_name, MOUNT_CONFIGS_DIR, -ENOENT);
1797                 GOTO(out, rc = -ENOENT);
1798         }
1799
1800         OBD_ALLOC(namedash, strlen(name) + 2);
1801         if (namedash == NULL)
1802                 GOTO(out, rc = -ENOMEM);
1803         snprintf(namedash, strlen(name) + 2, "%s-", name);
1804
1805         list_for_each_entry(dirent, &dentry_list, mde_list) {
1806                 if (strcmp(name, dirent->mde_name) &&
1807                     strncmp(namedash, dirent->mde_name, strlen(namedash)))
1808                         continue;
1809                 if (!config_to_clear(dirent->mde_name))
1810                         continue;
1811                 CDEBUG(D_MGS, "%s: Clear config log %s\n",
1812                        mgs_obd->obd_name, dirent->mde_name);
1813                 rc = mgs_replace_log(env, mgs_obd, dirent->mde_name, NULL,
1814                                      mgs_clear_config_handler, NULL);
1815                 if (rc)
1816                         break;
1817         }
1818
1819         list_for_each_entry_safe(dirent, n, &dentry_list, mde_list) {
1820                 list_del_init(&dirent->mde_list);
1821                 mgs_direntry_free(dirent);
1822         }
1823         OBD_FREE(namedash, strlen(name) + 2);
1824 out:
1825         spin_lock(&mgs_obd->obd_dev_lock);
1826         mgs_obd->obd_no_conn = conn_state;
1827         spin_unlock(&mgs_obd->obd_dev_lock);
1828
1829         RETURN(rc);
1830 }
1831
1832 static int record_lov_setup(const struct lu_env *env, struct llog_handle *llh,
1833                             char *devname, struct lov_desc *desc)
1834 {
1835         struct mgs_thread_info  *mgi = mgs_env_info(env);
1836         struct llog_cfg_rec     *lcr;
1837         int rc;
1838
1839         lustre_cfg_bufs_reset(&mgi->mgi_bufs, devname);
1840         lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, desc, sizeof(*desc));
1841         lcr = lustre_cfg_rec_new(LCFG_SETUP, &mgi->mgi_bufs);
1842         if (lcr == NULL)
1843                 return -ENOMEM;
1844
1845         rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1846         lustre_cfg_rec_free(lcr);
1847         return rc;
1848 }
1849
1850 static int record_lmv_setup(const struct lu_env *env, struct llog_handle *llh,
1851                             char *devname, struct lmv_desc *desc)
1852 {
1853         struct mgs_thread_info  *mgi = mgs_env_info(env);
1854         struct llog_cfg_rec     *lcr;
1855         int rc;
1856
1857         lustre_cfg_bufs_reset(&mgi->mgi_bufs, devname);
1858         lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, desc, sizeof(*desc));
1859         lcr = lustre_cfg_rec_new(LCFG_SETUP, &mgi->mgi_bufs);
1860         if (lcr == NULL)
1861                 return -ENOMEM;
1862
1863         rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1864         lustre_cfg_rec_free(lcr);
1865         return rc;
1866 }
1867
1868 static inline int record_mdc_add(const struct lu_env *env,
1869                                  struct llog_handle *llh,
1870                                  char *logname, char *mdcuuid,
1871                                  char *mdtuuid, char *index,
1872                                  char *gen)
1873 {
1874         return record_base(env,llh,logname,0,LCFG_ADD_MDC,
1875                            mdtuuid,index,gen,mdcuuid);
1876 }
1877
1878 static inline int record_lov_add(const struct lu_env *env,
1879                                  struct llog_handle *llh,
1880                                  char *lov_name, char *ost_uuid,
1881                                  char *index, char *gen)
1882 {
1883         return record_base(env, llh, lov_name, 0, LCFG_LOV_ADD_OBD,
1884                            ost_uuid, index, gen, NULL);
1885 }
1886
1887 static inline int record_mount_opt(const struct lu_env *env,
1888                                    struct llog_handle *llh,
1889                                    char *profile, char *lov_name,
1890                                    char *mdc_name)
1891 {
1892         return record_base(env, llh, NULL, 0, LCFG_MOUNTOPT,
1893                            profile, lov_name, mdc_name, NULL);
1894 }
1895
1896 static int record_marker(const struct lu_env *env,
1897                          struct llog_handle *llh,
1898                          struct fs_db *fsdb, __u32 flags,
1899                          char *tgtname, char *comment)
1900 {
1901         struct mgs_thread_info *mgi = mgs_env_info(env);
1902         struct llog_cfg_rec *lcr;
1903         int rc;
1904         int cplen = 0;
1905
1906         if (flags & CM_START)
1907                 fsdb->fsdb_gen++;
1908         mgi->mgi_marker.cm_step = fsdb->fsdb_gen;
1909         mgi->mgi_marker.cm_flags = flags;
1910         mgi->mgi_marker.cm_vers = LUSTRE_VERSION_CODE;
1911         cplen = strlcpy(mgi->mgi_marker.cm_tgtname, tgtname,
1912                         sizeof(mgi->mgi_marker.cm_tgtname));
1913         if (cplen >= sizeof(mgi->mgi_marker.cm_tgtname))
1914                 return -E2BIG;
1915         cplen = strlcpy(mgi->mgi_marker.cm_comment, comment,
1916                         sizeof(mgi->mgi_marker.cm_comment));
1917         if (cplen >= sizeof(mgi->mgi_marker.cm_comment))
1918                 return -E2BIG;
1919         mgi->mgi_marker.cm_createtime = ktime_get_real_seconds();
1920         mgi->mgi_marker.cm_canceltime = 0;
1921         lustre_cfg_bufs_reset(&mgi->mgi_bufs, NULL);
1922         lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, &mgi->mgi_marker,
1923                             sizeof(mgi->mgi_marker));
1924         lcr = lustre_cfg_rec_new(LCFG_MARKER, &mgi->mgi_bufs);
1925         if (lcr == NULL)
1926                 return -ENOMEM;
1927
1928         rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1929         lustre_cfg_rec_free(lcr);
1930         return rc;
1931 }
1932
1933 static int record_start_log(const struct lu_env *env, struct mgs_device *mgs,
1934                             struct llog_handle **llh, char *name)
1935 {
1936         static struct obd_uuid   cfg_uuid = { .uuid = "config_uuid" };
1937         struct llog_ctxt        *ctxt;
1938         int                      rc = 0;
1939         ENTRY;
1940
1941         if (*llh)
1942                 GOTO(out, rc = -EBUSY);
1943
1944         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
1945         if (!ctxt)
1946                 GOTO(out, rc = -ENODEV);
1947         LASSERT(ctxt->loc_obd == mgs->mgs_obd);
1948
1949         rc = llog_open_create(env, ctxt, llh, NULL, name);
1950         if (rc)
1951                 GOTO(out_ctxt, rc);
1952         rc = llog_init_handle(env, *llh, LLOG_F_IS_PLAIN, &cfg_uuid);
1953         if (rc)
1954                 llog_close(env, *llh);
1955 out_ctxt:
1956         llog_ctxt_put(ctxt);
1957 out:
1958         if (rc) {
1959                 CERROR("%s: can't start log %s: rc = %d\n",
1960                        mgs->mgs_obd->obd_name, name, rc);
1961                 *llh = NULL;
1962         }
1963         RETURN(rc);
1964 }
1965
1966 static int record_end_log(const struct lu_env *env, struct llog_handle **llh)
1967 {
1968         int rc;
1969
1970         rc = llog_close(env, *llh);
1971         *llh = NULL;
1972
1973         return rc;
1974 }
1975
1976 /******************** config "macros" *********************/
1977
1978 /* write an lcfg directly into a log (with markers) */
1979 static int mgs_write_log_direct(const struct lu_env *env,
1980                                 struct mgs_device *mgs, struct fs_db *fsdb,
1981                                 char *logname, struct llog_cfg_rec *lcr,
1982                                 char *devname, char *comment)
1983 {
1984         struct llog_handle *llh = NULL;
1985         int rc;
1986
1987         ENTRY;
1988
1989         rc = record_start_log(env, mgs, &llh, logname);
1990         if (rc)
1991                 RETURN(rc);
1992
1993         /* FIXME These should be a single journal transaction */
1994         rc = record_marker(env, llh, fsdb, CM_START, devname, comment);
1995         if (rc)
1996                 GOTO(out_end, rc);
1997         rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1998         if (rc)
1999                 GOTO(out_end, rc);
2000         rc = record_marker(env, llh, fsdb, CM_END, devname, comment);
2001         if (rc)
2002                 GOTO(out_end, rc);
2003 out_end:
2004         record_end_log(env, &llh);
2005         RETURN(rc);
2006 }
2007
2008 /* write the lcfg in all logs for the given fs */
2009 static int mgs_write_log_direct_all(const struct lu_env *env,
2010                                     struct mgs_device *mgs,
2011                                     struct fs_db *fsdb,
2012                                     struct mgs_target_info *mti,
2013                                     struct llog_cfg_rec *lcr, char *devname,
2014                                     char *comment, int server_only)
2015 {
2016         struct list_head         log_list;
2017         struct mgs_direntry     *dirent, *n;
2018         char                    *fsname = mti->mti_fsname;
2019         int                      rc = 0, len = strlen(fsname);
2020
2021         ENTRY;
2022         /* Find all the logs in the CONFIGS directory */
2023         rc = class_dentry_readdir(env, mgs, &log_list);
2024         if (rc)
2025                 RETURN(rc);
2026
2027         /* Could use fsdb index maps instead of directory listing */
2028         list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
2029                 list_del_init(&dirent->mde_list);
2030                 /* don't write to sptlrpc rule log */
2031                 if (strstr(dirent->mde_name, "-sptlrpc") != NULL)
2032                         goto next;
2033
2034                 /* caller wants write server logs only */
2035                 if (server_only && strstr(dirent->mde_name, "-client") != NULL)
2036                         goto next;
2037
2038                 if (strlen(dirent->mde_name) <= len ||
2039                     strncmp(fsname, dirent->mde_name, len) != 0 ||
2040                     dirent->mde_name[len] != '-')
2041                         goto next;
2042
2043                 CDEBUG(D_MGS, "Changing log %s\n", dirent->mde_name);
2044                 /* Erase any old settings of this same parameter */
2045                 rc = mgs_modify(env, mgs, fsdb, mti, dirent->mde_name,
2046                                 devname, comment, CM_SKIP);
2047                 if (rc < 0)
2048                         CERROR("%s: Can't modify llog %s: rc = %d\n",
2049                                mgs->mgs_obd->obd_name, dirent->mde_name, rc);
2050                 if (lcr == NULL)
2051                         goto next;
2052                 /* Write the new one */
2053                 rc = mgs_write_log_direct(env, mgs, fsdb, dirent->mde_name,
2054                                           lcr, devname, comment);
2055                 if (rc != 0)
2056                         CERROR("%s: writing log %s: rc = %d\n",
2057                                mgs->mgs_obd->obd_name, dirent->mde_name, rc);
2058 next:
2059                 mgs_direntry_free(dirent);
2060         }
2061
2062         RETURN(rc);
2063 }
2064
2065 static int mgs_write_log_osp_to_mdt(const struct lu_env *env,
2066                                     struct mgs_device *mgs,
2067                                     struct fs_db *fsdb,
2068                                     struct mgs_target_info *mti,
2069                                     int index, char *logname);
2070 static int mgs_write_log_osc_to_lov(const struct lu_env *env,
2071                                     struct mgs_device *mgs,
2072                                     struct fs_db *fsdb,
2073                                     struct mgs_target_info *mti,
2074                                     char *logname, char *suffix, char *lovname,
2075                                     enum lustre_sec_part sec_part, int flags);
2076 static int name_create_mdt_and_lov(char **logname, char **lovname,
2077                                    struct fs_db *fsdb, int i);
2078
2079 static int add_param(char *params, char *key, char *val)
2080 {
2081         char *start = params + strlen(params);
2082         char *end = params + sizeof(((struct mgs_target_info *)0)->mti_params);
2083         int keylen = 0;
2084
2085         if (key != NULL)
2086                 keylen = strlen(key);
2087         if (start + 1 + keylen + strlen(val) >= end) {
2088                 CERROR("params are too long: %s %s%s\n",
2089                        params, key != NULL ? key : "", val);
2090                 return -EINVAL;
2091         }
2092
2093         sprintf(start, " %s%s", key != NULL ? key : "", val);
2094         return 0;
2095 }
2096
2097 /**
2098  * Walk through client config log record and convert the related records
2099  * into the target.
2100  **/
2101 static int mgs_steal_client_llog_handler(const struct lu_env *env,
2102                                          struct llog_handle *llh,
2103                                          struct llog_rec_hdr *rec, void *data)
2104 {
2105         struct mgs_device *mgs;
2106         struct obd_device *obd;
2107         struct mgs_target_info *mti, *tmti;
2108         struct fs_db *fsdb;
2109         int cfg_len = rec->lrh_len;
2110         char *cfg_buf = (char*) (rec + 1);
2111         struct lustre_cfg *lcfg;
2112         int rc = 0;
2113         struct llog_handle *mdt_llh = NULL;
2114         static int got_an_osc_or_mdc = 0;
2115         /* 0: not found any osc/mdc;
2116            1: found osc;
2117            2: found mdc;
2118         */
2119         static int last_step = -1;
2120         int cplen = 0;
2121
2122         ENTRY;
2123
2124         mti = ((struct temp_comp*)data)->comp_mti;
2125         tmti = ((struct temp_comp*)data)->comp_tmti;
2126         fsdb = ((struct temp_comp*)data)->comp_fsdb;
2127         obd = ((struct temp_comp *)data)->comp_obd;
2128         mgs = lu2mgs_dev(obd->obd_lu_dev);
2129         LASSERT(mgs);
2130
2131         if (rec->lrh_type != OBD_CFG_REC) {
2132                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
2133                 RETURN(-EINVAL);
2134         }
2135
2136         rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
2137         if (rc) {
2138                 CERROR("Insane cfg\n");
2139                 RETURN(rc);
2140         }
2141
2142         lcfg = (struct lustre_cfg *)cfg_buf;
2143
2144         if (lcfg->lcfg_command == LCFG_MARKER) {
2145                 struct cfg_marker *marker;
2146                 marker = lustre_cfg_buf(lcfg, 1);
2147                 if (!strncmp(marker->cm_comment, "add osc", 7) &&
2148                     (marker->cm_flags & CM_START) &&
2149                      !(marker->cm_flags & CM_SKIP)) {
2150                         got_an_osc_or_mdc = 1;
2151                         cplen = strlcpy(tmti->mti_svname, marker->cm_tgtname,
2152                                         sizeof(tmti->mti_svname));
2153                         if (cplen >= sizeof(tmti->mti_svname))
2154                                 RETURN(-E2BIG);
2155                         rc = record_start_log(env, mgs, &mdt_llh,
2156                                               mti->mti_svname);
2157                         if (rc)
2158                                 RETURN(rc);
2159                         rc = record_marker(env, mdt_llh, fsdb, CM_START,
2160                                            mti->mti_svname, "add osc(copied)");
2161                         record_end_log(env, &mdt_llh);
2162                         last_step = marker->cm_step;
2163                         RETURN(rc);
2164                 }
2165                 if (!strncmp(marker->cm_comment, "add osc", 7) &&
2166                     (marker->cm_flags & CM_END) &&
2167                      !(marker->cm_flags & CM_SKIP)) {
2168                         LASSERT(last_step == marker->cm_step);
2169                         last_step = -1;
2170                         got_an_osc_or_mdc = 0;
2171                         memset(tmti, 0, sizeof(*tmti));
2172                         rc = record_start_log(env, mgs, &mdt_llh,
2173                                               mti->mti_svname);
2174                         if (rc)
2175                                 RETURN(rc);
2176                         rc = record_marker(env, mdt_llh, fsdb, CM_END,
2177                                            mti->mti_svname, "add osc(copied)");
2178                         record_end_log(env, &mdt_llh);
2179                         RETURN(rc);
2180                 }
2181                 if (!strncmp(marker->cm_comment, "add mdc", 7) &&
2182                     (marker->cm_flags & CM_START) &&
2183                      !(marker->cm_flags & CM_SKIP)) {
2184                         got_an_osc_or_mdc = 2;
2185                         last_step = marker->cm_step;
2186                         memcpy(tmti->mti_svname, marker->cm_tgtname,
2187                                strlen(marker->cm_tgtname));
2188
2189                         RETURN(rc);
2190                 }
2191                 if (!strncmp(marker->cm_comment, "add mdc", 7) &&
2192                     (marker->cm_flags & CM_END) &&
2193                      !(marker->cm_flags & CM_SKIP)) {
2194                         LASSERT(last_step == marker->cm_step);
2195                         last_step = -1;
2196                         got_an_osc_or_mdc = 0;
2197                         memset(tmti, 0, sizeof(*tmti));
2198                         RETURN(rc);
2199                 }
2200         }
2201
2202         if (got_an_osc_or_mdc == 0 || last_step < 0)
2203                 RETURN(rc);
2204
2205         if (lcfg->lcfg_command == LCFG_ADD_UUID) {
2206                 __u64 nodenid = lcfg->lcfg_nid;
2207
2208                 if (strlen(tmti->mti_uuid) == 0) {
2209                         /* target uuid not set, this config record is before
2210                          * LCFG_SETUP, this nid is one of target node nid.
2211                          */
2212                         tmti->mti_nids[tmti->mti_nid_count] = nodenid;
2213                         tmti->mti_nid_count++;
2214                 } else {
2215                         char nidstr[LNET_NIDSTR_SIZE];
2216
2217                         /* failover node nid */
2218                         libcfs_nid2str_r(nodenid, nidstr, sizeof(nidstr));
2219                         rc = add_param(tmti->mti_params, PARAM_FAILNODE,
2220                                         nidstr);
2221                 }
2222
2223                 RETURN(rc);
2224         }
2225
2226         if (lcfg->lcfg_command == LCFG_SETUP) {
2227                 char *target;
2228
2229                 target = lustre_cfg_string(lcfg, 1);
2230                 memcpy(tmti->mti_uuid, target, strlen(target));
2231                 RETURN(rc);
2232         }
2233
2234         /* ignore client side sptlrpc_conf_log */
2235         if (lcfg->lcfg_command == LCFG_SPTLRPC_CONF)
2236                 RETURN(rc);
2237
2238         if (lcfg->lcfg_command == LCFG_ADD_MDC &&
2239             strstr(lustre_cfg_string(lcfg, 0), "-clilmv") != NULL) {
2240                 int index;
2241
2242                 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1)
2243                         RETURN (-EINVAL);
2244
2245                 memcpy(tmti->mti_fsname, mti->mti_fsname,
2246                        strlen(mti->mti_fsname));
2247                 tmti->mti_stripe_index = index;
2248
2249                 rc = mgs_write_log_osp_to_mdt(env, mgs, fsdb, tmti,
2250                                               mti->mti_stripe_index,
2251                                               mti->mti_svname);
2252                 memset(tmti, 0, sizeof(*tmti));
2253                 RETURN(rc);
2254         }
2255
2256         if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD) {
2257                 int index;
2258                 char mdt_index[9];
2259                 char *logname, *lovname;
2260
2261                 rc = name_create_mdt_and_lov(&logname, &lovname, fsdb,
2262                                              mti->mti_stripe_index);
2263                 if (rc)
2264                         RETURN(rc);
2265                 sprintf(mdt_index, "-MDT%04x", mti->mti_stripe_index);
2266
2267                 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1) {
2268                         name_destroy(&logname);
2269                         name_destroy(&lovname);
2270                         RETURN(-EINVAL);
2271                 }
2272
2273                 tmti->mti_stripe_index = index;
2274                 rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, tmti, logname,
2275                                          mdt_index, lovname,
2276                                          LUSTRE_SP_MDT, 0);
2277                 name_destroy(&logname);
2278                 name_destroy(&lovname);
2279                 RETURN(rc);
2280         }
2281         RETURN(rc);
2282 }
2283
2284 /* fsdb->fsdb_mutex is already held  in mgs_write_log_target*/
2285 /* stealed from mgs_get_fsdb_from_llog*/
2286 static int mgs_steal_llog_for_mdt_from_client(const struct lu_env *env,
2287                                               struct mgs_device *mgs,
2288                                               char *client_name,
2289                                               struct temp_comp* comp)
2290 {
2291         struct llog_handle *loghandle;
2292         struct mgs_target_info *tmti;
2293         struct llog_ctxt *ctxt;
2294         int rc;
2295
2296         ENTRY;
2297
2298         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
2299         LASSERT(ctxt != NULL);
2300
2301         OBD_ALLOC_PTR(tmti);
2302         if (tmti == NULL)
2303                 GOTO(out_ctxt, rc = -ENOMEM);
2304
2305         comp->comp_tmti = tmti;
2306         comp->comp_obd = mgs->mgs_obd;
2307
2308         rc = llog_open(env, ctxt, &loghandle, NULL, client_name,
2309                        LLOG_OPEN_EXISTS);
2310         if (rc < 0) {
2311                 if (rc == -ENOENT)
2312                         rc = 0;
2313                 GOTO(out_pop, rc);
2314         }
2315
2316         rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
2317         if (rc)
2318                 GOTO(out_close, rc);
2319
2320         rc = llog_process_or_fork(env, loghandle, mgs_steal_client_llog_handler,
2321                                   (void *)comp, NULL, false);
2322         CDEBUG(D_MGS, "steal llog re = %d\n", rc);
2323 out_close:
2324         llog_close(env, loghandle);
2325 out_pop:
2326         OBD_FREE_PTR(tmti);
2327 out_ctxt:
2328         llog_ctxt_put(ctxt);
2329         RETURN(rc);
2330 }
2331
2332 /* lmv is the second thing for client logs */
2333 /* copied from mgs_write_log_lov. Please refer to that.  */
2334 static int mgs_write_log_lmv(const struct lu_env *env,
2335                              struct mgs_device *mgs,
2336                              struct fs_db *fsdb,
2337                              struct mgs_target_info *mti,
2338                              char *logname, char *lmvname)
2339 {
2340         struct llog_handle *llh = NULL;
2341         struct lmv_desc *lmvdesc;
2342         char *uuid;
2343         int rc = 0;
2344         ENTRY;
2345
2346         CDEBUG(D_MGS, "Writing lmv(%s) log for %s\n", lmvname,logname);
2347
2348         OBD_ALLOC_PTR(lmvdesc);
2349         if (lmvdesc == NULL)
2350                 RETURN(-ENOMEM);
2351         lmvdesc->ld_active_tgt_count = 0;
2352         lmvdesc->ld_tgt_count = 0;
2353         sprintf((char*)lmvdesc->ld_uuid.uuid, "%s_UUID", lmvname);
2354         uuid = (char *)lmvdesc->ld_uuid.uuid;
2355
2356         rc = record_start_log(env, mgs, &llh, logname);
2357         if (rc)
2358                 GOTO(out_free, rc);
2359         rc = record_marker(env, llh, fsdb, CM_START, lmvname, "lmv setup");
2360         if (rc)
2361                 GOTO(out_end, rc);
2362         rc = record_attach(env, llh, lmvname, "lmv", uuid);
2363         if (rc)
2364                 GOTO(out_end, rc);
2365         rc = record_lmv_setup(env, llh, lmvname, lmvdesc);
2366         if (rc)
2367                 GOTO(out_end, rc);
2368         rc = record_marker(env, llh, fsdb, CM_END, lmvname, "lmv setup");
2369         if (rc)
2370                 GOTO(out_end, rc);
2371 out_end:
2372         record_end_log(env, &llh);
2373 out_free:
2374         OBD_FREE_PTR(lmvdesc);
2375         RETURN(rc);
2376 }
2377
2378 /* lov is the first thing in the mdt and client logs */
2379 static int mgs_write_log_lov(const struct lu_env *env, struct mgs_device *mgs,
2380                              struct fs_db *fsdb, struct mgs_target_info *mti,
2381                              char *logname, char *lovname)
2382 {
2383         struct llog_handle *llh = NULL;
2384         struct lov_desc *lovdesc;
2385         char *uuid;
2386         int rc = 0;
2387         ENTRY;
2388
2389         CDEBUG(D_MGS, "Writing lov(%s) log for %s\n", lovname, logname);
2390
2391         /*
2392         #01 L attach   0:lov_mdsA  1:lov  2:71ccb_lov_mdsA_19f961a9e1
2393         #02 L lov_setup 0:lov_mdsA 1:(struct lov_desc)
2394               uuid=lov1_UUID, stripe count=1, size=1048576, offset=0, pattern=0
2395         */
2396
2397         /* FIXME just make lov_setup accept empty desc (put uuid in buf 2) */
2398         OBD_ALLOC_PTR(lovdesc);
2399         if (lovdesc == NULL)
2400                 RETURN(-ENOMEM);
2401         lovdesc->ld_magic = LOV_DESC_MAGIC;
2402         lovdesc->ld_tgt_count = 0;
2403         /* Defaults.  Can be changed later by lcfg config_param */
2404         lovdesc->ld_default_stripe_count = 1;
2405         lovdesc->ld_pattern = LOV_PATTERN_RAID0;
2406         lovdesc->ld_default_stripe_size = LOV_DESC_STRIPE_SIZE_DEFAULT;
2407         lovdesc->ld_default_stripe_offset = -1;
2408         lovdesc->ld_qos_maxage = LOV_DESC_QOS_MAXAGE_DEFAULT;
2409         sprintf((char*)lovdesc->ld_uuid.uuid, "%s_UUID", lovname);
2410         /* can these be the same? */
2411         uuid = (char *)lovdesc->ld_uuid.uuid;
2412
2413         /* This should always be the first entry in a log.
2414         rc = mgs_clear_log(obd, logname); */
2415         rc = record_start_log(env, mgs, &llh, logname);
2416         if (rc)
2417                 GOTO(out_free, rc);
2418         /* FIXME these should be a single journal transaction */
2419         rc = record_marker(env, llh, fsdb, CM_START, lovname, "lov setup");
2420         if (rc)
2421                 GOTO(out_end, rc);
2422         rc = record_attach(env, llh, lovname, "lov", uuid);
2423         if (rc)
2424                 GOTO(out_end, rc);
2425         rc = record_lov_setup(env, llh, lovname, lovdesc);
2426         if (rc)
2427                 GOTO(out_end, rc);
2428         rc = record_marker(env, llh, fsdb, CM_END, lovname, "lov setup");
2429         if (rc)
2430                 GOTO(out_end, rc);
2431         EXIT;
2432 out_end:
2433         record_end_log(env, &llh);
2434 out_free:
2435         OBD_FREE_PTR(lovdesc);
2436         return rc;
2437 }
2438
2439 /* add failnids to open log */
2440 static int mgs_write_log_failnids(const struct lu_env *env,
2441                                   struct mgs_target_info *mti,
2442                                   struct llog_handle *llh,
2443                                   char *cliname)
2444 {
2445         char *failnodeuuid = NULL;
2446         char *ptr = mti->mti_params;
2447         lnet_nid_t nid;
2448         int rc = 0;
2449
2450         /*
2451         #03 L add_uuid  nid=uml1@tcp(0x20000c0a80201) nal=90 0:  1:uml1_UUID
2452         #04 L add_uuid  nid=1@elan(0x1000000000001)   nal=90 0:  1:uml1_UUID
2453         #05 L setup    0:OSC_uml1_ost1_mdsA  1:ost1_UUID  2:uml1_UUID
2454         #06 L add_uuid  nid=uml2@tcp(0x20000c0a80202) nal=90 0:  1:uml2_UUID
2455         #0x L add_uuid  nid=2@elan(0x1000000000002)   nal=90 0:  1:uml2_UUID
2456         #07 L add_conn 0:OSC_uml1_ost1_mdsA  1:uml2_UUID
2457         */
2458
2459         /*
2460          * Pull failnid info out of params string, which may contain something
2461          * like "<nid1>,<nid2>:<nid3>,<nid4>".  class_parse_nid() does not
2462          * complain about abnormal inputs like ",:<nid1>", "<nid1>:,<nid2>",
2463          * etc.  However, convert_hostnames() should have caught those.
2464          */
2465         while (class_find_param(ptr, PARAM_FAILNODE, &ptr) == 0) {
2466                 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
2467                         char nidstr[LNET_NIDSTR_SIZE];
2468
2469                         if (failnodeuuid == NULL) {
2470                                 /* We don't know the failover node name,
2471                                  * so just use the first nid as the uuid */
2472                                 libcfs_nid2str_r(nid, nidstr, sizeof(nidstr));
2473                                 rc = name_create(&failnodeuuid, nidstr, "");
2474                                 if (rc != 0)
2475                                         return rc;
2476                         }
2477                         CDEBUG(D_MGS, "add nid %s for failover uuid %s, "
2478                                 "client %s\n",
2479                                 libcfs_nid2str_r(nid, nidstr, sizeof(nidstr)),
2480                                 failnodeuuid, cliname);
2481                         rc = record_add_uuid(env, llh, nid, failnodeuuid);
2482                         /*
2483                          * If *ptr is ':', we have added all NIDs for
2484                          * failnodeuuid.
2485                          */
2486                         if (*ptr == ':') {
2487                                 rc = record_add_conn(env, llh, cliname,
2488                                                      failnodeuuid);
2489                                 name_destroy(&failnodeuuid);
2490                                 failnodeuuid = NULL;
2491                         }
2492                 }
2493                 if (failnodeuuid) {
2494                         rc = record_add_conn(env, llh, cliname, failnodeuuid);
2495                         name_destroy(&failnodeuuid);
2496                         failnodeuuid = NULL;
2497                 }
2498         }
2499
2500         return rc;
2501 }
2502
2503 static int mgs_write_log_mdc_to_lmv(const struct lu_env *env,
2504                                     struct mgs_device *mgs,
2505                                     struct fs_db *fsdb,
2506                                     struct mgs_target_info *mti,
2507                                     char *logname, char *lmvname)
2508 {
2509         struct llog_handle *llh = NULL;
2510         char *mdcname = NULL;
2511         char *nodeuuid = NULL;
2512         char *mdcuuid = NULL;
2513         char *lmvuuid = NULL;
2514         char index[6];
2515         char nidstr[LNET_NIDSTR_SIZE];
2516         int i, rc;
2517         ENTRY;
2518
2519         if (mgs_log_is_empty(env, mgs, logname)) {
2520                 CERROR("log is empty! Logical error\n");
2521                 RETURN(-EINVAL);
2522         }
2523
2524         CDEBUG(D_MGS, "adding mdc for %s to log %s:lmv(%s)\n",
2525                mti->mti_svname, logname, lmvname);
2526
2527         libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2528         rc = name_create(&nodeuuid, nidstr, "");
2529         if (rc)
2530                 RETURN(rc);
2531         rc = name_create(&mdcname, mti->mti_svname, "-mdc");
2532         if (rc)
2533                 GOTO(out_free, rc);
2534         rc = name_create(&mdcuuid, mdcname, "_UUID");
2535         if (rc)
2536                 GOTO(out_free, rc);
2537         rc = name_create(&lmvuuid, lmvname, "_UUID");
2538         if (rc)
2539                 GOTO(out_free, rc);
2540
2541         rc = record_start_log(env, mgs, &llh, logname);
2542         if (rc)
2543                 GOTO(out_free, rc);
2544         rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
2545                            "add mdc");
2546         if (rc)
2547                 GOTO(out_end, rc);
2548         for (i = 0; i < mti->mti_nid_count; i++) {
2549                 CDEBUG(D_MGS, "add nid %s for mdt\n",
2550                         libcfs_nid2str_r(mti->mti_nids[i],
2551                                          nidstr, sizeof(nidstr)));
2552
2553                 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2554                 if (rc)
2555                         GOTO(out_end, rc);
2556         }
2557
2558         rc = record_attach(env, llh, mdcname, LUSTRE_MDC_NAME, lmvuuid);
2559         if (rc)
2560                 GOTO(out_end, rc);
2561         rc = record_setup(env, llh, mdcname, mti->mti_uuid, nodeuuid,
2562                           NULL, NULL);
2563         if (rc)
2564                 GOTO(out_end, rc);
2565         rc = mgs_write_log_failnids(env, mti, llh, mdcname);
2566         if (rc)
2567                 GOTO(out_end, rc);
2568         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
2569         rc = record_mdc_add(env, llh, lmvname, mdcuuid, mti->mti_uuid,
2570                             index, "1");
2571         if (rc)
2572                 GOTO(out_end, rc);
2573         rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname,
2574                            "add mdc");
2575         if (rc)
2576                 GOTO(out_end, rc);
2577 out_end:
2578         record_end_log(env, &llh);
2579 out_free:
2580         name_destroy(&lmvuuid);
2581         name_destroy(&mdcuuid);
2582         name_destroy(&mdcname);
2583         name_destroy(&nodeuuid);
2584         RETURN(rc);
2585 }
2586
2587 static inline int name_create_lov(char **lovname, char *mdtname,
2588                                   struct fs_db *fsdb, int index)
2589 {
2590         /* COMPAT_180 */
2591         if (index == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2592                 return name_create(lovname, fsdb->fsdb_name, "-mdtlov");
2593         else
2594                 return name_create(lovname, mdtname, "-mdtlov");
2595 }
2596
2597 static int name_create_mdt_and_lov(char **logname, char **lovname,
2598                                    struct fs_db *fsdb, int i)
2599 {
2600         int rc;
2601
2602         rc = name_create_mdt(logname, fsdb->fsdb_name, i);
2603         if (rc)
2604                 return rc;
2605         /* COMPAT_180 */
2606         if (i == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2607                 rc = name_create(lovname, fsdb->fsdb_name, "-mdtlov");
2608         else
2609                 rc = name_create(lovname, *logname, "-mdtlov");
2610         if (rc) {
2611                 name_destroy(logname);
2612                 *logname = NULL;
2613         }
2614         return rc;
2615 }
2616
2617 static inline int name_create_mdt_osc(char **oscname, char *ostname,
2618                                       struct fs_db *fsdb, int i)
2619 {
2620         char suffix[16];
2621
2622         if (i == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2623                 sprintf(suffix, "-osc");
2624         else
2625                 sprintf(suffix, "-osc-MDT%04x", i);
2626         return name_create(oscname, ostname, suffix);
2627 }
2628
2629 /* add new mdc to already existent MDS */
2630 static int mgs_write_log_osp_to_mdt(const struct lu_env *env,
2631                                     struct mgs_device *mgs,
2632                                     struct fs_db *fsdb,
2633                                     struct mgs_target_info *mti,
2634                                     int mdt_index, char *logname)
2635 {
2636         struct llog_handle      *llh = NULL;
2637         char    *nodeuuid = NULL;
2638         char    *ospname = NULL;
2639         char    *lovuuid = NULL;
2640         char    *mdtuuid = NULL;
2641         char    *svname = NULL;
2642         char    *mdtname = NULL;
2643         char    *lovname = NULL;
2644         char    index_str[16];
2645         char    nidstr[LNET_NIDSTR_SIZE];
2646         int     i, rc;
2647
2648         ENTRY;
2649         if (mgs_log_is_empty(env, mgs, mti->mti_svname)) {
2650                 CERROR("log is empty! Logical error\n");
2651                 RETURN (-EINVAL);
2652         }
2653
2654         CDEBUG(D_MGS, "adding osp index %d to %s\n", mti->mti_stripe_index,
2655                logname);
2656
2657         rc = name_create_mdt(&mdtname, fsdb->fsdb_name, mti->mti_stripe_index);
2658         if (rc)
2659                 RETURN(rc);
2660
2661         libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2662         rc = name_create(&nodeuuid, nidstr, "");
2663         if (rc)
2664                 GOTO(out_destory, rc);
2665
2666         rc = name_create(&svname, mdtname, "-osp");
2667         if (rc)
2668                 GOTO(out_destory, rc);
2669
2670         sprintf(index_str, "-MDT%04x", mdt_index);
2671         rc = name_create(&ospname, svname, index_str);
2672         if (rc)
2673                 GOTO(out_destory, rc);
2674
2675         rc = name_create_lov(&lovname, logname, fsdb, mdt_index);
2676         if (rc)
2677                 GOTO(out_destory, rc);
2678
2679         rc = name_create(&lovuuid, lovname, "_UUID");
2680         if (rc)
2681                 GOTO(out_destory, rc);
2682
2683         rc = name_create(&mdtuuid, mdtname, "_UUID");
2684         if (rc)
2685                 GOTO(out_destory, rc);
2686
2687         rc = record_start_log(env, mgs, &llh, logname);
2688         if (rc)
2689                 GOTO(out_destory, rc);
2690
2691         rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
2692                            "add osp");
2693         if (rc)
2694                 GOTO(out_destory, rc);
2695
2696         for (i = 0; i < mti->mti_nid_count; i++) {
2697                 CDEBUG(D_MGS, "add nid %s for mdt\n",
2698                         libcfs_nid2str_r(mti->mti_nids[i],
2699                                          nidstr, sizeof(nidstr)));
2700                 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2701                 if (rc)
2702                         GOTO(out_end, rc);
2703         }
2704
2705         rc = record_attach(env, llh, ospname, LUSTRE_OSP_NAME, lovuuid);
2706         if (rc)
2707                 GOTO(out_end, rc);
2708
2709         rc = record_setup(env, llh, ospname, mti->mti_uuid, nodeuuid,
2710                           NULL, NULL);
2711         if (rc)
2712                 GOTO(out_end, rc);
2713
2714         rc = mgs_write_log_failnids(env, mti, llh, ospname);
2715         if (rc)
2716                 GOTO(out_end, rc);
2717
2718         /* Add mdc(osp) to lod */
2719         snprintf(index_str, sizeof(index_str), "%d", mti->mti_stripe_index);
2720         rc = record_base(env, llh, lovname, 0, LCFG_ADD_MDC, mti->mti_uuid,
2721                          index_str, "1", NULL);
2722         if (rc)
2723                 GOTO(out_end, rc);
2724
2725         rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname, "add osp");
2726         if (rc)
2727                 GOTO(out_end, rc);
2728
2729 out_end:
2730         record_end_log(env, &llh);
2731
2732 out_destory:
2733         name_destroy(&mdtuuid);
2734         name_destroy(&lovuuid);
2735         name_destroy(&lovname);
2736         name_destroy(&ospname);
2737         name_destroy(&svname);
2738         name_destroy(&nodeuuid);
2739         name_destroy(&mdtname);
2740         RETURN(rc);
2741 }
2742
2743 static int mgs_write_log_mdt0(const struct lu_env *env,
2744                               struct mgs_device *mgs,
2745                               struct fs_db *fsdb,
2746                               struct mgs_target_info *mti)
2747 {
2748         char *log = mti->mti_svname;
2749         struct llog_handle *llh = NULL;
2750         struct obd_uuid *uuid;
2751         char *lovname;
2752         char mdt_index[6];
2753         char *ptr = mti->mti_params;
2754         int rc = 0, failout = 0;
2755         ENTRY;
2756
2757         OBD_ALLOC_PTR(uuid);
2758         if (uuid == NULL)
2759                 RETURN(-ENOMEM);
2760
2761         if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
2762                 failout = (strncmp(ptr, "failout", 7) == 0);
2763
2764         rc = name_create(&lovname, log, "-mdtlov");
2765         if (rc)
2766                 GOTO(out_free, rc);
2767         if (mgs_log_is_empty(env, mgs, log)) {
2768                 rc = mgs_write_log_lov(env, mgs, fsdb, mti, log, lovname);
2769                 if (rc)
2770                         GOTO(out_lod, rc);
2771         }
2772
2773         sprintf(mdt_index, "%d", mti->mti_stripe_index);
2774
2775         rc = record_start_log(env, mgs, &llh, log);
2776         if (rc)
2777                 GOTO(out_lod, rc);
2778
2779         /* add MDT itself */
2780
2781         /* FIXME this whole fn should be a single journal transaction */
2782         sprintf(uuid->uuid, "%s_UUID", log);
2783         rc = record_marker(env, llh, fsdb, CM_START, log, "add mdt");
2784         if (rc)
2785                 GOTO(out_lod, rc);
2786         rc = record_attach(env, llh, log, LUSTRE_MDT_NAME, uuid->uuid);
2787         if (rc)
2788                 GOTO(out_end, rc);
2789         rc = record_mount_opt(env, llh, log, lovname, NULL);
2790         if (rc)
2791                 GOTO(out_end, rc);
2792         rc = record_setup(env, llh, log, uuid->uuid, mdt_index, lovname,
2793                         failout ? "n" : "f");
2794         if (rc)
2795                 GOTO(out_end, rc);
2796         rc = record_marker(env, llh, fsdb, CM_END, log, "add mdt");
2797         if (rc)
2798                 GOTO(out_end, rc);
2799 out_end:
2800         record_end_log(env, &llh);
2801 out_lod:
2802         name_destroy(&lovname);
2803 out_free:
2804         OBD_FREE_PTR(uuid);
2805         RETURN(rc);
2806 }
2807
2808 /* envelope method for all layers log */
2809 static int mgs_write_log_mdt(const struct lu_env *env,
2810                              struct mgs_device *mgs,
2811                              struct fs_db *fsdb,
2812                              struct mgs_target_info *mti)
2813 {
2814         struct mgs_thread_info *mgi = mgs_env_info(env);
2815         struct llog_handle *llh = NULL;
2816         char *cliname;
2817         int rc, i = 0;
2818         ENTRY;
2819
2820         CDEBUG(D_MGS, "writing new mdt %s\n", mti->mti_svname);
2821
2822         if (mti->mti_uuid[0] == '\0') {
2823                 /* Make up our own uuid */
2824                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
2825                          "%s_UUID", mti->mti_svname);
2826         }
2827
2828         /* add mdt */
2829         rc = mgs_write_log_mdt0(env, mgs, fsdb, mti);
2830         if (rc)
2831                 RETURN(rc);
2832         /* Append the mdt info to the client log */
2833         rc = name_create(&cliname, mti->mti_fsname, "-client");
2834         if (rc)
2835                 RETURN(rc);
2836
2837         if (mgs_log_is_empty(env, mgs, cliname)) {
2838                 /* Start client log */
2839                 rc = mgs_write_log_lov(env, mgs, fsdb, mti, cliname,
2840                                        fsdb->fsdb_clilov);
2841                 if (rc)
2842                         GOTO(out_free, rc);
2843                 rc = mgs_write_log_lmv(env, mgs, fsdb, mti, cliname,
2844                                        fsdb->fsdb_clilmv);
2845                 if (rc)
2846                         GOTO(out_free, rc);
2847         }
2848
2849         /*
2850         #09 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
2851         #10 L attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f
2852         #11 L setup    0:MDC_uml1_mdsA_MNT_client  1:mdsA_UUID  2:uml1_UUID
2853         #12 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
2854         #13 L add_conn 0:MDC_uml1_mdsA_MNT_client  1:uml2_UUID
2855         #14 L mount_option 0:  1:client  2:lov1  3:MDC_uml1_mdsA_MNT_client
2856         */
2857
2858         /* copy client info about lov/lmv */
2859         mgi->mgi_comp.comp_mti = mti;
2860         mgi->mgi_comp.comp_fsdb = fsdb;
2861
2862         rc = mgs_steal_llog_for_mdt_from_client(env, mgs, cliname,
2863                                                 &mgi->mgi_comp);
2864         if (rc)
2865                 GOTO(out_free, rc);
2866         rc = mgs_write_log_mdc_to_lmv(env, mgs, fsdb, mti, cliname,
2867                                       fsdb->fsdb_clilmv);
2868         if (rc)
2869                 GOTO(out_free, rc);
2870
2871         /* add mountopts */
2872         rc = record_start_log(env, mgs, &llh, cliname);
2873         if (rc)
2874                 GOTO(out_free, rc);
2875
2876         rc = record_marker(env, llh, fsdb, CM_START, cliname, "mount opts");
2877         if (rc)
2878                 GOTO(out_end, rc);
2879         rc = record_mount_opt(env, llh, cliname, fsdb->fsdb_clilov,
2880                               fsdb->fsdb_clilmv);
2881         if (rc)
2882                 GOTO(out_end, rc);
2883         rc = record_marker(env, llh, fsdb, CM_END, cliname, "mount opts");
2884         if (rc)
2885                 GOTO(out_end, rc);
2886
2887         /* for_all_existing_mdt except current one */
2888         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
2889                 if (i !=  mti->mti_stripe_index &&
2890                     test_bit(i, fsdb->fsdb_mdt_index_map)) {
2891                         char *logname;
2892
2893                         rc = name_create_mdt(&logname, fsdb->fsdb_name, i);
2894                         if (rc)
2895                                 GOTO(out_end, rc);
2896
2897                         /* NB: If the log for the MDT is empty, it means
2898                          * the MDT is only added to the index
2899                          * map, and not being process yet, i.e. this
2900                          * is an unregistered MDT, see mgs_write_log_target().
2901                          * so we should skip it. Otherwise
2902                          *
2903                          * 1. MGS get register request for MDT1 and MDT2.
2904                          *
2905                          * 2. Then both MDT1 and MDT2 are added into
2906                          * fsdb_mdt_index_map. (see mgs_set_index()).
2907                          *
2908                          * 3. Then MDT1 get the lock of fsdb_mutex, then
2909                          * generate the config log, here, it will regard MDT2
2910                          * as an existent MDT, and generate "add osp" for
2911                          * lustre-MDT0001-osp-MDT0002. Note: at the moment
2912                          * MDT0002 config log is still empty, so it will
2913                          * add "add osp" even before "lov setup", which
2914                          * will definitly cause trouble.
2915                          *
2916                          * 4. MDT1 registeration finished, fsdb_mutex is
2917                          * released, then MDT2 get in, then in above
2918                          * mgs_steal_llog_for_mdt_from_client(), it will
2919                          * add another osp log for lustre-MDT0001-osp-MDT0002,
2920                          * which will cause another trouble.*/
2921                         if (!mgs_log_is_empty(env, mgs, logname))
2922                                 rc = mgs_write_log_osp_to_mdt(env, mgs, fsdb,
2923                                                               mti, i, logname);
2924
2925                         name_destroy(&logname);
2926                         if (rc)
2927                                 GOTO(out_end, rc);
2928                 }
2929         }
2930 out_end:
2931         record_end_log(env, &llh);
2932 out_free:
2933         name_destroy(&cliname);
2934         RETURN(rc);
2935 }
2936
2937 /* Add the ost info to the client/mdt lov */
2938 static int mgs_write_log_osc_to_lov(const struct lu_env *env,
2939                                     struct mgs_device *mgs, struct fs_db *fsdb,
2940                                     struct mgs_target_info *mti,
2941                                     char *logname, char *suffix, char *lovname,
2942                                     enum lustre_sec_part sec_part, int flags)
2943 {
2944         struct llog_handle *llh = NULL;
2945         char *nodeuuid = NULL;
2946         char *oscname = NULL;
2947         char *oscuuid = NULL;
2948         char *lovuuid = NULL;
2949         char *svname = NULL;
2950         char index[6];
2951         char nidstr[LNET_NIDSTR_SIZE];
2952         int i, rc;
2953         ENTRY;
2954
2955         CDEBUG(D_INFO, "adding osc for %s to log %s\n",
2956                 mti->mti_svname, logname);
2957
2958         if (mgs_log_is_empty(env, mgs, logname)) {
2959                 CERROR("log is empty! Logical error\n");
2960                 RETURN(-EINVAL);
2961         }
2962
2963         libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2964         rc = name_create(&nodeuuid, nidstr, "");
2965         if (rc)
2966                 RETURN(rc);
2967         rc = name_create(&svname, mti->mti_svname, "-osc");
2968         if (rc)
2969                 GOTO(out_free, rc);
2970
2971         /* for the system upgraded from old 1.8, keep using the old osc naming
2972          * style for mdt, see name_create_mdt_osc(). LU-1257 */
2973         if (test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2974                 rc = name_create(&oscname, svname, "");
2975         else
2976                 rc = name_create(&oscname, svname, suffix);
2977         if (rc)
2978                 GOTO(out_free, rc);
2979
2980         rc = name_create(&oscuuid, oscname, "_UUID");
2981         if (rc)
2982                 GOTO(out_free, rc);
2983         rc = name_create(&lovuuid, lovname, "_UUID");
2984         if (rc)
2985                 GOTO(out_free, rc);
2986
2987
2988         /*
2989         #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
2990         multihomed (#4)
2991         #04 L add_uuid  nid=1@elan(0x1000000000001)  nal=90 0:  1:uml1_UUID
2992         #04 L attach   0:OSC_uml1_ost1_MNT_client  1:osc  2:89070_lov1_a41dff51a
2993         #05 L setup    0:OSC_uml1_ost1_MNT_client  1:ost1_UUID  2:uml1_UUID
2994         failover (#6,7)
2995         #06 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
2996         #07 L add_conn 0:OSC_uml1_ost1_MNT_client  1:uml2_UUID
2997         #08 L lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1
2998         */
2999
3000         rc = record_start_log(env, mgs, &llh, logname);
3001         if (rc)
3002                 GOTO(out_free, rc);
3003
3004         /* FIXME these should be a single journal transaction */
3005         rc = record_marker(env, llh, fsdb, CM_START | flags, mti->mti_svname,
3006                            "add osc");
3007         if (rc)
3008                 GOTO(out_end, rc);
3009
3010         /* NB: don't change record order, because upon MDT steal OSC config
3011          * from client, it treats all nids before LCFG_SETUP as target nids
3012          * (multiple interfaces), while nids after as failover node nids.
3013          * See mgs_steal_client_llog_handler() LCFG_ADD_UUID.
3014          */
3015         for (i = 0; i < mti->mti_nid_count; i++) {
3016                 CDEBUG(D_MGS, "add nid %s\n",
3017                         libcfs_nid2str_r(mti->mti_nids[i],
3018                                          nidstr, sizeof(nidstr)));
3019                 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
3020                 if (rc)
3021                         GOTO(out_end, rc);
3022         }
3023         rc = record_attach(env, llh, oscname, LUSTRE_OSC_NAME, lovuuid);
3024         if (rc)
3025                 GOTO(out_end, rc);
3026         rc = record_setup(env, llh, oscname, mti->mti_uuid, nodeuuid,
3027                           NULL, NULL);
3028         if (rc)
3029                 GOTO(out_end, rc);
3030         rc = mgs_write_log_failnids(env, mti, llh, oscname);
3031         if (rc)
3032                 GOTO(out_end, rc);
3033
3034         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
3035
3036         rc = record_lov_add(env, llh, lovname, mti->mti_uuid, index, "1");
3037         if (rc)
3038                 GOTO(out_end, rc);
3039         rc = record_marker(env, llh, fsdb, CM_END | flags, mti->mti_svname,
3040                            "add osc");
3041         if (rc)
3042                 GOTO(out_end, rc);
3043 out_end:
3044         record_end_log(env, &llh);
3045 out_free:
3046         name_destroy(&lovuuid);
3047         name_destroy(&oscuuid);
3048         name_destroy(&oscname);
3049         name_destroy(&svname);
3050         name_destroy(&nodeuuid);
3051         RETURN(rc);
3052 }
3053
3054 static int mgs_write_log_ost(const struct lu_env *env,
3055                              struct mgs_device *mgs, struct fs_db *fsdb,
3056                              struct mgs_target_info *mti)
3057 {
3058         struct llog_handle *llh = NULL;
3059         char *logname, *lovname;
3060         char *ptr = mti->mti_params;
3061         int rc, flags = 0, failout = 0, i;
3062         ENTRY;
3063
3064         CDEBUG(D_MGS, "writing new ost %s\n", mti->mti_svname);
3065
3066         /* The ost startup log */
3067
3068         /* If the ost log already exists, that means that someone reformatted
3069            the ost and it called target_add again. */
3070         if (!mgs_log_is_empty(env, mgs, mti->mti_svname)) {
3071                 LCONSOLE_ERROR_MSG(0x141, "The config log for %s already "
3072                                    "exists, yet the server claims it never "
3073                                    "registered. It may have been reformatted, "
3074                                    "or the index changed. writeconf the MDT to "
3075                                    "regenerate all logs.\n", mti->mti_svname);
3076                 RETURN(-EALREADY);
3077         }
3078
3079         /*
3080         attach obdfilter ost1 ost1_UUID
3081         setup /dev/loop2 ldiskfs f|n errors=remount-ro,user_xattr
3082         */
3083         if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
3084                 failout = (strncmp(ptr, "failout", 7) == 0);
3085         rc = record_start_log(env, mgs, &llh, mti->mti_svname);
3086         if (rc)
3087                 RETURN(rc);
3088         /* FIXME these should be a single journal transaction */
3089         rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,"add ost");
3090         if (rc)
3091                 GOTO(out_end, rc);
3092         if (*mti->mti_uuid == '\0')
3093                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
3094                          "%s_UUID", mti->mti_svname);
3095         rc = record_attach(env, llh, mti->mti_svname,
3096                            "obdfilter"/*LUSTRE_OST_NAME*/, mti->mti_uuid);
3097         if (rc)
3098                 GOTO(out_end, rc);
3099         rc = record_setup(env, llh, mti->mti_svname,
3100                           "dev"/*ignored*/, "type"/*ignored*/,
3101                           failout ? "n" : "f", NULL/*options*/);
3102         if (rc)
3103                 GOTO(out_end, rc);
3104         rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname, "add ost");
3105         if (rc)
3106                 GOTO(out_end, rc);
3107 out_end:
3108         record_end_log(env, &llh);
3109         if (rc)
3110                 RETURN(rc);
3111         /* We also have to update the other logs where this osc is part of
3112            the lov */
3113
3114         if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
3115                 /* If we're upgrading, the old mdt log already has our
3116                    entry. Let's do a fake one for fun. */
3117                 /* Note that we can't add any new failnids, since we don't
3118                    know the old osc names. */
3119                 flags = CM_SKIP | CM_UPGRADE146;
3120
3121         } else if ((mti->mti_flags & LDD_F_UPDATE) != LDD_F_UPDATE) {
3122                 /* If the update flag isn't set, don't update client/mdt
3123                    logs. */
3124                 flags |= CM_SKIP;
3125                 LCONSOLE_WARN("Client log for %s was not updated; writeconf "
3126                               "the MDT first to regenerate it.\n",
3127                               mti->mti_svname);
3128         }
3129
3130         /* Add ost to all MDT lov defs */
3131         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
3132                 if (test_bit(i, fsdb->fsdb_mdt_index_map)) {
3133                         char mdt_index[13];
3134
3135                         rc = name_create_mdt_and_lov(&logname, &lovname, fsdb,
3136                                                      i);
3137                         if (rc)
3138                                 RETURN(rc);
3139
3140                         snprintf(mdt_index, sizeof(mdt_index), "-MDT%04x", i);
3141                         rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, mti,
3142                                                       logname, mdt_index,
3143                                                       lovname, LUSTRE_SP_MDT,
3144                                                       flags);
3145                         name_destroy(&logname);
3146                         name_destroy(&lovname);
3147                         if (rc)
3148                                 RETURN(rc);
3149                 }
3150         }
3151
3152         /* Append ost info to the client log */
3153         rc = name_create(&logname, mti->mti_fsname, "-client");
3154         if (rc)
3155                 RETURN(rc);
3156         if (mgs_log_is_empty(env, mgs, logname)) {
3157                 /* Start client log */
3158                 rc = mgs_write_log_lov(env, mgs, fsdb, mti, logname,
3159                                        fsdb->fsdb_clilov);
3160                 if (rc)
3161                         GOTO(out_free, rc);
3162                 rc = mgs_write_log_lmv(env, mgs, fsdb, mti, logname,
3163                                        fsdb->fsdb_clilmv);
3164                 if (rc)
3165                         GOTO(out_free, rc);
3166         }
3167         rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, mti, logname, "",
3168                                       fsdb->fsdb_clilov, LUSTRE_SP_CLI, flags);
3169 out_free:
3170         name_destroy(&logname);
3171         RETURN(rc);
3172 }
3173
3174 static __inline__ int mgs_param_empty(char *ptr)
3175 {
3176         char *tmp;
3177
3178         if ((tmp = strchr(ptr, '=')) && (*(++tmp) == '\0'))
3179                 return 1;
3180         return 0;
3181 }
3182
3183 static int mgs_write_log_failnid_internal(const struct lu_env *env,
3184                                           struct mgs_device *mgs,
3185                                           struct fs_db *fsdb,
3186                                           struct mgs_target_info *mti,
3187                                           char *logname, char *cliname)
3188 {
3189         int rc;
3190         struct llog_handle *llh = NULL;
3191
3192         if (mgs_param_empty(mti->mti_params)) {
3193                 /* Remove _all_ failnids */
3194                 rc = mgs_modify(env, mgs, fsdb, mti, logname,
3195                                 mti->mti_svname, "add failnid", CM_SKIP);
3196                 return rc < 0 ? rc : 0;
3197         }
3198
3199         /* Otherwise failover nids are additive */
3200         rc = record_start_log(env, mgs, &llh, logname);
3201         if (rc)
3202                 return rc;
3203                 /* FIXME this should be a single journal transaction */
3204         rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
3205                            "add failnid");
3206         if (rc)
3207                 goto out_end;
3208         rc = mgs_write_log_failnids(env, mti, llh, cliname);
3209         if (rc)
3210                 goto out_end;
3211         rc = record_marker(env, llh, fsdb, CM_END,
3212                            mti->mti_svname, "add failnid");
3213 out_end:
3214         record_end_log(env, &llh);
3215         return rc;
3216 }
3217
3218
3219 /* Add additional failnids to an existing log.
3220    The mdc/osc must have been added to logs first */
3221 /* tcp nids must be in dotted-quad ascii -
3222    we can't resolve hostnames from the kernel. */
3223 static int mgs_write_log_add_failnid(const struct lu_env *env,
3224                                      struct mgs_device *mgs,
3225                                      struct fs_db *fsdb,
3226                                      struct mgs_target_info *mti)
3227 {
3228         char *logname, *cliname;
3229         int rc;
3230         ENTRY;
3231
3232         /* FIXME we currently can't erase the failnids
3233          * given when a target first registers, since they aren't part of
3234          * an "add uuid" stanza
3235          */
3236
3237         /* Verify that we know about this target */
3238         if (mgs_log_is_empty(env, mgs, mti->mti_svname)) {
3239                 LCONSOLE_ERROR_MSG(0x142, "The target %s has not registered "
3240                                    "yet. It must be started before failnids "
3241                                    "can be added.\n", mti->mti_svname);
3242                 RETURN(-ENOENT);
3243         }
3244
3245         /* Create mdc/osc client name (e.g. lustre-OST0001-osc) */
3246         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
3247                 rc = name_create(&cliname, mti->mti_svname, "-mdc");
3248         } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
3249                 rc = name_create(&cliname, mti->mti_svname, "-osc");
3250         } else {
3251                 RETURN(-EINVAL);
3252         }
3253         if (rc)
3254                 RETURN(rc);
3255
3256         /* Add failover nids to the client log */
3257         rc = name_create(&logname, mti->mti_fsname, "-client");
3258         if (rc) {
3259                 name_destroy(&cliname);
3260                 RETURN(rc);
3261         }
3262
3263         rc = mgs_write_log_failnid_internal(env, mgs, fsdb,mti,logname,cliname);
3264         name_destroy(&logname);
3265         name_destroy(&cliname);
3266         if (rc)
3267                 RETURN(rc);
3268
3269         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
3270                 /* Add OST failover nids to the MDT logs as well */
3271                 int i;
3272
3273                 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
3274                         if (!test_bit(i, fsdb->fsdb_mdt_index_map))
3275                                 continue;
3276                         rc = name_create_mdt(&logname, mti->mti_fsname, i);
3277                         if (rc)
3278                                 RETURN(rc);
3279                         rc = name_create_mdt_osc(&cliname, mti->mti_svname,
3280                                                  fsdb, i);
3281                         if (rc) {
3282                                 name_destroy(&logname);
3283                                 RETURN(rc);
3284                         }
3285                         rc = mgs_write_log_failnid_internal(env, mgs, fsdb,
3286                                                             mti, logname,
3287                                                             cliname);
3288                         name_destroy(&cliname);
3289                         name_destroy(&logname);
3290                         if (rc)
3291                                 RETURN(rc);
3292                 }
3293         }
3294
3295         RETURN(rc);
3296 }
3297
3298 static int mgs_wlp_lcfg(const struct lu_env *env,
3299                         struct mgs_device *mgs, struct fs_db *fsdb,
3300                         struct mgs_target_info *mti,
3301                         char *logname, struct lustre_cfg_bufs *bufs,
3302                         char *tgtname, char *ptr)
3303 {
3304         char comment[MTI_NAME_MAXLEN];
3305         char *tmp;
3306         struct llog_cfg_rec *lcr;
3307         int rc, del;
3308
3309         /* Erase any old settings of this same parameter */
3310         strlcpy(comment, ptr, sizeof(comment));
3311         /* But don't try to match the value. */
3312         tmp = strchr(comment, '=');
3313         if (tmp != NULL)
3314                 *tmp = 0;
3315         /* FIXME we should skip settings that are the same as old values */
3316         rc = mgs_modify(env, mgs, fsdb, mti, logname, tgtname, comment,CM_SKIP);
3317         if (rc < 0)
3318                 return rc;
3319         del = mgs_param_empty(ptr);
3320
3321         LCONSOLE_INFO("%s parameter %s.%s in log %s\n", del ? "Disabling" : rc ?
3322                       "Setting" : "Modifying", tgtname, comment, logname);
3323         if (del) {
3324                 /* mgs_modify() will return 1 if nothing had to be done */
3325                 if (rc == 1)
3326                         rc = 0;
3327                 return rc;
3328         }
3329
3330         lustre_cfg_bufs_reset(bufs, tgtname);
3331         lustre_cfg_bufs_set_string(bufs, 1, ptr);
3332         if (mti->mti_flags & LDD_F_PARAM2)
3333                 lustre_cfg_bufs_set_string(bufs, 2, LCTL_UPCALL);
3334
3335         lcr = lustre_cfg_rec_new((mti->mti_flags & LDD_F_PARAM2) ?
3336                                  LCFG_SET_PARAM : LCFG_PARAM, bufs);
3337         if (lcr == NULL)
3338                 return -ENOMEM;
3339
3340         rc = mgs_write_log_direct(env, mgs, fsdb, logname, lcr, tgtname,
3341                                   comment);
3342         lustre_cfg_rec_free(lcr);
3343         return rc;
3344 }
3345
3346 /* write global variable settings into log */
3347 static int mgs_write_log_sys(const struct lu_env *env,
3348                              struct mgs_device *mgs, struct fs_db *fsdb,
3349                              struct mgs_target_info *mti, char *sys, char *ptr)
3350 {
3351         struct mgs_thread_info  *mgi = mgs_env_info(env);
3352         struct lustre_cfg       *lcfg;
3353         struct llog_cfg_rec     *lcr;
3354         char *tmp, sep;
3355         int rc, cmd, convert = 1;
3356
3357         if (class_match_param(ptr, PARAM_TIMEOUT, &tmp) == 0) {
3358                 cmd = LCFG_SET_TIMEOUT;
3359         } else if (class_match_param(ptr, PARAM_LDLM_TIMEOUT, &tmp) == 0) {
3360                 cmd = LCFG_SET_LDLM_TIMEOUT;
3361         /* Check for known params here so we can return error to lctl */
3362         } else if ((class_match_param(ptr, PARAM_AT_MIN, &tmp) == 0) ||
3363                 (class_match_param(ptr, PARAM_AT_MAX, &tmp) == 0) ||
3364                 (class_match_param(ptr, PARAM_AT_EXTRA, &tmp) == 0) ||
3365                 (class_match_param(ptr, PARAM_AT_EARLY_MARGIN, &tmp) == 0) ||
3366                 (class_match_param(ptr, PARAM_AT_HISTORY, &tmp) == 0)) {
3367                 cmd = LCFG_PARAM;
3368         } else if (class_match_param(ptr, PARAM_JOBID_VAR, &tmp) == 0) {
3369                 convert = 0; /* Don't convert string value to integer */
3370                 cmd = LCFG_PARAM;
3371         } else {
3372                 return -EINVAL;
3373         }
3374
3375         if (mgs_param_empty(ptr))
3376                 CDEBUG(D_MGS, "global '%s' removed\n", sys);
3377         else
3378                 CDEBUG(D_MGS, "global '%s' val=%s\n", sys, tmp);
3379
3380         lustre_cfg_bufs_reset(&mgi->mgi_bufs, NULL);
3381         lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, sys);
3382         if (!convert && *tmp != '\0')
3383                 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 2, tmp);
3384         lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
3385         if (lcr == NULL)
3386                 return -ENOMEM;
3387
3388         lcfg = &lcr->lcr_cfg;
3389         if (convert) {
3390                 rc = kstrtouint(tmp, 0, &lcfg->lcfg_num);
3391                 if (rc)
3392                         GOTO(out_rec_free, rc);
3393         } else {
3394                 lcfg->lcfg_num = 0;
3395         }
3396
3397         /* truncate the comment to the parameter name */
3398         ptr = tmp - 1;
3399         sep = *ptr;
3400         *ptr = '\0';
3401         /* modify all servers and clients */
3402         rc = mgs_write_log_direct_all(env, mgs, fsdb, mti,
3403                                       *tmp == '\0' ? NULL : lcr,
3404                                       mti->mti_fsname, sys, 0);
3405         if (rc == 0 && *tmp != '\0') {
3406                 switch (cmd) {
3407                 case LCFG_SET_TIMEOUT:
3408                         if (!obd_timeout_set || lcfg->lcfg_num > obd_timeout)
3409                                 class_process_config(lcfg);
3410                         break;
3411                 case LCFG_SET_LDLM_TIMEOUT:
3412                         if (!ldlm_timeout_set || lcfg->lcfg_num > ldlm_timeout)
3413                                 class_process_config(lcfg);
3414                         break;
3415                 default:
3416                         break;
3417                 }
3418         }
3419         *ptr = sep;
3420 out_rec_free:
3421         lustre_cfg_rec_free(lcr);
3422         return rc;
3423 }
3424
3425 /* write quota settings into log */
3426 static int mgs_write_log_quota(const struct lu_env *env, struct mgs_device *mgs,
3427                                struct fs_db *fsdb, struct mgs_target_info *mti,
3428                                char *quota, char *ptr)
3429 {
3430         struct mgs_thread_info  *mgi = mgs_env_info(env);
3431         struct llog_cfg_rec     *lcr;
3432         char                    *tmp;
3433         char                     sep;
3434         int                      rc, cmd = LCFG_PARAM;
3435
3436         /* support only 'meta' and 'data' pools so far */
3437         if (class_match_param(ptr, QUOTA_METAPOOL_NAME, &tmp) != 0 &&
3438             class_match_param(ptr, QUOTA_DATAPOOL_NAME, &tmp) != 0) {
3439                 CERROR("parameter quota.%s isn't supported (only quota.mdt "
3440                        "& quota.ost are)\n", ptr);
3441                 return -EINVAL;
3442         }
3443
3444         if (*tmp == '\0') {
3445                 CDEBUG(D_MGS, "global '%s' removed\n", quota);
3446         } else {
3447                 CDEBUG(D_MGS, "global '%s'\n", quota);
3448
3449                 if (strchr(tmp, 'u') == NULL && strchr(tmp, 'g') == NULL &&
3450                     strchr(tmp, 'p') == NULL &&
3451                     strcmp(tmp, "none") != 0) {
3452                         CERROR("enable option(%s) isn't supported\n", tmp);
3453                         return -EINVAL;
3454                 }
3455         }
3456
3457         lustre_cfg_bufs_reset(&mgi->mgi_bufs, mti->mti_fsname);
3458         lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, quota);
3459         lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
3460         if (lcr == NULL)
3461                 return -ENOMEM;
3462
3463         /* truncate the comment to the parameter name */
3464         ptr = tmp - 1;
3465         sep = *ptr;
3466         *ptr = '\0';
3467
3468         /* XXX we duplicated quota enable information in all server
3469          *     config logs, it should be moved to a separate config
3470          *     log once we cleanup the config log for global param. */
3471         /* modify all servers */
3472         rc = mgs_write_log_direct_all(env, mgs, fsdb, mti,
3473                                       *tmp == '\0' ? NULL : lcr,
3474                                       mti->mti_fsname, quota, 1);
3475         *ptr = sep;
3476         lustre_cfg_rec_free(lcr);
3477         return rc < 0 ? rc : 0;
3478 }
3479
3480 static int mgs_srpc_set_param_disk(const struct lu_env *env,
3481                                    struct mgs_device *mgs,
3482                                    struct fs_db *fsdb,
3483                                    struct mgs_target_info *mti,
3484                                    char *param)
3485 {
3486         struct mgs_thread_info  *mgi = mgs_env_info(env);
3487         struct llog_cfg_rec     *lcr;
3488         struct llog_handle      *llh = NULL;
3489         char                    *logname;
3490         char                    *comment, *ptr;
3491         int                      rc, len;
3492
3493         ENTRY;
3494
3495         /* get comment */
3496         ptr = strchr(param, '=');
3497         LASSERT(ptr != NULL);
3498         len = ptr - param;
3499
3500         OBD_ALLOC(comment, len + 1);
3501         if (comment == NULL)
3502                 RETURN(-ENOMEM);
3503         strncpy(comment, param, len);
3504         comment[len] = '\0';
3505
3506         /* prepare lcfg */
3507         lustre_cfg_bufs_reset(&mgi->mgi_bufs, mti->mti_svname);
3508         lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, param);
3509         lcr = lustre_cfg_rec_new(LCFG_SPTLRPC_CONF, &mgi->mgi_bufs);
3510         if (lcr == NULL)
3511                 GOTO(out_comment, rc = -ENOMEM);
3512
3513         /* construct log name */
3514         rc = name_create(&logname, mti->mti_fsname, "-sptlrpc");
3515         if (rc < 0)
3516                 GOTO(out_lcfg, rc);
3517
3518         if (mgs_log_is_empty(env, mgs, logname)) {
3519                 rc = record_start_log(env, mgs, &llh, logname);
3520                 if (rc < 0)
3521                         GOTO(out, rc);
3522                 record_end_log(env, &llh);
3523         }
3524
3525         /* obsolete old one */
3526         rc = mgs_modify(env, mgs, fsdb, mti, logname, mti->mti_svname,
3527                         comment, CM_SKIP);
3528         if (rc < 0)
3529                 GOTO(out, rc);
3530         /* write the new one */
3531         rc = mgs_write_log_direct(env, mgs, fsdb, logname, lcr,
3532                                   mti->mti_svname, comment);
3533         if (rc)
3534                 CERROR("%s: error writing log %s: rc = %d\n",
3535                        mgs->mgs_obd->obd_name, logname, rc);
3536 out:
3537         name_destroy(&logname);
3538 out_lcfg:
3539         lustre_cfg_rec_free(lcr);
3540 out_comment:
3541         OBD_FREE(comment, len + 1);
3542         RETURN(rc);
3543 }
3544
3545 static int mgs_srpc_set_param_udesc_mem(struct fs_db *fsdb,
3546                                         char *param)
3547 {
3548         char    *ptr;
3549
3550         /* disable the adjustable udesc parameter for now, i.e. use default
3551          * setting that client always ship udesc to MDT if possible. to enable
3552          * it simply remove the following line */
3553         goto error_out;
3554
3555         ptr = strchr(param, '=');
3556         if (ptr == NULL)
3557                 goto error_out;
3558         *ptr++ = '\0';
3559
3560         if (strcmp(param, PARAM_SRPC_UDESC))
3561                 goto error_out;
3562
3563         if (strcmp(ptr, "yes") == 0) {
3564                 set_bit(FSDB_UDESC, &fsdb->fsdb_flags);
3565                 CWARN("Enable user descriptor shipping from client to MDT\n");
3566         } else if (strcmp(ptr, "no") == 0) {
3567                 clear_bit(FSDB_UDESC, &fsdb->fsdb_flags);
3568                 CWARN("Disable user descriptor shipping from client to MDT\n");
3569         } else {
3570                 *(ptr - 1) = '=';
3571                 goto error_out;
3572         }
3573         return 0;
3574
3575 error_out:
3576         CERROR("Invalid param: %s\n", param);
3577         return -EINVAL;
3578 }
3579
3580 static int mgs_srpc_set_param_mem(struct fs_db *fsdb,
3581                                   const char *svname,
3582                                   char *param)
3583 {
3584         struct sptlrpc_rule      rule;
3585         struct sptlrpc_rule_set *rset;
3586         int                      rc;
3587         ENTRY;
3588
3589         if (strncmp(param, PARAM_SRPC, sizeof(PARAM_SRPC) - 1) != 0) {
3590                 CERROR("Invalid sptlrpc parameter: %s\n", param);
3591                 RETURN(-EINVAL);
3592         }
3593
3594         if (strncmp(param, PARAM_SRPC_UDESC,
3595                     sizeof(PARAM_SRPC_UDESC) - 1) == 0) {
3596                 RETURN(mgs_srpc_set_param_udesc_mem(fsdb, param));
3597         }
3598
3599         if (strncmp(param, PARAM_SRPC_FLVR, sizeof(PARAM_SRPC_FLVR) - 1) != 0) {
3600                 CERROR("Invalid sptlrpc flavor parameter: %s\n", param);
3601                 RETURN(-EINVAL);
3602         }
3603
3604         param += sizeof(PARAM_SRPC_FLVR) - 1;
3605
3606         rc = sptlrpc_parse_rule(param, &rule);
3607         if (rc)
3608                 RETURN(rc);
3609
3610         /* mgs rules implies must be mgc->mgs */
3611         if (test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
3612                 if ((rule.sr_from != LUSTRE_SP_MGC &&
3613                      rule.sr_from != LUSTRE_SP_ANY) ||
3614                     (rule.sr_to != LUSTRE_SP_MGS &&
3615                      rule.sr_to != LUSTRE_SP_ANY))
3616                         RETURN(-EINVAL);
3617         }
3618
3619         /* preapre room for this coming rule. svcname format should be:
3620          * - fsname: general rule
3621          * - fsname-tgtname: target-specific rule
3622          */
3623         if (strchr(svname, '-')) {
3624                 struct mgs_tgt_srpc_conf *tgtconf;
3625                 int                       found = 0;
3626
3627                 for (tgtconf = fsdb->fsdb_srpc_tgt; tgtconf != NULL;
3628                      tgtconf = tgtconf->mtsc_next) {
3629                         if (!strcmp(tgtconf->mtsc_tgt, svname)) {
3630                                 found = 1;
3631                                 break;
3632                         }
3633                 }
3634
3635                 if (!found) {
3636                         int name_len;
3637
3638                         OBD_ALLOC_PTR(tgtconf);
3639                         if (tgtconf == NULL)
3640                                 RETURN(-ENOMEM);
3641
3642                         name_len = strlen(svname);
3643
3644                         OBD_ALLOC(tgtconf->mtsc_tgt, name_len + 1);
3645                         if (tgtconf->mtsc_tgt == NULL) {
3646                                 OBD_FREE_PTR(tgtconf);
3647                                 RETURN(-ENOMEM);
3648                         }
3649                         memcpy(tgtconf->mtsc_tgt, svname, name_len);
3650
3651                         tgtconf->mtsc_next = fsdb->fsdb_srpc_tgt;
3652                         fsdb->fsdb_srpc_tgt = tgtconf;
3653                 }
3654
3655                 rset = &tgtconf->mtsc_rset;
3656         } else if (strcmp(svname, MGSSELF_NAME) == 0) {
3657                 /* put _mgs related srpc rule directly in mgs ruleset */
3658                 rset = &fsdb->fsdb_mgs->mgs_lut.lut_sptlrpc_rset;
3659         } else {
3660                 rset = &fsdb->fsdb_srpc_gen;
3661         }
3662
3663         rc = sptlrpc_rule_set_merge(rset, &rule);
3664
3665         RETURN(rc);
3666 }
3667
3668 static int mgs_srpc_set_param(const struct lu_env *env,
3669                               struct mgs_device *mgs,
3670                               struct fs_db *fsdb,
3671                               struct mgs_target_info *mti,
3672                               char *param)
3673 {
3674         char                   *copy;
3675         int                     rc, copy_size;
3676         ENTRY;
3677
3678 #ifndef HAVE_GSS
3679         RETURN(-EINVAL);
3680 #endif
3681         /* keep a copy of original param, which could be destroied
3682          * during parsing */
3683         copy_size = strlen(param) + 1;
3684         OBD_ALLOC(copy, copy_size);
3685         if (copy == NULL)
3686                 return -ENOMEM;
3687         memcpy(copy, param, copy_size);
3688
3689         rc = mgs_srpc_set_param_mem(fsdb, mti->mti_svname, param);
3690         if (rc)
3691                 goto out_free;
3692
3693         /* previous steps guaranteed the syntax is correct */
3694         rc = mgs_srpc_set_param_disk(env, mgs, fsdb, mti, copy);
3695         if (rc)
3696                 goto out_free;
3697
3698         if (test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
3699                 /*
3700                  * for mgs rules, make them effective immediately.
3701                  */
3702                 LASSERT(fsdb->fsdb_srpc_tgt == NULL);
3703                 sptlrpc_target_update_exp_flavor(mgs->mgs_obd,
3704                                                  &fsdb->fsdb_srpc_gen);
3705         }
3706
3707 out_free:
3708         OBD_FREE(copy, copy_size);
3709         RETURN(rc);
3710 }
3711
3712 struct mgs_srpc_read_data {
3713         struct fs_db   *msrd_fsdb;
3714         int             msrd_skip;
3715 };
3716
3717 static int mgs_srpc_read_handler(const struct lu_env *env,
3718                                  struct llog_handle *llh,
3719                                  struct llog_rec_hdr *rec, void *data)
3720 {
3721         struct mgs_srpc_read_data *msrd = data;
3722         struct cfg_marker         *marker;
3723         struct lustre_cfg         *lcfg = REC_DATA(rec);
3724         char                      *svname, *param;
3725         int                        cfg_len, rc;
3726         ENTRY;
3727
3728         if (rec->lrh_type != OBD_CFG_REC) {
3729                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
3730                 RETURN(-EINVAL);
3731         }
3732
3733         cfg_len = REC_DATA_LEN(rec);
3734
3735         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
3736         if (rc) {
3737                 CERROR("Insane cfg\n");
3738                 RETURN(rc);
3739         }
3740
3741         if (lcfg->lcfg_command == LCFG_MARKER) {
3742                 marker = lustre_cfg_buf(lcfg, 1);
3743
3744                 if (marker->cm_flags & CM_START &&
3745                     marker->cm_flags & CM_SKIP)
3746                         msrd->msrd_skip = 1;
3747                 if (marker->cm_flags & CM_END)
3748                         msrd->msrd_skip = 0;
3749
3750                 RETURN(0);
3751         }
3752
3753         if (msrd->msrd_skip)
3754                 RETURN(0);
3755
3756         if (lcfg->lcfg_command != LCFG_SPTLRPC_CONF) {
3757                 CERROR("invalid command (%x)\n", lcfg->lcfg_command);
3758                 RETURN(0);
3759         }
3760
3761         svname = lustre_cfg_string(lcfg, 0);
3762         if (svname == NULL) {
3763                 CERROR("svname is empty\n");
3764                 RETURN(0);
3765         }
3766
3767         param = lustre_cfg_string(lcfg, 1);
3768         if (param == NULL) {
3769                 CERROR("param is empty\n");
3770                 RETURN(0);
3771         }
3772
3773         rc = mgs_srpc_set_param_mem(msrd->msrd_fsdb, svname, param);
3774         if (rc)
3775                 CERROR("read sptlrpc record error (%d): %s\n", rc, param);
3776
3777         RETURN(0);
3778 }
3779
3780 int mgs_get_fsdb_srpc_from_llog(const struct lu_env *env,
3781                                 struct mgs_device *mgs,
3782                                 struct fs_db *fsdb)
3783 {
3784         struct llog_handle        *llh = NULL;
3785         struct llog_ctxt          *ctxt;
3786         char                      *logname;
3787         struct mgs_srpc_read_data  msrd;
3788         int                        rc;
3789         ENTRY;
3790
3791         /* construct log name */
3792         rc = name_create(&logname, fsdb->fsdb_name, "-sptlrpc");
3793         if (rc)
3794                 RETURN(rc);
3795
3796         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
3797         LASSERT(ctxt != NULL);
3798
3799         if (mgs_log_is_empty(env, mgs, logname))
3800                 GOTO(out, rc = 0);
3801
3802         rc = llog_open(env, ctxt, &llh, NULL, logname,
3803                        LLOG_OPEN_EXISTS);
3804         if (rc < 0) {
3805                 if (rc == -ENOENT)
3806                         rc = 0;
3807                 GOTO(out, rc);
3808         }
3809
3810         rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL);
3811         if (rc)
3812                 GOTO(out_close, rc);
3813
3814         if (llog_get_size(llh) <= 1)
3815                 GOTO(out_close, rc = 0);
3816
3817         msrd.msrd_fsdb = fsdb;
3818         msrd.msrd_skip = 0;
3819
3820         rc = llog_process(env, llh, mgs_srpc_read_handler, (void *)&msrd,
3821                           NULL);
3822
3823 out_close:
3824         llog_close(env, llh);
3825 out:
3826         llog_ctxt_put(ctxt);
3827         name_destroy(&logname);
3828
3829         if (rc)
3830                 CERROR("failed to read sptlrpc config database: %d\n", rc);
3831         RETURN(rc);
3832 }
3833
3834 static int mgs_write_log_param2(const struct lu_env *env,
3835                                 struct mgs_device *mgs,
3836                                 struct fs_db *fsdb,
3837                                 struct mgs_target_info *mti, char *ptr)
3838 {
3839         struct lustre_cfg_bufs bufs;
3840         int rc;
3841
3842         ENTRY;
3843         CDEBUG(D_MGS, "next param '%s'\n", ptr);
3844
3845         /* PARAM_MGSNODE and PARAM_NETWORK are set only when formating
3846          * or during the inital mount. It can never change after that.
3847          */
3848         if (!class_match_param(ptr, PARAM_MGSNODE, NULL) ||
3849             !class_match_param(ptr, PARAM_NETWORK, NULL)) {
3850                 rc = 0;
3851                 goto end;
3852         }
3853
3854         /* Processed in mgs_write_log_ost. Another value that can't
3855          * be changed by lctl set_param -P.
3856          */
3857         if (!class_match_param(ptr, PARAM_FAILMODE, NULL)) {
3858                 LCONSOLE_ERROR_MSG(0x169,
3859                                    "%s can only be changed with tunefs.lustre and --writeconf\n",
3860                                    ptr);
3861                 rc = -EPERM;
3862                 goto end;
3863         }
3864
3865         /* FIXME !!! Support for sptlrpc is incomplete. Currently the change
3866          * doesn't transmit to the client. See LU-7183.
3867          */
3868         if (!class_match_param(ptr, PARAM_SRPC, NULL)) {
3869                 rc = mgs_srpc_set_param(env, mgs, fsdb, mti, ptr);
3870                 goto end;
3871         }
3872
3873         /* Can't use class_match_param since ptr doesn't start with
3874          * PARAM_FAILNODE. So we look for PARAM_FAILNODE contained in ptr.
3875          */
3876         if (strstr(ptr, PARAM_FAILNODE)) {
3877                 /* Add a failover nidlist. We already processed failovers
3878                  * params for new targets in mgs_write_log_target.
3879                  */
3880                 const char *param;
3881
3882                 /* can't use wildcards with failover.node */
3883                 if (strchr(ptr, '*')) {
3884                         rc = -ENODEV;
3885                         goto end;
3886                 }
3887
3888                 param = strstr(ptr, PARAM_FAILNODE);
3889                 if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
3890                     sizeof(mti->mti_params)) {
3891                         rc = -E2BIG;
3892                         goto end;
3893                 }
3894
3895                 CDEBUG(D_MGS, "Adding failnode with param %s\n",
3896                        mti->mti_params);
3897                 rc = mgs_write_log_add_failnid(env, mgs, fsdb, mti);
3898                 goto end;
3899         }
3900
3901         rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, PARAMS_FILENAME, &bufs,
3902                           mti->mti_svname, ptr);
3903 end:
3904         RETURN(rc);
3905 }
3906
3907 /* Permanent settings of all parameters by writing into the appropriate
3908  * configuration logs.
3909  * A parameter with null value ("<param>='\0'") means to erase it out of
3910  * the logs.
3911  */
3912 static int mgs_write_log_param(const struct lu_env *env,
3913                                struct mgs_device *mgs, struct fs_db *fsdb,
3914                                struct mgs_target_info *mti, char *ptr)
3915 {
3916         struct mgs_thread_info *mgi = mgs_env_info(env);
3917         char *logname;
3918         char *tmp;
3919         int rc = 0;
3920         ENTRY;
3921
3922         /* For various parameter settings, we have to figure out which logs
3923            care about them (e.g. both mdt and client for lov settings) */
3924         CDEBUG(D_MGS, "next param '%s'\n", ptr);
3925
3926         /* The params are stored in MOUNT_DATA_FILE and modified via
3927            tunefs.lustre, or set using lctl conf_param */
3928
3929         /* Processed in lustre_start_mgc */
3930         if (class_match_param(ptr, PARAM_MGSNODE, NULL) == 0)
3931                 GOTO(end, rc);
3932
3933         /* Processed in ost/mdt */
3934         if (class_match_param(ptr, PARAM_NETWORK, NULL) == 0)
3935                 GOTO(end, rc);
3936
3937         /* Processed in mgs_write_log_ost */
3938         if (class_match_param(ptr, PARAM_FAILMODE, NULL) == 0) {
3939                 if (mti->mti_flags & LDD_F_PARAM) {
3940                         LCONSOLE_ERROR_MSG(0x169,
3941                                            "%s can only be changed with tunefs.lustre and --writeconf\n",
3942                                            ptr);
3943                         rc = -EPERM;
3944                 }
3945                 GOTO(end, rc);
3946         }
3947
3948         if (class_match_param(ptr, PARAM_SRPC, NULL) == 0) {
3949                 rc = mgs_srpc_set_param(env, mgs, fsdb, mti, ptr);
3950                 GOTO(end, rc);
3951         }
3952
3953         if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
3954                 /* Add a failover nidlist */
3955                 rc = 0;
3956                 /* We already processed failovers params for new
3957                    targets in mgs_write_log_target */
3958                 if (mti->mti_flags & LDD_F_PARAM) {
3959                         CDEBUG(D_MGS, "Adding failnode\n");
3960                         rc = mgs_write_log_add_failnid(env, mgs, fsdb, mti);
3961                 }
3962                 GOTO(end, rc);
3963         }
3964
3965         if (class_match_param(ptr, PARAM_SYS, &tmp) == 0) {
3966                 rc = mgs_write_log_sys(env, mgs, fsdb, mti, ptr, tmp);
3967                 GOTO(end, rc);
3968         }
3969
3970         if (class_match_param(ptr, PARAM_QUOTA, &tmp) == 0) {
3971                 rc = mgs_write_log_quota(env, mgs, fsdb, mti, ptr, tmp);
3972                 GOTO(end, rc);
3973         }
3974
3975         if (class_match_param(ptr, PARAM_OSC PARAM_ACTIVE, &tmp) == 0 ||
3976             class_match_param(ptr, PARAM_MDC PARAM_ACTIVE, &tmp) == 0) {
3977                 /* active=0 means off, anything else means on */
3978                 int flag = (*tmp == '0') ? CM_EXCLUDE : 0;
3979                 bool deactive_osc = memcmp(ptr, PARAM_OSC PARAM_ACTIVE,
3980                                           strlen(PARAM_OSC PARAM_ACTIVE)) == 0;
3981                 int i;
3982
3983                 if (!deactive_osc) {
3984                         __u32   index;
3985
3986                         rc = server_name2index(mti->mti_svname, &index, NULL);
3987                         if (rc < 0)
3988                                 GOTO(end, rc);
3989
3990                         if (index == 0) {
3991                                 LCONSOLE_ERROR_MSG(0x144, "%s: MDC0 can not be"
3992                                                    " (de)activated.\n",
3993                                                    mti->mti_svname);
3994                                 GOTO(end, rc = -EPERM);
3995                         }
3996                 }
3997
3998                 LCONSOLE_WARN("Permanently %sactivating %s\n",
3999                               flag ? "de" : "re", mti->mti_svname);
4000                 /* Modify clilov */
4001                 rc = name_create(&logname, mti->mti_fsname, "-client");
4002                 if (rc < 0)
4003                         GOTO(end, rc);
4004                 rc = mgs_modify(env, mgs, fsdb, mti, logname,
4005                                 mti->mti_svname,
4006                                 deactive_osc ? "add osc" : "add mdc", flag);
4007                 name_destroy(&logname);
4008                 if (rc < 0)
4009                         goto active_err;
4010
4011                 /* Modify mdtlov */
4012                 /* Add to all MDT logs for DNE */
4013                 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
4014                         if (!test_bit(i, fsdb->fsdb_mdt_index_map))
4015                                 continue;
4016                         rc = name_create_mdt(&logname, mti->mti_fsname, i);
4017                         if (rc < 0)
4018                                 GOTO(end, rc);
4019                         rc = mgs_modify(env, mgs, fsdb, mti, logname,
4020                                         mti->mti_svname,
4021                                         deactive_osc ? "add osc" : "add osp",
4022                                         flag);
4023                         name_destroy(&logname);
4024                         if (rc < 0)
4025                                 goto active_err;
4026                 }
4027 active_err:
4028                 if (rc < 0) {
4029                         LCONSOLE_ERROR_MSG(0x145,
4030                                            "Couldn't find %s in log (%d). No permanent changes were made to the config log.\n",
4031                                            mti->mti_svname, rc);
4032                         if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags))
4033                                 LCONSOLE_ERROR_MSG(0x146,
4034                                                    "This may be because the log is in the old 1.4 style. Consider --writeconf to update the logs.\n");
4035                         GOTO(end, rc);
4036                 }
4037                 /* Fall through to osc/mdc proc for deactivating live
4038                    OSC/OSP on running MDT / clients. */
4039         }
4040         /* Below here, let obd's XXX_process_config methods handle it */
4041
4042         /* All lov. in proc */
4043         if (class_match_param(ptr, PARAM_LOV, NULL) == 0) {
4044                 char *mdtlovname;
4045
4046                 CDEBUG(D_MGS, "lov param %s\n", ptr);
4047                 if (!(mti->mti_flags & LDD_F_SV_TYPE_MDT)) {
4048                         LCONSOLE_ERROR_MSG(0x147, "LOV params must be "
4049                                            "set on the MDT, not %s. "
4050                                            "Ignoring.\n",
4051                                            mti->mti_svname);
4052                         GOTO(end, rc = 0);
4053                 }
4054
4055                 /* Modify mdtlov */
4056                 if (mgs_log_is_empty(env, mgs, mti->mti_svname))
4057                         GOTO(end, rc = -ENODEV);
4058
4059                 rc = name_create_mdt_and_lov(&logname, &mdtlovname, fsdb,
4060                                              mti->mti_stripe_index);
4061                 if (rc)
4062                         GOTO(end, rc);
4063                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, mti->mti_svname,
4064                                   &mgi->mgi_bufs, mdtlovname, ptr);
4065                 name_destroy(&logname);
4066                 name_destroy(&mdtlovname);
4067                 if (rc)
4068                         GOTO(end, rc);
4069
4070                 /* Modify clilov */
4071                 rc = name_create(&logname, mti->mti_fsname, "-client");
4072                 if (rc)
4073                         GOTO(end, rc);
4074                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname, &mgi->mgi_bufs,
4075                                   fsdb->fsdb_clilov, ptr);
4076                 name_destroy(&logname);
4077                 GOTO(end, rc);
4078         }
4079
4080         /* All osc., mdc., llite. params in proc */
4081         if ((class_match_param(ptr, PARAM_OSC, NULL) == 0) ||
4082             (class_match_param(ptr, PARAM_MDC, NULL) == 0) ||
4083             (class_match_param(ptr, PARAM_LLITE, NULL) == 0)) {
4084                 char *cname;
4085
4086                 if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
4087                         LCONSOLE_ERROR_MSG(0x148, "Upgraded client logs for %s"
4088                                            " cannot be modified. Consider"
4089                                            " updating the configuration with"
4090                                            " --writeconf\n",
4091                                            mti->mti_svname);
4092                         GOTO(end, rc = -EINVAL);
4093                 }
4094                 if (memcmp(ptr, PARAM_LLITE, strlen(PARAM_LLITE)) == 0) {
4095                         rc = name_create(&cname, mti->mti_fsname, "-client");
4096                         /* Add the client type to match the obdname in
4097                            class_config_llog_handler */
4098                 } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
4099                         rc = name_create(&cname, mti->mti_svname, "-mdc");
4100                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
4101                         rc = name_create(&cname, mti->mti_svname, "-osc");
4102                 } else {
4103                         GOTO(end, rc = -EINVAL);
4104                 }
4105                 if (rc)
4106                         GOTO(end, rc);
4107
4108                 /* Forbid direct update of llite root squash parameters.
4109                  * These parameters are indirectly set via the MDT settings.
4110                  * See (LU-1778) */
4111                 if ((class_match_param(ptr, PARAM_LLITE, &tmp) == 0) &&
4112                     ((memcmp(tmp, "root_squash=", 12) == 0) ||
4113                      (memcmp(tmp, "nosquash_nids=", 14) == 0))) {
4114                         LCONSOLE_ERROR("%s: root squash parameters can only "
4115                                 "be updated through MDT component\n",
4116                                 mti->mti_fsname);
4117                         name_destroy(&cname);
4118                         GOTO(end, rc = -EINVAL);
4119                 }
4120
4121                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
4122
4123                 /* Modify client */
4124                 rc = name_create(&logname, mti->mti_fsname, "-client");
4125                 if (rc) {
4126                         name_destroy(&cname);
4127                         GOTO(end, rc);
4128                 }
4129                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname, &mgi->mgi_bufs,
4130                                   cname, ptr);
4131
4132                 /* osc params affect the MDT as well */
4133                 if (!rc && (mti->mti_flags & LDD_F_SV_TYPE_OST)) {
4134                         int i;
4135
4136                         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
4137                                 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
4138                                         continue;
4139                                 name_destroy(&cname);
4140                                 rc = name_create_mdt_osc(&cname, mti->mti_svname,
4141                                                          fsdb, i);
4142                                 name_destroy(&logname);
4143                                 if (rc)
4144                                         break;
4145                                 rc = name_create_mdt(&logname,
4146                                                      mti->mti_fsname, i);
4147                                 if (rc)
4148                                         break;
4149                                 if (!mgs_log_is_empty(env, mgs, logname)) {
4150                                         rc = mgs_wlp_lcfg(env, mgs, fsdb,
4151                                                           mti, logname,
4152                                                           &mgi->mgi_bufs,
4153                                                           cname, ptr);
4154                                         if (rc)
4155                                                 break;
4156                                 }
4157                         }
4158                 }
4159
4160                 /* For mdc activate/deactivate, it affects OSP on MDT as well */
4161                 if (class_match_param(ptr, PARAM_MDC PARAM_ACTIVE, &tmp) == 0 &&
4162                     rc == 0) {
4163                         char suffix[16];
4164                         char *lodname = NULL;
4165                         char *param_str = NULL;
4166                         int i;
4167                         int index;
4168
4169                         /* replace mdc with osp */
4170                         memcpy(ptr, PARAM_OSP, strlen(PARAM_OSP));
4171                         rc = server_name2index(mti->mti_svname, &index, NULL);
4172                         if (rc < 0) {
4173                                 memcpy(ptr, PARAM_MDC, strlen(PARAM_MDC));
4174                                 GOTO(end, rc);
4175                         }
4176
4177                         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
4178                                 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
4179                                         continue;
4180
4181                                 if (i == index)
4182                                         continue;
4183
4184                                 name_destroy(&logname);
4185                                 rc = name_create_mdt(&logname, mti->mti_fsname,
4186                                                      i);
4187                                 if (rc < 0)
4188                                         break;
4189
4190                                 if (mgs_log_is_empty(env, mgs, logname))
4191                                         continue;
4192
4193                                 snprintf(suffix, sizeof(suffix), "-osp-MDT%04x",
4194                                          i);
4195                                 name_destroy(&cname);
4196                                 rc = name_create(&cname, mti->mti_svname,
4197                                                  suffix);
4198                                 if (rc < 0)
4199                                         break;
4200
4201                                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,
4202                                                   &mgi->mgi_bufs, cname, ptr);
4203                                 if (rc < 0)
4204                                         break;
4205
4206                                 /* Add configuration log for noitfying LOD
4207                                  * to active/deactive the OSP. */
4208                                 name_destroy(&param_str);
4209                                 rc = name_create(&param_str, cname,
4210                                                  (*tmp == '0') ?  ".active=0" :
4211                                                  ".active=1");
4212                                 if (rc < 0)
4213                                         break;
4214
4215                                 name_destroy(&lodname);
4216                                 rc = name_create(&lodname, logname, "-mdtlov");
4217                                 if (rc < 0)
4218                                         break;
4219
4220                                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,
4221                                                   &mgi->mgi_bufs, lodname,
4222                                                   param_str);
4223                                 if (rc < 0)
4224                                         break;
4225                         }
4226                         memcpy(ptr, PARAM_MDC, strlen(PARAM_MDC));
4227                         name_destroy(&lodname);
4228                         name_destroy(&param_str);
4229                 }
4230
4231                 name_destroy(&logname);
4232                 name_destroy(&cname);
4233                 GOTO(end, rc);
4234         }
4235
4236         /* All mdt. params in proc */
4237         if (class_match_param(ptr, PARAM_MDT, &tmp) == 0) {
4238                 int i;
4239                 __u32 idx;
4240
4241                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
4242                 if (strncmp(mti->mti_svname, mti->mti_fsname,
4243                             MTI_NAME_MAXLEN) == 0)
4244                         /* device is unspecified completely? */
4245                         rc = LDD_F_SV_TYPE_MDT | LDD_F_SV_ALL;
4246                 else
4247                         rc = server_name2index(mti->mti_svname, &idx, NULL);
4248                 if (rc < 0)
4249                         goto active_err;
4250                 if ((rc & LDD_F_SV_TYPE_MDT) == 0)
4251                         goto active_err;
4252                 if (rc & LDD_F_SV_ALL) {
4253                         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
4254                                 if (!test_bit(i,
4255                                                   fsdb->fsdb_mdt_index_map))
4256                                         continue;
4257                                 rc = name_create_mdt(&logname,
4258                                                 mti->mti_fsname, i);
4259                                 if (rc)
4260                                         goto active_err;
4261                                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti,
4262                                                   logname, &mgi->mgi_bufs,
4263                                                   logname, ptr);
4264                                 name_destroy(&logname);
4265                                 if (rc)
4266                                         goto active_err;
4267                         }
4268                 } else {
4269                         if ((memcmp(tmp, "root_squash=", 12) == 0) ||
4270                             (memcmp(tmp, "nosquash_nids=", 14) == 0)) {
4271                                 LCONSOLE_ERROR("%s: root squash parameters "
4272                                         "cannot be applied to a single MDT\n",
4273                                         mti->mti_fsname);
4274                                 GOTO(end, rc = -EINVAL);
4275                         }
4276                         rc = mgs_wlp_lcfg(env, mgs, fsdb, mti,
4277                                           mti->mti_svname, &mgi->mgi_bufs,
4278                                           mti->mti_svname, ptr);
4279                         if (rc)
4280                                 goto active_err;
4281                 }
4282
4283                 /* root squash settings are also applied to llite
4284                  * config log (see LU-1778) */
4285                 if (rc == 0 &&
4286                     ((memcmp(tmp, "root_squash=", 12) == 0) ||
4287                      (memcmp(tmp, "nosquash_nids=", 14) == 0))) {
4288                         char *cname;
4289                         char *ptr2;
4290
4291                         rc = name_create(&cname, mti->mti_fsname, "-client");
4292                         if (rc)
4293                                 GOTO(end, rc);
4294                         rc = name_create(&logname, mti->mti_fsname, "-client");
4295                         if (rc) {
4296                                 name_destroy(&cname);
4297                                 GOTO(end, rc);
4298                         }
4299                         rc = name_create(&ptr2, PARAM_LLITE, tmp);
4300                         if (rc) {
4301                                 name_destroy(&cname);
4302                                 name_destroy(&logname);
4303                                 GOTO(end, rc);
4304                         }
4305                         rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,
4306                                           &mgi->mgi_bufs, cname, ptr2);
4307                         name_destroy(&ptr2);
4308                         name_destroy(&logname);
4309                         name_destroy(&cname);
4310                 }
4311                 GOTO(end, rc);
4312         }
4313
4314         /* All mdd., ost. and osd. params in proc */
4315         if ((class_match_param(ptr, PARAM_MDD, NULL) == 0) ||
4316             (class_match_param(ptr, PARAM_LOD, NULL) == 0) ||
4317             (class_match_param(ptr, PARAM_OST, NULL) == 0) ||
4318             (class_match_param(ptr, PARAM_OSD, NULL) == 0)) {
4319                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
4320                 if (mgs_log_is_empty(env, mgs, mti->mti_svname))
4321                         GOTO(end, rc = -ENODEV);
4322
4323                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, mti->mti_svname,
4324                                   &mgi->mgi_bufs, mti->mti_svname, ptr);
4325                 GOTO(end, rc);
4326         }
4327
4328         LCONSOLE_WARN("Ignoring unrecognized param '%s'\n", ptr);
4329
4330 end:
4331         if (rc)
4332                 CERROR("err %d on param '%s'\n", rc, ptr);
4333
4334         RETURN(rc);
4335 }
4336
4337 int mgs_write_log_target(const struct lu_env *env, struct mgs_device *mgs,
4338                          struct mgs_target_info *mti, struct fs_db *fsdb)
4339 {
4340         char    *buf, *params;
4341         int      rc = -EINVAL;
4342
4343         ENTRY;
4344
4345         /* set/check the new target index */
4346         rc = mgs_set_index(env, mgs, mti);
4347         if (rc < 0)
4348                 RETURN(rc);
4349
4350         if (rc == EALREADY) {
4351                 LCONSOLE_WARN("Found index %d for %s, updating log\n",
4352                               mti->mti_stripe_index, mti->mti_svname);
4353                 /* We would like to mark old log sections as invalid
4354                    and add new log sections in the client and mdt logs.
4355                    But if we add new sections, then live clients will
4356                    get repeat setup instructions for already running
4357                    osc's. So don't update the client/mdt logs. */
4358                 mti->mti_flags &= ~LDD_F_UPDATE;
4359                 rc = 0;
4360         }
4361
4362         OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_WRITE_TARGET_DELAY, cfs_fail_val > 0 ?
4363                          cfs_fail_val : 10);
4364
4365         mutex_lock(&fsdb->fsdb_mutex);
4366
4367         if (mti->mti_flags & (LDD_F_VIRGIN | LDD_F_WRITECONF)) {
4368                 /* Generate a log from scratch */
4369                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
4370                         rc = mgs_write_log_mdt(env, mgs, fsdb, mti);
4371                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
4372                         rc = mgs_write_log_ost(env, mgs, fsdb, mti);
4373                 } else {
4374                         CERROR("Unknown target type %#x, can't create log for %s\n",
4375                                mti->mti_flags, mti->mti_svname);
4376                 }
4377                 if (rc) {
4378                         CERROR("Can't write logs for %s (%d)\n",
4379                                mti->mti_svname, rc);
4380                         GOTO(out_up, rc);
4381                 }
4382         } else {
4383                 /* Just update the params from tunefs in mgs_write_log_params */
4384                 CDEBUG(D_MGS, "Update params for %s\n", mti->mti_svname);
4385                 mti->mti_flags |= LDD_F_PARAM;
4386         }
4387
4388         /* allocate temporary buffer, where class_get_next_param will
4389            make copy of a current  parameter */
4390         OBD_ALLOC(buf, strlen(mti->mti_params) + 1);
4391         if (buf == NULL)
4392                 GOTO(out_up, rc = -ENOMEM);
4393         params = mti->mti_params;
4394         while (params != NULL) {
4395                 rc = class_get_next_param(&params, buf);
4396                 if (rc) {
4397                         if (rc == 1)
4398                                 /* there is no next parameter, that is
4399                                    not an error */
4400                                 rc = 0;
4401                         break;
4402                 }
4403                 CDEBUG(D_MGS, "remaining string: '%s', param: '%s'\n",
4404                        params, buf);
4405                 rc = mgs_write_log_param(env, mgs, fsdb, mti, buf);
4406                 if (rc)
4407                         break;
4408         }
4409
4410         OBD_FREE(buf, strlen(mti->mti_params) + 1);
4411
4412 out_up:
4413         mutex_unlock(&fsdb->fsdb_mutex);
4414         RETURN(rc);
4415 }
4416
4417 int mgs_erase_log(const struct lu_env *env, struct mgs_device *mgs, char *name)
4418 {
4419         struct llog_ctxt        *ctxt;
4420         int                      rc = 0;
4421
4422         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
4423         if (ctxt == NULL) {
4424                 CERROR("%s: MGS config context doesn't exist\n",
4425                        mgs->mgs_obd->obd_name);
4426                 rc = -ENODEV;
4427         } else {
4428                 rc = llog_erase(env, ctxt, NULL, name);
4429                 /* llog may not exist */
4430                 if (rc == -ENOENT)
4431                         rc = 0;
4432                 llog_ctxt_put(ctxt);
4433         }
4434
4435         if (rc)
4436                 CERROR("%s: failed to clear log %s: %d\n",
4437                        mgs->mgs_obd->obd_name, name, rc);
4438
4439         return rc;
4440 }
4441
4442 /* erase all logs for the given fs */
4443 int mgs_erase_logs(const struct lu_env *env, struct mgs_device *mgs,
4444                    const char *fsname)
4445 {
4446         struct list_head log_list;
4447         struct mgs_direntry *dirent, *n;
4448         char barrier_name[20] = {};
4449         char *suffix;
4450         int count = 0;
4451         int rc, len = strlen(fsname);
4452         ENTRY;
4453
4454         mutex_lock(&mgs->mgs_mutex);
4455
4456         /* Find all the logs in the CONFIGS directory */
4457         rc = class_dentry_readdir(env, mgs, &log_list);
4458         if (rc) {
4459                 mutex_unlock(&mgs->mgs_mutex);
4460                 RETURN(rc);
4461         }
4462
4463         if (list_empty(&log_list)) {
4464                 mutex_unlock(&mgs->mgs_mutex);
4465                 RETURN(-ENOENT);
4466         }
4467
4468         snprintf(barrier_name, sizeof(barrier_name) - 1, "%s-%s",
4469                  fsname, BARRIER_FILENAME);
4470         /* Delete the barrier fsdb */
4471         mgs_remove_fsdb_by_name(mgs, barrier_name);
4472         /* Delete the fs db */
4473         mgs_remove_fsdb_by_name(mgs, fsname);
4474         mutex_unlock(&mgs->mgs_mutex);
4475
4476         list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4477                 list_del_init(&dirent->mde_list);
4478                 suffix = strrchr(dirent->mde_name, '-');
4479                 if (suffix != NULL) {
4480                         if ((len == suffix - dirent->mde_name) &&
4481                             (strncmp(fsname, dirent->mde_name, len) == 0)) {
4482                                 CDEBUG(D_MGS, "Removing log %s\n",
4483                                        dirent->mde_name);
4484                                 mgs_erase_log(env, mgs, dirent->mde_name);
4485                                 count++;
4486                         }
4487                 }
4488                 mgs_direntry_free(dirent);
4489         }
4490
4491         if (count == 0)
4492                 rc = -ENOENT;
4493
4494         RETURN(rc);
4495 }
4496
4497 /* list all logs for the given fs */
4498 int mgs_list_logs(const struct lu_env *env, struct mgs_device *mgs,
4499                   struct obd_ioctl_data *data)
4500 {
4501         struct list_head         log_list;
4502         struct mgs_direntry     *dirent, *n;
4503         char                    *out, *suffix, prefix[] = "config_log: ";
4504         int                      prefix_len = strlen(prefix);
4505         int                      len, remains, start = 0, rc;
4506
4507         ENTRY;
4508
4509         /* Find all the logs in the CONFIGS directory */
4510         rc = class_dentry_readdir(env, mgs, &log_list);
4511         if (rc)
4512                 RETURN(rc);
4513
4514         out = data->ioc_bulk;
4515         remains = data->ioc_inllen1;
4516         /* OBD_FAIL: fetch the config_log records from the specified one */
4517         if (OBD_FAIL_CHECK(OBD_FAIL_CATLIST))
4518                 data->ioc_count = cfs_fail_val;
4519
4520         list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4521                 list_del_init(&dirent->mde_list);
4522                 suffix = strrchr(dirent->mde_name, '-');
4523                 if (suffix != NULL) {
4524                         len = prefix_len + dirent->mde_len + 1;
4525                         if (remains - len < 0) {
4526                                 /* No enough space for this record */
4527                                 mgs_direntry_free(dirent);
4528                                 goto out;
4529                         }
4530                         start++;
4531                         if (start < data->ioc_count) {
4532                                 mgs_direntry_free(dirent);
4533                                 continue;
4534                         }
4535                         len = scnprintf(out, remains, "%s%s\n", prefix,
4536                                         dirent->mde_name);
4537                         out += len;
4538                         remains -= len;
4539                 }
4540                 mgs_direntry_free(dirent);
4541                 if (remains <= 1)
4542                         /* Full */
4543                         goto out;
4544         }
4545         /* Finished */
4546         start = 0;
4547 out:
4548         data->ioc_count = start;
4549         RETURN(rc);
4550 }
4551
4552 struct mgs_lcfg_fork_data {
4553         struct lustre_cfg_bufs   mlfd_bufs;
4554         struct mgs_device       *mlfd_mgs;
4555         struct llog_handle      *mlfd_llh;
4556         const char              *mlfd_oldname;
4557         const char              *mlfd_newname;
4558         char                     mlfd_data[0];
4559 };
4560
4561 static bool contain_valid_fsname(char *buf, const char *fsname,
4562                                  int buflen, int namelen)
4563 {
4564         if (buflen < namelen)
4565                 return false;
4566
4567         if (memcmp(buf, fsname, namelen) != 0)
4568                 return false;
4569
4570         if (buf[namelen] != '\0' && buf[namelen] != '-')
4571                 return false;
4572
4573         return true;
4574 }
4575
4576 static int mgs_lcfg_fork_handler(const struct lu_env *env,
4577                                  struct llog_handle *o_llh,
4578                                  struct llog_rec_hdr *o_rec, void *data)
4579 {
4580         struct mgs_lcfg_fork_data *mlfd = data;
4581         struct lustre_cfg_bufs *n_bufs = &mlfd->mlfd_bufs;
4582         struct lustre_cfg *o_lcfg = (struct lustre_cfg *)(o_rec + 1);
4583         struct llog_cfg_rec *lcr;
4584         char *o_buf;
4585         char *n_buf = mlfd->mlfd_data;
4586         int o_buflen;
4587         int o_namelen = strlen(mlfd->mlfd_oldname);
4588         int n_namelen = strlen(mlfd->mlfd_newname);
4589         int diff = n_namelen - o_namelen;
4590         __u32 cmd = o_lcfg->lcfg_command;
4591         __u32 cnt = o_lcfg->lcfg_bufcount;
4592         int rc;
4593         int i;
4594         ENTRY;
4595
4596         /* buf[0] */
4597         o_buf = lustre_cfg_buf(o_lcfg, 0);
4598         o_buflen = o_lcfg->lcfg_buflens[0];
4599         if (contain_valid_fsname(o_buf, mlfd->mlfd_oldname, o_buflen,
4600                                  o_namelen)) {
4601                 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4602                 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4603                        o_buflen - o_namelen);
4604                 lustre_cfg_bufs_reset(n_bufs, n_buf);
4605                 n_buf += cfs_size_round(o_buflen + diff);
4606         } else {
4607                 lustre_cfg_bufs_reset(n_bufs, o_buflen != 0 ? o_buf : NULL);
4608         }
4609
4610         switch (cmd) {
4611         case LCFG_MARKER: {
4612                 struct cfg_marker *o_marker;
4613                 struct cfg_marker *n_marker;
4614                 int tgt_namelen;
4615
4616                 if (cnt != 2) {
4617                         CDEBUG(D_MGS, "Unknown cfg marker entry with %d "
4618                                "buffers\n", cnt);
4619                         RETURN(-EINVAL);
4620                 }
4621
4622                 /* buf[1] is marker */
4623                 o_buf = lustre_cfg_buf(o_lcfg, 1);
4624                 o_buflen = o_lcfg->lcfg_buflens[1];
4625                 o_marker = (struct cfg_marker *)o_buf;
4626                 if (!contain_valid_fsname(o_marker->cm_tgtname,
4627                                           mlfd->mlfd_oldname,
4628                                           sizeof(o_marker->cm_tgtname),
4629                                           o_namelen)) {
4630                         lustre_cfg_bufs_set(n_bufs, 1, o_marker,
4631                                             sizeof(*o_marker));
4632                         break;
4633                 }
4634
4635                 n_marker = (struct cfg_marker *)n_buf;
4636                 *n_marker = *o_marker;
4637                 memcpy(n_marker->cm_tgtname, mlfd->mlfd_newname, n_namelen);
4638                 tgt_namelen = strlen(o_marker->cm_tgtname);
4639                 if (tgt_namelen > o_namelen)
4640                         memcpy(n_marker->cm_tgtname + n_namelen,
4641                                o_marker->cm_tgtname + o_namelen,
4642                                tgt_namelen - o_namelen);
4643                 n_marker->cm_tgtname[tgt_namelen + diff] = '\0';
4644                 lustre_cfg_bufs_set(n_bufs, 1, n_marker, sizeof(*n_marker));
4645                 break;
4646         }
4647         case LCFG_PARAM:
4648         case LCFG_SET_PARAM: {
4649                 for (i = 1; i < cnt; i++)
4650                         /* buf[i] is the param value, reuse it directly */
4651                         lustre_cfg_bufs_set(n_bufs, i,
4652                                             lustre_cfg_buf(o_lcfg, i),
4653                                             o_lcfg->lcfg_buflens[i]);
4654                 break;
4655         }
4656         case LCFG_POOL_NEW:
4657         case LCFG_POOL_ADD:
4658         case LCFG_POOL_REM:
4659         case LCFG_POOL_DEL: {
4660                 if (cnt < 3 || cnt > 4) {
4661                         CDEBUG(D_MGS, "Unknown cfg pool (%x) entry with %d "
4662                                "buffers\n", cmd, cnt);
4663                         RETURN(-EINVAL);
4664                 }
4665
4666                 /* buf[1] is fsname */
4667                 o_buf = lustre_cfg_buf(o_lcfg, 1);
4668                 o_buflen = o_lcfg->lcfg_buflens[1];
4669                 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4670                 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4671                        o_buflen - o_namelen);
4672                 lustre_cfg_bufs_set(n_bufs, 1, n_buf, o_buflen + diff);
4673                 n_buf += cfs_size_round(o_buflen + diff);
4674
4675                 /* buf[2] is the pool name, reuse it directly */
4676                 lustre_cfg_bufs_set(n_bufs, 2, lustre_cfg_buf(o_lcfg, 2),
4677                                     o_lcfg->lcfg_buflens[2]);
4678
4679                 if (cnt == 3)
4680                         break;
4681
4682                 /* buf[3] is ostname */
4683                 o_buf = lustre_cfg_buf(o_lcfg, 3);
4684                 o_buflen = o_lcfg->lcfg_buflens[3];
4685                 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4686                 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4687                        o_buflen - o_namelen);
4688                 lustre_cfg_bufs_set(n_bufs, 3, n_buf, o_buflen + diff);
4689                 break;
4690         }
4691         case LCFG_SETUP: {
4692                 if (cnt == 2) {
4693                         o_buflen = o_lcfg->lcfg_buflens[1];
4694                         if (o_buflen == sizeof(struct lov_desc) ||
4695                             o_buflen == sizeof(struct lmv_desc)) {
4696                                 char *o_uuid;
4697                                 char *n_uuid;
4698                                 int uuid_len;
4699
4700                                 /* buf[1] */
4701                                 o_buf = lustre_cfg_buf(o_lcfg, 1);
4702                                 if (o_buflen == sizeof(struct lov_desc)) {
4703                                         struct lov_desc *o_desc =
4704                                                 (struct lov_desc *)o_buf;
4705                                         struct lov_desc *n_desc =
4706                                                 (struct lov_desc *)n_buf;
4707
4708                                         *n_desc = *o_desc;
4709                                         o_uuid = o_desc->ld_uuid.uuid;
4710                                         n_uuid = n_desc->ld_uuid.uuid;
4711                                         uuid_len = sizeof(o_desc->ld_uuid.uuid);
4712                                 } else {
4713                                         struct lmv_desc *o_desc =
4714                                                 (struct lmv_desc *)o_buf;
4715                                         struct lmv_desc *n_desc =
4716                                                 (struct lmv_desc *)n_buf;
4717
4718                                         *n_desc = *o_desc;
4719                                         o_uuid = o_desc->ld_uuid.uuid;
4720                                         n_uuid = n_desc->ld_uuid.uuid;
4721                                         uuid_len = sizeof(o_desc->ld_uuid.uuid);
4722                                 }
4723
4724                                 if (unlikely(!contain_valid_fsname(o_uuid,
4725                                                 mlfd->mlfd_oldname, uuid_len,
4726                                                 o_namelen))) {
4727                                         lustre_cfg_bufs_set(n_bufs, 1, o_buf,
4728                                                             o_buflen);
4729                                         break;
4730                                 }
4731
4732                                 memcpy(n_uuid, mlfd->mlfd_newname, n_namelen);
4733                                 uuid_len = strlen(o_uuid);
4734                                 if (uuid_len > o_namelen)
4735                                         memcpy(n_uuid + n_namelen,
4736                                                o_uuid + o_namelen,
4737                                                uuid_len - o_namelen);
4738                                 n_uuid[uuid_len + diff] = '\0';
4739                                 lustre_cfg_bufs_set(n_bufs, 1, n_buf, o_buflen);
4740                                 break;
4741                         } /* else case fall through */
4742                 } /* else case fall through */
4743         }
4744         /* fallthrough */
4745         default: {
4746                 for (i = 1; i < cnt; i++) {
4747                         o_buflen = o_lcfg->lcfg_buflens[i];
4748                         if (o_buflen == 0)
4749                                 continue;
4750
4751                         o_buf = lustre_cfg_buf(o_lcfg, i);
4752                         if (!contain_valid_fsname(o_buf, mlfd->mlfd_oldname,
4753                                                   o_buflen, o_namelen)) {
4754                                 lustre_cfg_bufs_set(n_bufs, i, o_buf, o_buflen);
4755                                 continue;
4756                         }
4757
4758                         memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4759                         if (o_buflen == o_namelen) {
4760                                 lustre_cfg_bufs_set(n_bufs, i, n_buf,
4761                                                     n_namelen);
4762                                 n_buf += cfs_size_round(n_namelen);
4763                                 continue;
4764                         }
4765
4766                         memcpy(n_buf + n_namelen, o_buf + o_namelen,
4767                                o_buflen - o_namelen);
4768                         lustre_cfg_bufs_set(n_bufs, i, n_buf, o_buflen + diff);
4769                         n_buf += cfs_size_round(o_buflen + diff);
4770                 }
4771                 break;
4772         }
4773         }
4774
4775         lcr = lustre_cfg_rec_new(cmd, n_bufs);
4776         if (!lcr)
4777                 RETURN(-ENOMEM);
4778
4779         lcr->lcr_cfg = *o_lcfg;
4780         rc = llog_write(env, mlfd->mlfd_llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
4781         lustre_cfg_rec_free(lcr);
4782
4783         RETURN(rc);
4784 }
4785
4786 static int mgs_lcfg_fork_one(const struct lu_env *env, struct mgs_device *mgs,
4787                              struct mgs_direntry *mde, const char *oldname,
4788                              const char *newname)
4789 {
4790         struct llog_handle *old_llh = NULL;
4791         struct llog_handle *new_llh = NULL;
4792         struct llog_ctxt *ctxt = NULL;
4793         struct mgs_lcfg_fork_data *mlfd = NULL;
4794         char *name_buf = NULL;
4795         int name_buflen;
4796         int old_namelen = strlen(oldname);
4797         int new_namelen = strlen(newname);
4798         int rc;
4799         ENTRY;
4800
4801         name_buflen = mde->mde_len + new_namelen - old_namelen;
4802         OBD_ALLOC(name_buf, name_buflen);
4803         if (!name_buf)
4804                 RETURN(-ENOMEM);
4805
4806         memcpy(name_buf, newname, new_namelen);
4807         memcpy(name_buf + new_namelen, mde->mde_name + old_namelen,
4808                mde->mde_len - old_namelen);
4809
4810         CDEBUG(D_MGS, "Fork the config-log from %s to %s\n",
4811                mde->mde_name, name_buf);
4812
4813         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
4814         LASSERT(ctxt);
4815
4816         rc = llog_open_create(env, ctxt, &new_llh, NULL, name_buf);
4817         if (rc)
4818                 GOTO(out, rc);
4819
4820         rc = llog_init_handle(env, new_llh, LLOG_F_IS_PLAIN, NULL);
4821         if (rc)
4822                 GOTO(out, rc);
4823
4824         if (unlikely(mgs_log_is_empty(env, mgs, mde->mde_name)))
4825                 GOTO(out, rc = 0);
4826
4827         rc = llog_open(env, ctxt, &old_llh, NULL, mde->mde_name,
4828                        LLOG_OPEN_EXISTS);
4829         if (rc)
4830                 GOTO(out, rc);
4831
4832         rc = llog_init_handle(env, old_llh, LLOG_F_IS_PLAIN, NULL);
4833         if (rc)
4834                 GOTO(out, rc);
4835
4836         new_llh->lgh_hdr->llh_tgtuuid = old_llh->lgh_hdr->llh_tgtuuid;
4837
4838         OBD_ALLOC(mlfd, LLOG_MIN_CHUNK_SIZE);
4839         if (!mlfd)
4840                 GOTO(out, rc = -ENOMEM);
4841
4842         mlfd->mlfd_mgs = mgs;
4843         mlfd->mlfd_llh = new_llh;
4844         mlfd->mlfd_oldname = oldname;
4845         mlfd->mlfd_newname = newname;
4846
4847         rc = llog_process(env, old_llh, mgs_lcfg_fork_handler, mlfd, NULL);
4848         OBD_FREE(mlfd, LLOG_MIN_CHUNK_SIZE);
4849
4850         GOTO(out, rc);
4851
4852 out:
4853         if (old_llh)
4854                 llog_close(env, old_llh);
4855         if (new_llh)
4856                 llog_close(env, new_llh);
4857         if (name_buf)
4858                 OBD_FREE(name_buf, name_buflen);
4859         if (ctxt)
4860                 llog_ctxt_put(ctxt);
4861
4862         return rc;
4863 }
4864
4865 int mgs_lcfg_fork(const struct lu_env *env, struct mgs_device *mgs,
4866                   const char *oldname, const char *newname)
4867 {
4868         struct list_head log_list;
4869         struct mgs_direntry *dirent, *n;
4870         int olen = strlen(oldname);
4871         int nlen = strlen(newname);
4872         int count = 0;
4873         int rc = 0;
4874         ENTRY;
4875
4876         if (unlikely(!oldname || oldname[0] == '\0' ||
4877                      !newname || newname[0] == '\0'))
4878                 RETURN(-EINVAL);
4879
4880         if (strcmp(oldname, newname) == 0)
4881                 RETURN(-EINVAL);
4882
4883         /* lock it to prevent fork/erase/register in parallel. */
4884         mutex_lock(&mgs->mgs_mutex);
4885
4886         rc = class_dentry_readdir(env, mgs, &log_list);
4887         if (rc) {
4888                 mutex_unlock(&mgs->mgs_mutex);
4889                 RETURN(rc);
4890         }
4891
4892         if (list_empty(&log_list)) {
4893                 mutex_unlock(&mgs->mgs_mutex);
4894                 RETURN(-ENOENT);
4895         }
4896
4897         list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4898                 char *ptr;
4899
4900                 ptr = strrchr(dirent->mde_name, '-');
4901                 if (ptr) {
4902                         int tlen = ptr - dirent->mde_name;
4903
4904                         if (tlen == nlen &&
4905                             strncmp(newname, dirent->mde_name, tlen) == 0)
4906                                 GOTO(out, rc = -EEXIST);
4907
4908                         if (tlen == olen &&
4909                             strncmp(oldname, dirent->mde_name, tlen) == 0)
4910                                 continue;
4911                 }
4912
4913                 list_del_init(&dirent->mde_list);
4914                 mgs_direntry_free(dirent);
4915         }
4916
4917         if (list_empty(&log_list)) {
4918                 mutex_unlock(&mgs->mgs_mutex);
4919                 RETURN(-ENOENT);
4920         }
4921
4922         list_for_each_entry(dirent, &log_list, mde_list) {
4923                 rc = mgs_lcfg_fork_one(env, mgs, dirent, oldname, newname);
4924                 if (rc)
4925                         break;
4926
4927                 count++;
4928         }
4929
4930 out:
4931         mutex_unlock(&mgs->mgs_mutex);
4932
4933         list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4934                 list_del_init(&dirent->mde_list);
4935                 mgs_direntry_free(dirent);
4936         }
4937
4938         if (rc && count > 0)
4939                 mgs_erase_logs(env, mgs, newname);
4940
4941         RETURN(rc);
4942 }
4943
4944 int mgs_lcfg_erase(const struct lu_env *env, struct mgs_device *mgs,
4945                    const char *fsname)
4946 {
4947         int rc;
4948         ENTRY;
4949
4950         if (unlikely(!fsname || fsname[0] == '\0'))
4951                 RETURN(-EINVAL);
4952
4953         rc = mgs_erase_logs(env, mgs, fsname);
4954
4955         RETURN(rc);
4956 }
4957
4958 static int mgs_xattr_del(const struct lu_env *env, struct dt_object *obj)
4959 {
4960         struct dt_device *dev;
4961         struct thandle *th = NULL;
4962         int rc = 0;
4963
4964         ENTRY;
4965
4966         dev = container_of(obj->do_lu.lo_dev, struct dt_device, dd_lu_dev);
4967         th = dt_trans_create(env, dev);
4968         if (IS_ERR(th))
4969                 RETURN(PTR_ERR(th));
4970
4971         rc = dt_declare_xattr_del(env, obj, XATTR_TARGET_RENAME, th);
4972         if (rc)
4973                 GOTO(stop, rc);
4974
4975         rc = dt_trans_start_local(env, dev, th);
4976         if (rc)
4977                 GOTO(stop, rc);
4978
4979         dt_write_lock(env, obj, 0);
4980         rc = dt_xattr_del(env, obj, XATTR_TARGET_RENAME, th);
4981
4982         GOTO(unlock, rc);
4983
4984 unlock:
4985         dt_write_unlock(env, obj);
4986
4987 stop:
4988         dt_trans_stop(env, dev, th);
4989
4990         return rc;
4991 }
4992
4993 int mgs_lcfg_rename(const struct lu_env *env, struct mgs_device *mgs)
4994 {
4995         struct list_head log_list;
4996         struct mgs_direntry *dirent, *n;
4997         char fsname[16];
4998         struct lu_buf buf = {
4999                 .lb_buf = fsname,
5000                 .lb_len = sizeof(fsname)
5001         };
5002         int rc = 0;
5003
5004         ENTRY;
5005
5006         rc = class_dentry_readdir(env, mgs, &log_list);
5007         if (rc)
5008                 RETURN(rc);
5009
5010         if (list_empty(&log_list))
5011                 RETURN(0);
5012
5013         list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
5014                 struct dt_object *o = NULL;
5015                 char oldname[16];
5016                 char *ptr;
5017                 int len;
5018
5019                 list_del_init(&dirent->mde_list);
5020                 ptr = strrchr(dirent->mde_name, '-');
5021                 if (!ptr)
5022                         goto next;
5023
5024                 len = ptr - dirent->mde_name;
5025                 if (unlikely(len >= sizeof(oldname))) {
5026                         CDEBUG(D_MGS, "Skip invalid configuration file %s\n",
5027                                dirent->mde_name);
5028                         goto next;
5029                 }
5030
5031                 o = local_file_find(env, mgs->mgs_los, mgs->mgs_configs_dir,
5032                                     dirent->mde_name);
5033                 if (IS_ERR(o)) {
5034                         rc = PTR_ERR(o);
5035                         CDEBUG(D_MGS, "Fail to locate file %s: rc = %d\n",
5036                                dirent->mde_name, rc);
5037                         goto next;
5038                 }
5039
5040                 rc = dt_xattr_get(env, o, &buf, XATTR_TARGET_RENAME);
5041                 if (rc < 0) {
5042                         if (rc == -ENODATA)
5043                                 rc = 0;
5044                         else
5045                                 CDEBUG(D_MGS,
5046                                        "Fail to get EA for %s: rc = %d\n",
5047                                        dirent->mde_name, rc);
5048                         goto next;
5049                 }
5050
5051                 if (unlikely(rc == len &&
5052                              memcmp(fsname, dirent->mde_name, len) == 0)) {
5053                         /* The new fsname is the same as the old one. */
5054                         rc = mgs_xattr_del(env, o);
5055                         goto next;
5056                 }
5057
5058                 memcpy(oldname, dirent->mde_name, len);
5059                 oldname[len] = '\0';
5060                 fsname[rc] = '\0';
5061                 rc = mgs_lcfg_fork_one(env, mgs, dirent, oldname, fsname);
5062                 if (rc && rc != -EEXIST) {
5063                         CDEBUG(D_MGS, "Fail to fork %s: rc = %d\n",
5064                                dirent->mde_name, rc);
5065                         goto next;
5066                 }
5067
5068                 rc = mgs_erase_log(env, mgs, dirent->mde_name);
5069                 if (rc) {
5070                         CDEBUG(D_MGS, "Fail to erase old %s: rc = %d\n",
5071                                dirent->mde_name, rc);
5072                         /* keep it there if failed to remove it. */
5073                         rc = 0;
5074                 }
5075
5076 next:
5077                 if (o && !IS_ERR(o))
5078                         lu_object_put(env, &o->do_lu);
5079
5080                 mgs_direntry_free(dirent);
5081                 if (rc)
5082                         break;
5083         }
5084
5085         list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
5086                 list_del_init(&dirent->mde_list);
5087                 mgs_direntry_free(dirent);
5088         }
5089
5090         RETURN(rc);
5091 }
5092
5093 /* Setup _mgs fsdb and log
5094  */
5095 int mgs__mgs_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs)
5096 {
5097         struct fs_db *fsdb = NULL;
5098         int rc;
5099         ENTRY;
5100
5101         rc = mgs_find_or_make_fsdb(env, mgs, MGSSELF_NAME, &fsdb);
5102         if (!rc)
5103                 mgs_put_fsdb(mgs, fsdb);
5104
5105         RETURN(rc);
5106 }
5107
5108 /* Setup params fsdb and log
5109  */
5110 int mgs_params_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs)
5111 {
5112         struct fs_db *fsdb = NULL;
5113         struct llog_handle *params_llh = NULL;
5114         int rc;
5115         ENTRY;
5116
5117         rc = mgs_find_or_make_fsdb(env, mgs, PARAMS_FILENAME, &fsdb);
5118         if (!rc) {
5119                 mutex_lock(&fsdb->fsdb_mutex);
5120                 rc = record_start_log(env, mgs, &params_llh, PARAMS_FILENAME);
5121                 if (!rc)
5122                         rc = record_end_log(env, &params_llh);
5123                 mutex_unlock(&fsdb->fsdb_mutex);
5124                 mgs_put_fsdb(mgs, fsdb);
5125         }
5126
5127         RETURN(rc);
5128 }
5129
5130 /* Cleanup params fsdb and log
5131  */
5132 int mgs_params_fsdb_cleanup(const struct lu_env *env, struct mgs_device *mgs)
5133 {
5134         int rc;
5135
5136         rc = mgs_erase_logs(env, mgs, PARAMS_FILENAME);
5137         return rc == -ENOENT ? 0 : rc;
5138 }
5139
5140 /**
5141  * Fill in the mgs_target_info based on data devname and param provide.
5142  *
5143  * @env         thread context
5144  * @mgs         mgs device
5145  * @mti         mgs target info. We want to set this based other paramters
5146  *              passed to this function. Once setup we write it to the config
5147  *              logs.
5148  * @devname     optional OBD device name
5149  * @param       string that contains both what tunable to set and the value to
5150  *              set it to.
5151  *
5152  * RETURN       0 for success
5153  *              negative error number on failure
5154  **/
5155 static int mgs_set_conf_param(const struct lu_env *env, struct mgs_device *mgs,
5156                               struct mgs_target_info *mti, const char *devname,
5157                               const char *param)
5158 {
5159         struct fs_db *fsdb = NULL;
5160         int dev_type;
5161         int rc = 0;
5162
5163         ENTRY;
5164         /* lustre, lustre-mdtlov, lustre-client, lustre-MDT0000 */
5165         if (!devname) {
5166                 size_t len;
5167
5168                 /* We have two possible cases here:
5169                  *
5170                  * 1) the device name embedded in the param:
5171                  *    lustre-OST0000.osc.max_dirty_mb=32
5172                  *
5173                  * 2) the file system name is embedded in
5174                  *    the param: lustre.sys.at.min=0
5175                  */
5176                 len = strcspn(param, ".=");
5177                 if (!len || param[len] == '=')
5178                         RETURN(-EINVAL);
5179
5180                 if (len >= sizeof(mti->mti_svname))
5181                         RETURN(-E2BIG);
5182
5183                 snprintf(mti->mti_svname, sizeof(mti->mti_svname),
5184                          "%.*s", (int)len, param);
5185                 param += len + 1;
5186         } else {
5187                 if (strlcpy(mti->mti_svname, devname, sizeof(mti->mti_svname)) >=
5188                     sizeof(mti->mti_svname))
5189                         RETURN(-E2BIG);
5190         }
5191
5192         if (!strlen(mti->mti_svname)) {
5193                 LCONSOLE_ERROR_MSG(0x14d, "No target specified: %s\n", param);
5194                 RETURN(-ENOSYS);
5195         }
5196
5197         dev_type = mgs_parse_devname(mti->mti_svname, mti->mti_fsname,
5198                                      &mti->mti_stripe_index);
5199         switch (dev_type) {
5200         /* For this case we have an invalid obd device name */
5201         case -ENXIO:
5202                 CDEBUG(D_MGS, "%s don't contain an index\n", mti->mti_svname);
5203                 strlcpy(mti->mti_fsname, mti->mti_svname, MTI_NAME_MAXLEN);
5204                 dev_type = 0;
5205                 break;
5206         /* Not an obd device, assume devname is the fsname.
5207          * User might of only provided fsname and not obd device
5208          */
5209         case -EINVAL:
5210                 CDEBUG(D_MGS, "%s is seen as a file system name\n", mti->mti_svname);
5211                 strlcpy(mti->mti_fsname, mti->mti_svname, MTI_NAME_MAXLEN);
5212                 dev_type = 0;
5213                 break;
5214         default:
5215                 if (dev_type < 0)
5216                         GOTO(out, rc = dev_type);
5217
5218                 /* param related to llite isn't allowed to set by OST or MDT */
5219                 if (dev_type & LDD_F_SV_TYPE_OST ||
5220                     dev_type & LDD_F_SV_TYPE_MDT) {
5221                         /* param related to llite isn't allowed to set by OST
5222                          * or MDT
5223                          */
5224                         if (!strncmp(param, PARAM_LLITE,
5225                                      sizeof(PARAM_LLITE) - 1))
5226                                 GOTO(out, rc = -EINVAL);
5227
5228                         /* Strip -osc or -mdc suffix from svname */
5229                         if (server_make_name(dev_type, mti->mti_stripe_index,
5230                                              mti->mti_fsname, mti->mti_svname,
5231                                              sizeof(mti->mti_svname)))
5232                                 GOTO(out, rc = -EINVAL);
5233                 }
5234                 break;
5235         }
5236
5237         if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
5238             sizeof(mti->mti_params))
5239                 GOTO(out, rc = -E2BIG);
5240
5241         CDEBUG(D_MGS, "set_conf_param fs='%s' device='%s' param='%s'\n",
5242                mti->mti_fsname, mti->mti_svname, mti->mti_params);
5243
5244         rc = mgs_find_or_make_fsdb(env, mgs, mti->mti_fsname, &fsdb);
5245         if (rc)
5246                 GOTO(out, rc);
5247
5248         if (!test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags) &&
5249             test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
5250                 CERROR("No filesystem targets for %s. cfg_device from lctl "
5251                        "is '%s'\n", mti->mti_fsname, mti->mti_svname);
5252                 mgs_unlink_fsdb(mgs, fsdb);
5253                 GOTO(out, rc = -EINVAL);
5254         }
5255
5256         /*
5257          * Revoke lock so everyone updates.  Should be alright if
5258          * someone was already reading while we were updating the logs,
5259          * so we don't really need to hold the lock while we're
5260          * writing (above).
5261          */
5262         mti->mti_flags = dev_type | LDD_F_PARAM;
5263         mutex_lock(&fsdb->fsdb_mutex);
5264         rc = mgs_write_log_param(env, mgs, fsdb, mti, mti->mti_params);
5265         mutex_unlock(&fsdb->fsdb_mutex);
5266         mgs_revoke_lock(mgs, fsdb, CONFIG_T_CONFIG);
5267
5268 out:
5269         if (fsdb)
5270                 mgs_put_fsdb(mgs, fsdb);
5271
5272         RETURN(rc);
5273 }
5274
5275 static int mgs_set_param2(const struct lu_env *env, struct mgs_device *mgs,
5276                           struct mgs_target_info *mti, const char *param)
5277 {
5278         struct fs_db *fsdb = NULL;
5279         int dev_type;
5280         size_t len;
5281         int rc;
5282
5283         if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
5284             sizeof(mti->mti_params))
5285                 GOTO(out, rc = -E2BIG);
5286
5287         len = strcspn(param, ".=");
5288         if (len && param[len] != '=') {
5289                 struct list_head *tmp;
5290                 char *ptr;
5291
5292                 param += len + 1;
5293                 ptr = strchr(param, '.');
5294
5295                 len = strlen(param);
5296                 if (ptr)
5297                         len -= strlen(ptr);
5298                 if (len >= sizeof(mti->mti_svname))
5299                         GOTO(out, rc = -E2BIG);
5300
5301                 snprintf(mti->mti_svname, sizeof(mti->mti_svname), "%.*s",
5302                         (int)len, param);
5303
5304                 mutex_lock(&mgs->mgs_mutex);
5305                 if (unlikely(list_empty(&mgs->mgs_fs_db_list))) {
5306                         mutex_unlock(&mgs->mgs_mutex);
5307                         GOTO(out, rc = -ENODEV);
5308                 }
5309
5310                 list_for_each(tmp, &mgs->mgs_fs_db_list) {
5311                         fsdb = list_entry(tmp, struct fs_db, fsdb_list);
5312                         if (fsdb->fsdb_has_lproc_entry &&
5313                             strcmp(fsdb->fsdb_name, "params") != 0 &&
5314                             strstr(param, fsdb->fsdb_name)) {
5315                                 snprintf(mti->mti_svname,
5316                                          sizeof(mti->mti_svname), "%s",
5317                                          fsdb->fsdb_name);
5318                                 break;
5319                         }
5320                         fsdb = NULL;
5321                 }
5322
5323                 if (!fsdb) {
5324                         snprintf(mti->mti_svname, sizeof(mti->mti_svname),
5325                                  "general");
5326                 }
5327                 mutex_unlock(&mgs->mgs_mutex);
5328         } else {
5329                 snprintf(mti->mti_svname, sizeof(mti->mti_svname), "general");
5330         }
5331
5332         CDEBUG(D_MGS, "set_param2 fs='%s' device='%s' param='%s'\n",
5333                mti->mti_fsname, mti->mti_svname, mti->mti_params);
5334
5335         /* The return value should be the device type i.e LDD_F_SV_TYPE_XXX.
5336          * A returned error tells us we don't have a target obd device.
5337          */
5338         dev_type = server_name2index(mti->mti_svname, &mti->mti_stripe_index,
5339                                      NULL);
5340         if (dev_type < 0)
5341                 dev_type = 0;
5342
5343         /* the return value should be the device type i.e LDD_F_SV_TYPE_XXX.
5344          * Strip -osc or -mdc suffix from svname
5345          */
5346         if ((dev_type & LDD_F_SV_TYPE_OST || dev_type & LDD_F_SV_TYPE_MDT) &&
5347             server_make_name(dev_type, mti->mti_stripe_index,
5348                              mti->mti_fsname, mti->mti_svname,
5349                              sizeof(mti->mti_svname)))
5350                 GOTO(out, rc = -EINVAL);
5351
5352         rc = mgs_find_or_make_fsdb(env, mgs, PARAMS_FILENAME, &fsdb);
5353         if (rc)
5354                 GOTO(out, rc);
5355         /*
5356          * Revoke lock so everyone updates.  Should be alright if
5357          * someone was already reading while we were updating the logs,
5358          * so we don't really need to hold the lock while we're
5359          * writing (above).
5360          */
5361         mti->mti_flags = dev_type | LDD_F_PARAM2;
5362         mutex_lock(&fsdb->fsdb_mutex);
5363         rc = mgs_write_log_param2(env, mgs, fsdb, mti, mti->mti_params);
5364         mutex_unlock(&fsdb->fsdb_mutex);
5365         mgs_revoke_lock(mgs, fsdb, CONFIG_T_PARAMS);
5366         mgs_put_fsdb(mgs, fsdb);
5367 out:
5368         RETURN(rc);
5369 }
5370
5371 /* Set a permanent (config log) param for a target or fs
5372  *
5373  * @lcfg buf0 may contain the device (testfs-MDT0000) name
5374  *       buf1 contains the single parameter
5375  */
5376 int mgs_set_param(const struct lu_env *env, struct mgs_device *mgs,
5377                   struct lustre_cfg *lcfg)
5378 {
5379         const char *param = lustre_cfg_string(lcfg, 1);
5380         struct mgs_target_info *mti;
5381         int rc;
5382
5383         /* Create a fake mti to hold everything */
5384         OBD_ALLOC_PTR(mti);
5385         if (!mti)
5386                 return -ENOMEM;
5387
5388         print_lustre_cfg(lcfg);
5389
5390         if (lcfg->lcfg_command == LCFG_PARAM) {
5391                 /* For the case of lctl conf_param devname can be
5392                  * lustre, lustre-mdtlov, lustre-client, lustre-MDT0000
5393                  */
5394                 const char *devname = lustre_cfg_string(lcfg, 0);
5395
5396                 rc = mgs_set_conf_param(env, mgs, mti, devname, param);
5397         } else {
5398                 /* In the case of lctl set_param -P lcfg[0] will always
5399                  * be 'general'. At least for now.
5400                  */
5401                 rc = mgs_set_param2(env, mgs, mti, param);
5402         }
5403
5404         OBD_FREE_PTR(mti);
5405
5406         return rc;
5407 }
5408
5409 static int mgs_write_log_pool(const struct lu_env *env,
5410                               struct mgs_device *mgs, char *logname,
5411                               struct fs_db *fsdb, char *tgtname,
5412                               enum lcfg_command_type cmd,
5413                               char *fsname, char *poolname,
5414                               char *ostname, char *comment)
5415 {
5416         struct llog_handle *llh = NULL;
5417         int rc;
5418
5419         rc = record_start_log(env, mgs, &llh, logname);
5420         if (rc)
5421                 return rc;
5422         rc = record_marker(env, llh, fsdb, CM_START, tgtname, comment);
5423         if (rc)
5424                 goto out;
5425         rc = record_base(env, llh, tgtname, 0, cmd,
5426                          fsname, poolname, ostname, NULL);
5427         if (rc)
5428                 goto out;
5429         rc = record_marker(env, llh, fsdb, CM_END, tgtname, comment);
5430 out:
5431         record_end_log(env, &llh);
5432         return rc;
5433 }
5434
5435 int mgs_nodemap_cmd(const struct lu_env *env, struct mgs_device *mgs,
5436                     enum lcfg_command_type cmd, const char *nodemap_name,
5437                     char *param)
5438 {
5439         lnet_nid_t nid[2];
5440         u32 idmap[2];
5441         bool bool_switch;
5442         u32 int_id;
5443         int rc = 0;
5444
5445         ENTRY;
5446         switch (cmd) {
5447         case LCFG_NODEMAP_ADD:
5448                 rc = nodemap_add(nodemap_name);
5449                 break;
5450         case LCFG_NODEMAP_DEL:
5451                 rc = nodemap_del(nodemap_name);
5452                 break;
5453         case LCFG_NODEMAP_ADD_RANGE:
5454                 rc = nodemap_parse_range(param, nid);
5455                 if (rc != 0)
5456                         break;
5457                 rc = nodemap_add_range(nodemap_name, nid);
5458                 break;
5459         case LCFG_NODEMAP_DEL_RANGE:
5460                 rc = nodemap_parse_range(param, nid);
5461                 if (rc != 0)
5462                         break;
5463                 rc = nodemap_del_range(nodemap_name, nid);
5464                 break;
5465         case LCFG_NODEMAP_ADMIN:
5466                 rc = kstrtobool(param, &bool_switch);
5467                 if (rc)
5468                         break;
5469                 rc = nodemap_set_allow_root(nodemap_name, bool_switch);
5470                 break;
5471         case LCFG_NODEMAP_DENY_UNKNOWN:
5472                 rc = kstrtobool(param, &bool_switch);
5473                 if (rc)
5474                         break;
5475                 rc = nodemap_set_deny_unknown(nodemap_name, bool_switch);
5476                 break;
5477         case LCFG_NODEMAP_AUDIT_MODE:
5478                 rc = kstrtobool(param, &bool_switch);
5479                 if (rc == 0)
5480                         rc = nodemap_set_audit_mode(nodemap_name, bool_switch);
5481                 break;
5482         case LCFG_NODEMAP_FORBID_ENCRYPT:
5483                 rc = kstrtobool(param, &bool_switch);
5484                 if (rc == 0)
5485                         rc = nodemap_set_forbid_encryption(nodemap_name,
5486                                                            bool_switch);
5487                 break;
5488         case LCFG_NODEMAP_MAP_MODE:
5489                 if (strcmp("both", param) == 0)
5490                         rc = nodemap_set_mapping_mode(nodemap_name,
5491                                                       NODEMAP_MAP_BOTH);
5492                 else if (strcmp("uid_only", param) == 0)
5493                         rc = nodemap_set_mapping_mode(nodemap_name,
5494                                                       NODEMAP_MAP_UID_ONLY);
5495                 else if (strcmp("gid_only", param) == 0)
5496                         rc = nodemap_set_mapping_mode(nodemap_name,
5497                                                       NODEMAP_MAP_GID_ONLY);
5498                 else
5499                         rc = -EINVAL;
5500                 break;
5501         case LCFG_NODEMAP_TRUSTED:
5502                 rc = kstrtobool(param, &bool_switch);
5503                 if (rc)
5504                         break;
5505                 rc = nodemap_set_trust_client_ids(nodemap_name, bool_switch);
5506                 break;
5507         case LCFG_NODEMAP_SQUASH_UID:
5508                 rc = kstrtouint(param, 10, &int_id);
5509                 if (rc)
5510                         break;
5511                 rc = nodemap_set_squash_uid(nodemap_name, int_id);
5512                 break;
5513         case LCFG_NODEMAP_SQUASH_GID:
5514                 rc = kstrtouint(param, 10, &int_id);
5515                 if (rc)
5516                         break;
5517                 rc = nodemap_set_squash_gid(nodemap_name, int_id);
5518                 break;
5519         case LCFG_NODEMAP_ADD_UIDMAP:
5520         case LCFG_NODEMAP_ADD_GIDMAP:
5521                 rc = nodemap_parse_idmap(param, idmap);
5522                 if (rc != 0)
5523                         break;
5524                 if (cmd == LCFG_NODEMAP_ADD_UIDMAP)
5525                         rc = nodemap_add_idmap(nodemap_name, NODEMAP_UID,
5526                                                idmap);
5527                 else
5528                         rc = nodemap_add_idmap(nodemap_name, NODEMAP_GID,
5529                                                idmap);
5530                 break;
5531         case LCFG_NODEMAP_DEL_UIDMAP:
5532         case LCFG_NODEMAP_DEL_GIDMAP:
5533                 rc = nodemap_parse_idmap(param, idmap);
5534                 if (rc != 0)
5535                         break;
5536                 if (cmd == LCFG_NODEMAP_DEL_UIDMAP)
5537                         rc = nodemap_del_idmap(nodemap_name, NODEMAP_UID,
5538                                                idmap);
5539                 else
5540                         rc = nodemap_del_idmap(nodemap_name, NODEMAP_GID,
5541                                                idmap);
5542                 break;
5543         case LCFG_NODEMAP_SET_FILESET:
5544                 rc = nodemap_set_fileset(nodemap_name, param);
5545                 break;
5546         case LCFG_NODEMAP_SET_SEPOL:
5547                 rc = nodemap_set_sepol(nodemap_name, param);
5548                 break;
5549         default:
5550                 rc = -EINVAL;
5551         }
5552
5553         RETURN(rc);
5554 }
5555
5556 int mgs_pool_cmd(const struct lu_env *env, struct mgs_device *mgs,
5557                  enum lcfg_command_type cmd, char *fsname,
5558                  char *poolname, char *ostname)
5559 {
5560         struct fs_db *fsdb;
5561         char *lovname;
5562         char *logname;
5563         char *label = NULL, *canceled_label = NULL;
5564         int label_sz;
5565         struct mgs_target_info *mti = NULL;
5566         bool checked = false;
5567         bool locked = false;
5568         bool free = false;
5569         int rc, i;
5570         ENTRY;
5571
5572         rc = mgs_find_or_make_fsdb(env, mgs, fsname, &fsdb);
5573         if (rc) {
5574                 CERROR("Can't get db for %s\n", fsname);
5575                 RETURN(rc);
5576         }
5577         if (test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
5578                 CERROR("%s is not defined\n", fsname);
5579                 free = true;
5580                 GOTO(out_fsdb, rc = -EINVAL);
5581         }
5582
5583         label_sz = 10 + strlen(fsname) + strlen(poolname);
5584
5585         /* check if ostname match fsname */
5586         if (ostname != NULL) {
5587                 char *ptr;
5588
5589                 ptr = strrchr(ostname, '-');
5590                 if ((ptr == NULL) ||
5591                     (strncmp(fsname, ostname, ptr-ostname) != 0))
5592                         RETURN(-EINVAL);
5593                 label_sz += strlen(ostname);
5594         }
5595
5596         OBD_ALLOC(label, label_sz);
5597         if (!label)
5598                 GOTO(out_fsdb, rc = -ENOMEM);
5599
5600         switch(cmd) {
5601         case LCFG_POOL_NEW:
5602                 sprintf(label,
5603                         "new %s.%s", fsname, poolname);
5604                 break;
5605         case LCFG_POOL_ADD:
5606                 sprintf(label,
5607                         "add %s.%s.%s", fsname, poolname, ostname);
5608                 break;
5609         case LCFG_POOL_REM:
5610                 OBD_ALLOC(canceled_label, label_sz);
5611                 if (canceled_label == NULL)
5612                         GOTO(out_label, rc = -ENOMEM);
5613                 sprintf(label,
5614                         "rem %s.%s.%s", fsname, poolname, ostname);
5615                 sprintf(canceled_label,
5616                         "add %s.%s.%s", fsname, poolname, ostname);
5617                 break;
5618         case LCFG_POOL_DEL:
5619                 OBD_ALLOC(canceled_label, label_sz);
5620                 if (canceled_label == NULL)
5621                         GOTO(out_label, rc = -ENOMEM);
5622                 sprintf(label,
5623                         "del %s.%s", fsname, poolname);
5624                 sprintf(canceled_label,
5625                         "new %s.%s", fsname, poolname);
5626                 break;
5627         default:
5628                 break;
5629         }
5630
5631         OBD_ALLOC_PTR(mti);
5632         if (mti == NULL)
5633                 GOTO(out_cancel, rc = -ENOMEM);
5634         strncpy(mti->mti_svname, "lov pool", sizeof(mti->mti_svname));
5635
5636         mutex_lock(&fsdb->fsdb_mutex);
5637         locked = true;
5638         /* write pool def to all MDT logs */
5639         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
5640                 if (test_bit(i,  fsdb->fsdb_mdt_index_map)) {
5641                         rc = name_create_mdt_and_lov(&logname, &lovname,
5642                                                      fsdb, i);
5643                         if (rc)
5644                                 GOTO(out_mti, rc);
5645
5646                         if (!checked && (canceled_label == NULL)) {
5647                                 rc = mgs_check_marker(env, mgs, fsdb, mti,
5648                                                 logname, lovname, label);
5649                                 if (rc) {
5650                                         name_destroy(&logname);
5651                                         name_destroy(&lovname);
5652                                         GOTO(out_mti,
5653                                                 rc = (rc == LLOG_PROC_BREAK ?
5654                                                         -EEXIST : rc));
5655                                 }
5656                                 checked = true;
5657                         }
5658                         if (canceled_label != NULL)
5659                                 rc = mgs_modify(env, mgs, fsdb, mti, logname,
5660                                                 lovname, canceled_label,
5661                                                 CM_SKIP);
5662
5663                         if (rc >= 0)
5664                                 rc = mgs_write_log_pool(env, mgs, logname,
5665                                                         fsdb, lovname, cmd,
5666                                                         fsname, poolname,
5667                                                         ostname, label);
5668                         name_destroy(&logname);
5669                         name_destroy(&lovname);
5670                         if (rc)
5671                                 GOTO(out_mti, rc);
5672                 }
5673         }
5674
5675         rc = name_create(&logname, fsname, "-client");
5676         if (rc)
5677                 GOTO(out_mti, rc);
5678
5679         if (!checked && (canceled_label == NULL)) {
5680                 rc = mgs_check_marker(env, mgs, fsdb, mti, logname,
5681                                 fsdb->fsdb_clilov, label);
5682                 if (rc) {
5683                         name_destroy(&logname);
5684                         GOTO(out_mti, rc = (rc == LLOG_PROC_BREAK ?
5685                                 -EEXIST : rc));
5686                 }
5687         }
5688         if (canceled_label != NULL) {
5689                 rc = mgs_modify(env, mgs, fsdb, mti, logname,
5690                                 fsdb->fsdb_clilov, canceled_label, CM_SKIP);
5691                 if (rc < 0) {
5692                         name_destroy(&logname);
5693                         GOTO(out_mti, rc);
5694                 }
5695         }
5696
5697         rc = mgs_write_log_pool(env, mgs, logname, fsdb, fsdb->fsdb_clilov,
5698                                 cmd, fsname, poolname, ostname, label);
5699         mutex_unlock(&fsdb->fsdb_mutex);
5700         locked = false;
5701         name_destroy(&logname);
5702         /* request for update */
5703         mgs_revoke_lock(mgs, fsdb, CONFIG_T_CONFIG);
5704
5705         GOTO(out_mti, rc);
5706
5707 out_mti:
5708         if (locked)
5709                 mutex_unlock(&fsdb->fsdb_mutex);
5710         if (mti != NULL)
5711                 OBD_FREE_PTR(mti);
5712 out_cancel:
5713         if (canceled_label != NULL)
5714                 OBD_FREE(canceled_label, label_sz);
5715 out_label:
5716         OBD_FREE(label, label_sz);
5717 out_fsdb:
5718         if (free)
5719                 mgs_unlink_fsdb(mgs, fsdb);
5720         mgs_put_fsdb(mgs, fsdb);
5721
5722         return rc;
5723 }