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