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