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