Whamcloud - gitweb
LU-16413 osd-ldiskfs: fix T10PI for CentOS 8.x
[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 /* mount opt is the third thing in client logs */
2344 static int mgs_write_log_mount_opt(const struct lu_env *env,
2345                                    struct mgs_device *mgs, struct fs_db *fsdb,
2346                                    char *logname)
2347 {
2348         struct llog_handle *llh = NULL;
2349         int rc = 0;
2350
2351         ENTRY;
2352
2353         CDEBUG(D_MGS, "Writing mount options log for %s\n", logname);
2354
2355         rc = record_start_log(env, mgs, &llh, logname);
2356         if (rc)
2357                 RETURN(rc);
2358
2359         rc = record_marker(env, llh, fsdb, CM_START, logname, "mount opts");
2360         if (rc)
2361                 GOTO(out_end, rc);
2362         rc = record_mount_opt(env, llh, logname, fsdb->fsdb_clilov,
2363                               fsdb->fsdb_clilmv);
2364         if (rc)
2365                 GOTO(out_end, rc);
2366         rc = record_marker(env, llh, fsdb, CM_END, logname, "mount opts");
2367         if (rc)
2368                 GOTO(out_end, rc);
2369 out_end:
2370         record_end_log(env, &llh);
2371         RETURN(rc);
2372 }
2373
2374 /* lmv is the second thing for client logs */
2375 /* copied from mgs_write_log_lov. Please refer to that.  */
2376 static int mgs_write_log_lmv(const struct lu_env *env,
2377                              struct mgs_device *mgs,
2378                              struct fs_db *fsdb,
2379                              struct mgs_target_info *mti,
2380                              char *logname, char *lmvname)
2381 {
2382         struct llog_handle *llh = NULL;
2383         struct lmv_desc *lmvdesc;
2384         char *uuid;
2385         int rc = 0;
2386         ENTRY;
2387
2388         CDEBUG(D_MGS, "Writing lmv(%s) log for %s\n", lmvname,logname);
2389
2390         OBD_ALLOC_PTR(lmvdesc);
2391         if (lmvdesc == NULL)
2392                 RETURN(-ENOMEM);
2393         lmvdesc->ld_active_tgt_count = 0;
2394         lmvdesc->ld_tgt_count = 0;
2395         sprintf((char*)lmvdesc->ld_uuid.uuid, "%s_UUID", lmvname);
2396         uuid = (char *)lmvdesc->ld_uuid.uuid;
2397
2398         rc = record_start_log(env, mgs, &llh, logname);
2399         if (rc)
2400                 GOTO(out_free, rc);
2401         rc = record_marker(env, llh, fsdb, CM_START, lmvname, "lmv setup");
2402         if (rc)
2403                 GOTO(out_end, rc);
2404         rc = record_attach(env, llh, lmvname, "lmv", uuid);
2405         if (rc)
2406                 GOTO(out_end, rc);
2407         rc = record_lmv_setup(env, llh, lmvname, lmvdesc);
2408         if (rc)
2409                 GOTO(out_end, rc);
2410         rc = record_marker(env, llh, fsdb, CM_END, lmvname, "lmv setup");
2411         if (rc)
2412                 GOTO(out_end, rc);
2413 out_end:
2414         record_end_log(env, &llh);
2415 out_free:
2416         OBD_FREE_PTR(lmvdesc);
2417         RETURN(rc);
2418 }
2419
2420 /* lov is the first thing in the mdt and client logs */
2421 static int mgs_write_log_lov(const struct lu_env *env, struct mgs_device *mgs,
2422                              struct fs_db *fsdb, struct mgs_target_info *mti,
2423                              char *logname, char *lovname)
2424 {
2425         struct llog_handle *llh = NULL;
2426         struct lov_desc *lovdesc;
2427         char *uuid;
2428         int rc = 0;
2429         ENTRY;
2430
2431         CDEBUG(D_MGS, "Writing lov(%s) log for %s\n", lovname, logname);
2432
2433         /*
2434         #01 L attach   0:lov_mdsA  1:lov  2:71ccb_lov_mdsA_19f961a9e1
2435         #02 L lov_setup 0:lov_mdsA 1:(struct lov_desc)
2436               uuid=lov1_UUID, stripe count=1, size=1048576, offset=0, pattern=0
2437         */
2438
2439         /* FIXME just make lov_setup accept empty desc (put uuid in buf 2) */
2440         OBD_ALLOC_PTR(lovdesc);
2441         if (lovdesc == NULL)
2442                 RETURN(-ENOMEM);
2443         lovdesc->ld_magic = LOV_DESC_MAGIC;
2444         lovdesc->ld_tgt_count = 0;
2445         /* Defaults.  Can be changed later by lcfg config_param */
2446         lovdesc->ld_default_stripe_count = 1;
2447         lovdesc->ld_pattern = LOV_PATTERN_RAID0;
2448         lovdesc->ld_default_stripe_size = LOV_DESC_STRIPE_SIZE_DEFAULT;
2449         lovdesc->ld_default_stripe_offset = -1;
2450         lovdesc->ld_qos_maxage = LOV_DESC_QOS_MAXAGE_DEFAULT;
2451         sprintf((char*)lovdesc->ld_uuid.uuid, "%s_UUID", lovname);
2452         /* can these be the same? */
2453         uuid = (char *)lovdesc->ld_uuid.uuid;
2454
2455         /* This should always be the first entry in a log.
2456         rc = mgs_clear_log(obd, logname); */
2457         rc = record_start_log(env, mgs, &llh, logname);
2458         if (rc)
2459                 GOTO(out_free, rc);
2460         /* FIXME these should be a single journal transaction */
2461         rc = record_marker(env, llh, fsdb, CM_START, lovname, "lov setup");
2462         if (rc)
2463                 GOTO(out_end, rc);
2464         rc = record_attach(env, llh, lovname, "lov", uuid);
2465         if (rc)
2466                 GOTO(out_end, rc);
2467         rc = record_lov_setup(env, llh, lovname, lovdesc);
2468         if (rc)
2469                 GOTO(out_end, rc);
2470         rc = record_marker(env, llh, fsdb, CM_END, lovname, "lov setup");
2471         if (rc)
2472                 GOTO(out_end, rc);
2473         EXIT;
2474 out_end:
2475         record_end_log(env, &llh);
2476 out_free:
2477         OBD_FREE_PTR(lovdesc);
2478         return rc;
2479 }
2480
2481 /* add failnids to open log */
2482 static int mgs_write_log_failnids(const struct lu_env *env,
2483                                   struct mgs_target_info *mti,
2484                                   struct llog_handle *llh,
2485                                   char *cliname)
2486 {
2487         char *failnodeuuid = NULL;
2488         char *ptr = mti->mti_params;
2489         lnet_nid_t nid;
2490         int rc = 0;
2491
2492         /*
2493         #03 L add_uuid  nid=uml1@tcp(0x20000c0a80201) nal=90 0:  1:uml1_UUID
2494         #04 L add_uuid  nid=1@elan(0x1000000000001)   nal=90 0:  1:uml1_UUID
2495         #05 L setup    0:OSC_uml1_ost1_mdsA  1:ost1_UUID  2:uml1_UUID
2496         #06 L add_uuid  nid=uml2@tcp(0x20000c0a80202) nal=90 0:  1:uml2_UUID
2497         #0x L add_uuid  nid=2@elan(0x1000000000002)   nal=90 0:  1:uml2_UUID
2498         #07 L add_conn 0:OSC_uml1_ost1_mdsA  1:uml2_UUID
2499         */
2500
2501         /*
2502          * Pull failnid info out of params string, which may contain something
2503          * like "<nid1>,<nid2>:<nid3>,<nid4>".  class_parse_nid() does not
2504          * complain about abnormal inputs like ",:<nid1>", "<nid1>:,<nid2>",
2505          * etc.  However, convert_hostnames() should have caught those.
2506          */
2507         while (class_find_param(ptr, PARAM_FAILNODE, &ptr) == 0) {
2508                 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
2509                         char nidstr[LNET_NIDSTR_SIZE];
2510
2511                         if (failnodeuuid == NULL) {
2512                                 /* We don't know the failover node name,
2513                                  * so just use the first nid as the uuid */
2514                                 libcfs_nid2str_r(nid, nidstr, sizeof(nidstr));
2515                                 rc = name_create(&failnodeuuid, nidstr, "");
2516                                 if (rc != 0)
2517                                         return rc;
2518                         }
2519                         CDEBUG(D_MGS, "add nid %s for failover uuid %s, "
2520                                 "client %s\n",
2521                                 libcfs_nid2str_r(nid, nidstr, sizeof(nidstr)),
2522                                 failnodeuuid, cliname);
2523                         rc = record_add_uuid(env, llh, nid, failnodeuuid);
2524                         /*
2525                          * If *ptr is ':', we have added all NIDs for
2526                          * failnodeuuid.
2527                          */
2528                         if (*ptr == ':') {
2529                                 rc = record_add_conn(env, llh, cliname,
2530                                                      failnodeuuid);
2531                                 name_destroy(&failnodeuuid);
2532                                 failnodeuuid = NULL;
2533                         }
2534                 }
2535                 if (failnodeuuid) {
2536                         rc = record_add_conn(env, llh, cliname, failnodeuuid);
2537                         name_destroy(&failnodeuuid);
2538                         failnodeuuid = NULL;
2539                 }
2540         }
2541
2542         return rc;
2543 }
2544
2545 static int mgs_write_log_mdc_to_lmv(const struct lu_env *env,
2546                                     struct mgs_device *mgs,
2547                                     struct fs_db *fsdb,
2548                                     struct mgs_target_info *mti,
2549                                     char *logname, char *lmvname)
2550 {
2551         struct llog_handle *llh = NULL;
2552         char *mdcname = NULL;
2553         char *nodeuuid = NULL;
2554         char *mdcuuid = NULL;
2555         char *lmvuuid = NULL;
2556         char index[6];
2557         char nidstr[LNET_NIDSTR_SIZE];
2558         int i, rc;
2559         ENTRY;
2560
2561         if (mgs_log_is_empty(env, mgs, logname)) {
2562                 CERROR("log is empty! Logical error\n");
2563                 RETURN(-EINVAL);
2564         }
2565
2566         CDEBUG(D_MGS, "adding mdc for %s to log %s:lmv(%s)\n",
2567                mti->mti_svname, logname, lmvname);
2568
2569         libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2570         rc = name_create(&nodeuuid, nidstr, "");
2571         if (rc)
2572                 RETURN(rc);
2573         rc = name_create(&mdcname, mti->mti_svname, "-mdc");
2574         if (rc)
2575                 GOTO(out_free, rc);
2576         rc = name_create(&mdcuuid, mdcname, "_UUID");
2577         if (rc)
2578                 GOTO(out_free, rc);
2579         rc = name_create(&lmvuuid, lmvname, "_UUID");
2580         if (rc)
2581                 GOTO(out_free, rc);
2582
2583         rc = mgs_modify(env, mgs, fsdb, mti, logname, mti->mti_svname,
2584                         "add mdc", CM_SKIP);
2585         if (rc < 0)
2586                 GOTO(out_free, rc);
2587
2588         rc = record_start_log(env, mgs, &llh, logname);
2589         if (rc)
2590                 GOTO(out_free, rc);
2591         rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
2592                            "add mdc");
2593         if (rc)
2594                 GOTO(out_end, rc);
2595         for (i = 0; i < mti->mti_nid_count; i++) {
2596                 CDEBUG(D_MGS, "add nid %s for mdt\n",
2597                         libcfs_nid2str_r(mti->mti_nids[i],
2598                                          nidstr, sizeof(nidstr)));
2599
2600                 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2601                 if (rc)
2602                         GOTO(out_end, rc);
2603         }
2604
2605         rc = record_attach(env, llh, mdcname, LUSTRE_MDC_NAME, lmvuuid);
2606         if (rc)
2607                 GOTO(out_end, rc);
2608         rc = record_setup(env, llh, mdcname, mti->mti_uuid, nodeuuid,
2609                           NULL, NULL);
2610         if (rc)
2611                 GOTO(out_end, rc);
2612         rc = mgs_write_log_failnids(env, mti, llh, mdcname);
2613         if (rc)
2614                 GOTO(out_end, rc);
2615         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
2616         rc = record_mdc_add(env, llh, lmvname, mdcuuid, mti->mti_uuid,
2617                             index, "1");
2618         if (rc)
2619                 GOTO(out_end, rc);
2620         rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname,
2621                            "add mdc");
2622         if (rc)
2623                 GOTO(out_end, rc);
2624 out_end:
2625         record_end_log(env, &llh);
2626 out_free:
2627         name_destroy(&lmvuuid);
2628         name_destroy(&mdcuuid);
2629         name_destroy(&mdcname);
2630         name_destroy(&nodeuuid);
2631         RETURN(rc);
2632 }
2633
2634 static inline int name_create_lov(char **lovname, char *mdtname,
2635                                   struct fs_db *fsdb, int index)
2636 {
2637         /* COMPAT_180 */
2638         if (index == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2639                 return name_create(lovname, fsdb->fsdb_name, "-mdtlov");
2640         else
2641                 return name_create(lovname, mdtname, "-mdtlov");
2642 }
2643
2644 static int name_create_mdt_and_lov(char **logname, char **lovname,
2645                                    struct fs_db *fsdb, int i)
2646 {
2647         int rc;
2648
2649         rc = name_create_mdt(logname, fsdb->fsdb_name, i);
2650         if (rc)
2651                 return rc;
2652         /* COMPAT_180 */
2653         if (i == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2654                 rc = name_create(lovname, fsdb->fsdb_name, "-mdtlov");
2655         else
2656                 rc = name_create(lovname, *logname, "-mdtlov");
2657         if (rc) {
2658                 name_destroy(logname);
2659                 *logname = NULL;
2660         }
2661         return rc;
2662 }
2663
2664 static inline int name_create_mdt_osc(char **oscname, char *ostname,
2665                                       struct fs_db *fsdb, int i)
2666 {
2667         char suffix[16];
2668
2669         if (i == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2670                 sprintf(suffix, "-osc");
2671         else
2672                 sprintf(suffix, "-osc-MDT%04x", i);
2673         return name_create(oscname, ostname, suffix);
2674 }
2675
2676 /* add new mdc to already existent MDS */
2677 static int mgs_write_log_osp_to_mdt(const struct lu_env *env,
2678                                     struct mgs_device *mgs,
2679                                     struct fs_db *fsdb,
2680                                     struct mgs_target_info *mti,
2681                                     int mdt_index, char *logname)
2682 {
2683         struct llog_handle      *llh = NULL;
2684         char    *nodeuuid = NULL;
2685         char    *ospname = NULL;
2686         char    *lovuuid = NULL;
2687         char    *mdtuuid = NULL;
2688         char    *svname = NULL;
2689         char    *mdtname = NULL;
2690         char    *lovname = NULL;
2691         char    index_str[16];
2692         char    nidstr[LNET_NIDSTR_SIZE];
2693         int     i, rc;
2694
2695         ENTRY;
2696         if (mgs_log_is_empty(env, mgs, mti->mti_svname)) {
2697                 CERROR("log is empty! Logical error\n");
2698                 RETURN (-EINVAL);
2699         }
2700
2701         CDEBUG(D_MGS, "adding osp index %d to %s\n", mti->mti_stripe_index,
2702                logname);
2703
2704         rc = name_create_mdt(&mdtname, fsdb->fsdb_name, mti->mti_stripe_index);
2705         if (rc)
2706                 RETURN(rc);
2707
2708         libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2709         rc = name_create(&nodeuuid, nidstr, "");
2710         if (rc)
2711                 GOTO(out_destory, rc);
2712
2713         rc = name_create(&svname, mdtname, "-osp");
2714         if (rc)
2715                 GOTO(out_destory, rc);
2716
2717         sprintf(index_str, "-MDT%04x", mdt_index);
2718         rc = name_create(&ospname, svname, index_str);
2719         if (rc)
2720                 GOTO(out_destory, rc);
2721
2722         rc = name_create_lov(&lovname, logname, fsdb, mdt_index);
2723         if (rc)
2724                 GOTO(out_destory, rc);
2725
2726         rc = name_create(&lovuuid, lovname, "_UUID");
2727         if (rc)
2728                 GOTO(out_destory, rc);
2729
2730         rc = name_create(&mdtuuid, mdtname, "_UUID");
2731         if (rc)
2732                 GOTO(out_destory, rc);
2733
2734         rc = mgs_modify(env, mgs, fsdb, mti, logname, mti->mti_svname,
2735                         "add osp", CM_SKIP);
2736         if (rc < 0)
2737                 GOTO(out_destory, rc);
2738
2739         rc = record_start_log(env, mgs, &llh, logname);
2740         if (rc)
2741                 GOTO(out_destory, rc);
2742
2743         rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
2744                            "add osp");
2745         if (rc)
2746                 GOTO(out_destory, rc);
2747
2748         for (i = 0; i < mti->mti_nid_count; i++) {
2749                 CDEBUG(D_MGS, "add nid %s for mdt\n",
2750                         libcfs_nid2str_r(mti->mti_nids[i],
2751                                          nidstr, sizeof(nidstr)));
2752                 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2753                 if (rc)
2754                         GOTO(out_end, rc);
2755         }
2756
2757         rc = record_attach(env, llh, ospname, LUSTRE_OSP_NAME, lovuuid);
2758         if (rc)
2759                 GOTO(out_end, rc);
2760
2761         rc = record_setup(env, llh, ospname, mti->mti_uuid, nodeuuid,
2762                           NULL, NULL);
2763         if (rc)
2764                 GOTO(out_end, rc);
2765
2766         rc = mgs_write_log_failnids(env, mti, llh, ospname);
2767         if (rc)
2768                 GOTO(out_end, rc);
2769
2770         /* Add mdc(osp) to lod */
2771         snprintf(index_str, sizeof(index_str), "%d", mti->mti_stripe_index);
2772         rc = record_base(env, llh, lovname, 0, LCFG_ADD_MDC, mti->mti_uuid,
2773                          index_str, "1", NULL);
2774         if (rc)
2775                 GOTO(out_end, rc);
2776
2777         rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname, "add osp");
2778         if (rc)
2779                 GOTO(out_end, rc);
2780
2781 out_end:
2782         record_end_log(env, &llh);
2783
2784 out_destory:
2785         name_destroy(&mdtuuid);
2786         name_destroy(&lovuuid);
2787         name_destroy(&lovname);
2788         name_destroy(&ospname);
2789         name_destroy(&svname);
2790         name_destroy(&nodeuuid);
2791         name_destroy(&mdtname);
2792         RETURN(rc);
2793 }
2794
2795 static int mgs_write_log_mdt0(const struct lu_env *env,
2796                               struct mgs_device *mgs,
2797                               struct fs_db *fsdb,
2798                               struct mgs_target_info *mti)
2799 {
2800         char *log = mti->mti_svname;
2801         struct llog_handle *llh = NULL;
2802         struct obd_uuid *uuid;
2803         char *lovname;
2804         char mdt_index[6];
2805         char *ptr = mti->mti_params;
2806         int rc = 0, failout = 0;
2807         ENTRY;
2808
2809         OBD_ALLOC_PTR(uuid);
2810         if (uuid == NULL)
2811                 RETURN(-ENOMEM);
2812
2813         if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
2814                 failout = (strncmp(ptr, "failout", 7) == 0);
2815
2816         rc = name_create(&lovname, log, "-mdtlov");
2817         if (rc)
2818                 GOTO(out_free, rc);
2819         if (mgs_log_is_empty(env, mgs, log)) {
2820                 rc = mgs_write_log_lov(env, mgs, fsdb, mti, log, lovname);
2821                 if (rc)
2822                         GOTO(out_lod, rc);
2823         }
2824
2825         sprintf(mdt_index, "%d", mti->mti_stripe_index);
2826
2827         rc = record_start_log(env, mgs, &llh, log);
2828         if (rc)
2829                 GOTO(out_lod, rc);
2830
2831         /* add MDT itself */
2832
2833         /* FIXME this whole fn should be a single journal transaction */
2834         sprintf(uuid->uuid, "%s_UUID", log);
2835         rc = record_marker(env, llh, fsdb, CM_START, log, "add mdt");
2836         if (rc)
2837                 GOTO(out_lod, rc);
2838         rc = record_attach(env, llh, log, LUSTRE_MDT_NAME, uuid->uuid);
2839         if (rc)
2840                 GOTO(out_end, rc);
2841         rc = record_mount_opt(env, llh, log, lovname, NULL);
2842         if (rc)
2843                 GOTO(out_end, rc);
2844         rc = record_setup(env, llh, log, uuid->uuid, mdt_index, lovname,
2845                         failout ? "n" : "f");
2846         if (rc)
2847                 GOTO(out_end, rc);
2848         rc = record_marker(env, llh, fsdb, CM_END, log, "add mdt");
2849         if (rc)
2850                 GOTO(out_end, rc);
2851 out_end:
2852         record_end_log(env, &llh);
2853 out_lod:
2854         name_destroy(&lovname);
2855 out_free:
2856         OBD_FREE_PTR(uuid);
2857         RETURN(rc);
2858 }
2859
2860 /* envelope method for all layers log */
2861 static int mgs_write_log_mdt(const struct lu_env *env,
2862                              struct mgs_device *mgs,
2863                              struct fs_db *fsdb,
2864                              struct mgs_target_info *mti)
2865 {
2866         struct mgs_thread_info *mgi = mgs_env_info(env);
2867         struct llog_handle *llh = NULL;
2868         char *cliname;
2869         int rc, i = 0;
2870         ENTRY;
2871
2872         CDEBUG(D_MGS, "writing new mdt %s\n", mti->mti_svname);
2873
2874         if (mti->mti_uuid[0] == '\0') {
2875                 /* Make up our own uuid */
2876                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
2877                          "%s_UUID", mti->mti_svname);
2878         }
2879
2880         /* add mdt */
2881         rc = mgs_write_log_mdt0(env, mgs, fsdb, mti);
2882         if (rc)
2883                 RETURN(rc);
2884         /* Append the mdt info to the client log */
2885         rc = name_create(&cliname, mti->mti_fsname, "-client");
2886         if (rc)
2887                 RETURN(rc);
2888
2889         if (mgs_log_is_empty(env, mgs, cliname)) {
2890                 /* Start client log */
2891                 rc = mgs_write_log_lov(env, mgs, fsdb, mti, cliname,
2892                                        fsdb->fsdb_clilov);
2893                 if (rc)
2894                         GOTO(out_free, rc);
2895                 rc = mgs_write_log_lmv(env, mgs, fsdb, mti, cliname,
2896                                        fsdb->fsdb_clilmv);
2897                 if (rc)
2898                         GOTO(out_free, rc);
2899                 rc = mgs_write_log_mount_opt(env, mgs, fsdb, cliname);
2900                 if (rc)
2901                         GOTO(out_free, rc);
2902         }
2903
2904         /*
2905         #09 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
2906         #10 L attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f
2907         #11 L setup    0:MDC_uml1_mdsA_MNT_client  1:mdsA_UUID  2:uml1_UUID
2908         #12 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
2909         #13 L add_conn 0:MDC_uml1_mdsA_MNT_client  1:uml2_UUID
2910         */
2911
2912         /* copy client info about lov/lmv */
2913         mgi->mgi_comp.comp_mti = mti;
2914         mgi->mgi_comp.comp_fsdb = fsdb;
2915
2916         rc = mgs_steal_llog_for_mdt_from_client(env, mgs, cliname,
2917                                                 &mgi->mgi_comp);
2918         if (rc)
2919                 GOTO(out_free, rc);
2920         rc = mgs_write_log_mdc_to_lmv(env, mgs, fsdb, mti, cliname,
2921                                       fsdb->fsdb_clilmv);
2922         if (rc)
2923                 GOTO(out_free, rc);
2924
2925         rc = record_start_log(env, mgs, &llh, cliname);
2926         if (rc)
2927                 GOTO(out_free, rc);
2928
2929         /* for_all_existing_mdt except current one */
2930         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
2931                 if (i !=  mti->mti_stripe_index &&
2932                     test_bit(i, fsdb->fsdb_mdt_index_map)) {
2933                         char *logname;
2934
2935                         rc = name_create_mdt(&logname, fsdb->fsdb_name, i);
2936                         if (rc)
2937                                 GOTO(out_end, rc);
2938
2939                         /* NB: If the log for the MDT is empty, it means
2940                          * the MDT is only added to the index
2941                          * map, and not being process yet, i.e. this
2942                          * is an unregistered MDT, see mgs_write_log_target().
2943                          * so we should skip it. Otherwise
2944                          *
2945                          * 1. MGS get register request for MDT1 and MDT2.
2946                          *
2947                          * 2. Then both MDT1 and MDT2 are added into
2948                          * fsdb_mdt_index_map. (see mgs_set_index()).
2949                          *
2950                          * 3. Then MDT1 get the lock of fsdb_mutex, then
2951                          * generate the config log, here, it will regard MDT2
2952                          * as an existent MDT, and generate "add osp" for
2953                          * lustre-MDT0001-osp-MDT0002. Note: at the moment
2954                          * MDT0002 config log is still empty, so it will
2955                          * add "add osp" even before "lov setup", which
2956                          * will definitly cause trouble.
2957                          *
2958                          * 4. MDT1 registeration finished, fsdb_mutex is
2959                          * released, then MDT2 get in, then in above
2960                          * mgs_steal_llog_for_mdt_from_client(), it will
2961                          * add another osp log for lustre-MDT0001-osp-MDT0002,
2962                          * which will cause another trouble.*/
2963                         if (!mgs_log_is_empty(env, mgs, logname))
2964                                 rc = mgs_write_log_osp_to_mdt(env, mgs, fsdb,
2965                                                               mti, i, logname);
2966
2967                         name_destroy(&logname);
2968                         if (rc)
2969                                 GOTO(out_end, rc);
2970                 }
2971         }
2972 out_end:
2973         record_end_log(env, &llh);
2974 out_free:
2975         name_destroy(&cliname);
2976         RETURN(rc);
2977 }
2978
2979 /* Add the ost info to the client/mdt lov */
2980 static int mgs_write_log_osc_to_lov(const struct lu_env *env,
2981                                     struct mgs_device *mgs, struct fs_db *fsdb,
2982                                     struct mgs_target_info *mti,
2983                                     char *logname, char *suffix, char *lovname,
2984                                     enum lustre_sec_part sec_part, int flags)
2985 {
2986         struct llog_handle *llh = NULL;
2987         char *nodeuuid = NULL;
2988         char *oscname = NULL;
2989         char *oscuuid = NULL;
2990         char *lovuuid = NULL;
2991         char *svname = NULL;
2992         char index[6];
2993         char nidstr[LNET_NIDSTR_SIZE];
2994         int i, rc;
2995         ENTRY;
2996
2997         CDEBUG(D_INFO, "adding osc for %s to log %s\n",
2998                 mti->mti_svname, logname);
2999
3000         if (mgs_log_is_empty(env, mgs, logname)) {
3001                 CERROR("log is empty! Logical error\n");
3002                 RETURN(-EINVAL);
3003         }
3004
3005         libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
3006         rc = name_create(&nodeuuid, nidstr, "");
3007         if (rc)
3008                 RETURN(rc);
3009         rc = name_create(&svname, mti->mti_svname, "-osc");
3010         if (rc)
3011                 GOTO(out_free, rc);
3012
3013         /* for the system upgraded from old 1.8, keep using the old osc naming
3014          * style for mdt, see name_create_mdt_osc(). LU-1257 */
3015         if (test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
3016                 rc = name_create(&oscname, svname, "");
3017         else
3018                 rc = name_create(&oscname, svname, suffix);
3019         if (rc)
3020                 GOTO(out_free, rc);
3021
3022         rc = name_create(&oscuuid, oscname, "_UUID");
3023         if (rc)
3024                 GOTO(out_free, rc);
3025         rc = name_create(&lovuuid, lovname, "_UUID");
3026         if (rc)
3027                 GOTO(out_free, rc);
3028
3029
3030         /*
3031         #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
3032         multihomed (#4)
3033         #04 L add_uuid  nid=1@elan(0x1000000000001)  nal=90 0:  1:uml1_UUID
3034         #04 L attach   0:OSC_uml1_ost1_MNT_client  1:osc  2:89070_lov1_a41dff51a
3035         #05 L setup    0:OSC_uml1_ost1_MNT_client  1:ost1_UUID  2:uml1_UUID
3036         failover (#6,7)
3037         #06 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
3038         #07 L add_conn 0:OSC_uml1_ost1_MNT_client  1:uml2_UUID
3039         #08 L lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1
3040         */
3041
3042         rc = record_start_log(env, mgs, &llh, logname);
3043         if (rc)
3044                 GOTO(out_free, rc);
3045
3046         /* FIXME these should be a single journal transaction */
3047         rc = record_marker(env, llh, fsdb, CM_START | flags, mti->mti_svname,
3048                            "add osc");
3049         if (rc)
3050                 GOTO(out_end, rc);
3051
3052         /* NB: don't change record order, because upon MDT steal OSC config
3053          * from client, it treats all nids before LCFG_SETUP as target nids
3054          * (multiple interfaces), while nids after as failover node nids.
3055          * See mgs_steal_client_llog_handler() LCFG_ADD_UUID.
3056          */
3057         for (i = 0; i < mti->mti_nid_count; i++) {
3058                 CDEBUG(D_MGS, "add nid %s\n",
3059                         libcfs_nid2str_r(mti->mti_nids[i],
3060                                          nidstr, sizeof(nidstr)));
3061                 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
3062                 if (rc)
3063                         GOTO(out_end, rc);
3064         }
3065         rc = record_attach(env, llh, oscname, LUSTRE_OSC_NAME, lovuuid);
3066         if (rc)
3067                 GOTO(out_end, rc);
3068         rc = record_setup(env, llh, oscname, mti->mti_uuid, nodeuuid,
3069                           NULL, NULL);
3070         if (rc)
3071                 GOTO(out_end, rc);
3072         rc = mgs_write_log_failnids(env, mti, llh, oscname);
3073         if (rc)
3074                 GOTO(out_end, rc);
3075
3076         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
3077
3078         rc = record_lov_add(env, llh, lovname, mti->mti_uuid, index, "1");
3079         if (rc)
3080                 GOTO(out_end, rc);
3081         rc = record_marker(env, llh, fsdb, CM_END | flags, mti->mti_svname,
3082                            "add osc");
3083         if (rc)
3084                 GOTO(out_end, rc);
3085 out_end:
3086         record_end_log(env, &llh);
3087 out_free:
3088         name_destroy(&lovuuid);
3089         name_destroy(&oscuuid);
3090         name_destroy(&oscname);
3091         name_destroy(&svname);
3092         name_destroy(&nodeuuid);
3093         RETURN(rc);
3094 }
3095
3096 static int mgs_write_log_ost(const struct lu_env *env,
3097                              struct mgs_device *mgs, struct fs_db *fsdb,
3098                              struct mgs_target_info *mti)
3099 {
3100         struct llog_handle *llh = NULL;
3101         char *logname, *lovname;
3102         char *ptr = mti->mti_params;
3103         int rc, flags = 0, failout = 0, i;
3104         ENTRY;
3105
3106         CDEBUG(D_MGS, "writing new ost %s\n", mti->mti_svname);
3107
3108         /* The ost startup log */
3109
3110         /* If the ost log already exists, that means that someone reformatted
3111            the ost and it called target_add again. */
3112         if (!mgs_log_is_empty(env, mgs, mti->mti_svname)) {
3113                 LCONSOLE_ERROR_MSG(0x141, "The config log for %s already "
3114                                    "exists, yet the server claims it never "
3115                                    "registered. It may have been reformatted, "
3116                                    "or the index changed. writeconf the MDT to "
3117                                    "regenerate all logs.\n", mti->mti_svname);
3118                 RETURN(-EALREADY);
3119         }
3120
3121         /*
3122         attach obdfilter ost1 ost1_UUID
3123         setup /dev/loop2 ldiskfs f|n errors=remount-ro,user_xattr
3124         */
3125         if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
3126                 failout = (strncmp(ptr, "failout", 7) == 0);
3127         rc = record_start_log(env, mgs, &llh, mti->mti_svname);
3128         if (rc)
3129                 RETURN(rc);
3130         /* FIXME these should be a single journal transaction */
3131         rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,"add ost");
3132         if (rc)
3133                 GOTO(out_end, rc);
3134         if (*mti->mti_uuid == '\0')
3135                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
3136                          "%s_UUID", mti->mti_svname);
3137         rc = record_attach(env, llh, mti->mti_svname,
3138                            "obdfilter"/*LUSTRE_OST_NAME*/, mti->mti_uuid);
3139         if (rc)
3140                 GOTO(out_end, rc);
3141         rc = record_setup(env, llh, mti->mti_svname,
3142                           "dev"/*ignored*/, "type"/*ignored*/,
3143                           failout ? "n" : "f", NULL/*options*/);
3144         if (rc)
3145                 GOTO(out_end, rc);
3146         rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname, "add ost");
3147         if (rc)
3148                 GOTO(out_end, rc);
3149 out_end:
3150         record_end_log(env, &llh);
3151         if (rc)
3152                 RETURN(rc);
3153         /* We also have to update the other logs where this osc is part of
3154            the lov */
3155
3156         if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
3157                 /* If we're upgrading, the old mdt log already has our
3158                    entry. Let's do a fake one for fun. */
3159                 /* Note that we can't add any new failnids, since we don't
3160                    know the old osc names. */
3161                 flags = CM_SKIP | CM_UPGRADE146;
3162
3163         } else if ((mti->mti_flags & LDD_F_UPDATE) != LDD_F_UPDATE) {
3164                 /* If the update flag isn't set, don't update client/mdt
3165                    logs. */
3166                 flags |= CM_SKIP;
3167                 LCONSOLE_WARN("Client log for %s was not updated; writeconf "
3168                               "the MDT first to regenerate it.\n",
3169                               mti->mti_svname);
3170         }
3171
3172         /* Add ost to all MDT lov defs */
3173         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
3174                 if (test_bit(i, fsdb->fsdb_mdt_index_map)) {
3175                         char mdt_index[13];
3176
3177                         rc = name_create_mdt_and_lov(&logname, &lovname, fsdb,
3178                                                      i);
3179                         if (rc)
3180                                 RETURN(rc);
3181
3182                         snprintf(mdt_index, sizeof(mdt_index), "-MDT%04x", i);
3183                         rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, mti,
3184                                                       logname, mdt_index,
3185                                                       lovname, LUSTRE_SP_MDT,
3186                                                       flags);
3187                         name_destroy(&logname);
3188                         name_destroy(&lovname);
3189                         if (rc)
3190                                 RETURN(rc);
3191                 }
3192         }
3193
3194         /* Append ost info to the client log */
3195         rc = name_create(&logname, mti->mti_fsname, "-client");
3196         if (rc)
3197                 RETURN(rc);
3198         if (mgs_log_is_empty(env, mgs, logname)) {
3199                 /* Start client log */
3200                 rc = mgs_write_log_lov(env, mgs, fsdb, mti, logname,
3201                                        fsdb->fsdb_clilov);
3202                 if (rc)
3203                         GOTO(out_free, rc);
3204                 rc = mgs_write_log_lmv(env, mgs, fsdb, mti, logname,
3205                                        fsdb->fsdb_clilmv);
3206                 if (rc)
3207                         GOTO(out_free, rc);
3208                 rc = mgs_write_log_mount_opt(env, mgs, fsdb, logname);
3209                 if (rc)
3210                         GOTO(out_free, rc);
3211         }
3212         rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, mti, logname, "",
3213                                       fsdb->fsdb_clilov, LUSTRE_SP_CLI, flags);
3214 out_free:
3215         name_destroy(&logname);
3216         RETURN(rc);
3217 }
3218
3219 static __inline__ int mgs_param_empty(char *ptr)
3220 {
3221         char *tmp;
3222
3223         if ((tmp = strchr(ptr, '=')) && (*(++tmp) == '\0'))
3224                 return 1;
3225         return 0;
3226 }
3227
3228 static int mgs_write_log_failnid_internal(const struct lu_env *env,
3229                                           struct mgs_device *mgs,
3230                                           struct fs_db *fsdb,
3231                                           struct mgs_target_info *mti,
3232                                           char *logname, char *cliname)
3233 {
3234         int rc;
3235         struct llog_handle *llh = NULL;
3236
3237         if (mgs_param_empty(mti->mti_params)) {
3238                 /* Remove _all_ failnids */
3239                 rc = mgs_modify(env, mgs, fsdb, mti, logname,
3240                                 mti->mti_svname, "add failnid", CM_SKIP);
3241                 return rc < 0 ? rc : 0;
3242         }
3243
3244         /* Otherwise failover nids are additive */
3245         rc = record_start_log(env, mgs, &llh, logname);
3246         if (rc)
3247                 return rc;
3248                 /* FIXME this should be a single journal transaction */
3249         rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
3250                            "add failnid");
3251         if (rc)
3252                 goto out_end;
3253         rc = mgs_write_log_failnids(env, mti, llh, cliname);
3254         if (rc)
3255                 goto out_end;
3256         rc = record_marker(env, llh, fsdb, CM_END,
3257                            mti->mti_svname, "add failnid");
3258 out_end:
3259         record_end_log(env, &llh);
3260         return rc;
3261 }
3262
3263
3264 /* Add additional failnids to an existing log.
3265    The mdc/osc must have been added to logs first */
3266 /* tcp nids must be in dotted-quad ascii -
3267    we can't resolve hostnames from the kernel. */
3268 static int mgs_write_log_add_failnid(const struct lu_env *env,
3269                                      struct mgs_device *mgs,
3270                                      struct fs_db *fsdb,
3271                                      struct mgs_target_info *mti)
3272 {
3273         char *logname, *cliname;
3274         int rc;
3275         ENTRY;
3276
3277         /* FIXME we currently can't erase the failnids
3278          * given when a target first registers, since they aren't part of
3279          * an "add uuid" stanza
3280          */
3281
3282         /* Verify that we know about this target */
3283         if (mgs_log_is_empty(env, mgs, mti->mti_svname)) {
3284                 LCONSOLE_ERROR_MSG(0x142, "The target %s has not registered "
3285                                    "yet. It must be started before failnids "
3286                                    "can be added.\n", mti->mti_svname);
3287                 RETURN(-ENOENT);
3288         }
3289
3290         /* Create mdc/osc client name (e.g. lustre-OST0001-osc) */
3291         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
3292                 rc = name_create(&cliname, mti->mti_svname, "-mdc");
3293         } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
3294                 rc = name_create(&cliname, mti->mti_svname, "-osc");
3295         } else {
3296                 RETURN(-EINVAL);
3297         }
3298         if (rc)
3299                 RETURN(rc);
3300
3301         /* Add failover nids to the client log */
3302         rc = name_create(&logname, mti->mti_fsname, "-client");
3303         if (rc) {
3304                 name_destroy(&cliname);
3305                 RETURN(rc);
3306         }
3307
3308         rc = mgs_write_log_failnid_internal(env, mgs, fsdb,mti,logname,cliname);
3309         name_destroy(&logname);
3310         name_destroy(&cliname);
3311         if (rc)
3312                 RETURN(rc);
3313
3314         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
3315                 /* Add OST failover nids to the MDT logs as well */
3316                 int i;
3317
3318                 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
3319                         if (!test_bit(i, fsdb->fsdb_mdt_index_map))
3320                                 continue;
3321                         rc = name_create_mdt(&logname, mti->mti_fsname, i);
3322                         if (rc)
3323                                 RETURN(rc);
3324                         rc = name_create_mdt_osc(&cliname, mti->mti_svname,
3325                                                  fsdb, i);
3326                         if (rc) {
3327                                 name_destroy(&logname);
3328                                 RETURN(rc);
3329                         }
3330                         rc = mgs_write_log_failnid_internal(env, mgs, fsdb,
3331                                                             mti, logname,
3332                                                             cliname);
3333                         name_destroy(&cliname);
3334                         name_destroy(&logname);
3335                         if (rc)
3336                                 RETURN(rc);
3337                 }
3338         }
3339
3340         RETURN(rc);
3341 }
3342
3343 static int mgs_wlp_lcfg(const struct lu_env *env,
3344                         struct mgs_device *mgs, struct fs_db *fsdb,
3345                         struct mgs_target_info *mti,
3346                         char *logname, struct lustre_cfg_bufs *bufs,
3347                         char *tgtname, char *ptr)
3348 {
3349         char comment[MTI_NAME_MAXLEN];
3350         char *tmp;
3351         struct llog_cfg_rec *lcr;
3352         int rc, del;
3353
3354         /* Erase any old settings of this same parameter */
3355         strlcpy(comment, ptr, sizeof(comment));
3356         /* But don't try to match the value. */
3357         tmp = strchr(comment, '=');
3358         if (tmp != NULL)
3359                 *tmp = 0;
3360         /* FIXME we should skip settings that are the same as old values */
3361         rc = mgs_modify(env, mgs, fsdb, mti, logname, tgtname, comment,CM_SKIP);
3362         if (rc < 0)
3363                 return rc;
3364         del = mgs_param_empty(ptr);
3365
3366         LCONSOLE_INFO("%s parameter %s.%s in log %s\n", del ? "Disabling" : rc ?
3367                       "Setting" : "Modifying", tgtname, comment, logname);
3368         if (del) {
3369                 /* mgs_modify() will return 1 if nothing had to be done */
3370                 if (rc == 1)
3371                         rc = 0;
3372                 return rc;
3373         }
3374
3375         lustre_cfg_bufs_reset(bufs, tgtname);
3376         lustre_cfg_bufs_set_string(bufs, 1, ptr);
3377         if (mti->mti_flags & LDD_F_PARAM2)
3378                 lustre_cfg_bufs_set_string(bufs, 2, LCTL_UPCALL);
3379
3380         lcr = lustre_cfg_rec_new((mti->mti_flags & LDD_F_PARAM2) ?
3381                                  LCFG_SET_PARAM : LCFG_PARAM, bufs);
3382         if (lcr == NULL)
3383                 return -ENOMEM;
3384
3385         rc = mgs_write_log_direct(env, mgs, fsdb, logname, lcr, tgtname,
3386                                   comment);
3387         lustre_cfg_rec_free(lcr);
3388         return rc;
3389 }
3390
3391 /* write global variable settings into log */
3392 static int mgs_write_log_sys(const struct lu_env *env,
3393                              struct mgs_device *mgs, struct fs_db *fsdb,
3394                              struct mgs_target_info *mti, char *sys, char *ptr)
3395 {
3396         struct mgs_thread_info  *mgi = mgs_env_info(env);
3397         struct lustre_cfg       *lcfg;
3398         struct llog_cfg_rec     *lcr;
3399         char *tmp, sep;
3400         int rc, cmd, convert = 1;
3401
3402         if (class_match_param(ptr, PARAM_TIMEOUT, &tmp) == 0) {
3403                 cmd = LCFG_SET_TIMEOUT;
3404         } else if (class_match_param(ptr, PARAM_LDLM_TIMEOUT, &tmp) == 0) {
3405                 cmd = LCFG_SET_LDLM_TIMEOUT;
3406         /* Check for known params here so we can return error to lctl */
3407         } else if ((class_match_param(ptr, PARAM_AT_MIN, &tmp) == 0) ||
3408                 (class_match_param(ptr, PARAM_AT_MAX, &tmp) == 0) ||
3409                 (class_match_param(ptr, PARAM_AT_EXTRA, &tmp) == 0) ||
3410                 (class_match_param(ptr, PARAM_AT_EARLY_MARGIN, &tmp) == 0) ||
3411                 (class_match_param(ptr, PARAM_AT_HISTORY, &tmp) == 0)) {
3412                 cmd = LCFG_PARAM;
3413         } else if (class_match_param(ptr, PARAM_JOBID_VAR, &tmp) == 0) {
3414                 convert = 0; /* Don't convert string value to integer */
3415                 cmd = LCFG_PARAM;
3416         } else {
3417                 return -EINVAL;
3418         }
3419
3420         if (mgs_param_empty(ptr))
3421                 CDEBUG(D_MGS, "global '%s' removed\n", sys);
3422         else
3423                 CDEBUG(D_MGS, "global '%s' val=%s\n", sys, tmp);
3424
3425         lustre_cfg_bufs_reset(&mgi->mgi_bufs, NULL);
3426         lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, sys);
3427         if (!convert && *tmp != '\0')
3428                 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 2, tmp);
3429         lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
3430         if (lcr == NULL)
3431                 return -ENOMEM;
3432
3433         lcfg = &lcr->lcr_cfg;
3434         if (convert) {
3435                 rc = kstrtouint(tmp, 0, &lcfg->lcfg_num);
3436                 if (rc)
3437                         GOTO(out_rec_free, rc);
3438         } else {
3439                 lcfg->lcfg_num = 0;
3440         }
3441
3442         /* truncate the comment to the parameter name */
3443         ptr = tmp - 1;
3444         sep = *ptr;
3445         *ptr = '\0';
3446         /* modify all servers and clients */
3447         rc = mgs_write_log_direct_all(env, mgs, fsdb, mti,
3448                                       *tmp == '\0' ? NULL : lcr,
3449                                       mti->mti_fsname, sys, 0);
3450         if (rc == 0 && *tmp != '\0') {
3451                 switch (cmd) {
3452                 case LCFG_SET_TIMEOUT:
3453                         if (!obd_timeout_set || lcfg->lcfg_num > obd_timeout)
3454                                 class_process_config(lcfg);
3455                         break;
3456                 case LCFG_SET_LDLM_TIMEOUT:
3457                         if (!ldlm_timeout_set || lcfg->lcfg_num > ldlm_timeout)
3458                                 class_process_config(lcfg);
3459                         break;
3460                 default:
3461                         break;
3462                 }
3463         }
3464         *ptr = sep;
3465 out_rec_free:
3466         lustre_cfg_rec_free(lcr);
3467         return rc;
3468 }
3469
3470 /* write quota settings into log */
3471 static int mgs_write_log_quota(const struct lu_env *env, struct mgs_device *mgs,
3472                                struct fs_db *fsdb, struct mgs_target_info *mti,
3473                                char *quota, char *ptr)
3474 {
3475         struct mgs_thread_info  *mgi = mgs_env_info(env);
3476         struct llog_cfg_rec     *lcr;
3477         char                    *tmp;
3478         char                     sep;
3479         int                      rc, cmd = LCFG_PARAM;
3480
3481         /* support only 'meta' and 'data' pools so far */
3482         if (class_match_param(ptr, QUOTA_METAPOOL_NAME, &tmp) != 0 &&
3483             class_match_param(ptr, QUOTA_DATAPOOL_NAME, &tmp) != 0) {
3484                 CERROR("parameter quota.%s isn't supported (only quota.mdt "
3485                        "& quota.ost are)\n", ptr);
3486                 return -EINVAL;
3487         }
3488
3489         if (*tmp == '\0') {
3490                 CDEBUG(D_MGS, "global '%s' removed\n", quota);
3491         } else {
3492                 CDEBUG(D_MGS, "global '%s'\n", quota);
3493
3494                 if (strchr(tmp, 'u') == NULL && strchr(tmp, 'g') == NULL &&
3495                     strchr(tmp, 'p') == NULL &&
3496                     strcmp(tmp, "none") != 0) {
3497                         CERROR("enable option(%s) isn't supported\n", tmp);
3498                         return -EINVAL;
3499                 }
3500         }
3501
3502         lustre_cfg_bufs_reset(&mgi->mgi_bufs, mti->mti_fsname);
3503         lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, quota);
3504         lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
3505         if (lcr == NULL)
3506                 return -ENOMEM;
3507
3508         /* truncate the comment to the parameter name */
3509         ptr = tmp - 1;
3510         sep = *ptr;
3511         *ptr = '\0';
3512
3513         /* XXX we duplicated quota enable information in all server
3514          *     config logs, it should be moved to a separate config
3515          *     log once we cleanup the config log for global param. */
3516         /* modify all servers */
3517         rc = mgs_write_log_direct_all(env, mgs, fsdb, mti,
3518                                       *tmp == '\0' ? NULL : lcr,
3519                                       mti->mti_fsname, quota, 1);
3520         *ptr = sep;
3521         lustre_cfg_rec_free(lcr);
3522         return rc < 0 ? rc : 0;
3523 }
3524
3525 static int mgs_srpc_set_param_disk(const struct lu_env *env,
3526                                    struct mgs_device *mgs,
3527                                    struct fs_db *fsdb,
3528                                    struct mgs_target_info *mti,
3529                                    char *param)
3530 {
3531         struct mgs_thread_info  *mgi = mgs_env_info(env);
3532         struct llog_cfg_rec     *lcr;
3533         struct llog_handle      *llh = NULL;
3534         char                    *logname;
3535         char                    *comment, *ptr;
3536         int                      rc, len;
3537
3538         ENTRY;
3539
3540         /* get comment */
3541         ptr = strchr(param, '=');
3542         LASSERT(ptr != NULL);
3543         len = ptr - param;
3544
3545         OBD_ALLOC(comment, len + 1);
3546         if (comment == NULL)
3547                 RETURN(-ENOMEM);
3548         strncpy(comment, param, len);
3549         comment[len] = '\0';
3550
3551         /* prepare lcfg */
3552         lustre_cfg_bufs_reset(&mgi->mgi_bufs, mti->mti_svname);
3553         lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, param);
3554         lcr = lustre_cfg_rec_new(LCFG_SPTLRPC_CONF, &mgi->mgi_bufs);
3555         if (lcr == NULL)
3556                 GOTO(out_comment, rc = -ENOMEM);
3557
3558         /* construct log name */
3559         rc = name_create(&logname, mti->mti_fsname, "-sptlrpc");
3560         if (rc < 0)
3561                 GOTO(out_lcfg, rc);
3562
3563         if (mgs_log_is_empty(env, mgs, logname)) {
3564                 rc = record_start_log(env, mgs, &llh, logname);
3565                 if (rc < 0)
3566                         GOTO(out, rc);
3567                 record_end_log(env, &llh);
3568         }
3569
3570         /* obsolete old one */
3571         rc = mgs_modify(env, mgs, fsdb, mti, logname, mti->mti_svname,
3572                         comment, CM_SKIP);
3573         if (rc < 0)
3574                 GOTO(out, rc);
3575         /* write the new one */
3576         rc = mgs_write_log_direct(env, mgs, fsdb, logname, lcr,
3577                                   mti->mti_svname, comment);
3578         if (rc)
3579                 CERROR("%s: error writing log %s: rc = %d\n",
3580                        mgs->mgs_obd->obd_name, logname, rc);
3581 out:
3582         name_destroy(&logname);
3583 out_lcfg:
3584         lustre_cfg_rec_free(lcr);
3585 out_comment:
3586         OBD_FREE(comment, len + 1);
3587         RETURN(rc);
3588 }
3589
3590 static int mgs_srpc_set_param_udesc_mem(struct fs_db *fsdb,
3591                                         char *param)
3592 {
3593         char    *ptr;
3594
3595         /* disable the adjustable udesc parameter for now, i.e. use default
3596          * setting that client always ship udesc to MDT if possible. to enable
3597          * it simply remove the following line */
3598         goto error_out;
3599
3600         ptr = strchr(param, '=');
3601         if (ptr == NULL)
3602                 goto error_out;
3603         *ptr++ = '\0';
3604
3605         if (strcmp(param, PARAM_SRPC_UDESC))
3606                 goto error_out;
3607
3608         if (strcmp(ptr, "yes") == 0) {
3609                 set_bit(FSDB_UDESC, &fsdb->fsdb_flags);
3610                 CWARN("Enable user descriptor shipping from client to MDT\n");
3611         } else if (strcmp(ptr, "no") == 0) {
3612                 clear_bit(FSDB_UDESC, &fsdb->fsdb_flags);
3613                 CWARN("Disable user descriptor shipping from client to MDT\n");
3614         } else {
3615                 *(ptr - 1) = '=';
3616                 goto error_out;
3617         }
3618         return 0;
3619
3620 error_out:
3621         CERROR("Invalid param: %s\n", param);
3622         return -EINVAL;
3623 }
3624
3625 static int mgs_srpc_set_param_mem(struct fs_db *fsdb,
3626                                   const char *svname,
3627                                   char *param)
3628 {
3629         struct sptlrpc_rule      rule;
3630         struct sptlrpc_rule_set *rset;
3631         int                      rc;
3632         ENTRY;
3633
3634         if (strncmp(param, PARAM_SRPC, sizeof(PARAM_SRPC) - 1) != 0) {
3635                 CERROR("Invalid sptlrpc parameter: %s\n", param);
3636                 RETURN(-EINVAL);
3637         }
3638
3639         if (strncmp(param, PARAM_SRPC_UDESC,
3640                     sizeof(PARAM_SRPC_UDESC) - 1) == 0) {
3641                 RETURN(mgs_srpc_set_param_udesc_mem(fsdb, param));
3642         }
3643
3644         if (strncmp(param, PARAM_SRPC_FLVR, sizeof(PARAM_SRPC_FLVR) - 1) != 0) {
3645                 CERROR("Invalid sptlrpc flavor parameter: %s\n", param);
3646                 RETURN(-EINVAL);
3647         }
3648
3649         param += sizeof(PARAM_SRPC_FLVR) - 1;
3650
3651         rc = sptlrpc_parse_rule(param, &rule);
3652         if (rc)
3653                 RETURN(rc);
3654
3655         /* mgs rules implies must be mgc->mgs */
3656         if (test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
3657                 if ((rule.sr_from != LUSTRE_SP_MGC &&
3658                      rule.sr_from != LUSTRE_SP_ANY) ||
3659                     (rule.sr_to != LUSTRE_SP_MGS &&
3660                      rule.sr_to != LUSTRE_SP_ANY))
3661                         RETURN(-EINVAL);
3662         }
3663
3664         /* preapre room for this coming rule. svcname format should be:
3665          * - fsname: general rule
3666          * - fsname-tgtname: target-specific rule
3667          */
3668         if (strchr(svname, '-')) {
3669                 struct mgs_tgt_srpc_conf *tgtconf;
3670                 int                       found = 0;
3671
3672                 for (tgtconf = fsdb->fsdb_srpc_tgt; tgtconf != NULL;
3673                      tgtconf = tgtconf->mtsc_next) {
3674                         if (!strcmp(tgtconf->mtsc_tgt, svname)) {
3675                                 found = 1;
3676                                 break;
3677                         }
3678                 }
3679
3680                 if (!found) {
3681                         int name_len;
3682
3683                         OBD_ALLOC_PTR(tgtconf);
3684                         if (tgtconf == NULL)
3685                                 RETURN(-ENOMEM);
3686
3687                         name_len = strlen(svname);
3688
3689                         OBD_ALLOC(tgtconf->mtsc_tgt, name_len + 1);
3690                         if (tgtconf->mtsc_tgt == NULL) {
3691                                 OBD_FREE_PTR(tgtconf);
3692                                 RETURN(-ENOMEM);
3693                         }
3694                         memcpy(tgtconf->mtsc_tgt, svname, name_len);
3695
3696                         tgtconf->mtsc_next = fsdb->fsdb_srpc_tgt;
3697                         fsdb->fsdb_srpc_tgt = tgtconf;
3698                 }
3699
3700                 rset = &tgtconf->mtsc_rset;
3701         } else if (strcmp(svname, MGSSELF_NAME) == 0) {
3702                 /* put _mgs related srpc rule directly in mgs ruleset */
3703                 rset = &fsdb->fsdb_mgs->mgs_lut.lut_sptlrpc_rset;
3704         } else {
3705                 rset = &fsdb->fsdb_srpc_gen;
3706         }
3707
3708         rc = sptlrpc_rule_set_merge(rset, &rule);
3709
3710         RETURN(rc);
3711 }
3712
3713 static int mgs_srpc_set_param(const struct lu_env *env,
3714                               struct mgs_device *mgs,
3715                               struct fs_db *fsdb,
3716                               struct mgs_target_info *mti,
3717                               char *param)
3718 {
3719         char                   *copy;
3720         int                     rc, copy_size;
3721         ENTRY;
3722
3723 #ifndef HAVE_GSS
3724         RETURN(-EINVAL);
3725 #endif
3726         /* keep a copy of original param, which could be destroied
3727          * during parsing */
3728         copy_size = strlen(param) + 1;
3729         OBD_ALLOC(copy, copy_size);
3730         if (copy == NULL)
3731                 return -ENOMEM;
3732         memcpy(copy, param, copy_size);
3733
3734         rc = mgs_srpc_set_param_mem(fsdb, mti->mti_svname, param);
3735         if (rc)
3736                 goto out_free;
3737
3738         /* previous steps guaranteed the syntax is correct */
3739         rc = mgs_srpc_set_param_disk(env, mgs, fsdb, mti, copy);
3740         if (rc)
3741                 goto out_free;
3742
3743         if (test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
3744                 /*
3745                  * for mgs rules, make them effective immediately.
3746                  */
3747                 LASSERT(fsdb->fsdb_srpc_tgt == NULL);
3748                 sptlrpc_target_update_exp_flavor(mgs->mgs_obd,
3749                                                  &fsdb->fsdb_srpc_gen);
3750         }
3751
3752 out_free:
3753         OBD_FREE(copy, copy_size);
3754         RETURN(rc);
3755 }
3756
3757 struct mgs_srpc_read_data {
3758         struct fs_db   *msrd_fsdb;
3759         int             msrd_skip;
3760 };
3761
3762 static int mgs_srpc_read_handler(const struct lu_env *env,
3763                                  struct llog_handle *llh,
3764                                  struct llog_rec_hdr *rec, void *data)
3765 {
3766         struct mgs_srpc_read_data *msrd = data;
3767         struct cfg_marker         *marker;
3768         struct lustre_cfg         *lcfg = REC_DATA(rec);
3769         char                      *svname, *param;
3770         int                        cfg_len, rc;
3771         ENTRY;
3772
3773         if (rec->lrh_type != OBD_CFG_REC) {
3774                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
3775                 RETURN(-EINVAL);
3776         }
3777
3778         cfg_len = REC_DATA_LEN(rec);
3779
3780         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
3781         if (rc) {
3782                 CERROR("Insane cfg\n");
3783                 RETURN(rc);
3784         }
3785
3786         if (lcfg->lcfg_command == LCFG_MARKER) {
3787                 marker = lustre_cfg_buf(lcfg, 1);
3788
3789                 if (marker->cm_flags & CM_START &&
3790                     marker->cm_flags & CM_SKIP)
3791                         msrd->msrd_skip = 1;
3792                 if (marker->cm_flags & CM_END)
3793                         msrd->msrd_skip = 0;
3794
3795                 RETURN(0);
3796         }
3797
3798         if (msrd->msrd_skip)
3799                 RETURN(0);
3800
3801         if (lcfg->lcfg_command != LCFG_SPTLRPC_CONF) {
3802                 CERROR("invalid command (%x)\n", lcfg->lcfg_command);
3803                 RETURN(0);
3804         }
3805
3806         svname = lustre_cfg_string(lcfg, 0);
3807         if (svname == NULL) {
3808                 CERROR("svname is empty\n");
3809                 RETURN(0);
3810         }
3811
3812         param = lustre_cfg_string(lcfg, 1);
3813         if (param == NULL) {
3814                 CERROR("param is empty\n");
3815                 RETURN(0);
3816         }
3817
3818         rc = mgs_srpc_set_param_mem(msrd->msrd_fsdb, svname, param);
3819         if (rc)
3820                 CERROR("read sptlrpc record error (%d): %s\n", rc, param);
3821
3822         RETURN(0);
3823 }
3824
3825 int mgs_get_fsdb_srpc_from_llog(const struct lu_env *env,
3826                                 struct mgs_device *mgs,
3827                                 struct fs_db *fsdb)
3828 {
3829         struct llog_handle        *llh = NULL;
3830         struct llog_ctxt          *ctxt;
3831         char                      *logname;
3832         struct mgs_srpc_read_data  msrd;
3833         int                        rc;
3834         ENTRY;
3835
3836         /* construct log name */
3837         rc = name_create(&logname, fsdb->fsdb_name, "-sptlrpc");
3838         if (rc)
3839                 RETURN(rc);
3840
3841         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
3842         LASSERT(ctxt != NULL);
3843
3844         if (mgs_log_is_empty(env, mgs, logname))
3845                 GOTO(out, rc = 0);
3846
3847         rc = llog_open(env, ctxt, &llh, NULL, logname,
3848                        LLOG_OPEN_EXISTS);
3849         if (rc < 0) {
3850                 if (rc == -ENOENT)
3851                         rc = 0;
3852                 GOTO(out, rc);
3853         }
3854
3855         rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL);
3856         if (rc)
3857                 GOTO(out_close, rc);
3858
3859         if (llog_get_size(llh) <= 1)
3860                 GOTO(out_close, rc = 0);
3861
3862         msrd.msrd_fsdb = fsdb;
3863         msrd.msrd_skip = 0;
3864
3865         rc = llog_process(env, llh, mgs_srpc_read_handler, (void *)&msrd,
3866                           NULL);
3867
3868 out_close:
3869         llog_close(env, llh);
3870 out:
3871         llog_ctxt_put(ctxt);
3872         name_destroy(&logname);
3873
3874         if (rc)
3875                 CERROR("failed to read sptlrpc config database: %d\n", rc);
3876         RETURN(rc);
3877 }
3878
3879 static int mgs_write_log_param2(const struct lu_env *env,
3880                                 struct mgs_device *mgs,
3881                                 struct fs_db *fsdb,
3882                                 struct mgs_target_info *mti, char *ptr)
3883 {
3884         struct lustre_cfg_bufs bufs;
3885         int rc;
3886
3887         ENTRY;
3888         CDEBUG(D_MGS, "next param '%s'\n", ptr);
3889
3890         /* PARAM_MGSNODE and PARAM_NETWORK are set only when formating
3891          * or during the inital mount. It can never change after that.
3892          */
3893         if (!class_match_param(ptr, PARAM_MGSNODE, NULL) ||
3894             !class_match_param(ptr, PARAM_NETWORK, NULL)) {
3895                 rc = 0;
3896                 goto end;
3897         }
3898
3899         /* Processed in mgs_write_log_ost. Another value that can't
3900          * be changed by lctl set_param -P.
3901          */
3902         if (!class_match_param(ptr, PARAM_FAILMODE, NULL)) {
3903                 LCONSOLE_ERROR_MSG(0x169,
3904                                    "%s can only be changed with tunefs.lustre and --writeconf\n",
3905                                    ptr);
3906                 rc = -EPERM;
3907                 goto end;
3908         }
3909
3910         /* FIXME !!! Support for sptlrpc is incomplete. Currently the change
3911          * doesn't transmit to the client. See LU-7183.
3912          */
3913         if (!class_match_param(ptr, PARAM_SRPC, NULL)) {
3914                 rc = mgs_srpc_set_param(env, mgs, fsdb, mti, ptr);
3915                 goto end;
3916         }
3917
3918         /* Can't use class_match_param since ptr doesn't start with
3919          * PARAM_FAILNODE. So we look for PARAM_FAILNODE contained in ptr.
3920          */
3921         if (strstr(ptr, PARAM_FAILNODE)) {
3922                 /* Add a failover nidlist. We already processed failovers
3923                  * params for new targets in mgs_write_log_target.
3924                  */
3925                 const char *param;
3926
3927                 /* can't use wildcards with failover.node */
3928                 if (strchr(ptr, '*')) {
3929                         rc = -ENODEV;
3930                         goto end;
3931                 }
3932
3933                 param = strstr(ptr, PARAM_FAILNODE);
3934                 if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
3935                     sizeof(mti->mti_params)) {
3936                         rc = -E2BIG;
3937                         goto end;
3938                 }
3939
3940                 CDEBUG(D_MGS, "Adding failnode with param %s\n",
3941                        mti->mti_params);
3942                 rc = mgs_write_log_add_failnid(env, mgs, fsdb, mti);
3943                 goto end;
3944         }
3945
3946         /* root squash parameters must not be set on llite subsystem, this can
3947          * lead to inconsistencies between client and server values
3948          */
3949         if ((strstr(ptr, PARAM_NOSQUASHNIDS) ||
3950              strstr(ptr, PARAM_ROOTSQUASH)) &&
3951             strncmp(ptr, "llite.", strlen("llite.")) == 0) {
3952                 rc = -EINVAL;
3953                 CWARN("%s: cannot add %s param to llite subsystem, use mdt instead: rc=%d\n",
3954                       mgs->mgs_obd->obd_name,
3955                       strstr(ptr, PARAM_ROOTSQUASH) ?
3956                         PARAM_ROOTSQUASH : PARAM_NOSQUASHNIDS,
3957                       rc);
3958                 goto end;
3959         }
3960
3961         rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, PARAMS_FILENAME, &bufs,
3962                           mti->mti_svname, ptr);
3963 end:
3964         RETURN(rc);
3965 }
3966
3967 /* Permanent settings of all parameters by writing into the appropriate
3968  * configuration logs.
3969  * A parameter with null value ("<param>='\0'") means to erase it out of
3970  * the logs.
3971  */
3972 static int mgs_write_log_param(const struct lu_env *env,
3973                                struct mgs_device *mgs, struct fs_db *fsdb,
3974                                struct mgs_target_info *mti, char *ptr)
3975 {
3976         struct mgs_thread_info *mgi = mgs_env_info(env);
3977         char *logname;
3978         char *tmp;
3979         int rc = 0;
3980         ENTRY;
3981
3982         /* For various parameter settings, we have to figure out which logs
3983            care about them (e.g. both mdt and client for lov settings) */
3984         CDEBUG(D_MGS, "next param '%s'\n", ptr);
3985
3986         /* The params are stored in MOUNT_DATA_FILE and modified via
3987            tunefs.lustre, or set using lctl conf_param */
3988
3989         /* Processed in lustre_start_mgc */
3990         if (class_match_param(ptr, PARAM_MGSNODE, NULL) == 0)
3991                 GOTO(end, rc);
3992
3993         /* Processed in ost/mdt */
3994         if (class_match_param(ptr, PARAM_NETWORK, NULL) == 0)
3995                 GOTO(end, rc);
3996
3997         /* Processed in mgs_write_log_ost */
3998         if (class_match_param(ptr, PARAM_FAILMODE, NULL) == 0) {
3999                 if (mti->mti_flags & LDD_F_PARAM) {
4000                         LCONSOLE_ERROR_MSG(0x169,
4001                                            "%s can only be changed with tunefs.lustre and --writeconf\n",
4002                                            ptr);
4003                         rc = -EPERM;
4004                 }
4005                 GOTO(end, rc);
4006         }
4007
4008         if (class_match_param(ptr, PARAM_SRPC, NULL) == 0) {
4009                 rc = mgs_srpc_set_param(env, mgs, fsdb, mti, ptr);
4010                 GOTO(end, rc);
4011         }
4012
4013         if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
4014                 /* Add a failover nidlist */
4015                 rc = 0;
4016                 /* We already processed failovers params for new
4017                    targets in mgs_write_log_target */
4018                 if (mti->mti_flags & LDD_F_PARAM) {
4019                         CDEBUG(D_MGS, "Adding failnode\n");
4020                         rc = mgs_write_log_add_failnid(env, mgs, fsdb, mti);
4021                 }
4022                 GOTO(end, rc);
4023         }
4024
4025         if (class_match_param(ptr, PARAM_SYS, &tmp) == 0) {
4026                 rc = mgs_write_log_sys(env, mgs, fsdb, mti, ptr, tmp);
4027                 GOTO(end, rc);
4028         }
4029
4030         if (class_match_param(ptr, PARAM_QUOTA, &tmp) == 0) {
4031                 rc = mgs_write_log_quota(env, mgs, fsdb, mti, ptr, tmp);
4032                 GOTO(end, rc);
4033         }
4034
4035         if (class_match_param(ptr, PARAM_OSC PARAM_ACTIVE, &tmp) == 0 ||
4036             class_match_param(ptr, PARAM_MDC PARAM_ACTIVE, &tmp) == 0) {
4037                 /* active=0 means off, anything else means on */
4038                 int flag = (*tmp == '0') ? CM_EXCLUDE : 0;
4039                 bool deactive_osc = memcmp(ptr, PARAM_OSC PARAM_ACTIVE,
4040                                           strlen(PARAM_OSC PARAM_ACTIVE)) == 0;
4041                 int i;
4042
4043                 if (!deactive_osc) {
4044                         __u32   index;
4045
4046                         rc = server_name2index(mti->mti_svname, &index, NULL);
4047                         if (rc < 0)
4048                                 GOTO(end, rc);
4049
4050                         if (index == 0) {
4051                                 LCONSOLE_ERROR_MSG(0x144, "%s: MDC0 can not be"
4052                                                    " (de)activated.\n",
4053                                                    mti->mti_svname);
4054                                 GOTO(end, rc = -EPERM);
4055                         }
4056                 }
4057
4058                 LCONSOLE_WARN("Permanently %sactivating %s\n",
4059                               flag ? "de" : "re", mti->mti_svname);
4060                 /* Modify clilov */
4061                 rc = name_create(&logname, mti->mti_fsname, "-client");
4062                 if (rc < 0)
4063                         GOTO(end, rc);
4064                 rc = mgs_modify(env, mgs, fsdb, mti, logname,
4065                                 mti->mti_svname,
4066                                 deactive_osc ? "add osc" : "add mdc", flag);
4067                 name_destroy(&logname);
4068                 if (rc < 0)
4069                         goto active_err;
4070
4071                 /* Modify mdtlov */
4072                 /* Add to all MDT logs for DNE */
4073                 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
4074                         if (!test_bit(i, fsdb->fsdb_mdt_index_map))
4075                                 continue;
4076                         rc = name_create_mdt(&logname, mti->mti_fsname, i);
4077                         if (rc < 0)
4078                                 GOTO(end, rc);
4079                         rc = mgs_modify(env, mgs, fsdb, mti, logname,
4080                                         mti->mti_svname,
4081                                         deactive_osc ? "add osc" : "add osp",
4082                                         flag);
4083                         name_destroy(&logname);
4084                         if (rc < 0)
4085                                 goto active_err;
4086                 }
4087 active_err:
4088                 if (rc < 0) {
4089                         LCONSOLE_ERROR_MSG(0x145,
4090                                            "Couldn't find %s in log (%d). No permanent changes were made to the config log.\n",
4091                                            mti->mti_svname, rc);
4092                         if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags))
4093                                 LCONSOLE_ERROR_MSG(0x146,
4094                                                    "This may be because the log is in the old 1.4 style. Consider --writeconf to update the logs.\n");
4095                         GOTO(end, rc);
4096                 }
4097                 /* Fall through to osc/mdc proc for deactivating live
4098                    OSC/OSP on running MDT / clients. */
4099         }
4100         /* Below here, let obd's XXX_process_config methods handle it */
4101
4102         /* All lov. in proc */
4103         if (class_match_param(ptr, PARAM_LOV, NULL) == 0) {
4104                 char *mdtlovname;
4105
4106                 CDEBUG(D_MGS, "lov param %s\n", ptr);
4107                 if (!(mti->mti_flags & LDD_F_SV_TYPE_MDT)) {
4108                         LCONSOLE_ERROR_MSG(0x147, "LOV params must be "
4109                                            "set on the MDT, not %s. "
4110                                            "Ignoring.\n",
4111                                            mti->mti_svname);
4112                         GOTO(end, rc = 0);
4113                 }
4114
4115                 /* Modify mdtlov */
4116                 if (mgs_log_is_empty(env, mgs, mti->mti_svname))
4117                         GOTO(end, rc = -ENODEV);
4118
4119                 rc = name_create_mdt_and_lov(&logname, &mdtlovname, fsdb,
4120                                              mti->mti_stripe_index);
4121                 if (rc)
4122                         GOTO(end, rc);
4123                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, mti->mti_svname,
4124                                   &mgi->mgi_bufs, mdtlovname, ptr);
4125                 name_destroy(&logname);
4126                 name_destroy(&mdtlovname);
4127                 if (rc)
4128                         GOTO(end, rc);
4129
4130                 /* Modify clilov */
4131                 rc = name_create(&logname, mti->mti_fsname, "-client");
4132                 if (rc)
4133                         GOTO(end, rc);
4134                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname, &mgi->mgi_bufs,
4135                                   fsdb->fsdb_clilov, ptr);
4136                 name_destroy(&logname);
4137                 GOTO(end, rc);
4138         }
4139
4140         /* All osc., mdc., llite. params in proc */
4141         if ((class_match_param(ptr, PARAM_OSC, NULL) == 0) ||
4142             (class_match_param(ptr, PARAM_MDC, NULL) == 0) ||
4143             (class_match_param(ptr, PARAM_LLITE, NULL) == 0)) {
4144                 char *cname;
4145
4146                 if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
4147                         LCONSOLE_ERROR_MSG(0x148, "Upgraded client logs for %s"
4148                                            " cannot be modified. Consider"
4149                                            " updating the configuration with"
4150                                            " --writeconf\n",
4151                                            mti->mti_svname);
4152                         GOTO(end, rc = -EINVAL);
4153                 }
4154                 if (memcmp(ptr, PARAM_LLITE, strlen(PARAM_LLITE)) == 0) {
4155                         rc = name_create(&cname, mti->mti_fsname, "-client");
4156                         /* Add the client type to match the obdname in
4157                            class_config_llog_handler */
4158                 } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
4159                         rc = name_create(&cname, mti->mti_svname, "-mdc");
4160                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
4161                         rc = name_create(&cname, mti->mti_svname, "-osc");
4162                 } else {
4163                         GOTO(end, rc = -EINVAL);
4164                 }
4165                 if (rc)
4166                         GOTO(end, rc);
4167
4168                 /* Forbid direct update of llite root squash parameters.
4169                  * These parameters are indirectly set via the MDT settings.
4170                  * See (LU-1778) */
4171                 if ((class_match_param(ptr, PARAM_LLITE, &tmp) == 0) &&
4172                     ((memcmp(tmp, "root_squash=", 12) == 0) ||
4173                      (memcmp(tmp, "nosquash_nids=", 14) == 0))) {
4174                         LCONSOLE_ERROR("%s: root squash parameters can only "
4175                                 "be updated through MDT component\n",
4176                                 mti->mti_fsname);
4177                         name_destroy(&cname);
4178                         GOTO(end, rc = -EINVAL);
4179                 }
4180
4181                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
4182
4183                 /* Modify client */
4184                 rc = name_create(&logname, mti->mti_fsname, "-client");
4185                 if (rc) {
4186                         name_destroy(&cname);
4187                         GOTO(end, rc);
4188                 }
4189                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname, &mgi->mgi_bufs,
4190                                   cname, ptr);
4191
4192                 /* osc params affect the MDT as well */
4193                 if (!rc && (mti->mti_flags & LDD_F_SV_TYPE_OST)) {
4194                         int i;
4195
4196                         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
4197                                 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
4198                                         continue;
4199                                 name_destroy(&cname);
4200                                 rc = name_create_mdt_osc(&cname, mti->mti_svname,
4201                                                          fsdb, i);
4202                                 name_destroy(&logname);
4203                                 if (rc)
4204                                         break;
4205                                 rc = name_create_mdt(&logname,
4206                                                      mti->mti_fsname, i);
4207                                 if (rc)
4208                                         break;
4209                                 if (!mgs_log_is_empty(env, mgs, logname)) {
4210                                         rc = mgs_wlp_lcfg(env, mgs, fsdb,
4211                                                           mti, logname,
4212                                                           &mgi->mgi_bufs,
4213                                                           cname, ptr);
4214                                         if (rc)
4215                                                 break;
4216                                 }
4217                         }
4218                 }
4219
4220                 /* For mdc activate/deactivate, it affects OSP on MDT as well */
4221                 if (class_match_param(ptr, PARAM_MDC PARAM_ACTIVE, &tmp) == 0 &&
4222                     rc == 0) {
4223                         char suffix[16];
4224                         char *lodname = NULL;
4225                         char *param_str = NULL;
4226                         int i;
4227                         int index;
4228
4229                         /* replace mdc with osp */
4230                         memcpy(ptr, PARAM_OSP, strlen(PARAM_OSP));
4231                         rc = server_name2index(mti->mti_svname, &index, NULL);
4232                         if (rc < 0) {
4233                                 memcpy(ptr, PARAM_MDC, strlen(PARAM_MDC));
4234                                 GOTO(end, rc);
4235                         }
4236
4237                         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
4238                                 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
4239                                         continue;
4240
4241                                 if (i == index)
4242                                         continue;
4243
4244                                 name_destroy(&logname);
4245                                 rc = name_create_mdt(&logname, mti->mti_fsname,
4246                                                      i);
4247                                 if (rc < 0)
4248                                         break;
4249
4250                                 if (mgs_log_is_empty(env, mgs, logname))
4251                                         continue;
4252
4253                                 snprintf(suffix, sizeof(suffix), "-osp-MDT%04x",
4254                                          i);
4255                                 name_destroy(&cname);
4256                                 rc = name_create(&cname, mti->mti_svname,
4257                                                  suffix);
4258                                 if (rc < 0)
4259                                         break;
4260
4261                                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,
4262                                                   &mgi->mgi_bufs, cname, ptr);
4263                                 if (rc < 0)
4264                                         break;
4265
4266                                 /* Add configuration log for noitfying LOD
4267                                  * to active/deactive the OSP. */
4268                                 name_destroy(&param_str);
4269                                 rc = name_create(&param_str, cname,
4270                                                  (*tmp == '0') ?  ".active=0" :
4271                                                  ".active=1");
4272                                 if (rc < 0)
4273                                         break;
4274
4275                                 name_destroy(&lodname);
4276                                 rc = name_create(&lodname, logname, "-mdtlov");
4277                                 if (rc < 0)
4278                                         break;
4279
4280                                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,
4281                                                   &mgi->mgi_bufs, lodname,
4282                                                   param_str);
4283                                 if (rc < 0)
4284                                         break;
4285                         }
4286                         memcpy(ptr, PARAM_MDC, strlen(PARAM_MDC));
4287                         name_destroy(&lodname);
4288                         name_destroy(&param_str);
4289                 }
4290
4291                 name_destroy(&logname);
4292                 name_destroy(&cname);
4293                 GOTO(end, rc);
4294         }
4295
4296         /* All mdt. params in proc */
4297         if (class_match_param(ptr, PARAM_MDT, &tmp) == 0) {
4298                 int i;
4299                 __u32 idx;
4300
4301                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
4302                 if (strncmp(mti->mti_svname, mti->mti_fsname,
4303                             MTI_NAME_MAXLEN) == 0)
4304                         /* device is unspecified completely? */
4305                         rc = LDD_F_SV_TYPE_MDT | LDD_F_SV_ALL;
4306                 else
4307                         rc = server_name2index(mti->mti_svname, &idx, NULL);
4308                 if (rc < 0)
4309                         goto active_err;
4310                 if ((rc & LDD_F_SV_TYPE_MDT) == 0)
4311                         goto active_err;
4312                 if (rc & LDD_F_SV_ALL) {
4313                         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
4314                                 if (!test_bit(i,
4315                                                   fsdb->fsdb_mdt_index_map))
4316                                         continue;
4317                                 rc = name_create_mdt(&logname,
4318                                                 mti->mti_fsname, i);
4319                                 if (rc)
4320                                         goto active_err;
4321                                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti,
4322                                                   logname, &mgi->mgi_bufs,
4323                                                   logname, ptr);
4324                                 name_destroy(&logname);
4325                                 if (rc)
4326                                         goto active_err;
4327                         }
4328                 } else {
4329                         if ((memcmp(tmp, "root_squash=", 12) == 0) ||
4330                             (memcmp(tmp, "nosquash_nids=", 14) == 0)) {
4331                                 LCONSOLE_ERROR("%s: root squash parameters "
4332                                         "cannot be applied to a single MDT\n",
4333                                         mti->mti_fsname);
4334                                 GOTO(end, rc = -EINVAL);
4335                         }
4336                         rc = mgs_wlp_lcfg(env, mgs, fsdb, mti,
4337                                           mti->mti_svname, &mgi->mgi_bufs,
4338                                           mti->mti_svname, ptr);
4339                         if (rc)
4340                                 goto active_err;
4341                 }
4342
4343                 /* root squash settings are also applied to llite
4344                  * config log (see LU-1778) */
4345                 if (rc == 0 &&
4346                     ((memcmp(tmp, "root_squash=", 12) == 0) ||
4347                      (memcmp(tmp, "nosquash_nids=", 14) == 0))) {
4348                         char *cname;
4349                         char *ptr2;
4350
4351                         rc = name_create(&cname, mti->mti_fsname, "-client");
4352                         if (rc)
4353                                 GOTO(end, rc);
4354                         rc = name_create(&logname, mti->mti_fsname, "-client");
4355                         if (rc) {
4356                                 name_destroy(&cname);
4357                                 GOTO(end, rc);
4358                         }
4359                         rc = name_create(&ptr2, PARAM_LLITE, tmp);
4360                         if (rc) {
4361                                 name_destroy(&cname);
4362                                 name_destroy(&logname);
4363                                 GOTO(end, rc);
4364                         }
4365                         rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,
4366                                           &mgi->mgi_bufs, cname, ptr2);
4367                         name_destroy(&ptr2);
4368                         name_destroy(&logname);
4369                         name_destroy(&cname);
4370                 }
4371                 GOTO(end, rc);
4372         }
4373
4374         /* All mdd., ost. and osd. params in proc */
4375         if ((class_match_param(ptr, PARAM_MDD, NULL) == 0) ||
4376             (class_match_param(ptr, PARAM_LOD, NULL) == 0) ||
4377             (class_match_param(ptr, PARAM_OST, NULL) == 0) ||
4378             (class_match_param(ptr, PARAM_OSD, NULL) == 0)) {
4379                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
4380                 if (mgs_log_is_empty(env, mgs, mti->mti_svname))
4381                         GOTO(end, rc = -ENODEV);
4382
4383                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, mti->mti_svname,
4384                                   &mgi->mgi_bufs, mti->mti_svname, ptr);
4385                 GOTO(end, rc);
4386         }
4387
4388         LCONSOLE_WARN("Ignoring unrecognized param '%s'\n", ptr);
4389
4390 end:
4391         if (rc)
4392                 CERROR("err %d on param '%s'\n", rc, ptr);
4393
4394         RETURN(rc);
4395 }
4396
4397 int mgs_write_log_target(const struct lu_env *env, struct mgs_device *mgs,
4398                          struct mgs_target_info *mti, struct fs_db *fsdb)
4399 {
4400         char    *buf, *params;
4401         int      rc = -EINVAL;
4402
4403         ENTRY;
4404
4405         /* set/check the new target index */
4406         rc = mgs_set_index(env, mgs, mti);
4407         if (rc < 0)
4408                 RETURN(rc);
4409
4410         if (rc == EALREADY) {
4411                 LCONSOLE_WARN("Found index %d for %s, updating log\n",
4412                               mti->mti_stripe_index, mti->mti_svname);
4413                 /* We would like to mark old log sections as invalid
4414                    and add new log sections in the client and mdt logs.
4415                    But if we add new sections, then live clients will
4416                    get repeat setup instructions for already running
4417                    osc's. So don't update the client/mdt logs. */
4418                 mti->mti_flags &= ~LDD_F_UPDATE;
4419                 rc = 0;
4420         }
4421
4422         OBD_FAIL_TIMEOUT(OBD_FAIL_MGS_WRITE_TARGET_DELAY, cfs_fail_val > 0 ?
4423                          cfs_fail_val : 10);
4424
4425         mutex_lock(&fsdb->fsdb_mutex);
4426
4427         if (mti->mti_flags & (LDD_F_VIRGIN | LDD_F_WRITECONF)) {
4428                 /* Generate a log from scratch */
4429                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
4430                         rc = mgs_write_log_mdt(env, mgs, fsdb, mti);
4431                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
4432                         rc = mgs_write_log_ost(env, mgs, fsdb, mti);
4433                 } else {
4434                         CERROR("Unknown target type %#x, can't create log for %s\n",
4435                                mti->mti_flags, mti->mti_svname);
4436                 }
4437                 if (rc) {
4438                         CERROR("Can't write logs for %s (%d)\n",
4439                                mti->mti_svname, rc);
4440                         GOTO(out_up, rc);
4441                 }
4442         } else {
4443                 /* Just update the params from tunefs in mgs_write_log_params */
4444                 CDEBUG(D_MGS, "Update params for %s\n", mti->mti_svname);
4445                 mti->mti_flags |= LDD_F_PARAM;
4446         }
4447
4448         /* allocate temporary buffer, where class_get_next_param will
4449            make copy of a current  parameter */
4450         OBD_ALLOC(buf, strlen(mti->mti_params) + 1);
4451         if (buf == NULL)
4452                 GOTO(out_up, rc = -ENOMEM);
4453         params = mti->mti_params;
4454         while (params != NULL) {
4455                 rc = class_get_next_param(&params, buf);
4456                 if (rc) {
4457                         if (rc == 1)
4458                                 /* there is no next parameter, that is
4459                                    not an error */
4460                                 rc = 0;
4461                         break;
4462                 }
4463                 CDEBUG(D_MGS, "remaining string: '%s', param: '%s'\n",
4464                        params, buf);
4465                 rc = mgs_write_log_param(env, mgs, fsdb, mti, buf);
4466                 if (rc)
4467                         break;
4468         }
4469
4470         OBD_FREE(buf, strlen(mti->mti_params) + 1);
4471
4472 out_up:
4473         mutex_unlock(&fsdb->fsdb_mutex);
4474         RETURN(rc);
4475 }
4476
4477 int mgs_erase_log(const struct lu_env *env, struct mgs_device *mgs, char *name)
4478 {
4479         struct llog_ctxt        *ctxt;
4480         int                      rc = 0;
4481
4482         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
4483         if (ctxt == NULL) {
4484                 CERROR("%s: MGS config context doesn't exist\n",
4485                        mgs->mgs_obd->obd_name);
4486                 rc = -ENODEV;
4487         } else {
4488                 rc = llog_erase(env, ctxt, NULL, name);
4489                 /* llog may not exist */
4490                 if (rc == -ENOENT)
4491                         rc = 0;
4492                 llog_ctxt_put(ctxt);
4493         }
4494
4495         if (rc)
4496                 CERROR("%s: failed to clear log %s: %d\n",
4497                        mgs->mgs_obd->obd_name, name, rc);
4498
4499         return rc;
4500 }
4501
4502 /* erase all logs for the given fs */
4503 int mgs_erase_logs(const struct lu_env *env, struct mgs_device *mgs,
4504                    const char *fsname)
4505 {
4506         struct list_head log_list;
4507         struct mgs_direntry *dirent, *n;
4508         char barrier_name[20] = {};
4509         char *suffix;
4510         int count = 0;
4511         int rc, len = strlen(fsname);
4512         ENTRY;
4513
4514         mutex_lock(&mgs->mgs_mutex);
4515
4516         /* Find all the logs in the CONFIGS directory */
4517         rc = class_dentry_readdir(env, mgs, &log_list);
4518         if (rc) {
4519                 mutex_unlock(&mgs->mgs_mutex);
4520                 RETURN(rc);
4521         }
4522
4523         if (list_empty(&log_list)) {
4524                 mutex_unlock(&mgs->mgs_mutex);
4525                 RETURN(-ENOENT);
4526         }
4527
4528         snprintf(barrier_name, sizeof(barrier_name) - 1, "%s-%s",
4529                  fsname, BARRIER_FILENAME);
4530         /* Delete the barrier fsdb */
4531         mgs_remove_fsdb_by_name(mgs, barrier_name);
4532         /* Delete the fs db */
4533         mgs_remove_fsdb_by_name(mgs, fsname);
4534         mutex_unlock(&mgs->mgs_mutex);
4535
4536         list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4537                 list_del_init(&dirent->mde_list);
4538                 suffix = strrchr(dirent->mde_name, '-');
4539                 if (suffix != NULL) {
4540                         if ((len == suffix - dirent->mde_name) &&
4541                             (strncmp(fsname, dirent->mde_name, len) == 0)) {
4542                                 CDEBUG(D_MGS, "Removing log %s\n",
4543                                        dirent->mde_name);
4544                                 mgs_erase_log(env, mgs, dirent->mde_name);
4545                                 count++;
4546                         }
4547                 }
4548                 mgs_direntry_free(dirent);
4549         }
4550
4551         if (count == 0)
4552                 rc = -ENOENT;
4553
4554         RETURN(rc);
4555 }
4556
4557 /* list all logs for the given fs */
4558 int mgs_list_logs(const struct lu_env *env, struct mgs_device *mgs,
4559                   struct obd_ioctl_data *data)
4560 {
4561         struct list_head         log_list;
4562         struct mgs_direntry     *dirent, *n;
4563         char                    *out, *suffix, prefix[] = "config_log: ";
4564         int                      prefix_len = strlen(prefix);
4565         int                      len, remains, start = 0, rc;
4566
4567         ENTRY;
4568
4569         /* Find all the logs in the CONFIGS directory */
4570         rc = class_dentry_readdir(env, mgs, &log_list);
4571         if (rc)
4572                 RETURN(rc);
4573
4574         out = data->ioc_bulk;
4575         remains = data->ioc_inllen1;
4576         /* OBD_FAIL: fetch the config_log records from the specified one */
4577         if (OBD_FAIL_CHECK(OBD_FAIL_CATLIST))
4578                 data->ioc_count = cfs_fail_val;
4579
4580         list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4581                 list_del_init(&dirent->mde_list);
4582                 suffix = strrchr(dirent->mde_name, '-');
4583                 if (suffix != NULL) {
4584                         len = prefix_len + dirent->mde_len + 1;
4585                         if (remains - len < 0) {
4586                                 /* No enough space for this record */
4587                                 mgs_direntry_free(dirent);
4588                                 goto out;
4589                         }
4590                         start++;
4591                         if (start < data->ioc_count) {
4592                                 mgs_direntry_free(dirent);
4593                                 continue;
4594                         }
4595                         len = scnprintf(out, remains, "%s%s\n", prefix,
4596                                         dirent->mde_name);
4597                         out += len;
4598                         remains -= len;
4599                 }
4600                 mgs_direntry_free(dirent);
4601                 if (remains <= 1)
4602                         /* Full */
4603                         goto out;
4604         }
4605         /* Finished */
4606         start = 0;
4607 out:
4608         data->ioc_count = start;
4609         RETURN(rc);
4610 }
4611
4612 struct mgs_lcfg_fork_data {
4613         struct lustre_cfg_bufs   mlfd_bufs;
4614         struct mgs_device       *mlfd_mgs;
4615         struct llog_handle      *mlfd_llh;
4616         const char              *mlfd_oldname;
4617         const char              *mlfd_newname;
4618         char                     mlfd_data[0];
4619 };
4620
4621 static bool contain_valid_fsname(char *buf, const char *fsname,
4622                                  int buflen, int namelen)
4623 {
4624         if (buflen < namelen)
4625                 return false;
4626
4627         if (memcmp(buf, fsname, namelen) != 0)
4628                 return false;
4629
4630         if (buf[namelen] != '\0' && buf[namelen] != '-')
4631                 return false;
4632
4633         return true;
4634 }
4635
4636 static int mgs_lcfg_fork_handler(const struct lu_env *env,
4637                                  struct llog_handle *o_llh,
4638                                  struct llog_rec_hdr *o_rec, void *data)
4639 {
4640         struct mgs_lcfg_fork_data *mlfd = data;
4641         struct lustre_cfg_bufs *n_bufs = &mlfd->mlfd_bufs;
4642         struct lustre_cfg *o_lcfg = (struct lustre_cfg *)(o_rec + 1);
4643         struct llog_cfg_rec *lcr;
4644         char *o_buf;
4645         char *n_buf = mlfd->mlfd_data;
4646         int o_buflen;
4647         int o_namelen = strlen(mlfd->mlfd_oldname);
4648         int n_namelen = strlen(mlfd->mlfd_newname);
4649         int diff = n_namelen - o_namelen;
4650         __u32 cmd = o_lcfg->lcfg_command;
4651         __u32 cnt = o_lcfg->lcfg_bufcount;
4652         int rc;
4653         int i;
4654         ENTRY;
4655
4656         /* buf[0] */
4657         o_buf = lustre_cfg_buf(o_lcfg, 0);
4658         o_buflen = o_lcfg->lcfg_buflens[0];
4659         if (contain_valid_fsname(o_buf, mlfd->mlfd_oldname, o_buflen,
4660                                  o_namelen)) {
4661                 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4662                 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4663                        o_buflen - o_namelen);
4664                 lustre_cfg_bufs_reset(n_bufs, n_buf);
4665                 n_buf += cfs_size_round(o_buflen + diff);
4666         } else {
4667                 lustre_cfg_bufs_reset(n_bufs, o_buflen != 0 ? o_buf : NULL);
4668         }
4669
4670         switch (cmd) {
4671         case LCFG_MARKER: {
4672                 struct cfg_marker *o_marker;
4673                 struct cfg_marker *n_marker;
4674                 int tgt_namelen;
4675
4676                 if (cnt != 2) {
4677                         CDEBUG(D_MGS, "Unknown cfg marker entry with %d "
4678                                "buffers\n", cnt);
4679                         RETURN(-EINVAL);
4680                 }
4681
4682                 /* buf[1] is marker */
4683                 o_buf = lustre_cfg_buf(o_lcfg, 1);
4684                 o_buflen = o_lcfg->lcfg_buflens[1];
4685                 o_marker = (struct cfg_marker *)o_buf;
4686                 if (!contain_valid_fsname(o_marker->cm_tgtname,
4687                                           mlfd->mlfd_oldname,
4688                                           sizeof(o_marker->cm_tgtname),
4689                                           o_namelen)) {
4690                         lustre_cfg_bufs_set(n_bufs, 1, o_marker,
4691                                             sizeof(*o_marker));
4692                         break;
4693                 }
4694
4695                 n_marker = (struct cfg_marker *)n_buf;
4696                 *n_marker = *o_marker;
4697                 memcpy(n_marker->cm_tgtname, mlfd->mlfd_newname, n_namelen);
4698                 tgt_namelen = strlen(o_marker->cm_tgtname);
4699                 if (tgt_namelen > o_namelen)
4700                         memcpy(n_marker->cm_tgtname + n_namelen,
4701                                o_marker->cm_tgtname + o_namelen,
4702                                tgt_namelen - o_namelen);
4703                 n_marker->cm_tgtname[tgt_namelen + diff] = '\0';
4704                 lustre_cfg_bufs_set(n_bufs, 1, n_marker, sizeof(*n_marker));
4705                 break;
4706         }
4707         case LCFG_PARAM:
4708         case LCFG_SET_PARAM: {
4709                 for (i = 1; i < cnt; i++)
4710                         /* buf[i] is the param value, reuse it directly */
4711                         lustre_cfg_bufs_set(n_bufs, i,
4712                                             lustre_cfg_buf(o_lcfg, i),
4713                                             o_lcfg->lcfg_buflens[i]);
4714                 break;
4715         }
4716         case LCFG_POOL_NEW:
4717         case LCFG_POOL_ADD:
4718         case LCFG_POOL_REM:
4719         case LCFG_POOL_DEL: {
4720                 if (cnt < 3 || cnt > 4) {
4721                         CDEBUG(D_MGS, "Unknown cfg pool (%x) entry with %d "
4722                                "buffers\n", cmd, cnt);
4723                         RETURN(-EINVAL);
4724                 }
4725
4726                 /* buf[1] is fsname */
4727                 o_buf = lustre_cfg_buf(o_lcfg, 1);
4728                 o_buflen = o_lcfg->lcfg_buflens[1];
4729                 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4730                 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4731                        o_buflen - o_namelen);
4732                 lustre_cfg_bufs_set(n_bufs, 1, n_buf, o_buflen + diff);
4733                 n_buf += cfs_size_round(o_buflen + diff);
4734
4735                 /* buf[2] is the pool name, reuse it directly */
4736                 lustre_cfg_bufs_set(n_bufs, 2, lustre_cfg_buf(o_lcfg, 2),
4737                                     o_lcfg->lcfg_buflens[2]);
4738
4739                 if (cnt == 3)
4740                         break;
4741
4742                 /* buf[3] is ostname */
4743                 o_buf = lustre_cfg_buf(o_lcfg, 3);
4744                 o_buflen = o_lcfg->lcfg_buflens[3];
4745                 memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4746                 memcpy(n_buf + n_namelen, o_buf + o_namelen,
4747                        o_buflen - o_namelen);
4748                 lustre_cfg_bufs_set(n_bufs, 3, n_buf, o_buflen + diff);
4749                 break;
4750         }
4751         case LCFG_SETUP: {
4752                 if (cnt == 2) {
4753                         o_buflen = o_lcfg->lcfg_buflens[1];
4754                         if (o_buflen == sizeof(struct lov_desc) ||
4755                             o_buflen == sizeof(struct lmv_desc)) {
4756                                 char *o_uuid;
4757                                 char *n_uuid;
4758                                 int uuid_len;
4759
4760                                 /* buf[1] */
4761                                 o_buf = lustre_cfg_buf(o_lcfg, 1);
4762                                 if (o_buflen == sizeof(struct lov_desc)) {
4763                                         struct lov_desc *o_desc =
4764                                                 (struct lov_desc *)o_buf;
4765                                         struct lov_desc *n_desc =
4766                                                 (struct lov_desc *)n_buf;
4767
4768                                         *n_desc = *o_desc;
4769                                         o_uuid = o_desc->ld_uuid.uuid;
4770                                         n_uuid = n_desc->ld_uuid.uuid;
4771                                         uuid_len = sizeof(o_desc->ld_uuid.uuid);
4772                                 } else {
4773                                         struct lmv_desc *o_desc =
4774                                                 (struct lmv_desc *)o_buf;
4775                                         struct lmv_desc *n_desc =
4776                                                 (struct lmv_desc *)n_buf;
4777
4778                                         *n_desc = *o_desc;
4779                                         o_uuid = o_desc->ld_uuid.uuid;
4780                                         n_uuid = n_desc->ld_uuid.uuid;
4781                                         uuid_len = sizeof(o_desc->ld_uuid.uuid);
4782                                 }
4783
4784                                 if (unlikely(!contain_valid_fsname(o_uuid,
4785                                                 mlfd->mlfd_oldname, uuid_len,
4786                                                 o_namelen))) {
4787                                         lustre_cfg_bufs_set(n_bufs, 1, o_buf,
4788                                                             o_buflen);
4789                                         break;
4790                                 }
4791
4792                                 memcpy(n_uuid, mlfd->mlfd_newname, n_namelen);
4793                                 uuid_len = strlen(o_uuid);
4794                                 if (uuid_len > o_namelen)
4795                                         memcpy(n_uuid + n_namelen,
4796                                                o_uuid + o_namelen,
4797                                                uuid_len - o_namelen);
4798                                 n_uuid[uuid_len + diff] = '\0';
4799                                 lustre_cfg_bufs_set(n_bufs, 1, n_buf, o_buflen);
4800                                 break;
4801                         } /* else case fall through */
4802                 } /* else case fall through */
4803         }
4804         fallthrough;
4805         default: {
4806                 for (i = 1; i < cnt; i++) {
4807                         o_buflen = o_lcfg->lcfg_buflens[i];
4808                         if (o_buflen == 0)
4809                                 continue;
4810
4811                         o_buf = lustre_cfg_buf(o_lcfg, i);
4812                         if (!contain_valid_fsname(o_buf, mlfd->mlfd_oldname,
4813                                                   o_buflen, o_namelen)) {
4814                                 lustre_cfg_bufs_set(n_bufs, i, o_buf, o_buflen);
4815                                 continue;
4816                         }
4817
4818                         memcpy(n_buf, mlfd->mlfd_newname, n_namelen);
4819                         if (o_buflen == o_namelen) {
4820                                 lustre_cfg_bufs_set(n_bufs, i, n_buf,
4821                                                     n_namelen);
4822                                 n_buf += cfs_size_round(n_namelen);
4823                                 continue;
4824                         }
4825
4826                         memcpy(n_buf + n_namelen, o_buf + o_namelen,
4827                                o_buflen - o_namelen);
4828                         lustre_cfg_bufs_set(n_bufs, i, n_buf, o_buflen + diff);
4829                         n_buf += cfs_size_round(o_buflen + diff);
4830                 }
4831                 break;
4832         }
4833         }
4834
4835         lcr = lustre_cfg_rec_new(cmd, n_bufs);
4836         if (!lcr)
4837                 RETURN(-ENOMEM);
4838
4839         lcr->lcr_cfg = *o_lcfg;
4840         rc = llog_write(env, mlfd->mlfd_llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
4841         lustre_cfg_rec_free(lcr);
4842
4843         RETURN(rc);
4844 }
4845
4846 static int mgs_lcfg_fork_one(const struct lu_env *env, struct mgs_device *mgs,
4847                              struct mgs_direntry *mde, const char *oldname,
4848                              const char *newname)
4849 {
4850         struct llog_handle *old_llh = NULL;
4851         struct llog_handle *new_llh = NULL;
4852         struct llog_ctxt *ctxt = NULL;
4853         struct mgs_lcfg_fork_data *mlfd = NULL;
4854         char *name_buf = NULL;
4855         int name_buflen;
4856         int old_namelen = strlen(oldname);
4857         int new_namelen = strlen(newname);
4858         int rc;
4859         ENTRY;
4860
4861         name_buflen = mde->mde_len + new_namelen - old_namelen;
4862         OBD_ALLOC(name_buf, name_buflen);
4863         if (!name_buf)
4864                 RETURN(-ENOMEM);
4865
4866         memcpy(name_buf, newname, new_namelen);
4867         memcpy(name_buf + new_namelen, mde->mde_name + old_namelen,
4868                mde->mde_len - old_namelen);
4869
4870         CDEBUG(D_MGS, "Fork the config-log from %s to %s\n",
4871                mde->mde_name, name_buf);
4872
4873         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
4874         LASSERT(ctxt);
4875
4876         rc = llog_open_create(env, ctxt, &new_llh, NULL, name_buf);
4877         if (rc)
4878                 GOTO(out, rc);
4879
4880         rc = llog_init_handle(env, new_llh, LLOG_F_IS_PLAIN, NULL);
4881         if (rc)
4882                 GOTO(out, rc);
4883
4884         if (unlikely(mgs_log_is_empty(env, mgs, mde->mde_name)))
4885                 GOTO(out, rc = 0);
4886
4887         rc = llog_open(env, ctxt, &old_llh, NULL, mde->mde_name,
4888                        LLOG_OPEN_EXISTS);
4889         if (rc)
4890                 GOTO(out, rc);
4891
4892         rc = llog_init_handle(env, old_llh, LLOG_F_IS_PLAIN, NULL);
4893         if (rc)
4894                 GOTO(out, rc);
4895
4896         new_llh->lgh_hdr->llh_tgtuuid = old_llh->lgh_hdr->llh_tgtuuid;
4897
4898         OBD_ALLOC(mlfd, LLOG_MIN_CHUNK_SIZE);
4899         if (!mlfd)
4900                 GOTO(out, rc = -ENOMEM);
4901
4902         mlfd->mlfd_mgs = mgs;
4903         mlfd->mlfd_llh = new_llh;
4904         mlfd->mlfd_oldname = oldname;
4905         mlfd->mlfd_newname = newname;
4906
4907         rc = llog_process(env, old_llh, mgs_lcfg_fork_handler, mlfd, NULL);
4908         OBD_FREE(mlfd, LLOG_MIN_CHUNK_SIZE);
4909
4910         GOTO(out, rc);
4911
4912 out:
4913         if (old_llh)
4914                 llog_close(env, old_llh);
4915         if (new_llh)
4916                 llog_close(env, new_llh);
4917         if (name_buf)
4918                 OBD_FREE(name_buf, name_buflen);
4919         if (ctxt)
4920                 llog_ctxt_put(ctxt);
4921
4922         return rc;
4923 }
4924
4925 int mgs_lcfg_fork(const struct lu_env *env, struct mgs_device *mgs,
4926                   const char *oldname, const char *newname)
4927 {
4928         struct list_head log_list;
4929         struct mgs_direntry *dirent, *n;
4930         int olen = strlen(oldname);
4931         int nlen = strlen(newname);
4932         int count = 0;
4933         int rc = 0;
4934         ENTRY;
4935
4936         if (unlikely(!oldname || oldname[0] == '\0' ||
4937                      !newname || newname[0] == '\0'))
4938                 RETURN(-EINVAL);
4939
4940         if (strcmp(oldname, newname) == 0)
4941                 RETURN(-EINVAL);
4942
4943         /* lock it to prevent fork/erase/register in parallel. */
4944         mutex_lock(&mgs->mgs_mutex);
4945
4946         rc = class_dentry_readdir(env, mgs, &log_list);
4947         if (rc) {
4948                 mutex_unlock(&mgs->mgs_mutex);
4949                 RETURN(rc);
4950         }
4951
4952         if (list_empty(&log_list)) {
4953                 mutex_unlock(&mgs->mgs_mutex);
4954                 RETURN(-ENOENT);
4955         }
4956
4957         list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4958                 char *ptr;
4959
4960                 ptr = strrchr(dirent->mde_name, '-');
4961                 if (ptr) {
4962                         int tlen = ptr - dirent->mde_name;
4963
4964                         if (tlen == nlen &&
4965                             strncmp(newname, dirent->mde_name, tlen) == 0)
4966                                 GOTO(out, rc = -EEXIST);
4967
4968                         if (tlen == olen &&
4969                             strncmp(oldname, dirent->mde_name, tlen) == 0)
4970                                 continue;
4971                 }
4972
4973                 list_del_init(&dirent->mde_list);
4974                 mgs_direntry_free(dirent);
4975         }
4976
4977         if (list_empty(&log_list)) {
4978                 mutex_unlock(&mgs->mgs_mutex);
4979                 RETURN(-ENOENT);
4980         }
4981
4982         list_for_each_entry(dirent, &log_list, mde_list) {
4983                 rc = mgs_lcfg_fork_one(env, mgs, dirent, oldname, newname);
4984                 if (rc)
4985                         break;
4986
4987                 count++;
4988         }
4989
4990 out:
4991         mutex_unlock(&mgs->mgs_mutex);
4992
4993         list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
4994                 list_del_init(&dirent->mde_list);
4995                 mgs_direntry_free(dirent);
4996         }
4997
4998         if (rc && count > 0)
4999                 mgs_erase_logs(env, mgs, newname);
5000
5001         RETURN(rc);
5002 }
5003
5004 int mgs_lcfg_erase(const struct lu_env *env, struct mgs_device *mgs,
5005                    const char *fsname)
5006 {
5007         int rc;
5008         ENTRY;
5009
5010         if (unlikely(!fsname || fsname[0] == '\0'))
5011                 RETURN(-EINVAL);
5012
5013         rc = mgs_erase_logs(env, mgs, fsname);
5014
5015         RETURN(rc);
5016 }
5017
5018 static int mgs_xattr_del(const struct lu_env *env, struct dt_object *obj)
5019 {
5020         struct dt_device *dev;
5021         struct thandle *th = NULL;
5022         int rc = 0;
5023
5024         ENTRY;
5025
5026         dev = container_of(obj->do_lu.lo_dev, struct dt_device, dd_lu_dev);
5027         th = dt_trans_create(env, dev);
5028         if (IS_ERR(th))
5029                 RETURN(PTR_ERR(th));
5030
5031         rc = dt_declare_xattr_del(env, obj, XATTR_TARGET_RENAME, th);
5032         if (rc)
5033                 GOTO(stop, rc);
5034
5035         rc = dt_trans_start_local(env, dev, th);
5036         if (rc)
5037                 GOTO(stop, rc);
5038
5039         dt_write_lock(env, obj, 0);
5040         rc = dt_xattr_del(env, obj, XATTR_TARGET_RENAME, th);
5041
5042         GOTO(unlock, rc);
5043
5044 unlock:
5045         dt_write_unlock(env, obj);
5046
5047 stop:
5048         dt_trans_stop(env, dev, th);
5049
5050         return rc;
5051 }
5052
5053 int mgs_lcfg_rename(const struct lu_env *env, struct mgs_device *mgs)
5054 {
5055         struct list_head log_list;
5056         struct mgs_direntry *dirent, *n;
5057         char fsname[16];
5058         struct lu_buf buf = {
5059                 .lb_buf = fsname,
5060                 .lb_len = sizeof(fsname)
5061         };
5062         int rc = 0;
5063
5064         ENTRY;
5065
5066         rc = class_dentry_readdir(env, mgs, &log_list);
5067         if (rc)
5068                 RETURN(rc);
5069
5070         if (list_empty(&log_list))
5071                 RETURN(0);
5072
5073         list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
5074                 struct dt_object *o = NULL;
5075                 char oldname[16];
5076                 char *ptr;
5077                 int len;
5078
5079                 list_del_init(&dirent->mde_list);
5080                 ptr = strrchr(dirent->mde_name, '-');
5081                 if (!ptr)
5082                         goto next;
5083
5084                 len = ptr - dirent->mde_name;
5085                 if (unlikely(len >= sizeof(oldname))) {
5086                         CDEBUG(D_MGS, "Skip invalid configuration file %s\n",
5087                                dirent->mde_name);
5088                         goto next;
5089                 }
5090
5091                 o = local_file_find(env, mgs->mgs_los, mgs->mgs_configs_dir,
5092                                     dirent->mde_name);
5093                 if (IS_ERR(o)) {
5094                         rc = PTR_ERR(o);
5095                         CDEBUG(D_MGS, "Fail to locate file %s: rc = %d\n",
5096                                dirent->mde_name, rc);
5097                         goto next;
5098                 }
5099
5100                 rc = dt_xattr_get(env, o, &buf, XATTR_TARGET_RENAME);
5101                 if (rc < 0) {
5102                         if (rc == -ENODATA)
5103                                 rc = 0;
5104                         else
5105                                 CDEBUG(D_MGS,
5106                                        "Fail to get EA for %s: rc = %d\n",
5107                                        dirent->mde_name, rc);
5108                         goto next;
5109                 }
5110
5111                 if (unlikely(rc == len &&
5112                              memcmp(fsname, dirent->mde_name, len) == 0)) {
5113                         /* The new fsname is the same as the old one. */
5114                         rc = mgs_xattr_del(env, o);
5115                         goto next;
5116                 }
5117
5118                 memcpy(oldname, dirent->mde_name, len);
5119                 oldname[len] = '\0';
5120                 fsname[rc] = '\0';
5121                 rc = mgs_lcfg_fork_one(env, mgs, dirent, oldname, fsname);
5122                 if (rc && rc != -EEXIST) {
5123                         CDEBUG(D_MGS, "Fail to fork %s: rc = %d\n",
5124                                dirent->mde_name, rc);
5125                         goto next;
5126                 }
5127
5128                 rc = mgs_erase_log(env, mgs, dirent->mde_name);
5129                 if (rc) {
5130                         CDEBUG(D_MGS, "Fail to erase old %s: rc = %d\n",
5131                                dirent->mde_name, rc);
5132                         /* keep it there if failed to remove it. */
5133                         rc = 0;
5134                 }
5135
5136 next:
5137                 if (o && !IS_ERR(o))
5138                         lu_object_put(env, &o->do_lu);
5139
5140                 mgs_direntry_free(dirent);
5141                 if (rc)
5142                         break;
5143         }
5144
5145         list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
5146                 list_del_init(&dirent->mde_list);
5147                 mgs_direntry_free(dirent);
5148         }
5149
5150         RETURN(rc);
5151 }
5152
5153 /* Setup _mgs fsdb and log
5154  */
5155 int mgs__mgs_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs)
5156 {
5157         struct fs_db *fsdb = NULL;
5158         int rc;
5159         ENTRY;
5160
5161         rc = mgs_find_or_make_fsdb(env, mgs, MGSSELF_NAME, &fsdb);
5162         if (!rc)
5163                 mgs_put_fsdb(mgs, fsdb);
5164
5165         RETURN(rc);
5166 }
5167
5168 /* Setup params fsdb and log
5169  */
5170 int mgs_params_fsdb_setup(const struct lu_env *env, struct mgs_device *mgs)
5171 {
5172         struct fs_db *fsdb = NULL;
5173         struct llog_handle *params_llh = NULL;
5174         int rc;
5175         ENTRY;
5176
5177         rc = mgs_find_or_make_fsdb(env, mgs, PARAMS_FILENAME, &fsdb);
5178         if (!rc) {
5179                 mutex_lock(&fsdb->fsdb_mutex);
5180                 rc = record_start_log(env, mgs, &params_llh, PARAMS_FILENAME);
5181                 if (!rc)
5182                         rc = record_end_log(env, &params_llh);
5183                 mutex_unlock(&fsdb->fsdb_mutex);
5184                 mgs_put_fsdb(mgs, fsdb);
5185         }
5186
5187         RETURN(rc);
5188 }
5189
5190 /* Cleanup params fsdb and log
5191  */
5192 int mgs_params_fsdb_cleanup(const struct lu_env *env, struct mgs_device *mgs)
5193 {
5194         int rc;
5195
5196         rc = mgs_erase_logs(env, mgs, PARAMS_FILENAME);
5197         return rc == -ENOENT ? 0 : rc;
5198 }
5199
5200 /**
5201  * Fill in the mgs_target_info based on data devname and param provide.
5202  *
5203  * @env         thread context
5204  * @mgs         mgs device
5205  * @mti         mgs target info. We want to set this based other paramters
5206  *              passed to this function. Once setup we write it to the config
5207  *              logs.
5208  * @devname     optional OBD device name
5209  * @param       string that contains both what tunable to set and the value to
5210  *              set it to.
5211  *
5212  * RETURN       0 for success
5213  *              negative error number on failure
5214  **/
5215 static int mgs_set_conf_param(const struct lu_env *env, struct mgs_device *mgs,
5216                               struct mgs_target_info *mti, const char *devname,
5217                               const char *param)
5218 {
5219         struct fs_db *fsdb = NULL;
5220         int dev_type;
5221         int rc = 0;
5222
5223         ENTRY;
5224         /* lustre, lustre-mdtlov, lustre-client, lustre-MDT0000 */
5225         if (!devname) {
5226                 size_t len;
5227
5228                 /* We have two possible cases here:
5229                  *
5230                  * 1) the device name embedded in the param:
5231                  *    lustre-OST0000.osc.max_dirty_mb=32
5232                  *
5233                  * 2) the file system name is embedded in
5234                  *    the param: lustre.sys.at.min=0
5235                  */
5236                 len = strcspn(param, ".=");
5237                 if (!len || param[len] == '=')
5238                         RETURN(-EINVAL);
5239
5240                 if (len >= sizeof(mti->mti_svname))
5241                         RETURN(-E2BIG);
5242
5243                 snprintf(mti->mti_svname, sizeof(mti->mti_svname),
5244                          "%.*s", (int)len, param);
5245                 param += len + 1;
5246         } else {
5247                 if (strlcpy(mti->mti_svname, devname, sizeof(mti->mti_svname)) >=
5248                     sizeof(mti->mti_svname))
5249                         RETURN(-E2BIG);
5250         }
5251
5252         if (!strlen(mti->mti_svname)) {
5253                 LCONSOLE_ERROR_MSG(0x14d, "No target specified: %s\n", param);
5254                 RETURN(-ENOSYS);
5255         }
5256
5257         dev_type = mgs_parse_devname(mti->mti_svname, mti->mti_fsname,
5258                                      &mti->mti_stripe_index);
5259         switch (dev_type) {
5260         /* For this case we have an invalid obd device name */
5261         case -ENXIO:
5262                 CDEBUG(D_MGS, "%s don't contain an index\n", mti->mti_svname);
5263                 strlcpy(mti->mti_fsname, mti->mti_svname, MTI_NAME_MAXLEN);
5264                 dev_type = 0;
5265                 break;
5266         /* Not an obd device, assume devname is the fsname.
5267          * User might of only provided fsname and not obd device
5268          */
5269         case -EINVAL:
5270                 CDEBUG(D_MGS, "%s is seen as a file system name\n", mti->mti_svname);
5271                 strlcpy(mti->mti_fsname, mti->mti_svname, MTI_NAME_MAXLEN);
5272                 dev_type = 0;
5273                 break;
5274         default:
5275                 if (dev_type < 0)
5276                         GOTO(out, rc = dev_type);
5277
5278                 /* param related to llite isn't allowed to set by OST or MDT */
5279                 if (dev_type & LDD_F_SV_TYPE_OST ||
5280                     dev_type & LDD_F_SV_TYPE_MDT) {
5281                         /* param related to llite isn't allowed to set by OST
5282                          * or MDT
5283                          */
5284                         if (!strncmp(param, PARAM_LLITE,
5285                                      sizeof(PARAM_LLITE) - 1))
5286                                 GOTO(out, rc = -EINVAL);
5287
5288                         /* Strip -osc or -mdc suffix from svname */
5289                         if (server_make_name(dev_type, mti->mti_stripe_index,
5290                                              mti->mti_fsname, mti->mti_svname,
5291                                              sizeof(mti->mti_svname)))
5292                                 GOTO(out, rc = -EINVAL);
5293                 }
5294                 break;
5295         }
5296
5297         if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
5298             sizeof(mti->mti_params))
5299                 GOTO(out, rc = -E2BIG);
5300
5301         CDEBUG(D_MGS, "set_conf_param fs='%s' device='%s' param='%s'\n",
5302                mti->mti_fsname, mti->mti_svname, mti->mti_params);
5303
5304         rc = mgs_find_or_make_fsdb(env, mgs, mti->mti_fsname, &fsdb);
5305         if (rc)
5306                 GOTO(out, rc);
5307
5308         if (!test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags) &&
5309             test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
5310                 CERROR("No filesystem targets for %s. cfg_device from lctl "
5311                        "is '%s'\n", mti->mti_fsname, mti->mti_svname);
5312                 mgs_unlink_fsdb(mgs, fsdb);
5313                 GOTO(out, rc = -EINVAL);
5314         }
5315
5316         /*
5317          * Revoke lock so everyone updates.  Should be alright if
5318          * someone was already reading while we were updating the logs,
5319          * so we don't really need to hold the lock while we're
5320          * writing (above).
5321          */
5322         mti->mti_flags = dev_type | LDD_F_PARAM;
5323         mutex_lock(&fsdb->fsdb_mutex);
5324         rc = mgs_write_log_param(env, mgs, fsdb, mti, mti->mti_params);
5325         mutex_unlock(&fsdb->fsdb_mutex);
5326         mgs_revoke_lock(mgs, fsdb, MGS_CFG_T_CONFIG);
5327
5328 out:
5329         if (fsdb)
5330                 mgs_put_fsdb(mgs, fsdb);
5331
5332         RETURN(rc);
5333 }
5334
5335 static int mgs_set_param2(const struct lu_env *env, struct mgs_device *mgs,
5336                           struct mgs_target_info *mti, const char *param)
5337 {
5338         struct fs_db *fsdb = NULL;
5339         int dev_type;
5340         size_t len;
5341         int rc;
5342
5343         if (strlcpy(mti->mti_params, param, sizeof(mti->mti_params)) >=
5344             sizeof(mti->mti_params))
5345                 GOTO(out, rc = -E2BIG);
5346
5347         len = strcspn(param, ".=");
5348         if (len && param[len] != '=') {
5349                 struct list_head *tmp;
5350                 char *ptr;
5351
5352                 param += len + 1;
5353                 ptr = strchr(param, '.');
5354
5355                 len = strlen(param);
5356                 if (ptr)
5357                         len -= strlen(ptr);
5358                 if (len >= sizeof(mti->mti_svname))
5359                         GOTO(out, rc = -E2BIG);
5360
5361                 snprintf(mti->mti_svname, sizeof(mti->mti_svname), "%.*s",
5362                         (int)len, param);
5363
5364                 mutex_lock(&mgs->mgs_mutex);
5365                 if (unlikely(list_empty(&mgs->mgs_fs_db_list))) {
5366                         mutex_unlock(&mgs->mgs_mutex);
5367                         GOTO(out, rc = -ENODEV);
5368                 }
5369
5370                 list_for_each(tmp, &mgs->mgs_fs_db_list) {
5371                         fsdb = list_entry(tmp, struct fs_db, fsdb_list);
5372                         if (fsdb->fsdb_has_lproc_entry &&
5373                             strcmp(fsdb->fsdb_name, "params") != 0 &&
5374                             strstr(param, fsdb->fsdb_name)) {
5375                                 snprintf(mti->mti_svname,
5376                                          sizeof(mti->mti_svname), "%s",
5377                                          fsdb->fsdb_name);
5378                                 break;
5379                         }
5380                         fsdb = NULL;
5381                 }
5382
5383                 if (!fsdb) {
5384                         snprintf(mti->mti_svname, sizeof(mti->mti_svname),
5385                                  "general");
5386                 }
5387                 mutex_unlock(&mgs->mgs_mutex);
5388         } else {
5389                 snprintf(mti->mti_svname, sizeof(mti->mti_svname), "general");
5390         }
5391
5392         CDEBUG(D_MGS, "set_param2 fs='%s' device='%s' param='%s'\n",
5393                mti->mti_fsname, mti->mti_svname, mti->mti_params);
5394
5395         /* The return value should be the device type i.e LDD_F_SV_TYPE_XXX.
5396          * A returned error tells us we don't have a target obd device.
5397          */
5398         dev_type = server_name2index(mti->mti_svname, &mti->mti_stripe_index,
5399                                      NULL);
5400         if (dev_type < 0)
5401                 dev_type = 0;
5402
5403         /* the return value should be the device type i.e LDD_F_SV_TYPE_XXX.
5404          * Strip -osc or -mdc suffix from svname
5405          */
5406         if ((dev_type & LDD_F_SV_TYPE_OST || dev_type & LDD_F_SV_TYPE_MDT) &&
5407             server_make_name(dev_type, mti->mti_stripe_index,
5408                              mti->mti_fsname, mti->mti_svname,
5409                              sizeof(mti->mti_svname)))
5410                 GOTO(out, rc = -EINVAL);
5411
5412         rc = mgs_find_or_make_fsdb(env, mgs, PARAMS_FILENAME, &fsdb);
5413         if (rc)
5414                 GOTO(out, rc);
5415         /*
5416          * Revoke lock so everyone updates.  Should be alright if
5417          * someone was already reading while we were updating the logs,
5418          * so we don't really need to hold the lock while we're
5419          * writing (above).
5420          */
5421         mti->mti_flags = dev_type | LDD_F_PARAM2;
5422         mutex_lock(&fsdb->fsdb_mutex);
5423         rc = mgs_write_log_param2(env, mgs, fsdb, mti, mti->mti_params);
5424         mutex_unlock(&fsdb->fsdb_mutex);
5425         mgs_revoke_lock(mgs, fsdb, MGS_CFG_T_PARAMS);
5426         mgs_put_fsdb(mgs, fsdb);
5427 out:
5428         RETURN(rc);
5429 }
5430
5431 /* Set a permanent (config log) param for a target or fs
5432  *
5433  * @lcfg buf0 may contain the device (testfs-MDT0000) name
5434  *       buf1 contains the single parameter
5435  */
5436 int mgs_set_param(const struct lu_env *env, struct mgs_device *mgs,
5437                   struct lustre_cfg *lcfg)
5438 {
5439         const char *param = lustre_cfg_string(lcfg, 1);
5440         struct mgs_target_info *mti;
5441         int rc;
5442
5443         /* Create a fake mti to hold everything */
5444         OBD_ALLOC_PTR(mti);
5445         if (!mti)
5446                 return -ENOMEM;
5447
5448         print_lustre_cfg(lcfg);
5449
5450         if (lcfg->lcfg_command == LCFG_PARAM) {
5451                 /* For the case of lctl conf_param devname can be
5452                  * lustre, lustre-mdtlov, lustre-client, lustre-MDT0000
5453                  */
5454                 const char *devname = lustre_cfg_string(lcfg, 0);
5455
5456                 rc = mgs_set_conf_param(env, mgs, mti, devname, param);
5457         } else {
5458                 /* In the case of lctl set_param -P lcfg[0] will always
5459                  * be 'general'. At least for now.
5460                  */
5461                 rc = mgs_set_param2(env, mgs, mti, param);
5462         }
5463
5464         OBD_FREE_PTR(mti);
5465
5466         return rc;
5467 }
5468
5469 static int mgs_write_log_pool(const struct lu_env *env,
5470                               struct mgs_device *mgs, char *logname,
5471                               struct fs_db *fsdb, char *tgtname,
5472                               enum lcfg_command_type cmd,
5473                               char *fsname, char *poolname,
5474                               char *ostname, char *comment)
5475 {
5476         struct llog_handle *llh = NULL;
5477         int rc;
5478
5479         rc = record_start_log(env, mgs, &llh, logname);
5480         if (rc)
5481                 return rc;
5482         rc = record_marker(env, llh, fsdb, CM_START, tgtname, comment);
5483         if (rc)
5484                 goto out;
5485         rc = record_base(env, llh, tgtname, 0, cmd,
5486                          fsname, poolname, ostname, NULL);
5487         if (rc)
5488                 goto out;
5489         rc = record_marker(env, llh, fsdb, CM_END, tgtname, comment);
5490 out:
5491         record_end_log(env, &llh);
5492         return rc;
5493 }
5494
5495 int mgs_nodemap_cmd(const struct lu_env *env, struct mgs_device *mgs,
5496                     enum lcfg_command_type cmd, const char *nodemap_name,
5497                     char *param)
5498 {
5499         lnet_nid_t nid[2];
5500         u32 idmap[2];
5501         bool bool_switch;
5502         u32 int_id;
5503         int rc = 0;
5504
5505         ENTRY;
5506         switch (cmd) {
5507         case LCFG_NODEMAP_ADD:
5508                 rc = nodemap_add(nodemap_name);
5509                 break;
5510         case LCFG_NODEMAP_DEL:
5511                 rc = nodemap_del(nodemap_name);
5512                 break;
5513         case LCFG_NODEMAP_ADD_RANGE:
5514                 rc = nodemap_parse_range(param, nid);
5515                 if (rc != 0)
5516                         break;
5517                 rc = nodemap_add_range(nodemap_name, nid);
5518                 break;
5519         case LCFG_NODEMAP_DEL_RANGE:
5520                 rc = nodemap_parse_range(param, nid);
5521                 if (rc != 0)
5522                         break;
5523                 rc = nodemap_del_range(nodemap_name, nid);
5524                 break;
5525         case LCFG_NODEMAP_ADMIN:
5526                 rc = kstrtobool(param, &bool_switch);
5527                 if (rc)
5528                         break;
5529                 rc = nodemap_set_allow_root(nodemap_name, bool_switch);
5530                 break;
5531         case LCFG_NODEMAP_DENY_UNKNOWN:
5532                 rc = kstrtobool(param, &bool_switch);
5533                 if (rc)
5534                         break;
5535                 rc = nodemap_set_deny_unknown(nodemap_name, bool_switch);
5536                 break;
5537         case LCFG_NODEMAP_AUDIT_MODE:
5538                 rc = kstrtobool(param, &bool_switch);
5539                 if (rc == 0)
5540                         rc = nodemap_set_audit_mode(nodemap_name, bool_switch);
5541                 break;
5542         case LCFG_NODEMAP_FORBID_ENCRYPT:
5543                 rc = kstrtobool(param, &bool_switch);
5544                 if (rc == 0)
5545                         rc = nodemap_set_forbid_encryption(nodemap_name,
5546                                                            bool_switch);
5547                 break;
5548         case LCFG_NODEMAP_READONLY_MOUNT:
5549                 rc = kstrtobool(param, &bool_switch);
5550                 if (rc == 0)
5551                         rc = nodemap_set_readonly_mount(nodemap_name,
5552                                                         bool_switch);
5553                 break;
5554         case LCFG_NODEMAP_MAP_MODE:
5555         {
5556                 char *p;
5557                 __u8 map_mode = 0;
5558
5559                 if ((p = strstr(param, "all")) != NULL) {
5560                         if ((p == param || *(p-1) == ',') &&
5561                             (*(p+3) == '\0' || *(p+3) == ',')) {
5562                                 map_mode = NODEMAP_MAP_ALL;
5563                         } else {
5564                                 rc = -EINVAL;
5565                                 break;
5566                         }
5567                 } else {
5568                         while ((p = strsep(&param, ",")) != NULL) {
5569                                 if (!*p)
5570                                         break;
5571
5572                                 if (strcmp("both", p) == 0)
5573                                         map_mode |= NODEMAP_MAP_BOTH;
5574                                 else if (strcmp("uid_only", p) == 0 ||
5575                                          strcmp("uid", p) == 0)
5576                                         map_mode |= NODEMAP_MAP_UID;
5577                                 else if (strcmp("gid_only", p) == 0 ||
5578                                          strcmp("gid", p) == 0)
5579                                         map_mode |= NODEMAP_MAP_GID;
5580                                 else if (strcmp("projid_only", p) == 0 ||
5581                                          strcmp("projid", p) == 0)
5582                                         map_mode |= NODEMAP_MAP_PROJID;
5583                                 else
5584                                         break;
5585                         }
5586                         if (p) {
5587                                 rc = -EINVAL;
5588                                 break;
5589                         }
5590                 }
5591
5592                 rc = nodemap_set_mapping_mode(nodemap_name, map_mode);
5593                 break;
5594         }
5595         case LCFG_NODEMAP_TRUSTED:
5596                 rc = kstrtobool(param, &bool_switch);
5597                 if (rc)
5598                         break;
5599                 rc = nodemap_set_trust_client_ids(nodemap_name, bool_switch);
5600                 break;
5601         case LCFG_NODEMAP_SQUASH_UID:
5602                 rc = kstrtouint(param, 10, &int_id);
5603                 if (rc)
5604                         break;
5605                 rc = nodemap_set_squash_uid(nodemap_name, int_id);
5606                 break;
5607         case LCFG_NODEMAP_SQUASH_GID:
5608                 rc = kstrtouint(param, 10, &int_id);
5609                 if (rc)
5610                         break;
5611                 rc = nodemap_set_squash_gid(nodemap_name, int_id);
5612                 break;
5613         case LCFG_NODEMAP_SQUASH_PROJID:
5614                 rc = kstrtouint(param, 10, &int_id);
5615                 if (rc)
5616                         break;
5617                 rc = nodemap_set_squash_projid(nodemap_name, int_id);
5618                 break;
5619         case LCFG_NODEMAP_ADD_UIDMAP:
5620         case LCFG_NODEMAP_ADD_GIDMAP:
5621         case LCFG_NODEMAP_ADD_PROJIDMAP:
5622                 rc = nodemap_parse_idmap(param, idmap);
5623                 if (rc != 0)
5624                         break;
5625                 if (cmd == LCFG_NODEMAP_ADD_UIDMAP)
5626                         rc = nodemap_add_idmap(nodemap_name, NODEMAP_UID,
5627                                                idmap);
5628                 else if (cmd == LCFG_NODEMAP_ADD_GIDMAP)
5629                         rc = nodemap_add_idmap(nodemap_name, NODEMAP_GID,
5630                                                idmap);
5631                 else if (cmd == LCFG_NODEMAP_ADD_PROJIDMAP)
5632                         rc = nodemap_add_idmap(nodemap_name, NODEMAP_PROJID,
5633                                                idmap);
5634                 else
5635                         rc = -EINVAL;
5636                 break;
5637         case LCFG_NODEMAP_DEL_UIDMAP:
5638         case LCFG_NODEMAP_DEL_GIDMAP:
5639         case LCFG_NODEMAP_DEL_PROJIDMAP:
5640                 rc = nodemap_parse_idmap(param, idmap);
5641                 if (rc != 0)
5642                         break;
5643                 if (cmd == LCFG_NODEMAP_DEL_UIDMAP)
5644                         rc = nodemap_del_idmap(nodemap_name, NODEMAP_UID,
5645                                                idmap);
5646                 else if (cmd == LCFG_NODEMAP_DEL_GIDMAP)
5647                         rc = nodemap_del_idmap(nodemap_name, NODEMAP_GID,
5648                                                idmap);
5649                 else if (cmd == LCFG_NODEMAP_DEL_PROJIDMAP)
5650                         rc = nodemap_del_idmap(nodemap_name, NODEMAP_PROJID,
5651                                                idmap);
5652                 else
5653                         rc = -EINVAL;
5654                 break;
5655         case LCFG_NODEMAP_SET_FILESET:
5656                 rc = nodemap_set_fileset(nodemap_name, param);
5657                 break;
5658         case LCFG_NODEMAP_SET_SEPOL:
5659                 rc = nodemap_set_sepol(nodemap_name, param);
5660                 break;
5661         default:
5662                 rc = -EINVAL;
5663         }
5664
5665         RETURN(rc);
5666 }
5667
5668 int mgs_pool_cmd(const struct lu_env *env, struct mgs_device *mgs,
5669                  enum lcfg_command_type cmd, char *fsname,
5670                  char *poolname, char *ostname)
5671 {
5672         struct fs_db *fsdb;
5673         char *lovname;
5674         char *logname;
5675         char *label = NULL, *canceled_label = NULL;
5676         int label_sz;
5677         struct mgs_target_info *mti = NULL;
5678         bool checked = false;
5679         bool locked = false;
5680         bool free = false;
5681         int rc, i;
5682         ENTRY;
5683
5684         rc = mgs_find_or_make_fsdb(env, mgs, fsname, &fsdb);
5685         if (rc) {
5686                 CERROR("Can't get db for %s\n", fsname);
5687                 RETURN(rc);
5688         }
5689         if (test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags)) {
5690                 CERROR("%s is not defined\n", fsname);
5691                 free = true;
5692                 GOTO(out_fsdb, rc = -EINVAL);
5693         }
5694
5695         label_sz = 10 + strlen(fsname) + strlen(poolname);
5696
5697         /* check if ostname match fsname */
5698         if (ostname != NULL) {
5699                 char *ptr;
5700
5701                 ptr = strrchr(ostname, '-');
5702                 if ((ptr == NULL) ||
5703                     (strncmp(fsname, ostname, ptr-ostname) != 0))
5704                         RETURN(-EINVAL);
5705                 label_sz += strlen(ostname);
5706         }
5707
5708         OBD_ALLOC(label, label_sz);
5709         if (!label)
5710                 GOTO(out_fsdb, rc = -ENOMEM);
5711
5712         switch(cmd) {
5713         case LCFG_POOL_NEW:
5714                 sprintf(label,
5715                         "new %s.%s", fsname, poolname);
5716                 break;
5717         case LCFG_POOL_ADD:
5718                 sprintf(label,
5719                         "add %s.%s.%s", fsname, poolname, ostname);
5720                 break;
5721         case LCFG_POOL_REM:
5722                 OBD_ALLOC(canceled_label, label_sz);
5723                 if (canceled_label == NULL)
5724                         GOTO(out_label, rc = -ENOMEM);
5725                 sprintf(label,
5726                         "rem %s.%s.%s", fsname, poolname, ostname);
5727                 sprintf(canceled_label,
5728                         "add %s.%s.%s", fsname, poolname, ostname);
5729                 break;
5730         case LCFG_POOL_DEL:
5731                 OBD_ALLOC(canceled_label, label_sz);
5732                 if (canceled_label == NULL)
5733                         GOTO(out_label, rc = -ENOMEM);
5734                 sprintf(label,
5735                         "del %s.%s", fsname, poolname);
5736                 sprintf(canceled_label,
5737                         "new %s.%s", fsname, poolname);
5738                 break;
5739         default:
5740                 break;
5741         }
5742
5743         OBD_ALLOC_PTR(mti);
5744         if (mti == NULL)
5745                 GOTO(out_cancel, rc = -ENOMEM);
5746         strncpy(mti->mti_svname, "lov pool", sizeof(mti->mti_svname));
5747
5748         mutex_lock(&fsdb->fsdb_mutex);
5749         locked = true;
5750         /* write pool def to all MDT logs */
5751         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
5752                 if (test_bit(i,  fsdb->fsdb_mdt_index_map)) {
5753                         rc = name_create_mdt_and_lov(&logname, &lovname,
5754                                                      fsdb, i);
5755                         if (rc)
5756                                 GOTO(out_mti, rc);
5757
5758                         if (!checked && (canceled_label == NULL)) {
5759                                 rc = mgs_check_marker(env, mgs, fsdb, mti,
5760                                                 logname, lovname, label);
5761                                 if (rc) {
5762                                         name_destroy(&logname);
5763                                         name_destroy(&lovname);
5764                                         GOTO(out_mti,
5765                                                 rc = (rc == LLOG_PROC_BREAK ?
5766                                                         -EEXIST : rc));
5767                                 }
5768                                 checked = true;
5769                         }
5770                         if (canceled_label != NULL)
5771                                 rc = mgs_modify(env, mgs, fsdb, mti, logname,
5772                                                 lovname, canceled_label,
5773                                                 CM_SKIP);
5774
5775                         if (rc >= 0)
5776                                 rc = mgs_write_log_pool(env, mgs, logname,
5777                                                         fsdb, lovname, cmd,
5778                                                         fsname, poolname,
5779                                                         ostname, label);
5780                         name_destroy(&logname);
5781                         name_destroy(&lovname);
5782                         if (rc)
5783                                 GOTO(out_mti, rc);
5784                 }
5785         }
5786
5787         rc = name_create(&logname, fsname, "-client");
5788         if (rc)
5789                 GOTO(out_mti, rc);
5790
5791         if (!checked && (canceled_label == NULL)) {
5792                 rc = mgs_check_marker(env, mgs, fsdb, mti, logname,
5793                                 fsdb->fsdb_clilov, label);
5794                 if (rc) {
5795                         name_destroy(&logname);
5796                         GOTO(out_mti, rc = (rc == LLOG_PROC_BREAK ?
5797                                 -EEXIST : rc));
5798                 }
5799         }
5800         if (canceled_label != NULL) {
5801                 rc = mgs_modify(env, mgs, fsdb, mti, logname,
5802                                 fsdb->fsdb_clilov, canceled_label, CM_SKIP);
5803                 if (rc < 0) {
5804                         name_destroy(&logname);
5805                         GOTO(out_mti, rc);
5806                 }
5807         }
5808
5809         rc = mgs_write_log_pool(env, mgs, logname, fsdb, fsdb->fsdb_clilov,
5810                                 cmd, fsname, poolname, ostname, label);
5811         mutex_unlock(&fsdb->fsdb_mutex);
5812         locked = false;
5813         name_destroy(&logname);
5814         /* request for update */
5815         mgs_revoke_lock(mgs, fsdb, MGS_CFG_T_CONFIG);
5816
5817         GOTO(out_mti, rc);
5818
5819 out_mti:
5820         if (locked)
5821                 mutex_unlock(&fsdb->fsdb_mutex);
5822         if (mti != NULL)
5823                 OBD_FREE_PTR(mti);
5824 out_cancel:
5825         if (canceled_label != NULL)
5826                 OBD_FREE(canceled_label, label_sz);
5827 out_label:
5828         OBD_FREE(label, label_sz);
5829 out_fsdb:
5830         if (free)
5831                 mgs_unlink_fsdb(mgs, fsdb);
5832         mgs_put_fsdb(mgs, fsdb);
5833
5834         return rc;
5835 }