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