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