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