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