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