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