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