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