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