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