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