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