Whamcloud - gitweb
922f1e6427033cfa212d1a5b9d1d9aaeccaa7d7b
[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 <lustre_ioctl.h>
46 #include <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 /* Find all logs in CONFIG directory and link then into list */
55 int class_dentry_readdir(const struct lu_env *env,
56                          struct mgs_device *mgs, struct list_head *log_list)
57 {
58         struct dt_object    *dir = mgs->mgs_configs_dir;
59         const struct dt_it_ops *iops;
60         struct dt_it        *it;
61         struct mgs_direntry *de;
62         char                *key;
63         int                  rc, key_sz;
64
65         INIT_LIST_HEAD(log_list);
66
67         LASSERT(dir);
68         LASSERT(dir->do_index_ops);
69
70         iops = &dir->do_index_ops->dio_it;
71         it = iops->init(env, dir, LUDA_64BITHASH);
72         if (IS_ERR(it))
73                 RETURN(PTR_ERR(it));
74
75         rc = iops->load(env, it, 0);
76         if (rc <= 0)
77                 GOTO(fini, rc = 0);
78
79         /* main cycle */
80         do {
81                 key = (void *)iops->key(env, it);
82                 if (IS_ERR(key)) {
83                         CERROR("%s: key failed when listing %s: rc = %d\n",
84                                mgs->mgs_obd->obd_name, MOUNT_CONFIGS_DIR,
85                                (int) PTR_ERR(key));
86                         goto next;
87                 }
88                 key_sz = iops->key_size(env, it);
89                 LASSERT(key_sz > 0);
90
91                 /* filter out "." and ".." entries */
92                 if (key[0] == '.') {
93                         if (key_sz == 1)
94                                 goto next;
95                         if (key_sz == 2 && key[1] == '.')
96                                 goto next;
97                 }
98
99                 /* filter out ".bak" files */
100                 /* sizeof(".bak") - 1 == 3 */
101                 if (key_sz >= 3 &&
102                     !memcmp(".bak", key + key_sz - 3, 3)) {
103                         CDEBUG(D_MGS, "Skipping backup file %.*s\n",
104                                key_sz, key);
105                         goto next;
106                 }
107
108                 de = mgs_direntry_alloc(key_sz + 1);
109                 if (de == NULL) {
110                         rc = -ENOMEM;
111                         break;
112                 }
113
114                 memcpy(de->mde_name, key, key_sz);
115                 de->mde_name[key_sz] = 0;
116
117                 list_add(&de->mde_list, log_list);
118
119 next:
120                 rc = iops->next(env, it);
121         } while (rc == 0);
122         if (rc > 0)
123                 rc = 0;
124
125         iops->put(env, it);
126
127 fini:
128         iops->fini(env, it);
129         if (rc)
130                 CERROR("%s: key failed when listing %s: rc = %d\n",
131                        mgs->mgs_obd->obd_name, MOUNT_CONFIGS_DIR, rc);
132         RETURN(rc);
133 }
134
135 /******************** DB functions *********************/
136
137 static inline int name_create(char **newname, char *prefix, char *suffix)
138 {
139         LASSERT(newname);
140         OBD_ALLOC(*newname, strlen(prefix) + strlen(suffix) + 1);
141         if (!*newname)
142                 return -ENOMEM;
143         sprintf(*newname, "%s%s", prefix, suffix);
144         return 0;
145 }
146
147 static inline void name_destroy(char **name)
148 {
149         if (*name)
150                 OBD_FREE(*name, strlen(*name) + 1);
151         *name = NULL;
152 }
153
154 struct mgs_fsdb_handler_data
155 {
156         struct fs_db   *fsdb;
157         __u32           ver;
158 };
159
160 /* from the (client) config log, figure out:
161         1. which ost's/mdt's are configured (by index)
162         2. what the last config step is
163         3. COMPAT_18 osc name
164 */
165 /* It might be better to have a separate db file, instead of parsing the info
166    out of the client log.  This is slow and potentially error-prone. */
167 static int mgs_fsdb_handler(const struct lu_env *env, struct llog_handle *llh,
168                             struct llog_rec_hdr *rec, void *data)
169 {
170         struct mgs_fsdb_handler_data *d = data;
171         struct fs_db *fsdb = d->fsdb;
172         int cfg_len = rec->lrh_len;
173         char *cfg_buf = (char*) (rec + 1);
174         struct lustre_cfg *lcfg;
175         __u32 index;
176         int rc = 0;
177         ENTRY;
178
179         if (rec->lrh_type != OBD_CFG_REC) {
180                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
181                 RETURN(-EINVAL);
182         }
183
184         rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
185         if (rc) {
186                 CERROR("Insane cfg\n");
187                 RETURN(rc);
188         }
189
190         lcfg = (struct lustre_cfg *)cfg_buf;
191
192         CDEBUG(D_INFO, "cmd %x %s %s\n", lcfg->lcfg_command,
193                lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
194
195         /* Figure out ost indicies */
196         /* lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1 */
197         if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD ||
198             lcfg->lcfg_command == LCFG_LOV_DEL_OBD) {
199                 index = simple_strtoul(lustre_cfg_string(lcfg, 2),
200                                        NULL, 10);
201                 CDEBUG(D_MGS, "OST index for %s is %u (%s)\n",
202                        lustre_cfg_string(lcfg, 1), index,
203                        lustre_cfg_string(lcfg, 2));
204                 set_bit(index, fsdb->fsdb_ost_index_map);
205         }
206
207         /* Figure out mdt indicies */
208         /* attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f */
209         if ((lcfg->lcfg_command == LCFG_ATTACH) &&
210             (strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_MDC_NAME) == 0)) {
211                 rc = server_name2index(lustre_cfg_string(lcfg, 0),
212                                        &index, NULL);
213                 if (rc != LDD_F_SV_TYPE_MDT) {
214                         CWARN("Unparsable MDC name %s, assuming index 0\n",
215                               lustre_cfg_string(lcfg, 0));
216                         index = 0;
217                 }
218                 rc = 0;
219                 CDEBUG(D_MGS, "MDT index is %u\n", index);
220                 set_bit(index, fsdb->fsdb_mdt_index_map);
221                 fsdb->fsdb_mdt_count ++;
222         }
223
224         /**
225          * figure out the old config. fsdb_gen = 0 means old log
226          * It is obsoleted and not supported anymore
227          */
228         if (fsdb->fsdb_gen == 0) {
229                 CERROR("Old config format is not supported\n");
230                 RETURN(-EINVAL);
231         }
232
233         /*
234          * compat to 1.8, check osc name used by MDT0 to OSTs, bz18548.
235          */
236         if (!test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags) &&
237             lcfg->lcfg_command == LCFG_ATTACH &&
238             strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_OSC_NAME) == 0) {
239                 if (OBD_OCD_VERSION_MAJOR(d->ver) == 1 &&
240                     OBD_OCD_VERSION_MINOR(d->ver) <= 8) {
241                         CWARN("MDT using 1.8 OSC name scheme\n");
242                         set_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags);
243                 }
244         }
245
246         if (lcfg->lcfg_command == LCFG_MARKER) {
247                 struct cfg_marker *marker;
248                 marker = lustre_cfg_buf(lcfg, 1);
249
250                 d->ver = marker->cm_vers;
251
252                 /* Keep track of the latest marker step */
253                 fsdb->fsdb_gen = max(fsdb->fsdb_gen, marker->cm_step);
254         }
255
256         RETURN(rc);
257 }
258
259 /* fsdb->fsdb_mutex is already held  in mgs_find_or_make_fsdb*/
260 static int mgs_get_fsdb_from_llog(const struct lu_env *env,
261                                   struct mgs_device *mgs,
262                                   struct fs_db *fsdb)
263 {
264         char *logname;
265         struct llog_handle *loghandle;
266         struct llog_ctxt *ctxt;
267         struct mgs_fsdb_handler_data d = {
268                 .fsdb = fsdb,
269         };
270         int rc;
271
272         ENTRY;
273
274         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
275         LASSERT(ctxt != NULL);
276         rc = name_create(&logname, fsdb->fsdb_name, "-client");
277         if (rc)
278                 GOTO(out_put, rc);
279         rc = llog_open_create(env, ctxt, &loghandle, NULL, logname);
280         if (rc)
281                 GOTO(out_pop, rc);
282
283         rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
284         if (rc)
285                 GOTO(out_close, rc);
286
287         if (llog_get_size(loghandle) <= 1)
288                 set_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags);
289
290         rc = llog_process(env, loghandle, mgs_fsdb_handler, (void *)&d, NULL);
291         CDEBUG(D_INFO, "get_db = %d\n", rc);
292 out_close:
293         llog_close(env, loghandle);
294 out_pop:
295         name_destroy(&logname);
296 out_put:
297         llog_ctxt_put(ctxt);
298
299         RETURN(rc);
300 }
301
302 static void mgs_free_fsdb_srpc(struct fs_db *fsdb)
303 {
304         struct mgs_tgt_srpc_conf *tgtconf;
305
306         /* free target-specific rules */
307         while (fsdb->fsdb_srpc_tgt) {
308                 tgtconf = fsdb->fsdb_srpc_tgt;
309                 fsdb->fsdb_srpc_tgt = tgtconf->mtsc_next;
310
311                 LASSERT(tgtconf->mtsc_tgt);
312
313                 sptlrpc_rule_set_free(&tgtconf->mtsc_rset);
314                 OBD_FREE(tgtconf->mtsc_tgt, strlen(tgtconf->mtsc_tgt) + 1);
315                 OBD_FREE_PTR(tgtconf);
316         }
317
318         /* free general rules */
319         sptlrpc_rule_set_free(&fsdb->fsdb_srpc_gen);
320 }
321
322 struct fs_db *mgs_find_fsdb(struct mgs_device *mgs, char *fsname)
323 {
324         struct fs_db *fsdb;
325         struct list_head *tmp;
326
327         list_for_each(tmp, &mgs->mgs_fs_db_list) {
328                 fsdb = list_entry(tmp, struct fs_db, fsdb_list);
329                 if (strcmp(fsdb->fsdb_name, fsname) == 0)
330                         return fsdb;
331         }
332         return NULL;
333 }
334
335 /* caller must hold the mgs->mgs_fs_db_lock */
336 static struct fs_db *mgs_new_fsdb(const struct lu_env *env,
337                                   struct mgs_device *mgs, char *fsname)
338 {
339         struct fs_db *fsdb;
340         int rc;
341         ENTRY;
342
343         if (strlen(fsname) >= sizeof(fsdb->fsdb_name)) {
344                 CERROR("fsname %s is too long\n", fsname);
345                 RETURN(ERR_PTR(-EINVAL));
346         }
347
348         OBD_ALLOC_PTR(fsdb);
349         if (!fsdb)
350                 RETURN(ERR_PTR(-ENOMEM));
351
352         strcpy(fsdb->fsdb_name, fsname);
353         mutex_init(&fsdb->fsdb_mutex);
354         set_bit(FSDB_UDESC, &fsdb->fsdb_flags);
355         fsdb->fsdb_gen = 1;
356
357         if (strcmp(fsname, MGSSELF_NAME) == 0) {
358                 set_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags);
359                 fsdb->fsdb_mgs = mgs;
360         } else {
361                 OBD_ALLOC(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
362                 OBD_ALLOC(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
363                 if (!fsdb->fsdb_ost_index_map || !fsdb->fsdb_mdt_index_map) {
364                         CERROR("No memory for index maps\n");
365                         GOTO(err, rc = -ENOMEM);
366                 }
367
368                 rc = name_create(&fsdb->fsdb_clilov, fsname, "-clilov");
369                 if (rc)
370                         GOTO(err, rc);
371                 rc = name_create(&fsdb->fsdb_clilmv, fsname, "-clilmv");
372                 if (rc)
373                         GOTO(err, rc);
374
375                 /* initialise data for NID table */
376                 mgs_ir_init_fs(env, mgs, fsdb);
377
378                 lproc_mgs_add_live(mgs, fsdb);
379         }
380
381         list_add(&fsdb->fsdb_list, &mgs->mgs_fs_db_list);
382
383         RETURN(fsdb);
384 err:
385         if (fsdb->fsdb_ost_index_map)
386                 OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
387         if (fsdb->fsdb_mdt_index_map)
388                 OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
389         name_destroy(&fsdb->fsdb_clilov);
390         name_destroy(&fsdb->fsdb_clilmv);
391         OBD_FREE_PTR(fsdb);
392         RETURN(ERR_PTR(rc));
393 }
394
395 static void mgs_free_fsdb(struct mgs_device *mgs, struct fs_db *fsdb)
396 {
397         /* wait for anyone with the sem */
398         mutex_lock(&fsdb->fsdb_mutex);
399         lproc_mgs_del_live(mgs, fsdb);
400         list_del(&fsdb->fsdb_list);
401
402         /* deinitialize fsr */
403         mgs_ir_fini_fs(mgs, fsdb);
404
405         if (fsdb->fsdb_ost_index_map)
406                 OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
407         if (fsdb->fsdb_mdt_index_map)
408                 OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
409         name_destroy(&fsdb->fsdb_clilov);
410         name_destroy(&fsdb->fsdb_clilmv);
411         mgs_free_fsdb_srpc(fsdb);
412         mutex_unlock(&fsdb->fsdb_mutex);
413         OBD_FREE_PTR(fsdb);
414 }
415
416 int mgs_init_fsdb_list(struct mgs_device *mgs)
417 {
418         INIT_LIST_HEAD(&mgs->mgs_fs_db_list);
419         return 0;
420 }
421
422 int mgs_cleanup_fsdb_list(struct mgs_device *mgs)
423 {
424         struct fs_db *fsdb;
425         struct list_head *tmp, *tmp2;
426
427         mutex_lock(&mgs->mgs_mutex);
428         list_for_each_safe(tmp, tmp2, &mgs->mgs_fs_db_list) {
429                 fsdb = list_entry(tmp, struct fs_db, fsdb_list);
430                 mgs_free_fsdb(mgs, fsdb);
431         }
432         mutex_unlock(&mgs->mgs_mutex);
433         return 0;
434 }
435
436 int mgs_find_or_make_fsdb(const struct lu_env *env,
437                           struct mgs_device *mgs, char *name,
438                           struct fs_db **dbh)
439 {
440         struct fs_db *fsdb;
441         int rc = 0;
442
443         ENTRY;
444         mutex_lock(&mgs->mgs_mutex);
445         fsdb = mgs_find_fsdb(mgs, name);
446         if (fsdb) {
447                 mutex_unlock(&mgs->mgs_mutex);
448                 *dbh = fsdb;
449                 RETURN(0);
450         }
451
452         CDEBUG(D_MGS, "Creating new db\n");
453         fsdb = mgs_new_fsdb(env, mgs, name);
454         /* lock fsdb_mutex until the db is loaded from llogs */
455         if (!IS_ERR(fsdb))
456                 mutex_lock(&fsdb->fsdb_mutex);
457         mutex_unlock(&mgs->mgs_mutex);
458         if (IS_ERR(fsdb))
459                 RETURN(PTR_ERR(fsdb));
460
461         if (!test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
462                 /* populate the db from the client llog */
463                 rc = mgs_get_fsdb_from_llog(env, mgs, fsdb);
464                 if (rc) {
465                         CERROR("Can't get db from client log %d\n", rc);
466                         GOTO(out_free, rc);
467                 }
468         }
469
470         /* populate srpc rules from params llog */
471         rc = mgs_get_fsdb_srpc_from_llog(env, mgs, fsdb);
472         if (rc) {
473                 CERROR("Can't get db from params log %d\n", rc);
474                 GOTO(out_free, rc);
475         }
476
477         mutex_unlock(&fsdb->fsdb_mutex);
478         *dbh = fsdb;
479
480         RETURN(0);
481
482 out_free:
483         mutex_unlock(&fsdb->fsdb_mutex);
484         mgs_free_fsdb(mgs, fsdb);
485         return rc;
486 }
487
488 /* 1 = index in use
489    0 = index unused
490    -1= empty client log */
491 int mgs_check_index(const struct lu_env *env,
492                     struct mgs_device *mgs,
493                     struct mgs_target_info *mti)
494 {
495         struct fs_db *fsdb;
496         void *imap;
497         int rc = 0;
498         ENTRY;
499
500         LASSERT(!(mti->mti_flags & LDD_F_NEED_INDEX));
501
502         rc = mgs_find_or_make_fsdb(env, mgs, mti->mti_fsname, &fsdb);
503         if (rc) {
504                 CERROR("Can't get db for %s\n", mti->mti_fsname);
505                 RETURN(rc);
506         }
507
508         if (test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags))
509                 RETURN(-1);
510
511         if (mti->mti_flags & LDD_F_SV_TYPE_OST)
512                 imap = fsdb->fsdb_ost_index_map;
513         else if (mti->mti_flags & LDD_F_SV_TYPE_MDT)
514                 imap = fsdb->fsdb_mdt_index_map;
515         else
516                 RETURN(-EINVAL);
517
518         if (test_bit(mti->mti_stripe_index, imap))
519                 RETURN(1);
520         RETURN(0);
521 }
522
523 static __inline__ int next_index(void *index_map, int map_len)
524 {
525         int i;
526         for (i = 0; i < map_len * 8; i++)
527                 if (!test_bit(i, index_map)) {
528                          return i;
529                  }
530         CERROR("max index %d exceeded.\n", i);
531         return -1;
532 }
533
534 /* Return codes:
535         0  newly marked as in use
536         <0 err
537         +EALREADY for update of an old index */
538 static int mgs_set_index(const struct lu_env *env,
539                          struct mgs_device *mgs,
540                          struct mgs_target_info *mti)
541 {
542         struct fs_db *fsdb;
543         void *imap;
544         int rc = 0;
545         ENTRY;
546
547         rc = mgs_find_or_make_fsdb(env, mgs, mti->mti_fsname, &fsdb);
548         if (rc) {
549                 CERROR("Can't get db for %s\n", mti->mti_fsname);
550                 RETURN(rc);
551         }
552
553         mutex_lock(&fsdb->fsdb_mutex);
554         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
555                 imap = fsdb->fsdb_ost_index_map;
556         } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
557                 imap = fsdb->fsdb_mdt_index_map;
558         } else {
559                 GOTO(out_up, rc = -EINVAL);
560         }
561
562         if (mti->mti_flags & LDD_F_NEED_INDEX) {
563                 rc = next_index(imap, INDEX_MAP_SIZE);
564                 if (rc == -1)
565                         GOTO(out_up, rc = -ERANGE);
566                 mti->mti_stripe_index = rc;
567                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT)
568                         fsdb->fsdb_mdt_count ++;
569         }
570
571         /* the last index(0xffff) is reserved for default value. */
572         if (mti->mti_stripe_index >= INDEX_MAP_SIZE * 8 - 1) {
573                 LCONSOLE_ERROR_MSG(0x13f, "Server %s requested index %u, "
574                                    "but index must be less than %u.\n",
575                                    mti->mti_svname, mti->mti_stripe_index,
576                                    INDEX_MAP_SIZE * 8 - 1);
577                 GOTO(out_up, rc = -ERANGE);
578         }
579
580         if (test_bit(mti->mti_stripe_index, imap)) {
581                 if ((mti->mti_flags & LDD_F_VIRGIN) &&
582                     !(mti->mti_flags & LDD_F_WRITECONF)) {
583                         LCONSOLE_ERROR_MSG(0x140, "Server %s requested index "
584                                            "%d, but that index is already in "
585                                            "use. Use --writeconf to force\n",
586                                            mti->mti_svname,
587                                            mti->mti_stripe_index);
588                         GOTO(out_up, rc = -EADDRINUSE);
589                 } else {
590                         CDEBUG(D_MGS, "Server %s updating index %d\n",
591                                mti->mti_svname, mti->mti_stripe_index);
592                         GOTO(out_up, rc = EALREADY);
593                 }
594         }
595
596         set_bit(mti->mti_stripe_index, imap);
597         clear_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags);
598         mutex_unlock(&fsdb->fsdb_mutex);
599         if (server_make_name(mti->mti_flags & ~(LDD_F_VIRGIN | LDD_F_WRITECONF),
600                              mti->mti_stripe_index, mti->mti_fsname,
601                              mti->mti_svname)) {
602                 CERROR("unknown server type %#x\n", mti->mti_flags);
603                 return -EINVAL;
604         }
605
606         CDEBUG(D_MGS, "Set index for %s to %d\n", mti->mti_svname,
607                mti->mti_stripe_index);
608
609         RETURN(0);
610 out_up:
611         mutex_unlock(&fsdb->fsdb_mutex);
612         return rc;
613 }
614
615 struct mgs_modify_lookup {
616         struct cfg_marker mml_marker;
617         int               mml_modified;
618 };
619
620 static int mgs_check_record_match(const struct lu_env *env,
621                                 struct llog_handle *llh,
622                                 struct llog_rec_hdr *rec, void *data)
623 {
624         struct cfg_marker *mc_marker = data;
625         struct cfg_marker *marker;
626         struct lustre_cfg *lcfg = REC_DATA(rec);
627         int cfg_len = REC_DATA_LEN(rec);
628         int rc;
629         ENTRY;
630
631
632         if (rec->lrh_type != OBD_CFG_REC) {
633                 CDEBUG(D_ERROR, "Unhandled lrh_type: %#x\n", rec->lrh_type);
634                 RETURN(-EINVAL);
635         }
636
637         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
638         if (rc) {
639                 CDEBUG(D_ERROR, "Insane cfg\n");
640                 RETURN(rc);
641         }
642
643         /* We only care about markers */
644         if (lcfg->lcfg_command != LCFG_MARKER)
645                 RETURN(0);
646
647         marker = lustre_cfg_buf(lcfg, 1);
648
649         if (marker->cm_flags & CM_SKIP)
650                 RETURN(0);
651
652         if ((strcmp(mc_marker->cm_comment, marker->cm_comment) == 0) &&
653                 (strcmp(mc_marker->cm_tgtname, marker->cm_tgtname) == 0)) {
654                 /* Found a non-skipped marker match */
655                 CDEBUG(D_MGS, "Matched rec %u marker %d flag %x %s %s\n",
656                         rec->lrh_index, marker->cm_step,
657                         marker->cm_flags, marker->cm_tgtname,
658                         marker->cm_comment);
659                 rc = LLOG_PROC_BREAK;
660         }
661
662         RETURN(rc);
663 }
664
665 /**
666  * Check an existing config log record with matching comment and device
667  * Return code:
668  * 0 - checked successfully,
669  * LLOG_PROC_BREAK - record matches
670  * negative - error
671  */
672 static int mgs_check_marker(const struct lu_env *env, struct mgs_device *mgs,
673                 struct fs_db *fsdb, struct mgs_target_info *mti,
674                 char *logname, char *devname, char *comment)
675 {
676         struct llog_handle *loghandle;
677         struct llog_ctxt *ctxt;
678         struct cfg_marker *mc_marker;
679         int rc;
680
681         ENTRY;
682
683         LASSERT(mutex_is_locked(&fsdb->fsdb_mutex));
684         CDEBUG(D_MGS, "mgs check %s/%s/%s\n", logname, devname, comment);
685
686         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
687         LASSERT(ctxt != NULL);
688         rc = llog_open(env, ctxt, &loghandle, NULL, logname, LLOG_OPEN_EXISTS);
689         if (rc < 0) {
690                 if (rc == -ENOENT)
691                         rc = 0;
692                 GOTO(out_pop, rc);
693         }
694
695         rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
696         if (rc)
697                 GOTO(out_close, rc);
698
699         if (llog_get_size(loghandle) <= 1)
700                 GOTO(out_close, rc = 0);
701
702         OBD_ALLOC_PTR(mc_marker);
703         if (!mc_marker)
704                 GOTO(out_close, rc = -ENOMEM);
705         if (strlcpy(mc_marker->cm_comment, comment,
706                 sizeof(mc_marker->cm_comment)) >=
707                 sizeof(mc_marker->cm_comment))
708                 GOTO(out_free, rc = -E2BIG);
709         if (strlcpy(mc_marker->cm_tgtname, devname,
710                 sizeof(mc_marker->cm_tgtname)) >=
711                 sizeof(mc_marker->cm_tgtname))
712                 GOTO(out_free, rc = -E2BIG);
713
714         rc = llog_process(env, loghandle, mgs_check_record_match,
715                         (void *)mc_marker, NULL);
716
717 out_free:
718         OBD_FREE_PTR(mc_marker);
719
720 out_close:
721         llog_close(env, loghandle);
722 out_pop:
723         if (rc && rc != LLOG_PROC_BREAK)
724                 CDEBUG(D_ERROR, "%s: mgs check %s/%s failed: rc = %d\n",
725                         mgs->mgs_obd->obd_name, mti->mti_svname, comment, rc);
726         llog_ctxt_put(ctxt);
727         RETURN(rc);
728 }
729
730 static int mgs_modify_handler(const struct lu_env *env,
731                               struct llog_handle *llh,
732                               struct llog_rec_hdr *rec, void *data)
733 {
734         struct mgs_modify_lookup *mml = 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         if (rec->lrh_type != OBD_CFG_REC) {
742                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
743                 RETURN(-EINVAL);
744         }
745
746         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
747         if (rc) {
748                 CERROR("Insane cfg\n");
749                 RETURN(rc);
750         }
751
752         /* We only care about markers */
753         if (lcfg->lcfg_command != LCFG_MARKER)
754                 RETURN(0);
755
756         marker = lustre_cfg_buf(lcfg, 1);
757         if ((strcmp(mml->mml_marker.cm_comment, marker->cm_comment) == 0) &&
758             (strcmp(mml->mml_marker.cm_tgtname, marker->cm_tgtname) == 0) &&
759             !(marker->cm_flags & CM_SKIP)) {
760                 /* Found a non-skipped marker match */
761                 CDEBUG(D_MGS, "Changing rec %u marker %d %x->%x: %s %s\n",
762                        rec->lrh_index, marker->cm_step,
763                        marker->cm_flags, mml->mml_marker.cm_flags,
764                        marker->cm_tgtname, marker->cm_comment);
765                 /* Overwrite the old marker llog entry */
766                 marker->cm_flags &= ~CM_EXCLUDE; /* in case we're unexcluding */
767                 marker->cm_flags |= mml->mml_marker.cm_flags;
768                 marker->cm_canceltime = mml->mml_marker.cm_canceltime;
769                 rc = llog_write(env, llh, rec, rec->lrh_index);
770                 if (!rc)
771                          mml->mml_modified++;
772         }
773
774         RETURN(rc);
775 }
776
777 /**
778  * Modify an existing config log record (for CM_SKIP or CM_EXCLUDE)
779  * Return code:
780  * 0 - modified successfully,
781  * 1 - no modification was done
782  * negative - error
783  */
784 static int mgs_modify(const struct lu_env *env, struct mgs_device *mgs,
785                       struct fs_db *fsdb, struct mgs_target_info *mti,
786                       char *logname, char *devname, char *comment, int flags)
787 {
788         struct llog_handle *loghandle;
789         struct llog_ctxt *ctxt;
790         struct mgs_modify_lookup *mml;
791         int rc;
792
793         ENTRY;
794
795         LASSERT(mutex_is_locked(&fsdb->fsdb_mutex));
796         CDEBUG(D_MGS, "modify %s/%s/%s fl=%x\n", logname, devname, comment,
797                flags);
798
799         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
800         LASSERT(ctxt != NULL);
801         rc = llog_open(env, ctxt, &loghandle, NULL, logname, LLOG_OPEN_EXISTS);
802         if (rc < 0) {
803                 if (rc == -ENOENT)
804                         rc = 0;
805                 GOTO(out_pop, rc);
806         }
807
808         rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
809         if (rc)
810                 GOTO(out_close, rc);
811
812         if (llog_get_size(loghandle) <= 1)
813                 GOTO(out_close, rc = 0);
814
815         OBD_ALLOC_PTR(mml);
816         if (!mml)
817                 GOTO(out_close, rc = -ENOMEM);
818         if (strlcpy(mml->mml_marker.cm_comment, comment,
819                     sizeof(mml->mml_marker.cm_comment)) >=
820             sizeof(mml->mml_marker.cm_comment))
821                 GOTO(out_free, rc = -E2BIG);
822         if (strlcpy(mml->mml_marker.cm_tgtname, devname,
823                     sizeof(mml->mml_marker.cm_tgtname)) >=
824             sizeof(mml->mml_marker.cm_tgtname))
825                 GOTO(out_free, rc = -E2BIG);
826         /* Modify mostly means cancel */
827         mml->mml_marker.cm_flags = flags;
828         mml->mml_marker.cm_canceltime = flags ? cfs_time_current_sec() : 0;
829         mml->mml_modified = 0;
830         rc = llog_process(env, loghandle, mgs_modify_handler, (void *)mml,
831                           NULL);
832         if (!rc && !mml->mml_modified)
833                 rc = 1;
834
835 out_free:
836         OBD_FREE_PTR(mml);
837
838 out_close:
839         llog_close(env, loghandle);
840 out_pop:
841         if (rc < 0)
842                 CERROR("%s: modify %s/%s failed: rc = %d\n",
843                        mgs->mgs_obd->obd_name, mti->mti_svname, comment, rc);
844         llog_ctxt_put(ctxt);
845         RETURN(rc);
846 }
847
848 /** This structure is passed to mgs_replace_handler */
849 struct mgs_replace_uuid_lookup {
850         /* Nids are replaced for this target device */
851         struct mgs_target_info target;
852         /* Temporary modified llog */
853         struct llog_handle *temp_llh;
854         /* Flag is set if in target block*/
855         int in_target_device;
856         /* Nids already added. Just skip (multiple nids) */
857         int device_nids_added;
858         /* Flag is set if this block should not be copied */
859         int skip_it;
860 };
861
862 /**
863  * Check: a) if block should be skipped
864  * b) is it target block
865  *
866  * \param[in] lcfg
867  * \param[in] mrul
868  *
869  * \retval 0 should not to be skipped
870  * \retval 1 should to be skipped
871  */
872 static int check_markers(struct lustre_cfg *lcfg,
873                          struct mgs_replace_uuid_lookup *mrul)
874 {
875          struct cfg_marker *marker;
876
877         /* Track markers. Find given device */
878         if (lcfg->lcfg_command == LCFG_MARKER) {
879                 marker = lustre_cfg_buf(lcfg, 1);
880                 /* Clean llog from records marked as CM_EXCLUDE.
881                    CM_SKIP records are used for "active" command
882                    and can be restored if needed */
883                 if ((marker->cm_flags & (CM_EXCLUDE | CM_START)) ==
884                     (CM_EXCLUDE | CM_START)) {
885                         mrul->skip_it = 1;
886                         return 1;
887                 }
888
889                 if ((marker->cm_flags & (CM_EXCLUDE | CM_END)) ==
890                     (CM_EXCLUDE | CM_END)) {
891                         mrul->skip_it = 0;
892                         return 1;
893                 }
894
895                 if (strcmp(mrul->target.mti_svname, marker->cm_tgtname) == 0) {
896                         LASSERT(!(marker->cm_flags & CM_START) ||
897                                 !(marker->cm_flags & CM_END));
898                         if (marker->cm_flags & CM_START) {
899                                 mrul->in_target_device = 1;
900                                 mrul->device_nids_added = 0;
901                         } else if (marker->cm_flags & CM_END)
902                                 mrul->in_target_device = 0;
903                 }
904         }
905
906         return 0;
907 }
908
909 static int record_base(const struct lu_env *env, struct llog_handle *llh,
910                      char *cfgname, lnet_nid_t nid, int cmd,
911                      char *s1, char *s2, char *s3, char *s4)
912 {
913         struct mgs_thread_info  *mgi = mgs_env_info(env);
914         struct llog_cfg_rec     *lcr;
915         int rc;
916
917         CDEBUG(D_MGS, "lcfg %s %#x %s %s %s %s\n", cfgname,
918                cmd, s1, s2, s3, s4);
919
920         lustre_cfg_bufs_reset(&mgi->mgi_bufs, cfgname);
921         if (s1)
922                 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, s1);
923         if (s2)
924                 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 2, s2);
925         if (s3)
926                 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 3, s3);
927         if (s4)
928                 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 4, s4);
929
930         lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
931         if (lcr == NULL)
932                 return -ENOMEM;
933
934         lcr->lcr_cfg.lcfg_nid = nid;
935         rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
936
937         lustre_cfg_rec_free(lcr);
938
939         if (rc < 0)
940                 CDEBUG(D_MGS,
941                        "failed to write lcfg %s %#x %s %s %s %s: rc = %d\n",
942                        cfgname, cmd, s1, s2, s3, s4, rc);
943         return rc;
944 }
945
946 static inline int record_add_uuid(const struct lu_env *env,
947                                   struct llog_handle *llh,
948                                   uint64_t nid, char *uuid)
949 {
950         return record_base(env, llh, NULL, nid, LCFG_ADD_UUID, uuid,
951                            NULL, NULL, NULL);
952 }
953
954 static inline int record_add_conn(const struct lu_env *env,
955                                   struct llog_handle *llh,
956                                   char *devname, char *uuid)
957 {
958         return record_base(env, llh, devname, 0, LCFG_ADD_CONN, uuid,
959                            NULL, NULL, NULL);
960 }
961
962 static inline int record_attach(const struct lu_env *env,
963                                 struct llog_handle *llh, char *devname,
964                                 char *type, char *uuid)
965 {
966         return record_base(env, llh, devname, 0, LCFG_ATTACH, type, uuid,
967                            NULL, NULL);
968 }
969
970 static inline int record_setup(const struct lu_env *env,
971                                struct llog_handle *llh, char *devname,
972                                char *s1, char *s2, char *s3, char *s4)
973 {
974         return record_base(env, llh, devname, 0, LCFG_SETUP, s1, s2, s3, s4);
975 }
976
977 /**
978  * \retval <0 record processing error
979  * \retval n record is processed. No need copy original one.
980  * \retval 0 record is not processed.
981  */
982 static int process_command(const struct lu_env *env, struct lustre_cfg *lcfg,
983                            struct mgs_replace_uuid_lookup *mrul)
984 {
985         int nids_added = 0;
986         lnet_nid_t nid;
987         char *ptr;
988         int rc;
989
990         if (lcfg->lcfg_command == LCFG_ADD_UUID) {
991                 /* LCFG_ADD_UUID command found. Let's skip original command
992                    and add passed nids */
993                 ptr = mrul->target.mti_params;
994                 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
995                         CDEBUG(D_MGS, "add nid %s with uuid %s, "
996                                "device %s\n", libcfs_nid2str(nid),
997                                 mrul->target.mti_params,
998                                 mrul->target.mti_svname);
999                         rc = record_add_uuid(env,
1000                                              mrul->temp_llh, nid,
1001                                              mrul->target.mti_params);
1002                         if (!rc)
1003                                 nids_added++;
1004                 }
1005
1006                 if (nids_added == 0) {
1007                         CERROR("No new nids were added, nid %s with uuid %s, "
1008                                "device %s\n", libcfs_nid2str(nid),
1009                                mrul->target.mti_params,
1010                                mrul->target.mti_svname);
1011                         RETURN(-ENXIO);
1012                 } else {
1013                         mrul->device_nids_added = 1;
1014                 }
1015
1016                 return nids_added;
1017         }
1018
1019         if (mrul->device_nids_added && lcfg->lcfg_command == LCFG_SETUP) {
1020                 /* LCFG_SETUP command found. UUID should be changed */
1021                 rc = record_setup(env,
1022                                   mrul->temp_llh,
1023                                   /* devname the same */
1024                                   lustre_cfg_string(lcfg, 0),
1025                                   /* s1 is not changed */
1026                                   lustre_cfg_string(lcfg, 1),
1027                                   /* new uuid should be
1028                                   the full nidlist */
1029                                   mrul->target.mti_params,
1030                                   /* s3 is not changed */
1031                                   lustre_cfg_string(lcfg, 3),
1032                                   /* s4 is not changed */
1033                                   lustre_cfg_string(lcfg, 4));
1034                 return rc ? rc : 1;
1035         }
1036
1037         /* Another commands in target device block */
1038         return 0;
1039 }
1040
1041 /**
1042  * Handler that called for every record in llog.
1043  * Records are processed in order they placed in llog.
1044  *
1045  * \param[in] llh       log to be processed
1046  * \param[in] rec       current record
1047  * \param[in] data      mgs_replace_uuid_lookup structure
1048  *
1049  * \retval 0    success
1050  */
1051 static int mgs_replace_handler(const struct lu_env *env,
1052                                struct llog_handle *llh,
1053                                struct llog_rec_hdr *rec,
1054                                void *data)
1055 {
1056         struct mgs_replace_uuid_lookup *mrul;
1057         struct lustre_cfg *lcfg = REC_DATA(rec);
1058         int cfg_len = REC_DATA_LEN(rec);
1059         int rc;
1060         ENTRY;
1061
1062         mrul = (struct mgs_replace_uuid_lookup *)data;
1063
1064         if (rec->lrh_type != OBD_CFG_REC) {
1065                 CERROR("unhandled lrh_type: %#x, cmd %x %s %s\n",
1066                        rec->lrh_type, lcfg->lcfg_command,
1067                        lustre_cfg_string(lcfg, 0),
1068                        lustre_cfg_string(lcfg, 1));
1069                 RETURN(-EINVAL);
1070         }
1071
1072         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
1073         if (rc) {
1074                 /* Do not copy any invalidated records */
1075                 GOTO(skip_out, rc = 0);
1076         }
1077
1078         rc = check_markers(lcfg, mrul);
1079         if (rc || mrul->skip_it)
1080                 GOTO(skip_out, rc = 0);
1081
1082         /* Write to new log all commands outside target device block */
1083         if (!mrul->in_target_device)
1084                 GOTO(copy_out, rc = 0);
1085
1086         /* Skip all other LCFG_ADD_UUID and LCFG_ADD_CONN records
1087            (failover nids) for this target, assuming that if then
1088            primary is changing then so is the failover */
1089         if (mrul->device_nids_added &&
1090             (lcfg->lcfg_command == LCFG_ADD_UUID ||
1091              lcfg->lcfg_command == LCFG_ADD_CONN))
1092                 GOTO(skip_out, rc = 0);
1093
1094         rc = process_command(env, lcfg, mrul);
1095         if (rc < 0)
1096                 RETURN(rc);
1097
1098         if (rc)
1099                 RETURN(0);
1100 copy_out:
1101         /* Record is placed in temporary llog as is */
1102         rc = llog_write(env, mrul->temp_llh, rec, LLOG_NEXT_IDX);
1103
1104         CDEBUG(D_MGS, "Copied idx=%d, rc=%d, len=%d, cmd %x %s %s\n",
1105                rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
1106                lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
1107         RETURN(rc);
1108
1109 skip_out:
1110         CDEBUG(D_MGS, "Skipped idx=%d, rc=%d, len=%d, cmd %x %s %s\n",
1111                rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
1112                lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
1113         RETURN(rc);
1114 }
1115
1116 static int mgs_log_is_empty(const struct lu_env *env,
1117                             struct mgs_device *mgs, char *name)
1118 {
1119         struct llog_ctxt        *ctxt;
1120         int                      rc;
1121
1122         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
1123         LASSERT(ctxt != NULL);
1124
1125         rc = llog_is_empty(env, ctxt, name);
1126         llog_ctxt_put(ctxt);
1127         return rc;
1128 }
1129
1130 static int mgs_replace_nids_log(const struct lu_env *env,
1131                                 struct obd_device *mgs, struct fs_db *fsdb,
1132                                 char *logname, char *devname, char *nids)
1133 {
1134         struct llog_handle *orig_llh, *backup_llh;
1135         struct llog_ctxt *ctxt;
1136         struct mgs_replace_uuid_lookup *mrul;
1137         struct mgs_device *mgs_dev = lu2mgs_dev(mgs->obd_lu_dev);
1138         static struct obd_uuid   cfg_uuid = { .uuid = "config_uuid" };
1139         char *backup;
1140         int rc, rc2;
1141         ENTRY;
1142
1143         CDEBUG(D_MGS, "Replace nids for %s in %s\n", devname, logname);
1144
1145         ctxt = llog_get_context(mgs, LLOG_CONFIG_ORIG_CTXT);
1146         LASSERT(ctxt != NULL);
1147
1148         if (mgs_log_is_empty(env, mgs_dev, logname)) {
1149                 /* Log is empty. Nothing to replace */
1150                 GOTO(out_put, rc = 0);
1151         }
1152
1153         OBD_ALLOC(backup, strlen(logname) + strlen(".bak") + 1);
1154         if (backup == NULL)
1155                 GOTO(out_put, rc = -ENOMEM);
1156
1157         sprintf(backup, "%s.bak", logname);
1158
1159         rc = llog_backup(env, mgs, ctxt, ctxt, logname, backup);
1160         if (rc == 0) {
1161                 /* Now erase original log file. Connections are not allowed.
1162                    Backup is already saved */
1163                 rc = llog_erase(env, ctxt, NULL, logname);
1164                 if (rc < 0)
1165                         GOTO(out_free, rc);
1166         } else if (rc != -ENOENT) {
1167                 CERROR("%s: can't make backup for %s: rc = %d\n",
1168                        mgs->obd_name, logname, rc);
1169                 GOTO(out_free,rc);
1170         }
1171
1172         /* open local log */
1173         rc = llog_open_create(env, ctxt, &orig_llh, NULL, logname);
1174         if (rc)
1175                 GOTO(out_restore, rc);
1176
1177         rc = llog_init_handle(env, orig_llh, LLOG_F_IS_PLAIN, &cfg_uuid);
1178         if (rc)
1179                 GOTO(out_closel, rc);
1180
1181         /* open backup llog */
1182         rc = llog_open(env, ctxt, &backup_llh, NULL, backup,
1183                        LLOG_OPEN_EXISTS);
1184         if (rc)
1185                 GOTO(out_closel, rc);
1186
1187         rc = llog_init_handle(env, backup_llh, LLOG_F_IS_PLAIN, NULL);
1188         if (rc)
1189                 GOTO(out_close, rc);
1190
1191         if (llog_get_size(backup_llh) <= 1)
1192                 GOTO(out_close, rc = 0);
1193
1194         OBD_ALLOC_PTR(mrul);
1195         if (!mrul)
1196                 GOTO(out_close, rc = -ENOMEM);
1197         /* devname is only needed information to replace UUID records */
1198         strlcpy(mrul->target.mti_svname, devname,
1199                 sizeof(mrul->target.mti_svname));
1200         /* parse nids later */
1201         strlcpy(mrul->target.mti_params, nids, sizeof(mrul->target.mti_params));
1202         /* Copy records to this temporary llog */
1203         mrul->temp_llh = orig_llh;
1204
1205         rc = llog_process(env, backup_llh, mgs_replace_handler,
1206                           (void *)mrul, NULL);
1207         OBD_FREE_PTR(mrul);
1208 out_close:
1209         rc2 = llog_close(NULL, backup_llh);
1210         if (!rc)
1211                 rc = rc2;
1212 out_closel:
1213         rc2 = llog_close(NULL, orig_llh);
1214         if (!rc)
1215                 rc = rc2;
1216
1217 out_restore:
1218         if (rc) {
1219                 CERROR("%s: llog should be restored: rc = %d\n",
1220                        mgs->obd_name, rc);
1221                 rc2 = llog_backup(env, mgs, ctxt, ctxt, backup,
1222                                   logname);
1223                 if (rc2 < 0)
1224                         CERROR("%s: can't restore backup %s: rc = %d\n",
1225                                mgs->obd_name, logname, rc2);
1226         }
1227
1228 out_free:
1229         OBD_FREE(backup, strlen(backup) + 1);
1230
1231 out_put:
1232         llog_ctxt_put(ctxt);
1233
1234         if (rc)
1235                 CERROR("%s: failed to replace nids in log %s: rc = %d\n",
1236                        mgs->obd_name, logname, rc);
1237
1238         RETURN(rc);
1239 }
1240
1241 /**
1242  * Parse device name and get file system name and/or device index
1243  *
1244  * \param[in]   devname device name (ex. lustre-MDT0000)
1245  * \param[out]  fsname  file system name(optional)
1246  * \param[out]  index   device index(optional)
1247  *
1248  * \retval 0    success
1249  */
1250 static int mgs_parse_devname(char *devname, char *fsname, __u32 *index)
1251 {
1252         int rc;
1253         ENTRY;
1254
1255         /* Extract fsname */
1256         if (fsname) {
1257                 rc = server_name2fsname(devname, fsname, NULL);
1258                 if (rc < 0) {
1259                         CDEBUG(D_MGS, "Device name %s without fsname\n",
1260                                devname);
1261                         RETURN(-EINVAL);
1262                 }
1263         }
1264
1265         if (index) {
1266                 rc = server_name2index(devname, index, NULL);
1267                 if (rc < 0) {
1268                         CDEBUG(D_MGS, "Device name %s with wrong index\n",
1269                                devname);
1270                         RETURN(-EINVAL);
1271                 }
1272         }
1273
1274         RETURN(0);
1275 }
1276
1277 /* This is only called during replace_nids */
1278 static int only_mgs_is_running(struct obd_device *mgs_obd)
1279 {
1280         /* TDB: Is global variable with devices count exists? */
1281         int num_devices = get_devices_count();
1282         int num_exports = 0;
1283         struct obd_export *exp;
1284
1285         spin_lock(&mgs_obd->obd_dev_lock);
1286         list_for_each_entry(exp, &mgs_obd->obd_exports, exp_obd_chain) {
1287                 /* skip self export */
1288                 if (exp == mgs_obd->obd_self_export)
1289                         continue;
1290                 if (exp_connect_flags(exp) & OBD_CONNECT_MDS_MDS)
1291                         continue;
1292
1293                 ++num_exports;
1294
1295                 CERROR("%s: node %s still connected during replace_nids "
1296                        "connect_flags:%llx\n",
1297                        mgs_obd->obd_name,
1298                        libcfs_nid2str(exp->exp_nid_stats->nid),
1299                        exp_connect_flags(exp));
1300
1301         }
1302         spin_unlock(&mgs_obd->obd_dev_lock);
1303
1304         /* osd, MGS and MGC + self_export
1305            (wc -l /proc/fs/lustre/devices <= 2) && (non self exports == 0) */
1306         return (num_devices <= 3) && (num_exports == 0);
1307 }
1308
1309 static int name_create_mdt(char **logname, char *fsname, int i)
1310 {
1311         char mdt_index[9];
1312
1313         sprintf(mdt_index, "-MDT%04x", i);
1314         return name_create(logname, fsname, mdt_index);
1315 }
1316
1317 /**
1318  * Replace nids for \a device to \a nids values
1319  *
1320  * \param obd           MGS obd device
1321  * \param devname       nids need to be replaced for this device
1322  * (ex. lustre-OST0000)
1323  * \param nids          nids list (ex. nid1,nid2,nid3)
1324  *
1325  * \retval 0    success
1326  */
1327 int mgs_replace_nids(const struct lu_env *env,
1328                      struct mgs_device *mgs,
1329                      char *devname, char *nids)
1330 {
1331         /* Assume fsname is part of device name */
1332         char fsname[MTI_NAME_MAXLEN];
1333         int rc;
1334         __u32 index;
1335         char *logname;
1336         struct fs_db *fsdb;
1337         unsigned int i;
1338         int conn_state;
1339         struct obd_device *mgs_obd = mgs->mgs_obd;
1340         ENTRY;
1341
1342         /* We can only change NIDs if no other nodes are connected */
1343         spin_lock(&mgs_obd->obd_dev_lock);
1344         conn_state = mgs_obd->obd_no_conn;
1345         mgs_obd->obd_no_conn = 1;
1346         spin_unlock(&mgs_obd->obd_dev_lock);
1347
1348         /* We can not change nids if not only MGS is started */
1349         if (!only_mgs_is_running(mgs_obd)) {
1350                 CERROR("Only MGS is allowed to be started\n");
1351                 GOTO(out, rc = -EINPROGRESS);
1352         }
1353
1354         /* Get fsname and index*/
1355         rc = mgs_parse_devname(devname, fsname, &index);
1356         if (rc)
1357                 GOTO(out, rc);
1358
1359         rc = mgs_find_or_make_fsdb(env, mgs, fsname, &fsdb);
1360         if (rc) {
1361                 CERROR("%s: can't find fsdb: rc = %d\n", fsname, rc);
1362                 GOTO(out, rc);
1363         }
1364
1365         /* Process client llogs */
1366         name_create(&logname, fsname, "-client");
1367         rc = mgs_replace_nids_log(env, mgs_obd, fsdb, logname, devname, nids);
1368         name_destroy(&logname);
1369         if (rc) {
1370                 CERROR("%s: error while replacing NIDs for %s: rc = %d\n",
1371                        fsname, devname, rc);
1372                 GOTO(out, rc);
1373         }
1374
1375         /* Process MDT llogs */
1376         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
1377                 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
1378                         continue;
1379                 name_create_mdt(&logname, fsname, i);
1380                 rc = mgs_replace_nids_log(env, mgs_obd, fsdb, logname, devname, nids);
1381                 name_destroy(&logname);
1382                 if (rc)
1383                         GOTO(out, rc);
1384         }
1385
1386 out:
1387         spin_lock(&mgs_obd->obd_dev_lock);
1388         mgs_obd->obd_no_conn = conn_state;
1389         spin_unlock(&mgs_obd->obd_dev_lock);
1390
1391         RETURN(rc);
1392 }
1393
1394 static int record_lov_setup(const struct lu_env *env, struct llog_handle *llh,
1395                             char *devname, struct lov_desc *desc)
1396 {
1397         struct mgs_thread_info  *mgi = mgs_env_info(env);
1398         struct llog_cfg_rec     *lcr;
1399         int rc;
1400
1401         lustre_cfg_bufs_reset(&mgi->mgi_bufs, devname);
1402         lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, desc, sizeof(*desc));
1403         lcr = lustre_cfg_rec_new(LCFG_SETUP, &mgi->mgi_bufs);
1404         if (lcr == NULL)
1405                 return -ENOMEM;
1406
1407         rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1408         lustre_cfg_rec_free(lcr);
1409         return rc;
1410 }
1411
1412 static int record_lmv_setup(const struct lu_env *env, struct llog_handle *llh,
1413                             char *devname, struct lmv_desc *desc)
1414 {
1415         struct mgs_thread_info  *mgi = mgs_env_info(env);
1416         struct llog_cfg_rec     *lcr;
1417         int rc;
1418
1419         lustre_cfg_bufs_reset(&mgi->mgi_bufs, devname);
1420         lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, desc, sizeof(*desc));
1421         lcr = lustre_cfg_rec_new(LCFG_SETUP, &mgi->mgi_bufs);
1422         if (lcr == NULL)
1423                 return -ENOMEM;
1424
1425         rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1426         lustre_cfg_rec_free(lcr);
1427         return rc;
1428 }
1429
1430 static inline int record_mdc_add(const struct lu_env *env,
1431                                  struct llog_handle *llh,
1432                                  char *logname, char *mdcuuid,
1433                                  char *mdtuuid, char *index,
1434                                  char *gen)
1435 {
1436         return record_base(env,llh,logname,0,LCFG_ADD_MDC,
1437                            mdtuuid,index,gen,mdcuuid);
1438 }
1439
1440 static inline int record_lov_add(const struct lu_env *env,
1441                                  struct llog_handle *llh,
1442                                  char *lov_name, char *ost_uuid,
1443                                  char *index, char *gen)
1444 {
1445         return record_base(env, llh, lov_name, 0, LCFG_LOV_ADD_OBD,
1446                            ost_uuid, index, gen, NULL);
1447 }
1448
1449 static inline int record_mount_opt(const struct lu_env *env,
1450                                    struct llog_handle *llh,
1451                                    char *profile, char *lov_name,
1452                                    char *mdc_name)
1453 {
1454         return record_base(env, llh, NULL, 0, LCFG_MOUNTOPT,
1455                            profile, lov_name, mdc_name, NULL);
1456 }
1457
1458 static int record_marker(const struct lu_env *env,
1459                          struct llog_handle *llh,
1460                          struct fs_db *fsdb, __u32 flags,
1461                          char *tgtname, char *comment)
1462 {
1463         struct mgs_thread_info *mgi = mgs_env_info(env);
1464         struct llog_cfg_rec *lcr;
1465         int rc;
1466         int cplen = 0;
1467
1468         if (flags & CM_START)
1469                 fsdb->fsdb_gen++;
1470         mgi->mgi_marker.cm_step = fsdb->fsdb_gen;
1471         mgi->mgi_marker.cm_flags = flags;
1472         mgi->mgi_marker.cm_vers = LUSTRE_VERSION_CODE;
1473         cplen = strlcpy(mgi->mgi_marker.cm_tgtname, tgtname,
1474                         sizeof(mgi->mgi_marker.cm_tgtname));
1475         if (cplen >= sizeof(mgi->mgi_marker.cm_tgtname))
1476                 return -E2BIG;
1477         cplen = strlcpy(mgi->mgi_marker.cm_comment, comment,
1478                         sizeof(mgi->mgi_marker.cm_comment));
1479         if (cplen >= sizeof(mgi->mgi_marker.cm_comment))
1480                 return -E2BIG;
1481         mgi->mgi_marker.cm_createtime = cfs_time_current_sec();
1482         mgi->mgi_marker.cm_canceltime = 0;
1483         lustre_cfg_bufs_reset(&mgi->mgi_bufs, NULL);
1484         lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, &mgi->mgi_marker,
1485                             sizeof(mgi->mgi_marker));
1486         lcr = lustre_cfg_rec_new(LCFG_MARKER, &mgi->mgi_bufs);
1487         if (lcr == NULL)
1488                 return -ENOMEM;
1489
1490         rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1491         lustre_cfg_rec_free(lcr);
1492         return rc;
1493 }
1494
1495 static int record_start_log(const struct lu_env *env, struct mgs_device *mgs,
1496                             struct llog_handle **llh, char *name)
1497 {
1498         static struct obd_uuid   cfg_uuid = { .uuid = "config_uuid" };
1499         struct llog_ctxt        *ctxt;
1500         int                      rc = 0;
1501         ENTRY;
1502
1503         if (*llh)
1504                 GOTO(out, rc = -EBUSY);
1505
1506         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
1507         if (!ctxt)
1508                 GOTO(out, rc = -ENODEV);
1509         LASSERT(ctxt->loc_obd == mgs->mgs_obd);
1510
1511         rc = llog_open_create(env, ctxt, llh, NULL, name);
1512         if (rc)
1513                 GOTO(out_ctxt, rc);
1514         rc = llog_init_handle(env, *llh, LLOG_F_IS_PLAIN, &cfg_uuid);
1515         if (rc)
1516                 llog_close(env, *llh);
1517 out_ctxt:
1518         llog_ctxt_put(ctxt);
1519 out:
1520         if (rc) {
1521                 CERROR("%s: can't start log %s: rc = %d\n",
1522                        mgs->mgs_obd->obd_name, name, rc);
1523                 *llh = NULL;
1524         }
1525         RETURN(rc);
1526 }
1527
1528 static int record_end_log(const struct lu_env *env, struct llog_handle **llh)
1529 {
1530         int rc;
1531
1532         rc = llog_close(env, *llh);
1533         *llh = NULL;
1534
1535         return rc;
1536 }
1537
1538 /******************** config "macros" *********************/
1539
1540 /* write an lcfg directly into a log (with markers) */
1541 static int mgs_write_log_direct(const struct lu_env *env,
1542                                 struct mgs_device *mgs, struct fs_db *fsdb,
1543                                 char *logname, struct llog_cfg_rec *lcr,
1544                                 char *devname, char *comment)
1545 {
1546         struct llog_handle *llh = NULL;
1547         int rc;
1548
1549         ENTRY;
1550
1551         rc = record_start_log(env, mgs, &llh, logname);
1552         if (rc)
1553                 RETURN(rc);
1554
1555         /* FIXME These should be a single journal transaction */
1556         rc = record_marker(env, llh, fsdb, CM_START, devname, comment);
1557         if (rc)
1558                 GOTO(out_end, rc);
1559         rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1560         if (rc)
1561                 GOTO(out_end, rc);
1562         rc = record_marker(env, llh, fsdb, CM_END, devname, comment);
1563         if (rc)
1564                 GOTO(out_end, rc);
1565 out_end:
1566         record_end_log(env, &llh);
1567         RETURN(rc);
1568 }
1569
1570 /* write the lcfg in all logs for the given fs */
1571 static int mgs_write_log_direct_all(const struct lu_env *env,
1572                                     struct mgs_device *mgs,
1573                                     struct fs_db *fsdb,
1574                                     struct mgs_target_info *mti,
1575                                     struct llog_cfg_rec *lcr, char *devname,
1576                                     char *comment, int server_only)
1577 {
1578         struct list_head         log_list;
1579         struct mgs_direntry     *dirent, *n;
1580         char                    *fsname = mti->mti_fsname;
1581         int                      rc = 0, len = strlen(fsname);
1582
1583         ENTRY;
1584         /* Find all the logs in the CONFIGS directory */
1585         rc = class_dentry_readdir(env, mgs, &log_list);
1586         if (rc)
1587                 RETURN(rc);
1588
1589         /* Could use fsdb index maps instead of directory listing */
1590         list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
1591                 list_del_init(&dirent->mde_list);
1592                 /* don't write to sptlrpc rule log */
1593                 if (strstr(dirent->mde_name, "-sptlrpc") != NULL)
1594                         goto next;
1595
1596                 /* caller wants write server logs only */
1597                 if (server_only && strstr(dirent->mde_name, "-client") != NULL)
1598                         goto next;
1599
1600                 if (strlen(dirent->mde_name) <= len ||
1601                     strncmp(fsname, dirent->mde_name, len) != 0 ||
1602                     dirent->mde_name[len] != '-')
1603                         goto next;
1604
1605                 CDEBUG(D_MGS, "Changing log %s\n", dirent->mde_name);
1606                 /* Erase any old settings of this same parameter */
1607                 rc = mgs_modify(env, mgs, fsdb, mti, dirent->mde_name,
1608                                 devname, comment, CM_SKIP);
1609                 if (rc < 0)
1610                         CERROR("%s: Can't modify llog %s: rc = %d\n",
1611                                mgs->mgs_obd->obd_name, dirent->mde_name, rc);
1612                 if (lcr == NULL)
1613                         goto next;
1614                 /* Write the new one */
1615                 rc = mgs_write_log_direct(env, mgs, fsdb, dirent->mde_name,
1616                                           lcr, devname, comment);
1617                 if (rc != 0)
1618                         CERROR("%s: writing log %s: rc = %d\n",
1619                                mgs->mgs_obd->obd_name, dirent->mde_name, rc);
1620 next:
1621                 mgs_direntry_free(dirent);
1622         }
1623
1624         RETURN(rc);
1625 }
1626
1627 static int mgs_write_log_osp_to_mdt(const struct lu_env *env,
1628                                     struct mgs_device *mgs,
1629                                     struct fs_db *fsdb,
1630                                     struct mgs_target_info *mti,
1631                                     int index, char *logname);
1632 static int mgs_write_log_osc_to_lov(const struct lu_env *env,
1633                                     struct mgs_device *mgs,
1634                                     struct fs_db *fsdb,
1635                                     struct mgs_target_info *mti,
1636                                     char *logname, char *suffix, char *lovname,
1637                                     enum lustre_sec_part sec_part, int flags);
1638 static int name_create_mdt_and_lov(char **logname, char **lovname,
1639                                    struct fs_db *fsdb, int i);
1640
1641 static int add_param(char *params, char *key, char *val)
1642 {
1643         char *start = params + strlen(params);
1644         char *end = params + sizeof(((struct mgs_target_info *)0)->mti_params);
1645         int keylen = 0;
1646
1647         if (key != NULL)
1648                 keylen = strlen(key);
1649         if (start + 1 + keylen + strlen(val) >= end) {
1650                 CERROR("params are too long: %s %s%s\n",
1651                        params, key != NULL ? key : "", val);
1652                 return -EINVAL;
1653         }
1654
1655         sprintf(start, " %s%s", key != NULL ? key : "", val);
1656         return 0;
1657 }
1658
1659 /**
1660  * Walk through client config log record and convert the related records
1661  * into the target.
1662  **/
1663 static int mgs_steal_client_llog_handler(const struct lu_env *env,
1664                                          struct llog_handle *llh,
1665                                          struct llog_rec_hdr *rec, void *data)
1666 {
1667         struct mgs_device *mgs;
1668         struct obd_device *obd;
1669         struct mgs_target_info *mti, *tmti;
1670         struct fs_db *fsdb;
1671         int cfg_len = rec->lrh_len;
1672         char *cfg_buf = (char*) (rec + 1);
1673         struct lustre_cfg *lcfg;
1674         int rc = 0;
1675         struct llog_handle *mdt_llh = NULL;
1676         static int got_an_osc_or_mdc = 0;
1677         /* 0: not found any osc/mdc;
1678            1: found osc;
1679            2: found mdc;
1680         */
1681         static int last_step = -1;
1682         int cplen = 0;
1683
1684         ENTRY;
1685
1686         mti = ((struct temp_comp*)data)->comp_mti;
1687         tmti = ((struct temp_comp*)data)->comp_tmti;
1688         fsdb = ((struct temp_comp*)data)->comp_fsdb;
1689         obd = ((struct temp_comp *)data)->comp_obd;
1690         mgs = lu2mgs_dev(obd->obd_lu_dev);
1691         LASSERT(mgs);
1692
1693         if (rec->lrh_type != OBD_CFG_REC) {
1694                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
1695                 RETURN(-EINVAL);
1696         }
1697
1698         rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
1699         if (rc) {
1700                 CERROR("Insane cfg\n");
1701                 RETURN(rc);
1702         }
1703
1704         lcfg = (struct lustre_cfg *)cfg_buf;
1705
1706         if (lcfg->lcfg_command == LCFG_MARKER) {
1707                 struct cfg_marker *marker;
1708                 marker = lustre_cfg_buf(lcfg, 1);
1709                 if (!strncmp(marker->cm_comment, "add osc", 7) &&
1710                     (marker->cm_flags & CM_START) &&
1711                      !(marker->cm_flags & CM_SKIP)) {
1712                         got_an_osc_or_mdc = 1;
1713                         cplen = strlcpy(tmti->mti_svname, marker->cm_tgtname,
1714                                         sizeof(tmti->mti_svname));
1715                         if (cplen >= sizeof(tmti->mti_svname))
1716                                 RETURN(-E2BIG);
1717                         rc = record_start_log(env, mgs, &mdt_llh,
1718                                               mti->mti_svname);
1719                         if (rc)
1720                                 RETURN(rc);
1721                         rc = record_marker(env, mdt_llh, fsdb, CM_START,
1722                                            mti->mti_svname, "add osc(copied)");
1723                         record_end_log(env, &mdt_llh);
1724                         last_step = marker->cm_step;
1725                         RETURN(rc);
1726                 }
1727                 if (!strncmp(marker->cm_comment, "add osc", 7) &&
1728                     (marker->cm_flags & CM_END) &&
1729                      !(marker->cm_flags & CM_SKIP)) {
1730                         LASSERT(last_step == marker->cm_step);
1731                         last_step = -1;
1732                         got_an_osc_or_mdc = 0;
1733                         memset(tmti, 0, sizeof(*tmti));
1734                         rc = record_start_log(env, mgs, &mdt_llh,
1735                                               mti->mti_svname);
1736                         if (rc)
1737                                 RETURN(rc);
1738                         rc = record_marker(env, mdt_llh, fsdb, CM_END,
1739                                            mti->mti_svname, "add osc(copied)");
1740                         record_end_log(env, &mdt_llh);
1741                         RETURN(rc);
1742                 }
1743                 if (!strncmp(marker->cm_comment, "add mdc", 7) &&
1744                     (marker->cm_flags & CM_START) &&
1745                      !(marker->cm_flags & CM_SKIP)) {
1746                         got_an_osc_or_mdc = 2;
1747                         last_step = marker->cm_step;
1748                         memcpy(tmti->mti_svname, marker->cm_tgtname,
1749                                strlen(marker->cm_tgtname));
1750
1751                         RETURN(rc);
1752                 }
1753                 if (!strncmp(marker->cm_comment, "add mdc", 7) &&
1754                     (marker->cm_flags & CM_END) &&
1755                      !(marker->cm_flags & CM_SKIP)) {
1756                         LASSERT(last_step == marker->cm_step);
1757                         last_step = -1;
1758                         got_an_osc_or_mdc = 0;
1759                         memset(tmti, 0, sizeof(*tmti));
1760                         RETURN(rc);
1761                 }
1762         }
1763
1764         if (got_an_osc_or_mdc == 0 || last_step < 0)
1765                 RETURN(rc);
1766
1767         if (lcfg->lcfg_command == LCFG_ADD_UUID) {
1768                 __u64 nodenid = lcfg->lcfg_nid;
1769
1770                 if (strlen(tmti->mti_uuid) == 0) {
1771                         /* target uuid not set, this config record is before
1772                          * LCFG_SETUP, this nid is one of target node nid.
1773                          */
1774                         tmti->mti_nids[tmti->mti_nid_count] = nodenid;
1775                         tmti->mti_nid_count++;
1776                 } else {
1777                         char nidstr[LNET_NIDSTR_SIZE];
1778
1779                         /* failover node nid */
1780                         libcfs_nid2str_r(nodenid, nidstr, sizeof(nidstr));
1781                         rc = add_param(tmti->mti_params, PARAM_FAILNODE,
1782                                         nidstr);
1783                 }
1784
1785                 RETURN(rc);
1786         }
1787
1788         if (lcfg->lcfg_command == LCFG_SETUP) {
1789                 char *target;
1790
1791                 target = lustre_cfg_string(lcfg, 1);
1792                 memcpy(tmti->mti_uuid, target, strlen(target));
1793                 RETURN(rc);
1794         }
1795
1796         /* ignore client side sptlrpc_conf_log */
1797         if (lcfg->lcfg_command == LCFG_SPTLRPC_CONF)
1798                 RETURN(rc);
1799
1800         if (lcfg->lcfg_command == LCFG_ADD_MDC) {
1801                 int index;
1802
1803                 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1)
1804                         RETURN (-EINVAL);
1805
1806                 memcpy(tmti->mti_fsname, mti->mti_fsname,
1807                        strlen(mti->mti_fsname));
1808                 tmti->mti_stripe_index = index;
1809
1810                 rc = mgs_write_log_osp_to_mdt(env, mgs, fsdb, tmti,
1811                                               mti->mti_stripe_index,
1812                                               mti->mti_svname);
1813                 memset(tmti, 0, sizeof(*tmti));
1814                 RETURN(rc);
1815         }
1816
1817         if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD) {
1818                 int index;
1819                 char mdt_index[9];
1820                 char *logname, *lovname;
1821
1822                 rc = name_create_mdt_and_lov(&logname, &lovname, fsdb,
1823                                              mti->mti_stripe_index);
1824                 if (rc)
1825                         RETURN(rc);
1826                 sprintf(mdt_index, "-MDT%04x", mti->mti_stripe_index);
1827
1828                 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1) {
1829                         name_destroy(&logname);
1830                         name_destroy(&lovname);
1831                         RETURN(-EINVAL);
1832                 }
1833
1834                 tmti->mti_stripe_index = index;
1835                 rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, tmti, logname,
1836                                          mdt_index, lovname,
1837                                          LUSTRE_SP_MDT, 0);
1838                 name_destroy(&logname);
1839                 name_destroy(&lovname);
1840                 RETURN(rc);
1841         }
1842         RETURN(rc);
1843 }
1844
1845 /* fsdb->fsdb_mutex is already held  in mgs_write_log_target*/
1846 /* stealed from mgs_get_fsdb_from_llog*/
1847 static int mgs_steal_llog_for_mdt_from_client(const struct lu_env *env,
1848                                               struct mgs_device *mgs,
1849                                               char *client_name,
1850                                               struct temp_comp* comp)
1851 {
1852         struct llog_handle *loghandle;
1853         struct mgs_target_info *tmti;
1854         struct llog_ctxt *ctxt;
1855         int rc;
1856
1857         ENTRY;
1858
1859         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
1860         LASSERT(ctxt != NULL);
1861
1862         OBD_ALLOC_PTR(tmti);
1863         if (tmti == NULL)
1864                 GOTO(out_ctxt, rc = -ENOMEM);
1865
1866         comp->comp_tmti = tmti;
1867         comp->comp_obd = mgs->mgs_obd;
1868
1869         rc = llog_open(env, ctxt, &loghandle, NULL, client_name,
1870                        LLOG_OPEN_EXISTS);
1871         if (rc < 0) {
1872                 if (rc == -ENOENT)
1873                         rc = 0;
1874                 GOTO(out_pop, rc);
1875         }
1876
1877         rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
1878         if (rc)
1879                 GOTO(out_close, rc);
1880
1881         rc = llog_process_or_fork(env, loghandle, mgs_steal_client_llog_handler,
1882                                   (void *)comp, NULL, false);
1883         CDEBUG(D_MGS, "steal llog re = %d\n", rc);
1884 out_close:
1885         llog_close(env, loghandle);
1886 out_pop:
1887         OBD_FREE_PTR(tmti);
1888 out_ctxt:
1889         llog_ctxt_put(ctxt);
1890         RETURN(rc);
1891 }
1892
1893 /* lmv is the second thing for client logs */
1894 /* copied from mgs_write_log_lov. Please refer to that.  */
1895 static int mgs_write_log_lmv(const struct lu_env *env,
1896                              struct mgs_device *mgs,
1897                              struct fs_db *fsdb,
1898                              struct mgs_target_info *mti,
1899                              char *logname, char *lmvname)
1900 {
1901         struct llog_handle *llh = NULL;
1902         struct lmv_desc *lmvdesc;
1903         char *uuid;
1904         int rc = 0;
1905         ENTRY;
1906
1907         CDEBUG(D_MGS, "Writing lmv(%s) log for %s\n", lmvname,logname);
1908
1909         OBD_ALLOC_PTR(lmvdesc);
1910         if (lmvdesc == NULL)
1911                 RETURN(-ENOMEM);
1912         lmvdesc->ld_active_tgt_count = 0;
1913         lmvdesc->ld_tgt_count = 0;
1914         sprintf((char*)lmvdesc->ld_uuid.uuid, "%s_UUID", lmvname);
1915         uuid = (char *)lmvdesc->ld_uuid.uuid;
1916
1917         rc = record_start_log(env, mgs, &llh, logname);
1918         if (rc)
1919                 GOTO(out_free, rc);
1920         rc = record_marker(env, llh, fsdb, CM_START, lmvname, "lmv setup");
1921         if (rc)
1922                 GOTO(out_end, rc);
1923         rc = record_attach(env, llh, lmvname, "lmv", uuid);
1924         if (rc)
1925                 GOTO(out_end, rc);
1926         rc = record_lmv_setup(env, llh, lmvname, lmvdesc);
1927         if (rc)
1928                 GOTO(out_end, rc);
1929         rc = record_marker(env, llh, fsdb, CM_END, lmvname, "lmv setup");
1930         if (rc)
1931                 GOTO(out_end, rc);
1932 out_end:
1933         record_end_log(env, &llh);
1934 out_free:
1935         OBD_FREE_PTR(lmvdesc);
1936         RETURN(rc);
1937 }
1938
1939 /* lov is the first thing in the mdt and client logs */
1940 static int mgs_write_log_lov(const struct lu_env *env, struct mgs_device *mgs,
1941                              struct fs_db *fsdb, struct mgs_target_info *mti,
1942                              char *logname, char *lovname)
1943 {
1944         struct llog_handle *llh = NULL;
1945         struct lov_desc *lovdesc;
1946         char *uuid;
1947         int rc = 0;
1948         ENTRY;
1949
1950         CDEBUG(D_MGS, "Writing lov(%s) log for %s\n", lovname, logname);
1951
1952         /*
1953         #01 L attach   0:lov_mdsA  1:lov  2:71ccb_lov_mdsA_19f961a9e1
1954         #02 L lov_setup 0:lov_mdsA 1:(struct lov_desc)
1955               uuid=lov1_UUID, stripe count=1, size=1048576, offset=0, pattern=0
1956         */
1957
1958         /* FIXME just make lov_setup accept empty desc (put uuid in buf 2) */
1959         OBD_ALLOC_PTR(lovdesc);
1960         if (lovdesc == NULL)
1961                 RETURN(-ENOMEM);
1962         lovdesc->ld_magic = LOV_DESC_MAGIC;
1963         lovdesc->ld_tgt_count = 0;
1964         /* Defaults.  Can be changed later by lcfg config_param */
1965         lovdesc->ld_default_stripe_count = 1;
1966         lovdesc->ld_pattern = LOV_PATTERN_RAID0;
1967         lovdesc->ld_default_stripe_size = LOV_DESC_STRIPE_SIZE_DEFAULT;
1968         lovdesc->ld_default_stripe_offset = -1;
1969         lovdesc->ld_qos_maxage = LOV_DESC_QOS_MAXAGE_DEFAULT;
1970         sprintf((char*)lovdesc->ld_uuid.uuid, "%s_UUID", lovname);
1971         /* can these be the same? */
1972         uuid = (char *)lovdesc->ld_uuid.uuid;
1973
1974         /* This should always be the first entry in a log.
1975         rc = mgs_clear_log(obd, logname); */
1976         rc = record_start_log(env, mgs, &llh, logname);
1977         if (rc)
1978                 GOTO(out_free, rc);
1979         /* FIXME these should be a single journal transaction */
1980         rc = record_marker(env, llh, fsdb, CM_START, lovname, "lov setup");
1981         if (rc)
1982                 GOTO(out_end, rc);
1983         rc = record_attach(env, llh, lovname, "lov", uuid);
1984         if (rc)
1985                 GOTO(out_end, rc);
1986         rc = record_lov_setup(env, llh, lovname, lovdesc);
1987         if (rc)
1988                 GOTO(out_end, rc);
1989         rc = record_marker(env, llh, fsdb, CM_END, lovname, "lov setup");
1990         if (rc)
1991                 GOTO(out_end, rc);
1992         EXIT;
1993 out_end:
1994         record_end_log(env, &llh);
1995 out_free:
1996         OBD_FREE_PTR(lovdesc);
1997         return rc;
1998 }
1999
2000 /* add failnids to open log */
2001 static int mgs_write_log_failnids(const struct lu_env *env,
2002                                   struct mgs_target_info *mti,
2003                                   struct llog_handle *llh,
2004                                   char *cliname)
2005 {
2006         char *failnodeuuid = NULL;
2007         char *ptr = mti->mti_params;
2008         lnet_nid_t nid;
2009         int rc = 0;
2010
2011         /*
2012         #03 L add_uuid  nid=uml1@tcp(0x20000c0a80201) nal=90 0:  1:uml1_UUID
2013         #04 L add_uuid  nid=1@elan(0x1000000000001)   nal=90 0:  1:uml1_UUID
2014         #05 L setup    0:OSC_uml1_ost1_mdsA  1:ost1_UUID  2:uml1_UUID
2015         #06 L add_uuid  nid=uml2@tcp(0x20000c0a80202) nal=90 0:  1:uml2_UUID
2016         #0x L add_uuid  nid=2@elan(0x1000000000002)   nal=90 0:  1:uml2_UUID
2017         #07 L add_conn 0:OSC_uml1_ost1_mdsA  1:uml2_UUID
2018         */
2019
2020         /*
2021          * Pull failnid info out of params string, which may contain something
2022          * like "<nid1>,<nid2>:<nid3>,<nid4>".  class_parse_nid() does not
2023          * complain about abnormal inputs like ",:<nid1>", "<nid1>:,<nid2>",
2024          * etc.  However, convert_hostnames() should have caught those.
2025          */
2026         while (class_find_param(ptr, PARAM_FAILNODE, &ptr) == 0) {
2027                 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
2028                         char nidstr[LNET_NIDSTR_SIZE];
2029
2030                         if (failnodeuuid == NULL) {
2031                                 /* We don't know the failover node name,
2032                                  * so just use the first nid as the uuid */
2033                                 libcfs_nid2str_r(nid, nidstr, sizeof(nidstr));
2034                                 rc = name_create(&failnodeuuid, nidstr, "");
2035                                 if (rc != 0)
2036                                         return rc;
2037                         }
2038                         CDEBUG(D_MGS, "add nid %s for failover uuid %s, "
2039                                 "client %s\n",
2040                                 libcfs_nid2str_r(nid, nidstr, sizeof(nidstr)),
2041                                 failnodeuuid, cliname);
2042                         rc = record_add_uuid(env, llh, nid, failnodeuuid);
2043                         /*
2044                          * If *ptr is ':', we have added all NIDs for
2045                          * failnodeuuid.
2046                          */
2047                         if (*ptr == ':') {
2048                                 rc = record_add_conn(env, llh, cliname,
2049                                                      failnodeuuid);
2050                                 name_destroy(&failnodeuuid);
2051                                 failnodeuuid = NULL;
2052                         }
2053                 }
2054                 if (failnodeuuid) {
2055                         rc = record_add_conn(env, llh, cliname, failnodeuuid);
2056                         name_destroy(&failnodeuuid);
2057                         failnodeuuid = NULL;
2058                 }
2059         }
2060
2061         return rc;
2062 }
2063
2064 static int mgs_write_log_mdc_to_lmv(const struct lu_env *env,
2065                                     struct mgs_device *mgs,
2066                                     struct fs_db *fsdb,
2067                                     struct mgs_target_info *mti,
2068                                     char *logname, char *lmvname)
2069 {
2070         struct llog_handle *llh = NULL;
2071         char *mdcname = NULL;
2072         char *nodeuuid = NULL;
2073         char *mdcuuid = NULL;
2074         char *lmvuuid = NULL;
2075         char index[6];
2076         char nidstr[LNET_NIDSTR_SIZE];
2077         int i, rc;
2078         ENTRY;
2079
2080         if (mgs_log_is_empty(env, mgs, logname)) {
2081                 CERROR("log is empty! Logical error\n");
2082                 RETURN(-EINVAL);
2083         }
2084
2085         CDEBUG(D_MGS, "adding mdc for %s to log %s:lmv(%s)\n",
2086                mti->mti_svname, logname, lmvname);
2087
2088         libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2089         rc = name_create(&nodeuuid, nidstr, "");
2090         if (rc)
2091                 RETURN(rc);
2092         rc = name_create(&mdcname, mti->mti_svname, "-mdc");
2093         if (rc)
2094                 GOTO(out_free, rc);
2095         rc = name_create(&mdcuuid, mdcname, "_UUID");
2096         if (rc)
2097                 GOTO(out_free, rc);
2098         rc = name_create(&lmvuuid, lmvname, "_UUID");
2099         if (rc)
2100                 GOTO(out_free, rc);
2101
2102         rc = record_start_log(env, mgs, &llh, logname);
2103         if (rc)
2104                 GOTO(out_free, rc);
2105         rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
2106                            "add mdc");
2107         if (rc)
2108                 GOTO(out_end, rc);
2109         for (i = 0; i < mti->mti_nid_count; i++) {
2110                 CDEBUG(D_MGS, "add nid %s for mdt\n",
2111                         libcfs_nid2str_r(mti->mti_nids[i],
2112                                          nidstr, sizeof(nidstr)));
2113
2114                 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2115                 if (rc)
2116                         GOTO(out_end, rc);
2117         }
2118
2119         rc = record_attach(env, llh, mdcname, LUSTRE_MDC_NAME, lmvuuid);
2120         if (rc)
2121                 GOTO(out_end, rc);
2122         rc = record_setup(env, llh, mdcname, mti->mti_uuid, nodeuuid,
2123                           NULL, NULL);
2124         if (rc)
2125                 GOTO(out_end, rc);
2126         rc = mgs_write_log_failnids(env, mti, llh, mdcname);
2127         if (rc)
2128                 GOTO(out_end, rc);
2129         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
2130         rc = record_mdc_add(env, llh, lmvname, mdcuuid, mti->mti_uuid,
2131                             index, "1");
2132         if (rc)
2133                 GOTO(out_end, rc);
2134         rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname,
2135                            "add mdc");
2136         if (rc)
2137                 GOTO(out_end, rc);
2138 out_end:
2139         record_end_log(env, &llh);
2140 out_free:
2141         name_destroy(&lmvuuid);
2142         name_destroy(&mdcuuid);
2143         name_destroy(&mdcname);
2144         name_destroy(&nodeuuid);
2145         RETURN(rc);
2146 }
2147
2148 static inline int name_create_lov(char **lovname, char *mdtname,
2149                                   struct fs_db *fsdb, int index)
2150 {
2151         /* COMPAT_180 */
2152         if (index == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2153                 return name_create(lovname, fsdb->fsdb_name, "-mdtlov");
2154         else
2155                 return name_create(lovname, mdtname, "-mdtlov");
2156 }
2157
2158 static int name_create_mdt_and_lov(char **logname, char **lovname,
2159                                    struct fs_db *fsdb, int i)
2160 {
2161         int rc;
2162
2163         rc = name_create_mdt(logname, fsdb->fsdb_name, i);
2164         if (rc)
2165                 return rc;
2166         /* COMPAT_180 */
2167         if (i == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2168                 rc = name_create(lovname, fsdb->fsdb_name, "-mdtlov");
2169         else
2170                 rc = name_create(lovname, *logname, "-mdtlov");
2171         if (rc) {
2172                 name_destroy(logname);
2173                 *logname = NULL;
2174         }
2175         return rc;
2176 }
2177
2178 static inline int name_create_mdt_osc(char **oscname, char *ostname,
2179                                       struct fs_db *fsdb, int i)
2180 {
2181         char suffix[16];
2182
2183         if (i == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2184                 sprintf(suffix, "-osc");
2185         else
2186                 sprintf(suffix, "-osc-MDT%04x", i);
2187         return name_create(oscname, ostname, suffix);
2188 }
2189
2190 /* add new mdc to already existent MDS */
2191 static int mgs_write_log_osp_to_mdt(const struct lu_env *env,
2192                                     struct mgs_device *mgs,
2193                                     struct fs_db *fsdb,
2194                                     struct mgs_target_info *mti,
2195                                     int mdt_index, char *logname)
2196 {
2197         struct llog_handle      *llh = NULL;
2198         char    *nodeuuid = NULL;
2199         char    *ospname = NULL;
2200         char    *lovuuid = NULL;
2201         char    *mdtuuid = NULL;
2202         char    *svname = NULL;
2203         char    *mdtname = NULL;
2204         char    *lovname = NULL;
2205         char    index_str[16];
2206         char    nidstr[LNET_NIDSTR_SIZE];
2207         int     i, rc;
2208
2209         ENTRY;
2210         if (mgs_log_is_empty(env, mgs, mti->mti_svname)) {
2211                 CERROR("log is empty! Logical error\n");
2212                 RETURN (-EINVAL);
2213         }
2214
2215         CDEBUG(D_MGS, "adding osp index %d to %s\n", mti->mti_stripe_index,
2216                logname);
2217
2218         rc = name_create_mdt(&mdtname, fsdb->fsdb_name, mti->mti_stripe_index);
2219         if (rc)
2220                 RETURN(rc);
2221
2222         libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2223         rc = name_create(&nodeuuid, nidstr, "");
2224         if (rc)
2225                 GOTO(out_destory, rc);
2226
2227         rc = name_create(&svname, mdtname, "-osp");
2228         if (rc)
2229                 GOTO(out_destory, rc);
2230
2231         sprintf(index_str, "-MDT%04x", mdt_index);
2232         rc = name_create(&ospname, svname, index_str);
2233         if (rc)
2234                 GOTO(out_destory, rc);
2235
2236         rc = name_create_lov(&lovname, logname, fsdb, mdt_index);
2237         if (rc)
2238                 GOTO(out_destory, rc);
2239
2240         rc = name_create(&lovuuid, lovname, "_UUID");
2241         if (rc)
2242                 GOTO(out_destory, rc);
2243
2244         rc = name_create(&mdtuuid, mdtname, "_UUID");
2245         if (rc)
2246                 GOTO(out_destory, rc);
2247
2248         rc = record_start_log(env, mgs, &llh, logname);
2249         if (rc)
2250                 GOTO(out_destory, rc);
2251
2252         rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
2253                            "add osp");
2254         if (rc)
2255                 GOTO(out_destory, rc);
2256
2257         for (i = 0; i < mti->mti_nid_count; i++) {
2258                 CDEBUG(D_MGS, "add nid %s for mdt\n",
2259                         libcfs_nid2str_r(mti->mti_nids[i],
2260                                          nidstr, sizeof(nidstr)));
2261                 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2262                 if (rc)
2263                         GOTO(out_end, rc);
2264         }
2265
2266         rc = record_attach(env, llh, ospname, LUSTRE_OSP_NAME, lovuuid);
2267         if (rc)
2268                 GOTO(out_end, rc);
2269
2270         rc = record_setup(env, llh, ospname, mti->mti_uuid, nodeuuid,
2271                           NULL, NULL);
2272         if (rc)
2273                 GOTO(out_end, rc);
2274
2275         rc = mgs_write_log_failnids(env, mti, llh, ospname);
2276         if (rc)
2277                 GOTO(out_end, rc);
2278
2279         /* Add mdc(osp) to lod */
2280         snprintf(index_str, sizeof(index_str), "%d", mti->mti_stripe_index);
2281         rc = record_base(env, llh, lovname, 0, LCFG_ADD_MDC, mti->mti_uuid,
2282                          index_str, "1", NULL);
2283         if (rc)
2284                 GOTO(out_end, rc);
2285
2286         rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname, "add osp");
2287         if (rc)
2288                 GOTO(out_end, rc);
2289
2290 out_end:
2291         record_end_log(env, &llh);
2292
2293 out_destory:
2294         name_destroy(&mdtuuid);
2295         name_destroy(&lovuuid);
2296         name_destroy(&lovname);
2297         name_destroy(&ospname);
2298         name_destroy(&svname);
2299         name_destroy(&nodeuuid);
2300         name_destroy(&mdtname);
2301         RETURN(rc);
2302 }
2303
2304 static int mgs_write_log_mdt0(const struct lu_env *env,
2305                               struct mgs_device *mgs,
2306                               struct fs_db *fsdb,
2307                               struct mgs_target_info *mti)
2308 {
2309         char *log = mti->mti_svname;
2310         struct llog_handle *llh = NULL;
2311         char *uuid, *lovname;
2312         char mdt_index[6];
2313         char *ptr = mti->mti_params;
2314         int rc = 0, failout = 0;
2315         ENTRY;
2316
2317         OBD_ALLOC(uuid, sizeof(struct obd_uuid));
2318         if (uuid == NULL)
2319                 RETURN(-ENOMEM);
2320
2321         if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
2322                 failout = (strncmp(ptr, "failout", 7) == 0);
2323
2324         rc = name_create(&lovname, log, "-mdtlov");
2325         if (rc)
2326                 GOTO(out_free, rc);
2327         if (mgs_log_is_empty(env, mgs, log)) {
2328                 rc = mgs_write_log_lov(env, mgs, fsdb, mti, log, lovname);
2329                 if (rc)
2330                         GOTO(out_lod, rc);
2331         }
2332
2333         sprintf(mdt_index, "%d", mti->mti_stripe_index);
2334
2335         rc = record_start_log(env, mgs, &llh, log);
2336         if (rc)
2337                 GOTO(out_lod, rc);
2338
2339         /* add MDT itself */
2340
2341         /* FIXME this whole fn should be a single journal transaction */
2342         sprintf(uuid, "%s_UUID", log);
2343         rc = record_marker(env, llh, fsdb, CM_START, log, "add mdt");
2344         if (rc)
2345                 GOTO(out_lod, rc);
2346         rc = record_attach(env, llh, log, LUSTRE_MDT_NAME, uuid);
2347         if (rc)
2348                 GOTO(out_end, rc);
2349         rc = record_mount_opt(env, llh, log, lovname, NULL);
2350         if (rc)
2351                 GOTO(out_end, rc);
2352         rc = record_setup(env, llh, log, uuid, mdt_index, lovname,
2353                         failout ? "n" : "f");
2354         if (rc)
2355                 GOTO(out_end, rc);
2356         rc = record_marker(env, llh, fsdb, CM_END, log, "add mdt");
2357         if (rc)
2358                 GOTO(out_end, rc);
2359 out_end:
2360         record_end_log(env, &llh);
2361 out_lod:
2362         name_destroy(&lovname);
2363 out_free:
2364         OBD_FREE(uuid, sizeof(struct obd_uuid));
2365         RETURN(rc);
2366 }
2367
2368 /* envelope method for all layers log */
2369 static int mgs_write_log_mdt(const struct lu_env *env,
2370                              struct mgs_device *mgs,
2371                              struct fs_db *fsdb,
2372                              struct mgs_target_info *mti)
2373 {
2374         struct mgs_thread_info *mgi = mgs_env_info(env);
2375         struct llog_handle *llh = NULL;
2376         char *cliname;
2377         int rc, i = 0;
2378         ENTRY;
2379
2380         CDEBUG(D_MGS, "writing new mdt %s\n", mti->mti_svname);
2381
2382         if (mti->mti_uuid[0] == '\0') {
2383                 /* Make up our own uuid */
2384                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
2385                          "%s_UUID", mti->mti_svname);
2386         }
2387
2388         /* add mdt */
2389         rc = mgs_write_log_mdt0(env, mgs, fsdb, mti);
2390         if (rc)
2391                 RETURN(rc);
2392         /* Append the mdt info to the client log */
2393         rc = name_create(&cliname, mti->mti_fsname, "-client");
2394         if (rc)
2395                 RETURN(rc);
2396
2397         if (mgs_log_is_empty(env, mgs, cliname)) {
2398                 /* Start client log */
2399                 rc = mgs_write_log_lov(env, mgs, fsdb, mti, cliname,
2400                                        fsdb->fsdb_clilov);
2401                 if (rc)
2402                         GOTO(out_free, rc);
2403                 rc = mgs_write_log_lmv(env, mgs, fsdb, mti, cliname,
2404                                        fsdb->fsdb_clilmv);
2405                 if (rc)
2406                         GOTO(out_free, rc);
2407         }
2408
2409         /*
2410         #09 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
2411         #10 L attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f
2412         #11 L setup    0:MDC_uml1_mdsA_MNT_client  1:mdsA_UUID  2:uml1_UUID
2413         #12 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
2414         #13 L add_conn 0:MDC_uml1_mdsA_MNT_client  1:uml2_UUID
2415         #14 L mount_option 0:  1:client  2:lov1  3:MDC_uml1_mdsA_MNT_client
2416         */
2417
2418         /* copy client info about lov/lmv */
2419         mgi->mgi_comp.comp_mti = mti;
2420         mgi->mgi_comp.comp_fsdb = fsdb;
2421
2422         rc = mgs_steal_llog_for_mdt_from_client(env, mgs, cliname,
2423                                                 &mgi->mgi_comp);
2424         if (rc)
2425                 GOTO(out_free, rc);
2426         rc = mgs_write_log_mdc_to_lmv(env, mgs, fsdb, mti, cliname,
2427                                       fsdb->fsdb_clilmv);
2428         if (rc)
2429                 GOTO(out_free, rc);
2430
2431         /* add mountopts */
2432         rc = record_start_log(env, mgs, &llh, cliname);
2433         if (rc)
2434                 GOTO(out_free, rc);
2435
2436         rc = record_marker(env, llh, fsdb, CM_START, cliname,
2437                            "mount opts");
2438         if (rc)
2439                 GOTO(out_end, rc);
2440         rc = record_mount_opt(env, llh, cliname, fsdb->fsdb_clilov,
2441                               fsdb->fsdb_clilmv);
2442         if (rc)
2443                 GOTO(out_end, rc);
2444         rc = record_marker(env, llh, fsdb, CM_END, cliname,
2445                            "mount opts");
2446
2447         if (rc)
2448                 GOTO(out_end, rc);
2449
2450         /* for_all_existing_mdt except current one */
2451         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
2452                 if (i !=  mti->mti_stripe_index &&
2453                     test_bit(i, fsdb->fsdb_mdt_index_map)) {
2454                         char *logname;
2455
2456                         rc = name_create_mdt(&logname, fsdb->fsdb_name, i);
2457                         if (rc)
2458                                 GOTO(out_end, rc);
2459
2460                         /* NB: If the log for the MDT is empty, it means
2461                          * the MDT is only added to the index
2462                          * map, and not being process yet, i.e. this
2463                          * is an unregistered MDT, see mgs_write_log_target().
2464                          * so we should skip it. Otherwise
2465                          *
2466                          * 1. MGS get register request for MDT1 and MDT2.
2467                          *
2468                          * 2. Then both MDT1 and MDT2 are added into
2469                          * fsdb_mdt_index_map. (see mgs_set_index()).
2470                          *
2471                          * 3. Then MDT1 get the lock of fsdb_mutex, then
2472                          * generate the config log, here, it will regard MDT2
2473                          * as an existent MDT, and generate "add osp" for
2474                          * lustre-MDT0001-osp-MDT0002. Note: at the moment
2475                          * MDT0002 config log is still empty, so it will
2476                          * add "add osp" even before "lov setup", which
2477                          * will definitly cause trouble.
2478                          *
2479                          * 4. MDT1 registeration finished, fsdb_mutex is
2480                          * released, then MDT2 get in, then in above
2481                          * mgs_steal_llog_for_mdt_from_client(), it will
2482                          * add another osp log for lustre-MDT0001-osp-MDT0002,
2483                          * which will cause another trouble.*/
2484                         if (!mgs_log_is_empty(env, mgs, logname))
2485                                 rc = mgs_write_log_osp_to_mdt(env, mgs, fsdb,
2486                                                               mti, i, logname);
2487
2488                         name_destroy(&logname);
2489                         if (rc)
2490                                 GOTO(out_end, rc);
2491                 }
2492         }
2493 out_end:
2494         record_end_log(env, &llh);
2495 out_free:
2496         name_destroy(&cliname);
2497         RETURN(rc);
2498 }
2499
2500 /* Add the ost info to the client/mdt lov */
2501 static int mgs_write_log_osc_to_lov(const struct lu_env *env,
2502                                     struct mgs_device *mgs, struct fs_db *fsdb,
2503                                     struct mgs_target_info *mti,
2504                                     char *logname, char *suffix, char *lovname,
2505                                     enum lustre_sec_part sec_part, int flags)
2506 {
2507         struct llog_handle *llh = NULL;
2508         char *nodeuuid = NULL;
2509         char *oscname = NULL;
2510         char *oscuuid = NULL;
2511         char *lovuuid = NULL;
2512         char *svname = NULL;
2513         char index[6];
2514         char nidstr[LNET_NIDSTR_SIZE];
2515         int i, rc;
2516         ENTRY;
2517
2518         CDEBUG(D_INFO, "adding osc for %s to log %s\n",
2519                 mti->mti_svname, logname);
2520
2521         if (mgs_log_is_empty(env, mgs, logname)) {
2522                 CERROR("log is empty! Logical error\n");
2523                 RETURN(-EINVAL);
2524         }
2525
2526         libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2527         rc = name_create(&nodeuuid, nidstr, "");
2528         if (rc)
2529                 RETURN(rc);
2530         rc = name_create(&svname, mti->mti_svname, "-osc");
2531         if (rc)
2532                 GOTO(out_free, rc);
2533
2534         /* for the system upgraded from old 1.8, keep using the old osc naming
2535          * style for mdt, see name_create_mdt_osc(). LU-1257 */
2536         if (test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2537                 rc = name_create(&oscname, svname, "");
2538         else
2539                 rc = name_create(&oscname, svname, suffix);
2540         if (rc)
2541                 GOTO(out_free, rc);
2542
2543         rc = name_create(&oscuuid, oscname, "_UUID");
2544         if (rc)
2545                 GOTO(out_free, rc);
2546         rc = name_create(&lovuuid, lovname, "_UUID");
2547         if (rc)
2548                 GOTO(out_free, rc);
2549
2550
2551         /*
2552         #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
2553         multihomed (#4)
2554         #04 L add_uuid  nid=1@elan(0x1000000000001)  nal=90 0:  1:uml1_UUID
2555         #04 L attach   0:OSC_uml1_ost1_MNT_client  1:osc  2:89070_lov1_a41dff51a
2556         #05 L setup    0:OSC_uml1_ost1_MNT_client  1:ost1_UUID  2:uml1_UUID
2557         failover (#6,7)
2558         #06 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
2559         #07 L add_conn 0:OSC_uml1_ost1_MNT_client  1:uml2_UUID
2560         #08 L lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1
2561         */
2562
2563         rc = record_start_log(env, mgs, &llh, logname);
2564         if (rc)
2565                 GOTO(out_free, rc);
2566
2567         /* FIXME these should be a single journal transaction */
2568         rc = record_marker(env, llh, fsdb, CM_START | flags, mti->mti_svname,
2569                            "add osc");
2570         if (rc)
2571                 GOTO(out_end, rc);
2572
2573         /* NB: don't change record order, because upon MDT steal OSC config
2574          * from client, it treats all nids before LCFG_SETUP as target nids
2575          * (multiple interfaces), while nids after as failover node nids.
2576          * See mgs_steal_client_llog_handler() LCFG_ADD_UUID.
2577          */
2578         for (i = 0; i < mti->mti_nid_count; i++) {
2579                 CDEBUG(D_MGS, "add nid %s\n",
2580                         libcfs_nid2str_r(mti->mti_nids[i],
2581                                          nidstr, sizeof(nidstr)));
2582                 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2583                 if (rc)
2584                         GOTO(out_end, rc);
2585         }
2586         rc = record_attach(env, llh, oscname, LUSTRE_OSC_NAME, lovuuid);
2587         if (rc)
2588                 GOTO(out_end, rc);
2589         rc = record_setup(env, llh, oscname, mti->mti_uuid, nodeuuid,
2590                           NULL, NULL);
2591         if (rc)
2592                 GOTO(out_end, rc);
2593         rc = mgs_write_log_failnids(env, mti, llh, oscname);
2594         if (rc)
2595                 GOTO(out_end, rc);
2596
2597         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
2598
2599         rc = record_lov_add(env, llh, lovname, mti->mti_uuid, index, "1");
2600         if (rc)
2601                 GOTO(out_end, rc);
2602         rc = record_marker(env, llh, fsdb, CM_END | flags, mti->mti_svname,
2603                            "add osc");
2604         if (rc)
2605                 GOTO(out_end, rc);
2606 out_end:
2607         record_end_log(env, &llh);
2608 out_free:
2609         name_destroy(&lovuuid);
2610         name_destroy(&oscuuid);
2611         name_destroy(&oscname);
2612         name_destroy(&svname);
2613         name_destroy(&nodeuuid);
2614         RETURN(rc);
2615 }
2616
2617 static int mgs_write_log_ost(const struct lu_env *env,
2618                              struct mgs_device *mgs, struct fs_db *fsdb,
2619                              struct mgs_target_info *mti)
2620 {
2621         struct llog_handle *llh = NULL;
2622         char *logname, *lovname;
2623         char *ptr = mti->mti_params;
2624         int rc, flags = 0, failout = 0, i;
2625         ENTRY;
2626
2627         CDEBUG(D_MGS, "writing new ost %s\n", mti->mti_svname);
2628
2629         /* The ost startup log */
2630
2631         /* If the ost log already exists, that means that someone reformatted
2632            the ost and it called target_add again. */
2633         if (!mgs_log_is_empty(env, mgs, mti->mti_svname)) {
2634                 LCONSOLE_ERROR_MSG(0x141, "The config log for %s already "
2635                                    "exists, yet the server claims it never "
2636                                    "registered. It may have been reformatted, "
2637                                    "or the index changed. writeconf the MDT to "
2638                                    "regenerate all logs.\n", mti->mti_svname);
2639                 RETURN(-EALREADY);
2640         }
2641
2642         /*
2643         attach obdfilter ost1 ost1_UUID
2644         setup /dev/loop2 ldiskfs f|n errors=remount-ro,user_xattr
2645         */
2646         if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
2647                 failout = (strncmp(ptr, "failout", 7) == 0);
2648         rc = record_start_log(env, mgs, &llh, mti->mti_svname);
2649         if (rc)
2650                 RETURN(rc);
2651         /* FIXME these should be a single journal transaction */
2652         rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,"add ost");
2653         if (rc)
2654                 GOTO(out_end, rc);
2655         if (*mti->mti_uuid == '\0')
2656                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
2657                          "%s_UUID", mti->mti_svname);
2658         rc = record_attach(env, llh, mti->mti_svname,
2659                            "obdfilter"/*LUSTRE_OST_NAME*/, mti->mti_uuid);
2660         if (rc)
2661                 GOTO(out_end, rc);
2662         rc = record_setup(env, llh, mti->mti_svname,
2663                           "dev"/*ignored*/, "type"/*ignored*/,
2664                           failout ? "n" : "f", NULL/*options*/);
2665         if (rc)
2666                 GOTO(out_end, rc);
2667         rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname, "add ost");
2668         if (rc)
2669                 GOTO(out_end, rc);
2670 out_end:
2671         record_end_log(env, &llh);
2672         if (rc)
2673                 RETURN(rc);
2674         /* We also have to update the other logs where this osc is part of
2675            the lov */
2676
2677         if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
2678                 /* If we're upgrading, the old mdt log already has our
2679                    entry. Let's do a fake one for fun. */
2680                 /* Note that we can't add any new failnids, since we don't
2681                    know the old osc names. */
2682                 flags = CM_SKIP | CM_UPGRADE146;
2683
2684         } else if ((mti->mti_flags & LDD_F_UPDATE) != LDD_F_UPDATE) {
2685                 /* If the update flag isn't set, don't update client/mdt
2686                    logs. */
2687                 flags |= CM_SKIP;
2688                 LCONSOLE_WARN("Client log for %s was not updated; writeconf "
2689                               "the MDT first to regenerate it.\n",
2690                               mti->mti_svname);
2691         }
2692
2693         /* Add ost to all MDT lov defs */
2694         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
2695                 if (test_bit(i, fsdb->fsdb_mdt_index_map)) {
2696                         char mdt_index[9];
2697
2698                         rc = name_create_mdt_and_lov(&logname, &lovname, fsdb,
2699                                                      i);
2700                         if (rc)
2701                                 RETURN(rc);
2702                         sprintf(mdt_index, "-MDT%04x", i);
2703                         rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, mti,
2704                                                       logname, mdt_index,
2705                                                       lovname, LUSTRE_SP_MDT,
2706                                                       flags);
2707                         name_destroy(&logname);
2708                         name_destroy(&lovname);
2709                         if (rc)
2710                                 RETURN(rc);
2711                 }
2712         }
2713
2714         /* Append ost info to the client log */
2715         rc = name_create(&logname, mti->mti_fsname, "-client");
2716         if (rc)
2717                 RETURN(rc);
2718         if (mgs_log_is_empty(env, mgs, logname)) {
2719                 /* Start client log */
2720                 rc = mgs_write_log_lov(env, mgs, fsdb, mti, logname,
2721                                        fsdb->fsdb_clilov);
2722                 if (rc)
2723                         GOTO(out_free, rc);
2724                 rc = mgs_write_log_lmv(env, mgs, fsdb, mti, logname,
2725                                        fsdb->fsdb_clilmv);
2726                 if (rc)
2727                         GOTO(out_free, rc);
2728         }
2729         rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, mti, logname, "",
2730                                       fsdb->fsdb_clilov, LUSTRE_SP_CLI, flags);
2731 out_free:
2732         name_destroy(&logname);
2733         RETURN(rc);
2734 }
2735
2736 static __inline__ int mgs_param_empty(char *ptr)
2737 {
2738         char *tmp;
2739
2740         if ((tmp = strchr(ptr, '=')) && (*(++tmp) == '\0'))
2741                 return 1;
2742         return 0;
2743 }
2744
2745 static int mgs_write_log_failnid_internal(const struct lu_env *env,
2746                                           struct mgs_device *mgs,
2747                                           struct fs_db *fsdb,
2748                                           struct mgs_target_info *mti,
2749                                           char *logname, char *cliname)
2750 {
2751         int rc;
2752         struct llog_handle *llh = NULL;
2753
2754         if (mgs_param_empty(mti->mti_params)) {
2755                 /* Remove _all_ failnids */
2756                 rc = mgs_modify(env, mgs, fsdb, mti, logname,
2757                                 mti->mti_svname, "add failnid", CM_SKIP);
2758                 return rc < 0 ? rc : 0;
2759         }
2760
2761         /* Otherwise failover nids are additive */
2762         rc = record_start_log(env, mgs, &llh, logname);
2763         if (rc)
2764                 return rc;
2765                 /* FIXME this should be a single journal transaction */
2766         rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
2767                            "add failnid");
2768         if (rc)
2769                 goto out_end;
2770         rc = mgs_write_log_failnids(env, mti, llh, cliname);
2771         if (rc)
2772                 goto out_end;
2773         rc = record_marker(env, llh, fsdb, CM_END,
2774                            mti->mti_svname, "add failnid");
2775 out_end:
2776         record_end_log(env, &llh);
2777         return rc;
2778 }
2779
2780
2781 /* Add additional failnids to an existing log.
2782    The mdc/osc must have been added to logs first */
2783 /* tcp nids must be in dotted-quad ascii -
2784    we can't resolve hostnames from the kernel. */
2785 static int mgs_write_log_add_failnid(const struct lu_env *env,
2786                                      struct mgs_device *mgs,
2787                                      struct fs_db *fsdb,
2788                                      struct mgs_target_info *mti)
2789 {
2790         char *logname, *cliname;
2791         int rc;
2792         ENTRY;
2793
2794         /* FIXME we currently can't erase the failnids
2795          * given when a target first registers, since they aren't part of
2796          * an "add uuid" stanza */
2797
2798         /* Verify that we know about this target */
2799         if (mgs_log_is_empty(env, mgs, mti->mti_svname)) {
2800                 LCONSOLE_ERROR_MSG(0x142, "The target %s has not registered "
2801                                    "yet. It must be started before failnids "
2802                                    "can be added.\n", mti->mti_svname);
2803                 RETURN(-ENOENT);
2804         }
2805
2806         /* Create mdc/osc client name (e.g. lustre-OST0001-osc) */
2807         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
2808                 rc = name_create(&cliname, mti->mti_svname, "-mdc");
2809         } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
2810                 rc = name_create(&cliname, mti->mti_svname, "-osc");
2811         } else {
2812                 RETURN(-EINVAL);
2813         }
2814         if (rc)
2815                 RETURN(rc);
2816         /* Add failover nids to the client log */
2817         rc = name_create(&logname, mti->mti_fsname, "-client");
2818         if (rc) {
2819                 name_destroy(&cliname);
2820                 RETURN(rc);
2821         }
2822         rc = mgs_write_log_failnid_internal(env, mgs, fsdb,mti,logname,cliname);
2823         name_destroy(&logname);
2824         name_destroy(&cliname);
2825         if (rc)
2826                 RETURN(rc);
2827
2828         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
2829                 /* Add OST failover nids to the MDT logs as well */
2830                 int i;
2831
2832                 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
2833                         if (!test_bit(i, fsdb->fsdb_mdt_index_map))
2834                                 continue;
2835                         rc = name_create_mdt(&logname, mti->mti_fsname, i);
2836                         if (rc)
2837                                 RETURN(rc);
2838                         rc = name_create_mdt_osc(&cliname, mti->mti_svname,
2839                                                  fsdb, i);
2840                         if (rc) {
2841                                 name_destroy(&logname);
2842                                 RETURN(rc);
2843                         }
2844                         rc = mgs_write_log_failnid_internal(env, mgs, fsdb,
2845                                                             mti, logname,
2846                                                             cliname);
2847                         name_destroy(&cliname);
2848                         name_destroy(&logname);
2849                         if (rc)
2850                                 RETURN(rc);
2851                 }
2852         }
2853
2854         RETURN(rc);
2855 }
2856
2857 static int mgs_wlp_lcfg(const struct lu_env *env,
2858                         struct mgs_device *mgs, struct fs_db *fsdb,
2859                         struct mgs_target_info *mti,
2860                         char *logname, struct lustre_cfg_bufs *bufs,
2861                         char *tgtname, char *ptr)
2862 {
2863         char comment[MTI_NAME_MAXLEN];
2864         char *tmp;
2865         struct llog_cfg_rec *lcr;
2866         int rc, del;
2867
2868         /* Erase any old settings of this same parameter */
2869         memcpy(comment, ptr, MTI_NAME_MAXLEN);
2870         comment[MTI_NAME_MAXLEN - 1] = 0;
2871         /* But don't try to match the value. */
2872         tmp = strchr(comment, '=');
2873         if (tmp != NULL)
2874                 *tmp = 0;
2875         /* FIXME we should skip settings that are the same as old values */
2876         rc = mgs_modify(env, mgs, fsdb, mti, logname, tgtname, comment,CM_SKIP);
2877         if (rc < 0)
2878                 return rc;
2879         del = mgs_param_empty(ptr);
2880
2881         LCONSOLE_INFO("%s parameter %s.%s in log %s\n", del ? "Disabling" : rc ?
2882                       "Setting" : "Modifying", tgtname, comment, logname);
2883         if (del) {
2884                 /* mgs_modify() will return 1 if nothing had to be done */
2885                 if (rc == 1)
2886                         rc = 0;
2887                 return rc;
2888         }
2889
2890         lustre_cfg_bufs_reset(bufs, tgtname);
2891         lustre_cfg_bufs_set_string(bufs, 1, ptr);
2892         if (mti->mti_flags & LDD_F_PARAM2)
2893                 lustre_cfg_bufs_set_string(bufs, 2, LCTL_UPCALL);
2894
2895         lcr = lustre_cfg_rec_new((mti->mti_flags & LDD_F_PARAM2) ?
2896                                  LCFG_SET_PARAM : LCFG_PARAM, bufs);
2897         if (lcr == NULL)
2898                 return -ENOMEM;
2899
2900         rc = mgs_write_log_direct(env, mgs, fsdb, logname, lcr, tgtname,
2901                                   comment);
2902         lustre_cfg_rec_free(lcr);
2903         return rc;
2904 }
2905
2906 static int mgs_write_log_param2(const struct lu_env *env,
2907                                 struct mgs_device *mgs,
2908                                 struct fs_db *fsdb,
2909                                 struct mgs_target_info *mti, char *ptr)
2910 {
2911         struct lustre_cfg_bufs  bufs;
2912         int                     rc = 0;
2913         ENTRY;
2914
2915         CDEBUG(D_MGS, "next param '%s'\n", ptr);
2916         rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, PARAMS_FILENAME, &bufs,
2917                           mti->mti_svname, ptr);
2918
2919         RETURN(rc);
2920 }
2921
2922 /* write global variable settings into log */
2923 static int mgs_write_log_sys(const struct lu_env *env,
2924                              struct mgs_device *mgs, struct fs_db *fsdb,
2925                              struct mgs_target_info *mti, char *sys, char *ptr)
2926 {
2927         struct mgs_thread_info  *mgi = mgs_env_info(env);
2928         struct lustre_cfg       *lcfg;
2929         struct llog_cfg_rec     *lcr;
2930         char *tmp, sep;
2931         int rc, cmd, convert = 1;
2932
2933         if (class_match_param(ptr, PARAM_TIMEOUT, &tmp) == 0) {
2934                 cmd = LCFG_SET_TIMEOUT;
2935         } else if (class_match_param(ptr, PARAM_LDLM_TIMEOUT, &tmp) == 0) {
2936                 cmd = LCFG_SET_LDLM_TIMEOUT;
2937         /* Check for known params here so we can return error to lctl */
2938         } else if ((class_match_param(ptr, PARAM_AT_MIN, &tmp) == 0) ||
2939                 (class_match_param(ptr, PARAM_AT_MAX, &tmp) == 0) ||
2940                 (class_match_param(ptr, PARAM_AT_EXTRA, &tmp) == 0) ||
2941                 (class_match_param(ptr, PARAM_AT_EARLY_MARGIN, &tmp) == 0) ||
2942                 (class_match_param(ptr, PARAM_AT_HISTORY, &tmp) == 0)) {
2943                 cmd = LCFG_PARAM;
2944         } else if (class_match_param(ptr, PARAM_JOBID_VAR, &tmp) == 0) {
2945                 convert = 0; /* Don't convert string value to integer */
2946                 cmd = LCFG_PARAM;
2947         } else {
2948                 return -EINVAL;
2949         }
2950
2951         if (mgs_param_empty(ptr))
2952                 CDEBUG(D_MGS, "global '%s' removed\n", sys);
2953         else
2954                 CDEBUG(D_MGS, "global '%s' val=%s\n", sys, tmp);
2955
2956         lustre_cfg_bufs_reset(&mgi->mgi_bufs, NULL);
2957         lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, sys);
2958         if (!convert && *tmp != '\0')
2959                 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 2, tmp);
2960         lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
2961         if (lcr == NULL)
2962                 return -ENOMEM;
2963
2964         lcfg = &lcr->lcr_cfg;
2965         lcfg->lcfg_num = convert ? simple_strtoul(tmp, NULL, 0) : 0;
2966         /* truncate the comment to the parameter name */
2967         ptr = tmp - 1;
2968         sep = *ptr;
2969         *ptr = '\0';
2970         /* modify all servers and clients */
2971         rc = mgs_write_log_direct_all(env, mgs, fsdb, mti,
2972                                       *tmp == '\0' ? NULL : lcr,
2973                                       mti->mti_fsname, sys, 0);
2974         if (rc == 0 && *tmp != '\0') {
2975                 switch (cmd) {
2976                 case LCFG_SET_TIMEOUT:
2977                         if (!obd_timeout_set || lcfg->lcfg_num > obd_timeout)
2978                                 class_process_config(lcfg);
2979                         break;
2980                 case LCFG_SET_LDLM_TIMEOUT:
2981                         if (!ldlm_timeout_set || lcfg->lcfg_num > ldlm_timeout)
2982                                 class_process_config(lcfg);
2983                         break;
2984                 default:
2985                         break;
2986                 }
2987         }
2988         *ptr = sep;
2989         lustre_cfg_rec_free(lcr);
2990         return rc;
2991 }
2992
2993 /* write quota settings into log */
2994 static int mgs_write_log_quota(const struct lu_env *env, struct mgs_device *mgs,
2995                                struct fs_db *fsdb, struct mgs_target_info *mti,
2996                                char *quota, char *ptr)
2997 {
2998         struct mgs_thread_info  *mgi = mgs_env_info(env);
2999         struct llog_cfg_rec     *lcr;
3000         char                    *tmp;
3001         char                     sep;
3002         int                      rc, cmd = LCFG_PARAM;
3003
3004         /* support only 'meta' and 'data' pools so far */
3005         if (class_match_param(ptr, QUOTA_METAPOOL_NAME, &tmp) != 0 &&
3006             class_match_param(ptr, QUOTA_DATAPOOL_NAME, &tmp) != 0) {
3007                 CERROR("parameter quota.%s isn't supported (only quota.mdt "
3008                        "& quota.ost are)\n", ptr);
3009                 return -EINVAL;
3010         }
3011
3012         if (*tmp == '\0') {
3013                 CDEBUG(D_MGS, "global '%s' removed\n", quota);
3014         } else {
3015                 CDEBUG(D_MGS, "global '%s'\n", quota);
3016
3017                 if (strchr(tmp, 'u') == NULL && strchr(tmp, 'g') == NULL &&
3018                     strcmp(tmp, "none") != 0) {
3019                         CERROR("enable option(%s) isn't supported\n", tmp);
3020                         return -EINVAL;
3021                 }
3022         }
3023
3024         lustre_cfg_bufs_reset(&mgi->mgi_bufs, mti->mti_fsname);
3025         lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, quota);
3026         lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
3027         if (lcr == NULL)
3028                 return -ENOMEM;
3029
3030         /* truncate the comment to the parameter name */
3031         ptr = tmp - 1;
3032         sep = *ptr;
3033         *ptr = '\0';
3034
3035         /* XXX we duplicated quota enable information in all server
3036          *     config logs, it should be moved to a separate config
3037          *     log once we cleanup the config log for global param. */
3038         /* modify all servers */
3039         rc = mgs_write_log_direct_all(env, mgs, fsdb, mti,
3040                                       *tmp == '\0' ? NULL : lcr,
3041                                       mti->mti_fsname, quota, 1);
3042         *ptr = sep;
3043         lustre_cfg_rec_free(lcr);
3044         return rc < 0 ? rc : 0;
3045 }
3046
3047 static int mgs_srpc_set_param_disk(const struct lu_env *env,
3048                                    struct mgs_device *mgs,
3049                                    struct fs_db *fsdb,
3050                                    struct mgs_target_info *mti,
3051                                    char *param)
3052 {
3053         struct mgs_thread_info  *mgi = mgs_env_info(env);
3054         struct llog_cfg_rec     *lcr;
3055         struct llog_handle      *llh = NULL;
3056         char                    *logname;
3057         char                    *comment, *ptr;
3058         int                      rc, len;
3059
3060         ENTRY;
3061
3062         /* get comment */
3063         ptr = strchr(param, '=');
3064         LASSERT(ptr != NULL);
3065         len = ptr - param;
3066
3067         OBD_ALLOC(comment, len + 1);
3068         if (comment == NULL)
3069                 RETURN(-ENOMEM);
3070         strncpy(comment, param, len);
3071         comment[len] = '\0';
3072
3073         /* prepare lcfg */
3074         lustre_cfg_bufs_reset(&mgi->mgi_bufs, mti->mti_svname);
3075         lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, param);
3076         lcr = lustre_cfg_rec_new(LCFG_SPTLRPC_CONF, &mgi->mgi_bufs);
3077         if (lcr == NULL)
3078                 GOTO(out_comment, rc = -ENOMEM);
3079
3080         /* construct log name */
3081         rc = name_create(&logname, mti->mti_fsname, "-sptlrpc");
3082         if (rc < 0)
3083                 GOTO(out_lcfg, rc);
3084
3085         if (mgs_log_is_empty(env, mgs, logname)) {
3086                 rc = record_start_log(env, mgs, &llh, logname);
3087                 if (rc < 0)
3088                         GOTO(out, rc);
3089                 record_end_log(env, &llh);
3090         }
3091
3092         /* obsolete old one */
3093         rc = mgs_modify(env, mgs, fsdb, mti, logname, mti->mti_svname,
3094                         comment, CM_SKIP);
3095         if (rc < 0)
3096                 GOTO(out, rc);
3097         /* write the new one */
3098         rc = mgs_write_log_direct(env, mgs, fsdb, logname, lcr,
3099                                   mti->mti_svname, comment);
3100         if (rc)
3101                 CERROR("%s: error writing log %s: rc = %d\n",
3102                        mgs->mgs_obd->obd_name, logname, rc);
3103 out:
3104         name_destroy(&logname);
3105 out_lcfg:
3106         lustre_cfg_rec_free(lcr);
3107 out_comment:
3108         OBD_FREE(comment, len + 1);
3109         RETURN(rc);
3110 }
3111
3112 static int mgs_srpc_set_param_udesc_mem(struct fs_db *fsdb,
3113                                         char *param)
3114 {
3115         char    *ptr;
3116
3117         /* disable the adjustable udesc parameter for now, i.e. use default
3118          * setting that client always ship udesc to MDT if possible. to enable
3119          * it simply remove the following line */
3120         goto error_out;
3121
3122         ptr = strchr(param, '=');
3123         if (ptr == NULL)
3124                 goto error_out;
3125         *ptr++ = '\0';
3126
3127         if (strcmp(param, PARAM_SRPC_UDESC))
3128                 goto error_out;
3129
3130         if (strcmp(ptr, "yes") == 0) {
3131                 set_bit(FSDB_UDESC, &fsdb->fsdb_flags);
3132                 CWARN("Enable user descriptor shipping from client to MDT\n");
3133         } else if (strcmp(ptr, "no") == 0) {
3134                 clear_bit(FSDB_UDESC, &fsdb->fsdb_flags);
3135                 CWARN("Disable user descriptor shipping from client to MDT\n");
3136         } else {
3137                 *(ptr - 1) = '=';
3138                 goto error_out;
3139         }
3140         return 0;
3141
3142 error_out:
3143         CERROR("Invalid param: %s\n", param);
3144         return -EINVAL;
3145 }
3146
3147 static int mgs_srpc_set_param_mem(struct fs_db *fsdb,
3148                                   const char *svname,
3149                                   char *param)
3150 {
3151         struct sptlrpc_rule      rule;
3152         struct sptlrpc_rule_set *rset;
3153         int                      rc;
3154         ENTRY;
3155
3156         if (strncmp(param, PARAM_SRPC, sizeof(PARAM_SRPC) - 1) != 0) {
3157                 CERROR("Invalid sptlrpc parameter: %s\n", param);
3158                 RETURN(-EINVAL);
3159         }
3160
3161         if (strncmp(param, PARAM_SRPC_UDESC,
3162                     sizeof(PARAM_SRPC_UDESC) - 1) == 0) {
3163                 RETURN(mgs_srpc_set_param_udesc_mem(fsdb, param));
3164         }
3165
3166         if (strncmp(param, PARAM_SRPC_FLVR, sizeof(PARAM_SRPC_FLVR) - 1) != 0) {
3167                 CERROR("Invalid sptlrpc flavor parameter: %s\n", param);
3168                 RETURN(-EINVAL);
3169         }
3170
3171         param += sizeof(PARAM_SRPC_FLVR) - 1;
3172
3173         rc = sptlrpc_parse_rule(param, &rule);
3174         if (rc)
3175                 RETURN(rc);
3176
3177         /* mgs rules implies must be mgc->mgs */
3178         if (test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
3179                 if ((rule.sr_from != LUSTRE_SP_MGC &&
3180                      rule.sr_from != LUSTRE_SP_ANY) ||
3181                     (rule.sr_to != LUSTRE_SP_MGS &&
3182                      rule.sr_to != LUSTRE_SP_ANY))
3183                         RETURN(-EINVAL);
3184         }
3185
3186         /* preapre room for this coming rule. svcname format should be:
3187          * - fsname: general rule
3188          * - fsname-tgtname: target-specific rule
3189          */
3190         if (strchr(svname, '-')) {
3191                 struct mgs_tgt_srpc_conf *tgtconf;
3192                 int                       found = 0;
3193
3194                 for (tgtconf = fsdb->fsdb_srpc_tgt; tgtconf != NULL;
3195                      tgtconf = tgtconf->mtsc_next) {
3196                         if (!strcmp(tgtconf->mtsc_tgt, svname)) {
3197                                 found = 1;
3198                                 break;
3199                         }
3200                 }
3201
3202                 if (!found) {
3203                         int name_len;
3204
3205                         OBD_ALLOC_PTR(tgtconf);
3206                         if (tgtconf == NULL)
3207                                 RETURN(-ENOMEM);
3208
3209                         name_len = strlen(svname);
3210
3211                         OBD_ALLOC(tgtconf->mtsc_tgt, name_len + 1);
3212                         if (tgtconf->mtsc_tgt == NULL) {
3213                                 OBD_FREE_PTR(tgtconf);
3214                                 RETURN(-ENOMEM);
3215                         }
3216                         memcpy(tgtconf->mtsc_tgt, svname, name_len);
3217
3218                         tgtconf->mtsc_next = fsdb->fsdb_srpc_tgt;
3219                         fsdb->fsdb_srpc_tgt = tgtconf;
3220                 }
3221
3222                 rset = &tgtconf->mtsc_rset;
3223         } else if (strcmp(svname, MGSSELF_NAME) == 0) {
3224                 /* put _mgs related srpc rule directly in mgs ruleset */
3225                 rset = &fsdb->fsdb_mgs->mgs_lut.lut_sptlrpc_rset;
3226         } else {
3227                 rset = &fsdb->fsdb_srpc_gen;
3228         }
3229
3230         rc = sptlrpc_rule_set_merge(rset, &rule);
3231
3232         RETURN(rc);
3233 }
3234
3235 static int mgs_srpc_set_param(const struct lu_env *env,
3236                               struct mgs_device *mgs,
3237                               struct fs_db *fsdb,
3238                               struct mgs_target_info *mti,
3239                               char *param)
3240 {
3241         char                   *copy;
3242         int                     rc, copy_size;
3243         ENTRY;
3244
3245 #ifndef HAVE_GSS
3246         RETURN(-EINVAL);
3247 #endif
3248         /* keep a copy of original param, which could be destroied
3249          * during parsing */
3250         copy_size = strlen(param) + 1;
3251         OBD_ALLOC(copy, copy_size);
3252         if (copy == NULL)
3253                 return -ENOMEM;
3254         memcpy(copy, param, copy_size);
3255
3256         rc = mgs_srpc_set_param_mem(fsdb, mti->mti_svname, param);
3257         if (rc)
3258                 goto out_free;
3259
3260         /* previous steps guaranteed the syntax is correct */
3261         rc = mgs_srpc_set_param_disk(env, mgs, fsdb, mti, copy);
3262         if (rc)
3263                 goto out_free;
3264
3265         if (test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
3266                 /*
3267                  * for mgs rules, make them effective immediately.
3268                  */
3269                 LASSERT(fsdb->fsdb_srpc_tgt == NULL);
3270                 sptlrpc_target_update_exp_flavor(mgs->mgs_obd,
3271                                                  &fsdb->fsdb_srpc_gen);
3272         }
3273
3274 out_free:
3275         OBD_FREE(copy, copy_size);
3276         RETURN(rc);
3277 }
3278
3279 struct mgs_srpc_read_data {
3280         struct fs_db   *msrd_fsdb;
3281         int             msrd_skip;
3282 };
3283
3284 static int mgs_srpc_read_handler(const struct lu_env *env,
3285                                  struct llog_handle *llh,
3286                                  struct llog_rec_hdr *rec, void *data)
3287 {
3288         struct mgs_srpc_read_data *msrd = data;
3289         struct cfg_marker         *marker;
3290         struct lustre_cfg         *lcfg = REC_DATA(rec);
3291         char                      *svname, *param;
3292         int                        cfg_len, rc;
3293         ENTRY;
3294
3295         if (rec->lrh_type != OBD_CFG_REC) {
3296                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
3297                 RETURN(-EINVAL);
3298         }
3299
3300         cfg_len = REC_DATA_LEN(rec);
3301
3302         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
3303         if (rc) {
3304                 CERROR("Insane cfg\n");
3305                 RETURN(rc);
3306         }
3307
3308         if (lcfg->lcfg_command == LCFG_MARKER) {
3309                 marker = lustre_cfg_buf(lcfg, 1);
3310
3311                 if (marker->cm_flags & CM_START &&
3312                     marker->cm_flags & CM_SKIP)
3313                         msrd->msrd_skip = 1;
3314                 if (marker->cm_flags & CM_END)
3315                         msrd->msrd_skip = 0;
3316
3317                 RETURN(0);
3318         }
3319
3320         if (msrd->msrd_skip)
3321                 RETURN(0);
3322
3323         if (lcfg->lcfg_command != LCFG_SPTLRPC_CONF) {
3324                 CERROR("invalid command (%x)\n", lcfg->lcfg_command);
3325                 RETURN(0);
3326         }
3327
3328         svname = lustre_cfg_string(lcfg, 0);
3329         if (svname == NULL) {
3330                 CERROR("svname is empty\n");
3331                 RETURN(0);
3332         }
3333
3334         param = lustre_cfg_string(lcfg, 1);
3335         if (param == NULL) {
3336                 CERROR("param is empty\n");
3337                 RETURN(0);
3338         }
3339
3340         rc = mgs_srpc_set_param_mem(msrd->msrd_fsdb, svname, param);
3341         if (rc)
3342                 CERROR("read sptlrpc record error (%d): %s\n", rc, param);
3343
3344         RETURN(0);
3345 }
3346
3347 int mgs_get_fsdb_srpc_from_llog(const struct lu_env *env,
3348                                 struct mgs_device *mgs,
3349                                 struct fs_db *fsdb)
3350 {
3351         struct llog_handle        *llh = NULL;
3352         struct llog_ctxt          *ctxt;
3353         char                      *logname;
3354         struct mgs_srpc_read_data  msrd;
3355         int                        rc;
3356         ENTRY;
3357
3358         /* construct log name */
3359         rc = name_create(&logname, fsdb->fsdb_name, "-sptlrpc");
3360         if (rc)
3361                 RETURN(rc);
3362
3363         ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
3364         LASSERT(ctxt != NULL);
3365
3366         if (mgs_log_is_empty(env, mgs, logname))
3367                 GOTO(out, rc = 0);
3368
3369         rc = llog_open(env, ctxt, &llh, NULL, logname,
3370                        LLOG_OPEN_EXISTS);
3371         if (rc < 0) {
3372                 if (rc == -ENOENT)
3373                         rc = 0;
3374                 GOTO(out, rc);
3375         }
3376
3377         rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL);
3378         if (rc)
3379                 GOTO(out_close, rc);
3380
3381         if (llog_get_size(llh) <= 1)
3382                 GOTO(out_close, rc = 0);
3383
3384         msrd.msrd_fsdb = fsdb;
3385         msrd.msrd_skip = 0;
3386
3387         rc = llog_process(env, llh, mgs_srpc_read_handler, (void *)&msrd,
3388                           NULL);
3389
3390 out_close:
3391         llog_close(env, llh);
3392 out:
3393         llog_ctxt_put(ctxt);
3394         name_destroy(&logname);
3395
3396         if (rc)
3397                 CERROR("failed to read sptlrpc config database: %d\n", rc);
3398         RETURN(rc);
3399 }
3400
3401 /* Permanent settings of all parameters by writing into the appropriate
3402  * configuration logs.
3403  * A parameter with null value ("<param>='\0'") means to erase it out of
3404  * the logs.
3405  */
3406 static int mgs_write_log_param(const struct lu_env *env,
3407                                struct mgs_device *mgs, struct fs_db *fsdb,
3408                                struct mgs_target_info *mti, char *ptr)
3409 {
3410         struct mgs_thread_info *mgi = mgs_env_info(env);
3411         char *logname;
3412         char *tmp;
3413         int rc = 0;
3414         ENTRY;
3415
3416         /* For various parameter settings, we have to figure out which logs
3417            care about them (e.g. both mdt and client for lov settings) */
3418         CDEBUG(D_MGS, "next param '%s'\n", ptr);
3419
3420         /* The params are stored in MOUNT_DATA_FILE and modified via
3421            tunefs.lustre, or set using lctl conf_param */
3422
3423         /* Processed in lustre_start_mgc */
3424         if (class_match_param(ptr, PARAM_MGSNODE, NULL) == 0)
3425                 GOTO(end, rc);
3426
3427         /* Processed in ost/mdt */
3428         if (class_match_param(ptr, PARAM_NETWORK, NULL) == 0)
3429                 GOTO(end, rc);
3430
3431         /* Processed in mgs_write_log_ost */
3432         if (class_match_param(ptr, PARAM_FAILMODE, NULL) == 0) {
3433                 if (mti->mti_flags & LDD_F_PARAM) {
3434                         LCONSOLE_ERROR_MSG(0x169, "%s can only be "
3435                                            "changed with tunefs.lustre"
3436                                            "and --writeconf\n", ptr);
3437                         rc = -EPERM;
3438                 }
3439                 GOTO(end, rc);
3440         }
3441
3442         if (class_match_param(ptr, PARAM_SRPC, NULL) == 0) {
3443                 rc = mgs_srpc_set_param(env, mgs, fsdb, mti, ptr);
3444                 GOTO(end, rc);
3445         }
3446
3447         if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
3448                 /* Add a failover nidlist */
3449                 rc = 0;
3450                 /* We already processed failovers params for new
3451                    targets in mgs_write_log_target */
3452                 if (mti->mti_flags & LDD_F_PARAM) {
3453                         CDEBUG(D_MGS, "Adding failnode\n");
3454                         rc = mgs_write_log_add_failnid(env, mgs, fsdb, mti);
3455                 }
3456                 GOTO(end, rc);
3457         }
3458
3459         if (class_match_param(ptr, PARAM_SYS, &tmp) == 0) {
3460                 rc = mgs_write_log_sys(env, mgs, fsdb, mti, ptr, tmp);
3461                 GOTO(end, rc);
3462         }
3463
3464         if (class_match_param(ptr, PARAM_QUOTA, &tmp) == 0) {
3465                 rc = mgs_write_log_quota(env, mgs, fsdb, mti, ptr, tmp);
3466                 GOTO(end, rc);
3467         }
3468
3469         if (class_match_param(ptr, PARAM_OSC PARAM_ACTIVE, &tmp) == 0 ||
3470             class_match_param(ptr, PARAM_MDC PARAM_ACTIVE, &tmp) == 0) {
3471                 /* active=0 means off, anything else means on */
3472                 int flag = (*tmp == '0') ? CM_EXCLUDE : 0;
3473                 bool deactive_osc = memcmp(ptr, PARAM_OSC PARAM_ACTIVE,
3474                                           strlen(PARAM_OSC PARAM_ACTIVE)) == 0;
3475                 int i;
3476
3477                 if (!deactive_osc) {
3478                         __u32   index;
3479
3480                         rc = server_name2index(mti->mti_svname, &index, NULL);
3481                         if (rc < 0)
3482                                 GOTO(end, rc);
3483
3484                         if (index == 0) {
3485                                 LCONSOLE_ERROR_MSG(0x144, "%s: MDC0 can not be"
3486                                                    " (de)activated.\n",
3487                                                    mti->mti_svname);
3488                                 GOTO(end, rc = -EPERM);
3489                         }
3490                 }
3491
3492                 LCONSOLE_WARN("Permanently %sactivating %s\n",
3493                               flag ? "de" : "re", mti->mti_svname);
3494                 /* Modify clilov */
3495                 rc = name_create(&logname, mti->mti_fsname, "-client");
3496                 if (rc < 0)
3497                         GOTO(end, rc);
3498                 rc = mgs_modify(env, mgs, fsdb, mti, logname,
3499                                 mti->mti_svname,
3500                                 deactive_osc ? "add osc" : "add mdc", flag);
3501                 name_destroy(&logname);
3502                 if (rc < 0)
3503                         goto active_err;
3504
3505                 /* Modify mdtlov */
3506                 /* Add to all MDT logs for DNE */
3507                 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
3508                         if (!test_bit(i, fsdb->fsdb_mdt_index_map))
3509                                 continue;
3510                         rc = name_create_mdt(&logname, mti->mti_fsname, i);
3511                         if (rc < 0)
3512                                 GOTO(end, rc);
3513                         rc = mgs_modify(env, mgs, fsdb, mti, logname,
3514                                         mti->mti_svname,
3515                                         deactive_osc ? "add osc" : "add osp",
3516                                         flag);
3517                         name_destroy(&logname);
3518                         if (rc < 0)
3519                                 goto active_err;
3520                 }
3521 active_err:
3522                 if (rc < 0) {
3523                         LCONSOLE_ERROR_MSG(0x145, "Couldn't find %s in"
3524                                            "log (%d). No permanent "
3525                                            "changes were made to the "
3526                                            "config log.\n",
3527                                            mti->mti_svname, rc);
3528                         if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags))
3529                                 LCONSOLE_ERROR_MSG(0x146, "This may be"
3530                                                    " because the log"
3531                                                    "is in the old 1.4"
3532                                                    "style. Consider "
3533                                                    " --writeconf to "
3534                                                    "update the logs.\n");
3535                         GOTO(end, rc);
3536                 }
3537                 /* Fall through to osc/mdc proc for deactivating live
3538                    OSC/OSP on running MDT / clients. */
3539         }
3540         /* Below here, let obd's XXX_process_config methods handle it */
3541
3542         /* All lov. in proc */
3543         if (class_match_param(ptr, PARAM_LOV, NULL) == 0) {
3544                 char *mdtlovname;
3545
3546                 CDEBUG(D_MGS, "lov param %s\n", ptr);
3547                 if (!(mti->mti_flags & LDD_F_SV_TYPE_MDT)) {
3548                         LCONSOLE_ERROR_MSG(0x147, "LOV params must be "
3549                                            "set on the MDT, not %s. "
3550                                            "Ignoring.\n",
3551                                            mti->mti_svname);
3552                         GOTO(end, rc = 0);
3553                 }
3554
3555                 /* Modify mdtlov */
3556                 if (mgs_log_is_empty(env, mgs, mti->mti_svname))
3557                         GOTO(end, rc = -ENODEV);
3558
3559                 rc = name_create_mdt_and_lov(&logname, &mdtlovname, fsdb,
3560                                              mti->mti_stripe_index);
3561                 if (rc)
3562                         GOTO(end, rc);
3563                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, mti->mti_svname,
3564                                   &mgi->mgi_bufs, mdtlovname, ptr);
3565                 name_destroy(&logname);
3566                 name_destroy(&mdtlovname);
3567                 if (rc)
3568                         GOTO(end, rc);
3569
3570                 /* Modify clilov */
3571                 rc = name_create(&logname, mti->mti_fsname, "-client");
3572                 if (rc)
3573                         GOTO(end, rc);
3574                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname, &mgi->mgi_bufs,
3575                                   fsdb->fsdb_clilov, ptr);
3576                 name_destroy(&logname);
3577                 GOTO(end, rc);
3578         }
3579
3580         /* All osc., mdc., llite. params in proc */
3581         if ((class_match_param(ptr, PARAM_OSC, NULL) == 0) ||
3582             (class_match_param(ptr, PARAM_MDC, NULL) == 0) ||
3583             (class_match_param(ptr, PARAM_LLITE, NULL) == 0)) {
3584                 char *cname;
3585
3586                 if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
3587                         LCONSOLE_ERROR_MSG(0x148, "Upgraded client logs for %s"
3588                                            " cannot be modified. Consider"
3589                                            " updating the configuration with"
3590                                            " --writeconf\n",
3591                                            mti->mti_svname);
3592                         GOTO(end, rc = -EINVAL);
3593                 }
3594                 if (memcmp(ptr, PARAM_LLITE, strlen(PARAM_LLITE)) == 0) {
3595                         rc = name_create(&cname, mti->mti_fsname, "-client");
3596                         /* Add the client type to match the obdname in
3597                            class_config_llog_handler */
3598                 } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
3599                         rc = name_create(&cname, mti->mti_svname, "-mdc");
3600                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
3601                         rc = name_create(&cname, mti->mti_svname, "-osc");
3602                 } else {
3603                         GOTO(end, rc = -EINVAL);
3604                 }
3605                 if (rc)
3606                         GOTO(end, rc);
3607
3608                 /* Forbid direct update of llite root squash parameters.
3609                  * These parameters are indirectly set via the MDT settings.
3610                  * See (LU-1778) */
3611                 if ((class_match_param(ptr, PARAM_LLITE, &tmp) == 0) &&
3612                     ((memcmp(tmp, "root_squash=", 12) == 0) ||
3613                      (memcmp(tmp, "nosquash_nids=", 14) == 0))) {
3614                         LCONSOLE_ERROR("%s: root squash parameters can only "
3615                                 "be updated through MDT component\n",
3616                                 mti->mti_fsname);
3617                         name_destroy(&cname);
3618                         GOTO(end, rc = -EINVAL);
3619                 }
3620
3621                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
3622
3623                 /* Modify client */
3624                 rc = name_create(&logname, mti->mti_fsname, "-client");
3625                 if (rc) {
3626                         name_destroy(&cname);
3627                         GOTO(end, rc);
3628                 }
3629                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname, &mgi->mgi_bufs,
3630                                   cname, ptr);
3631
3632                 /* osc params affect the MDT as well */
3633                 if (!rc && (mti->mti_flags & LDD_F_SV_TYPE_OST)) {
3634                         int i;
3635
3636                         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
3637                                 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
3638                                         continue;
3639                                 name_destroy(&cname);
3640                                 rc = name_create_mdt_osc(&cname, mti->mti_svname,
3641                                                          fsdb, i);
3642                                 name_destroy(&logname);
3643                                 if (rc)
3644                                         break;
3645                                 rc = name_create_mdt(&logname,
3646                                                      mti->mti_fsname, i);
3647                                 if (rc)
3648                                         break;
3649                                 if (!mgs_log_is_empty(env, mgs, logname)) {
3650                                         rc = mgs_wlp_lcfg(env, mgs, fsdb,
3651                                                           mti, logname,
3652                                                           &mgi->mgi_bufs,
3653                                                           cname, ptr);
3654                                         if (rc)
3655                                                 break;
3656                                 }
3657                         }
3658                 }
3659
3660                 /* For mdc activate/deactivate, it affects OSP on MDT as well */
3661                 if (class_match_param(ptr, PARAM_MDC PARAM_ACTIVE, &tmp) == 0 &&
3662                     rc == 0) {
3663                         char suffix[16];
3664                         char *lodname = NULL;
3665                         char *param_str = NULL;
3666                         int i;
3667                         int index;
3668
3669                         /* replace mdc with osp */
3670                         memcpy(ptr, PARAM_OSP, strlen(PARAM_OSP));
3671                         rc = server_name2index(mti->mti_svname, &index, NULL);
3672                         if (rc < 0) {
3673                                 memcpy(ptr, PARAM_MDC, strlen(PARAM_MDC));
3674                                 GOTO(end, rc);
3675                         }
3676
3677                         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
3678                                 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
3679                                         continue;
3680
3681                                 if (i == index)
3682                                         continue;
3683
3684                                 name_destroy(&logname);
3685                                 rc = name_create_mdt(&logname, mti->mti_fsname,
3686                                                      i);
3687                                 if (rc < 0)
3688                                         break;
3689
3690                                 if (mgs_log_is_empty(env, mgs, logname))
3691                                         continue;
3692
3693                                 snprintf(suffix, sizeof(suffix), "-osp-MDT%04x",
3694                                          i);
3695                                 name_destroy(&cname);
3696                                 rc = name_create(&cname, mti->mti_svname,
3697                                                  suffix);
3698                                 if (rc < 0)
3699                                         break;
3700
3701                                 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,