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