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