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