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