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