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