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