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