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