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