Whamcloud - gitweb
b=20689
[fs/lustre-release.git] / lustre / mgs / mgs_llog.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/mgs/mgs_llog.c
37  *
38  * Lustre Management Server (mgs) config llog creation
39  *
40  * Author: Nathan Rutman <nathan@clusterfs.com>
41  */
42
43 #ifndef EXPORT_SYMTAB
44 #define EXPORT_SYMTAB
45 #endif
46 #define DEBUG_SUBSYSTEM S_MGS
47 #define D_MGS D_CONFIG /*|D_WARNING*/
48
49 #ifdef __KERNEL__
50 #include <linux/module.h>
51 #include <linux/pagemap.h>
52 #include <linux/fs.h>
53 #endif
54
55 #include <obd.h>
56 #include <obd_lov.h>
57 #include <obd_class.h>
58 #include <lustre_log.h>
59 #include <obd_ost.h>
60 #include <libcfs/list.h>
61 #include <linux/lvfs.h>
62 #include <lustre_fsfilt.h>
63 #include <lustre_disk.h>
64 #include <lustre_param.h>
65 #include <lustre_sec.h>
66 #include "mgs_internal.h"
67
68 /********************** Class functions ********************/
69
70 /* Caller must list_del and OBD_FREE each dentry from the list */
71 int class_dentry_readdir(struct obd_device *obd, struct dentry *dir,
72                                 struct vfsmount *inmnt,
73                                 struct list_head *dentry_list){
74         /* see mds_cleanup_pending */
75         struct lvfs_run_ctxt saved;
76         struct file *file;
77         struct dentry *dentry;
78         struct vfsmount *mnt;
79         int rc = 0;
80         ENTRY;
81
82         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
83         dentry = dget(dir);
84         if (IS_ERR(dentry))
85                 GOTO(out_pop, rc = PTR_ERR(dentry));
86         mnt = mntget(inmnt);
87         if (IS_ERR(mnt)) {
88                 l_dput(dentry);
89                 GOTO(out_pop, rc = PTR_ERR(mnt));
90         }
91
92         file = dentry_open(dentry, mnt, O_RDONLY);
93         if (IS_ERR(file))
94                 /* dentry_open_it() drops the dentry, mnt refs */
95                 GOTO(out_pop, rc = PTR_ERR(file));
96
97         CFS_INIT_LIST_HEAD(dentry_list);
98         rc = l_readdir(file, dentry_list);
99         filp_close(file, 0);
100         /*  filp_close->fput() drops the dentry, mnt refs */
101
102 out_pop:
103         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
104         RETURN(rc);
105 }
106
107 /******************** DB functions *********************/
108
109 static inline int name_create(char **newname, char *prefix, char *suffix)
110 {
111         LASSERT(newname);
112         OBD_ALLOC(*newname, strlen(prefix) + strlen(suffix) + 1);
113         if (!*newname)
114                 return -ENOMEM;
115         sprintf(*newname, "%s%s", prefix, suffix);
116         return 0;
117 }
118
119 static inline void name_destroy(char **name)
120 {
121         if (*name)
122                 OBD_FREE(*name, strlen(*name) + 1);
123         *name = NULL;
124 }
125
126 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                 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                 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         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         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         struct list_head *tmp;
331
332         list_for_each(tmp, &mgs->mgs_fs_db_list) {
333                 fsdb = 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         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         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         down(&fsdb->fsdb_sem);
407         lproc_mgs_del_live(obd, fsdb);
408         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         struct list_head *tmp, *tmp2;
434         down(&mgs->mgs_sem);
435         list_for_each_safe(tmp, tmp2, &mgs->mgs_fs_db_list) {
436                 fsdb = list_entry(tmp, struct fs_db, fsdb_list);
437                 mgs_free_fsdb(obd, fsdb);
438         }
439         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         down(&mgs->mgs_sem);
451         fsdb = mgs_find_fsdb(obd, name);
452         if (fsdb) {
453                 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         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 (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 (!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 (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         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         struct list_head 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         list_for_each_entry_safe(dirent, n, &dentry_list, lld_list) {
1031                 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 /* envelope method for all layers log */
1527 static int mgs_write_log_mdt(struct obd_device *obd, struct fs_db *fsdb,
1528                               struct mgs_target_info *mti)
1529 {
1530         struct llog_handle *llh = NULL;
1531         char *cliname;
1532         struct temp_comp comp = { 0 };
1533         int rc, i = 0;
1534         ENTRY;
1535
1536         CDEBUG(D_MGS, "writing new mdt %s\n", mti->mti_svname);
1537
1538 #if 0
1539         /* COMPAT_146 */
1540         if (mti->mti_flags & LDD_F_UPGRADE14) {
1541                 /* We're starting with an old uuid.  Assume old name for lov
1542                    as well since the lov entry already exists in the log. */
1543                 CDEBUG(D_MGS, "old mds uuid %s\n", mti->mti_uuid);
1544                 if (strncmp(mti->mti_uuid, fsdb->fsdb_mdtlov + 4,
1545                             strlen(fsdb->fsdb_mdtlov) - 4) != 0) {
1546                         CERROR("old mds uuid %s doesn't match log %s (%s)\n",
1547                                mti->mti_uuid, fsdb->fsdb_mdtlov,
1548                                fsdb->fsdb_mdtlov + 4);
1549                         RETURN(-EINVAL);
1550                 }
1551         }
1552         /* end COMPAT_146 */
1553 #endif
1554         if (mti->mti_uuid[0] == '\0') {
1555                 /* Make up our own uuid */
1556                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
1557                          "%s_UUID", mti->mti_svname);
1558         }
1559
1560         /* add mdt */
1561         rc = mgs_write_log_mdt0(obd, fsdb, mti);
1562
1563         /* Append the mdt info to the client log */
1564         name_create(&cliname, mti->mti_fsname, "-client");
1565
1566         if (mgs_log_is_empty(obd, cliname)) {
1567                 /* Start client log */
1568                 rc = mgs_write_log_lov(obd, fsdb, mti, cliname,
1569                                        fsdb->fsdb_clilov);
1570                 rc = mgs_write_log_lmv(obd, fsdb, mti, cliname,
1571                                        fsdb->fsdb_clilmv);
1572         }
1573
1574         /*
1575         #09 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
1576         #10 L attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f
1577         #11 L setup    0:MDC_uml1_mdsA_MNT_client  1:mdsA_UUID  2:uml1_UUID
1578         #12 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
1579         #13 L add_conn 0:MDC_uml1_mdsA_MNT_client  1:uml2_UUID
1580         #14 L mount_option 0:  1:client  2:lov1  3:MDC_uml1_mdsA_MNT_client
1581         */
1582
1583 #if 0
1584         /* COMPAT_146 */
1585         if (mti->mti_flags & LDD_F_UPGRADE14) {
1586                 rc = record_start_log(obd, &llh, cliname);
1587                 if (rc)
1588                         GOTO(out, rc);
1589
1590                 rc = record_marker(obd, llh, fsdb, CM_START,
1591                                    mti->mti_svname,"add mdc");
1592
1593                 /* Old client log already has MDC entry, but needs mount opt
1594                    for new client name (lustre-client) */
1595                 /* FIXME Old MDT log already has an old mount opt
1596                    which we should remove (currently handled by
1597                    class_del_profiles()) */
1598                 rc = record_mount_opt(obd, llh, cliname, fsdb->fsdb_clilov,
1599                                       fsdb->fsdb_mdc);
1600                 /* end COMPAT_146 */
1601
1602                 rc = record_marker(obd, llh, fsdb, CM_END,
1603                                    mti->mti_svname, "add mdc");
1604         } else
1605 #endif
1606         {
1607                 /* copy client info about lov/lmv */
1608                 comp.comp_mti = mti;
1609                 comp.comp_fsdb = fsdb;
1610
1611                 rc = mgs_steal_llog_for_mdt_from_client(obd, cliname,
1612                                                         &comp);
1613
1614                 rc = mgs_write_log_mdc_to_lmv(obd, fsdb, mti, cliname,
1615                                               fsdb->fsdb_clilmv);
1616                 /* add mountopts */
1617                 rc = record_start_log(obd, &llh, cliname);
1618                 if (rc)
1619                         GOTO(out, rc);
1620
1621                 rc = record_marker(obd, llh, fsdb, CM_START, cliname,
1622                                    "mount opts");
1623                 rc = record_mount_opt(obd, llh, cliname, fsdb->fsdb_clilov,
1624                                       fsdb->fsdb_clilmv);
1625                 rc = record_marker(obd, llh, fsdb, CM_END, cliname,
1626                                    "mount opts");
1627         }
1628
1629         rc = record_end_log(obd, &llh);
1630 out:
1631         name_destroy(&cliname);
1632
1633         // for_all_existing_mdt except current one
1634         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
1635                 char *mdtname;
1636                 if (i !=  mti->mti_stripe_index &&
1637                     test_bit(i,  fsdb->fsdb_mdt_index_map)) {
1638                         name_create_mdt(&mdtname, mti->mti_fsname, i);
1639                         rc = mgs_write_log_mdc_to_mdt(obd, fsdb, mti, mdtname);
1640                         name_destroy(&mdtname);
1641                 }
1642         }
1643
1644         RETURN(rc);
1645 }
1646
1647 /* Add the ost info to the client/mdt lov */
1648 static int mgs_write_log_osc_to_lov(struct obd_device *obd, struct fs_db *fsdb,
1649                                     struct mgs_target_info *mti,
1650                                     char *logname, char *suffix, char *lovname,
1651                                     enum lustre_sec_part sec_part, int flags)
1652 {
1653         struct llog_handle *llh = NULL;
1654         char *nodeuuid, *oscname, *oscuuid, *lovuuid, *svname;
1655         char index[5];
1656         int i, rc;
1657
1658         ENTRY;
1659         CDEBUG(D_INFO, "adding osc for %s to log %s\n",
1660                mti->mti_svname, logname);
1661
1662         if (mgs_log_is_empty(obd, logname)) {
1663                 /* The first item in the log must be the lov, so we have
1664                    somewhere to add our osc. */
1665                 rc = mgs_write_log_lov(obd, fsdb, mti, logname, lovname);
1666         }
1667
1668         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
1669         name_create(&svname, mti->mti_svname, "-osc");
1670         name_create(&oscname, svname, suffix);
1671         name_create(&oscuuid, oscname, "_UUID");
1672         name_create(&lovuuid, lovname, "_UUID");
1673
1674         /*
1675         #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
1676         multihomed (#4)
1677         #04 L add_uuid  nid=1@elan(0x1000000000001)  nal=90 0:  1:uml1_UUID
1678         #04 L attach   0:OSC_uml1_ost1_MNT_client  1:osc  2:89070_lov1_a41dff51a
1679         #05 L setup    0:OSC_uml1_ost1_MNT_client  1:ost1_UUID  2:uml1_UUID
1680         failover (#6,7)
1681         #06 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
1682         #07 L add_conn 0:OSC_uml1_ost1_MNT_client  1:uml2_UUID
1683         #08 L lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1
1684         */
1685
1686         rc = record_start_log(obd, &llh, logname);
1687         if (rc)
1688                 GOTO(out, rc);
1689         /* FIXME these should be a single journal transaction */
1690         rc = record_marker(obd, llh, fsdb, CM_START | flags, mti->mti_svname,
1691                            "add osc");
1692         for (i = 0; i < mti->mti_nid_count; i++) {
1693                 CDEBUG(D_MGS, "add nid %s\n", libcfs_nid2str(mti->mti_nids[i]));
1694                 rc = record_add_uuid(obd, llh, mti->mti_nids[i], nodeuuid);
1695         }
1696         rc = record_attach(obd, llh, oscname, LUSTRE_OSC_NAME, lovuuid);
1697         rc = record_setup(obd, llh, oscname, mti->mti_uuid, nodeuuid, 0, 0);
1698         rc = mgs_write_log_failnids(obd, mti, llh, oscname);
1699         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
1700         rc = record_lov_add(obd, llh, lovname, mti->mti_uuid, index, "1");
1701         rc = record_marker(obd, llh, fsdb, CM_END | flags, mti->mti_svname,
1702                            "add osc");
1703         rc = record_end_log(obd, &llh);
1704 out:
1705         name_destroy(&lovuuid);
1706         name_destroy(&oscuuid);
1707         name_destroy(&oscname);
1708         name_destroy(&svname);
1709         name_destroy(&nodeuuid);
1710         RETURN(rc);
1711 }
1712
1713 static int mgs_write_log_ost(struct obd_device *obd, struct fs_db *fsdb,
1714                              struct mgs_target_info *mti)
1715 {
1716         struct llog_handle *llh = NULL;
1717         char *logname, *lovname;
1718         char *ptr = mti->mti_params;
1719         int rc, flags = 0, failout = 0, i;
1720         ENTRY;
1721
1722         CDEBUG(D_MGS, "writing new ost %s\n", mti->mti_svname);
1723
1724         /* The ost startup log */
1725
1726         /* If the ost log already exists, that means that someone reformatted
1727            the ost and it called target_add again. */
1728         if (!mgs_log_is_empty(obd, mti->mti_svname)) {
1729                 LCONSOLE_ERROR_MSG(0x141, "The config log for %s already "
1730                                    "exists, yet the server claims it never "
1731                                    "registered. It may have been reformatted, "
1732                                    "or the index changed. writeconf the MDT to "
1733                                    "regenerate all logs.\n", mti->mti_svname);
1734                 RETURN(-EALREADY);
1735         }
1736
1737         /*
1738         attach obdfilter ost1 ost1_UUID
1739         setup /dev/loop2 ldiskfs f|n errors=remount-ro,user_xattr
1740         */
1741         if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
1742                 failout = (strncmp(ptr, "failout", 7) == 0);
1743         rc = record_start_log(obd, &llh, mti->mti_svname);
1744         if (rc)
1745                 RETURN(rc);
1746         /* FIXME these should be a single journal transaction */
1747         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,"add ost");
1748         if (*mti->mti_uuid == '\0')
1749                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
1750                          "%s_UUID", mti->mti_svname);
1751         rc = record_attach(obd, llh, mti->mti_svname,
1752                            "obdfilter"/*LUSTRE_OST_NAME*/, mti->mti_uuid);
1753         rc = record_setup(obd, llh, mti->mti_svname,
1754                           "dev"/*ignored*/, "type"/*ignored*/,
1755                           failout ? "n" : "f", 0/*options*/);
1756         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname, "add ost");
1757         rc = record_end_log(obd, &llh);
1758
1759         /* We also have to update the other logs where this osc is part of
1760            the lov */
1761
1762         if (fsdb->fsdb_flags & FSDB_OLDLOG14) {
1763                 /* If we're upgrading, the old mdt log already has our
1764                    entry. Let's do a fake one for fun. */
1765                 /* Note that we can't add any new failnids, since we don't
1766                    know the old osc names. */
1767                 flags = CM_SKIP | CM_UPGRADE146;
1768
1769         } else if ((mti->mti_flags & LDD_F_UPDATE) != LDD_F_UPDATE) {
1770                 /* If the update flag isn't set, don't update client/mdt
1771                    logs. */
1772                 flags |= CM_SKIP;
1773                 LCONSOLE_WARN("Client log for %s was not updated; writeconf "
1774                               "the MDT first to regenerate it.\n",
1775                               mti->mti_svname);
1776         }
1777
1778         /* Add ost to all MDT lov defs */
1779         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
1780                 if (test_bit(i, fsdb->fsdb_mdt_index_map)) {
1781                         char mdt_index[9];
1782
1783                         name_create_mdt_and_lov(&logname, &lovname, fsdb, i);
1784                         sprintf(mdt_index, "-MDT%04x", i);
1785                         mgs_write_log_osc_to_lov(obd, fsdb, mti, logname,
1786                                                  mdt_index, lovname,
1787                                                  LUSTRE_SP_MDT, flags);
1788                         name_destroy(&logname);
1789                         name_destroy(&lovname);
1790                 }
1791         }
1792
1793         /* Append ost info to the client log */
1794         name_create(&logname, mti->mti_fsname, "-client");
1795         mgs_write_log_osc_to_lov(obd, fsdb, mti, logname, "",
1796                                  fsdb->fsdb_clilov, LUSTRE_SP_CLI, 0);
1797         name_destroy(&logname);
1798         RETURN(rc);
1799 }
1800
1801 /* Add additional failnids to an existing log.
1802    The mdc/osc must have been added to logs first */
1803 /* tcp nids must be in dotted-quad ascii -
1804    we can't resolve hostnames from the kernel. */
1805 static int mgs_write_log_add_failnid(struct obd_device *obd, struct fs_db *fsdb,
1806                                      struct mgs_target_info *mti)
1807 {
1808         char *logname, *cliname;
1809         struct llog_handle *llh = NULL;
1810         int rc;
1811         ENTRY;
1812
1813         /* FIXME how do we delete a failnid? Currently --writeconf is the
1814            only way.  Maybe make --erase-params pass a flag to really
1815            erase all params from logs - except it can't erase the failnids
1816            given when a target first registers, since they aren't processed
1817            as params... */
1818
1819         /* Verify that we know about this target */
1820         if (mgs_log_is_empty(obd, mti->mti_svname)) {
1821                 LCONSOLE_ERROR_MSG(0x142, "The target %s has not registered "
1822                                    "yet. It must be started before failnids "
1823                                    "can be added.\n", mti->mti_svname);
1824                 RETURN(-ENOENT);
1825         }
1826
1827         /* Create mdc/osc client name (e.g. lustre-OST0001-osc) */
1828         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
1829                 name_create(&cliname, mti->mti_svname, "-mdc");
1830         } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1831                 name_create(&cliname, mti->mti_svname, "-osc");
1832         } else {
1833                 RETURN(-EINVAL);
1834         }
1835
1836         /* Add failover nids to client log */
1837         name_create(&logname, mti->mti_fsname, "-client");
1838         rc = record_start_log(obd, &llh, logname);
1839         if (!rc) {
1840                 /* FIXME this fn should be a single journal transaction */
1841                 rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,
1842                                    "add failnid");
1843                 rc = mgs_write_log_failnids(obd, mti, llh, cliname);
1844                 rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname,
1845                                    "add failnid");
1846                 rc = record_end_log(obd, &llh);
1847         }
1848         name_destroy(&logname);
1849
1850         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1851                 /* Add OST failover nids to the MDT log as well */
1852                 name_create(&logname, mti->mti_fsname, "-MDT0000");
1853                 rc = record_start_log(obd, &llh, logname);
1854                 if (!rc) {
1855                         rc = record_marker(obd, llh, fsdb, CM_START,
1856                                            mti->mti_svname, "add failnid");
1857                         rc = mgs_write_log_failnids(obd, mti, llh, cliname);
1858                         rc = record_marker(obd, llh, fsdb, CM_END,
1859                                            mti->mti_svname, "add failnid");
1860                         rc = record_end_log(obd, &llh);
1861                 }
1862                 name_destroy(&logname);
1863         }
1864
1865         name_destroy(&cliname);
1866         RETURN(rc);
1867 }
1868
1869 static int mgs_wlp_lcfg(struct obd_device *obd, struct fs_db *fsdb,
1870                         struct mgs_target_info *mti,
1871                         char *logname, struct lustre_cfg_bufs *bufs,
1872                         char *tgtname, char *ptr)
1873 {
1874         char comment[MTI_NAME_MAXLEN];
1875         char *tmp;
1876         struct lustre_cfg *lcfg;
1877         int rc;
1878
1879         /* Erase any old settings of this same parameter */
1880         memcpy(comment, ptr, MTI_NAME_MAXLEN);
1881         comment[MTI_NAME_MAXLEN - 1] = 0;
1882         /* But don't try to match the value. */
1883         if ((tmp = strchr(comment, '=')))
1884             *tmp = 0;
1885         /* FIXME we should skip settings that are the same as old values */
1886         rc = mgs_modify(obd, fsdb, mti, logname, tgtname, comment, CM_SKIP);
1887         LCONSOLE_INFO("%sing parameter %s.%s in log %s\n", rc ?
1888                       "Sett" : "Modify", tgtname, comment, logname);
1889
1890         lustre_cfg_bufs_reset(bufs, tgtname);
1891         lustre_cfg_bufs_set_string(bufs, 1, ptr);
1892         lcfg = lustre_cfg_new(LCFG_PARAM, bufs);
1893         if (!lcfg)
1894                 return -ENOMEM;
1895         rc = mgs_write_log_direct(obd, fsdb, logname, lcfg, tgtname, comment);
1896         lustre_cfg_free(lcfg);
1897         return rc;
1898 }
1899
1900 /* write global variable settings into log */
1901 static int mgs_write_log_sys(struct obd_device *obd, struct fs_db *fsdb,
1902                              struct mgs_target_info *mti, char *sys, char *ptr)
1903 {
1904         struct lustre_cfg_bufs bufs;
1905         struct lustre_cfg *lcfg;
1906         char *tmp;
1907         int cmd, val;
1908         int rc;
1909
1910         if (class_match_param(ptr, PARAM_TIMEOUT, &tmp) == 0)
1911                 cmd = LCFG_SET_TIMEOUT;
1912         else if (class_match_param(ptr, PARAM_LDLM_TIMEOUT, &tmp) == 0)
1913                 cmd = LCFG_SET_LDLM_TIMEOUT;
1914         /* Check for known params here so we can return error to lctl */
1915         else if ((class_match_param(ptr, PARAM_AT_MIN, &tmp) == 0)
1916                  || (class_match_param(ptr, PARAM_AT_MAX, &tmp) == 0)
1917                  || (class_match_param(ptr, PARAM_AT_EXTRA, &tmp) == 0)
1918                  || (class_match_param(ptr, PARAM_AT_EARLY_MARGIN, &tmp) == 0)
1919                  || (class_match_param(ptr, PARAM_AT_HISTORY, &tmp) == 0))
1920                 cmd = LCFG_PARAM;
1921         else
1922                 return -EINVAL;
1923
1924         val = simple_strtoul(tmp, NULL, 0);
1925         CDEBUG(D_MGS, "global %s = %d\n", ptr, val);
1926
1927         lustre_cfg_bufs_reset(&bufs, NULL);
1928         lustre_cfg_bufs_set_string(&bufs, 1, sys);
1929         lcfg = lustre_cfg_new(cmd, &bufs);
1930         lcfg->lcfg_num = val;
1931         /* modify all servers and clients */
1932         rc = mgs_write_log_direct_all(obd, fsdb, mti, lcfg, mti->mti_fsname,
1933                                       ptr);
1934         lustre_cfg_free(lcfg);
1935         return rc;
1936 }
1937
1938 static int mgs_srpc_set_param_disk(struct obd_device *obd,
1939                                    struct fs_db *fsdb,
1940                                    struct mgs_target_info *mti,
1941                                    char *param)
1942 {
1943         struct llog_handle     *llh = NULL;
1944         char                   *logname;
1945         char                   *comment, *ptr;
1946         struct lustre_cfg_bufs  bufs;
1947         struct lustre_cfg      *lcfg;
1948         int                     rc, len;
1949         ENTRY;
1950
1951         /* get comment */
1952         ptr = strchr(param, '=');
1953         LASSERT(ptr);
1954         len = ptr - param;
1955
1956         OBD_ALLOC(comment, len + 1);
1957         if (comment == NULL)
1958                 RETURN(-ENOMEM);
1959         strncpy(comment, param, len);
1960         comment[len] = '\0';
1961
1962         /* prepare lcfg */
1963         lustre_cfg_bufs_reset(&bufs, mti->mti_svname);
1964         lustre_cfg_bufs_set_string(&bufs, 1, param);
1965         lcfg = lustre_cfg_new(LCFG_SPTLRPC_CONF, &bufs);
1966         if (lcfg == NULL)
1967                 GOTO(out_comment, rc = -ENOMEM);
1968
1969         /* construct log name */
1970         rc = name_create(&logname, mti->mti_fsname, "-sptlrpc");
1971         if (rc)
1972                 GOTO(out_lcfg, rc);
1973
1974         if (mgs_log_is_empty(obd, logname)) {
1975                 rc = record_start_log(obd, &llh, logname);
1976                 record_end_log(obd, &llh);
1977                 if (rc)
1978                         GOTO(out, rc);
1979         }
1980
1981         /* obsolete old one */
1982         mgs_modify(obd, fsdb, mti, logname, mti->mti_svname, comment, CM_SKIP);
1983
1984         /* write the new one */
1985         rc = mgs_write_log_direct(obd, fsdb, logname, lcfg,
1986                                   mti->mti_svname, comment);
1987         if (rc)
1988                 CERROR("err %d writing log %s\n", rc, logname);
1989
1990 out:
1991         name_destroy(&logname);
1992 out_lcfg:
1993         lustre_cfg_free(lcfg);
1994 out_comment:
1995         OBD_FREE(comment, len + 1);
1996         RETURN(rc);
1997 }
1998
1999 static int mgs_srpc_set_param_udesc_mem(struct fs_db *fsdb,
2000                                         char *param)
2001 {
2002         char    *ptr;
2003
2004         /* disable the adjustable udesc parameter for now, i.e. use default
2005          * setting that client always ship udesc to MDT if possible. to enable
2006          * it simply remove the following line */
2007         goto error_out;
2008
2009         ptr = strchr(param, '=');
2010         if (ptr == NULL)
2011                 goto error_out;
2012         *ptr++ = '\0';
2013
2014         if (strcmp(param, PARAM_SRPC_UDESC))
2015                 goto error_out;
2016
2017         if (strcmp(ptr, "yes") == 0) {
2018                 fsdb->fsdb_fl_udesc = 1;
2019                 CWARN("Enable user descriptor shipping from client to MDT\n");
2020         } else if (strcmp(ptr, "no") == 0) {
2021                 fsdb->fsdb_fl_udesc = 0;
2022                 CWARN("Disable user descriptor shipping from client to MDT\n");
2023         } else {
2024                 *(ptr - 1) = '=';
2025                 goto error_out;
2026         }
2027         return 0;
2028
2029 error_out:
2030         CERROR("Invalid param: %s\n", param);
2031         return -EINVAL;
2032 }
2033
2034 static int mgs_srpc_set_param_mem(struct fs_db *fsdb,
2035                                   const char *svname,
2036                                   char *param)
2037 {
2038         struct sptlrpc_rule      rule;
2039         struct sptlrpc_rule_set *rset;
2040         int                      rc;
2041         ENTRY;
2042
2043         if (strncmp(param, PARAM_SRPC, sizeof(PARAM_SRPC) - 1) != 0) {
2044                 CERROR("Invalid sptlrpc parameter: %s\n", param);
2045                 RETURN(-EINVAL);
2046         }
2047
2048         if (strncmp(param, PARAM_SRPC_UDESC,
2049                     sizeof(PARAM_SRPC_UDESC) - 1) == 0) {
2050                 RETURN(mgs_srpc_set_param_udesc_mem(fsdb, param));
2051         }
2052
2053         if (strncmp(param, PARAM_SRPC_FLVR, sizeof(PARAM_SRPC_FLVR) - 1) != 0) {
2054                 CERROR("Invalid sptlrpc flavor parameter: %s\n", param);
2055                 RETURN(-EINVAL);
2056         }
2057
2058         param += sizeof(PARAM_SRPC_FLVR) - 1;
2059
2060         rc = sptlrpc_parse_rule(param, &rule);
2061         if (rc)
2062                 RETURN(rc);
2063
2064         /* mgs rules implies must be mgc->mgs */
2065         if (fsdb->fsdb_fl_mgsself) {
2066                 if ((rule.sr_from != LUSTRE_SP_MGC &&
2067                      rule.sr_from != LUSTRE_SP_ANY) ||
2068                     (rule.sr_to != LUSTRE_SP_MGS &&
2069                      rule.sr_to != LUSTRE_SP_ANY))
2070                         RETURN(-EINVAL);
2071         }
2072
2073         /* preapre room for this coming rule. svcname format should be:
2074          * - fsname: general rule
2075          * - fsname-tgtname: target-specific rule
2076          */
2077         if (strchr(svname, '-')) {
2078                 struct mgs_tgt_srpc_conf *tgtconf;
2079                 int                       found = 0;
2080
2081                 for (tgtconf = fsdb->fsdb_srpc_tgt; tgtconf != NULL;
2082                      tgtconf = tgtconf->mtsc_next) {
2083                         if (!strcmp(tgtconf->mtsc_tgt, svname)) {
2084                                 found = 1;
2085                                 break;
2086                         }
2087                 }
2088
2089                 if (!found) {
2090                         int name_len;
2091
2092                         OBD_ALLOC_PTR(tgtconf);
2093                         if (tgtconf == NULL)
2094                                 RETURN(-ENOMEM);
2095
2096                         name_len = strlen(svname);
2097
2098                         OBD_ALLOC(tgtconf->mtsc_tgt, name_len + 1);
2099                         if (tgtconf->mtsc_tgt == NULL) {
2100                                 OBD_FREE_PTR(tgtconf);
2101                                 RETURN(-ENOMEM);
2102                         }
2103                         memcpy(tgtconf->mtsc_tgt, svname, name_len);
2104
2105                         tgtconf->mtsc_next = fsdb->fsdb_srpc_tgt;
2106                         fsdb->fsdb_srpc_tgt = tgtconf;
2107                 }
2108
2109                 rset = &tgtconf->mtsc_rset;
2110         } else {
2111                 rset = &fsdb->fsdb_srpc_gen;
2112         }
2113
2114         rc = sptlrpc_rule_set_merge(rset, &rule);
2115
2116         RETURN(rc);
2117 }
2118
2119 static int mgs_srpc_set_param(struct obd_device *obd,
2120                               struct fs_db *fsdb,
2121                               struct mgs_target_info *mti,
2122                               char *param)
2123 {
2124         char                   *copy;
2125         int                     rc, copy_size;
2126         ENTRY;
2127
2128 #ifndef HAVE_GSS
2129         RETURN(-EINVAL);
2130 #endif
2131         /* keep a copy of original param, which could be destroied
2132          * during parsing */
2133         copy_size = strlen(param) + 1;
2134         OBD_ALLOC(copy, copy_size);
2135         if (copy == NULL)
2136                 return -ENOMEM;
2137         memcpy(copy, param, copy_size);
2138
2139         rc = mgs_srpc_set_param_mem(fsdb, mti->mti_svname, param);
2140         if (rc)
2141                 goto out_free;
2142
2143         /* previous steps guaranteed the syntax is correct */
2144         rc = mgs_srpc_set_param_disk(obd, fsdb, mti, copy);
2145         if (rc)
2146                 goto out_free;
2147
2148         if (fsdb->fsdb_fl_mgsself) {
2149                 /*
2150                  * for mgs rules, make them effective immediately.
2151                  */
2152                 LASSERT(fsdb->fsdb_srpc_tgt == NULL);
2153                 sptlrpc_target_update_exp_flavor(obd, &fsdb->fsdb_srpc_gen);
2154         }
2155
2156 out_free:
2157         OBD_FREE(copy, copy_size);
2158         RETURN(rc);
2159 }
2160
2161 struct mgs_srpc_read_data {
2162         struct fs_db   *msrd_fsdb;
2163         int             msrd_skip;
2164 };
2165
2166 static int mgs_srpc_read_handler(struct llog_handle *llh,
2167                                  struct llog_rec_hdr *rec,
2168                                  void *data)
2169 {
2170         struct mgs_srpc_read_data *msrd = (struct mgs_srpc_read_data *) data;
2171         struct cfg_marker         *marker;
2172         struct lustre_cfg         *lcfg = (struct lustre_cfg *)(rec + 1);
2173         char                      *svname, *param;
2174         int                        cfg_len, rc;
2175         ENTRY;
2176
2177         if (rec->lrh_type != OBD_CFG_REC) {
2178                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
2179                 RETURN(-EINVAL);
2180         }
2181
2182         cfg_len = rec->lrh_len - sizeof(struct llog_rec_hdr) -
2183                   sizeof(struct llog_rec_tail);
2184
2185         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
2186         if (rc) {
2187                 CERROR("Insane cfg\n");
2188                 RETURN(rc);
2189         }
2190
2191         if (lcfg->lcfg_command == LCFG_MARKER) {
2192                 marker = lustre_cfg_buf(lcfg, 1);
2193
2194                 if (marker->cm_flags & CM_START &&
2195                     marker->cm_flags & CM_SKIP)
2196                         msrd->msrd_skip = 1;
2197                 if (marker->cm_flags & CM_END)
2198                         msrd->msrd_skip = 0;
2199
2200                 RETURN(0);
2201         }
2202
2203         if (msrd->msrd_skip)
2204                 RETURN(0);
2205
2206         if (lcfg->lcfg_command != LCFG_SPTLRPC_CONF) {
2207                 CERROR("invalid command (%x)\n", lcfg->lcfg_command);
2208                 RETURN(0);
2209         }
2210
2211         svname = lustre_cfg_string(lcfg, 0);
2212         if (svname == NULL) {
2213                 CERROR("svname is empty\n");
2214                 RETURN(0);
2215         }
2216
2217         param = lustre_cfg_string(lcfg, 1);
2218         if (param == NULL) {
2219                 CERROR("param is empty\n");
2220                 RETURN(0);
2221         }
2222
2223         rc = mgs_srpc_set_param_mem(msrd->msrd_fsdb, svname, param);
2224         if (rc)
2225                 CERROR("read sptlrpc record error (%d): %s\n", rc, param);
2226
2227         RETURN(0);
2228 }
2229
2230 int mgs_get_fsdb_srpc_from_llog(struct obd_device *obd,
2231                                 struct fs_db *fsdb)
2232 {
2233         struct llog_handle        *llh = NULL;
2234         struct lvfs_run_ctxt       saved;
2235         struct llog_ctxt          *ctxt;
2236         char                      *logname;
2237         struct mgs_srpc_read_data  msrd;
2238         int                        rc;
2239         ENTRY;
2240
2241         /* construct log name */
2242         rc = name_create(&logname, fsdb->fsdb_name, "-sptlrpc");
2243         if (rc)
2244                 RETURN(rc);
2245
2246         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
2247         LASSERT(ctxt != NULL);
2248
2249         if (mgs_log_is_empty(obd, logname))
2250                 GOTO(out, rc = 0);
2251
2252         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2253
2254         rc = llog_create(ctxt, &llh, NULL, logname);
2255         if (rc)
2256                 GOTO(out_pop, rc);
2257
2258         rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
2259         if (rc)
2260                 GOTO(out_close, rc);
2261
2262         if (llog_get_size(llh) <= 1)
2263                 GOTO(out_close, rc = 0);
2264
2265         msrd.msrd_fsdb = fsdb;
2266         msrd.msrd_skip = 0;
2267
2268         rc = llog_process(llh, mgs_srpc_read_handler, (void *) &msrd, NULL);
2269
2270 out_close:
2271         llog_close(llh);
2272 out_pop:
2273         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2274 out:
2275         llog_ctxt_put(ctxt);
2276         name_destroy(&logname);
2277
2278         if (rc)
2279                 CERROR("failed to read sptlrpc config database: %d\n", rc);
2280         RETURN(rc);
2281 }
2282
2283 static int mgs_write_log_param(struct obd_device *obd, struct fs_db *fsdb,
2284                                struct mgs_target_info *mti, char *ptr)
2285 {
2286         struct lustre_cfg_bufs bufs;
2287         char *logname;
2288         char *tmp;
2289         int rc = 0;
2290         ENTRY;
2291
2292         /* For various parameter settings, we have to figure out which logs
2293            care about them (e.g. both mdt and client for lov settings) */
2294         CDEBUG(D_MGS, "next param '%s'\n", ptr);
2295
2296         /* The params are stored in MOUNT_DATA_FILE and modified via
2297            tunefs.lustre, or set using lctl conf_param */
2298
2299         /* Processed in lustre_start_mgc */
2300         if (class_match_param(ptr, PARAM_MGSNODE, NULL) == 0)
2301                 GOTO(end, rc);
2302
2303         /* Processed in mgs_write_log_ost */
2304         if (class_match_param(ptr, PARAM_FAILMODE, NULL) == 0) {
2305                 if (mti->mti_flags & LDD_F_PARAM) {
2306                         LCONSOLE_ERROR_MSG(0x169, "%s can only be "
2307                                            "changed with tunefs.lustre"
2308                                            "and --writeconf\n", ptr);
2309                         rc = -EPERM;
2310                 }
2311                 GOTO(end, rc);
2312         }
2313
2314         if (class_match_param(ptr, PARAM_SRPC, NULL) == 0) {
2315                 rc = mgs_srpc_set_param(obd, fsdb, mti, ptr);
2316                 GOTO(end, rc);
2317         }
2318
2319         if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
2320                 /* Add a failover nidlist */
2321                 rc = 0;
2322                 /* We already processed failovers params for new
2323                    targets in mgs_write_log_target */
2324                 if (mti->mti_flags & LDD_F_PARAM) {
2325                         CDEBUG(D_MGS, "Adding failnode\n");
2326                         rc = mgs_write_log_add_failnid(obd, fsdb, mti);
2327                 }
2328                 GOTO(end, rc);
2329         }
2330
2331         if (class_match_param(ptr, PARAM_SYS, &tmp) == 0) {
2332                 rc = mgs_write_log_sys(obd, fsdb, mti, ptr, tmp);
2333                 GOTO(end, rc);
2334         }
2335
2336         if (class_match_param(ptr, PARAM_OSC""PARAM_ACTIVE, &tmp) == 0) {
2337                 /* active=0 means off, anything else means on */
2338                 int flag = (*tmp == '0') ? CM_EXCLUDE : 0;
2339                 int i;
2340
2341                 if (!(mti->mti_flags & LDD_F_SV_TYPE_OST)) {
2342                         LCONSOLE_ERROR_MSG(0x144, "%s: Only OSCs can "
2343                                            "be (de)activated.\n",
2344                                            mti->mti_svname);
2345                         GOTO(end, rc = -EINVAL);
2346                 }
2347                 LCONSOLE_WARN("Permanently %sactivating %s\n",
2348                               flag ? "de": "re", mti->mti_svname);
2349                 /* Modify clilov */
2350                 name_create(&logname, mti->mti_fsname, "-client");
2351                 rc = mgs_modify(obd, fsdb, mti, logname,
2352                                 mti->mti_svname, "add osc", flag);
2353                 name_destroy(&logname);
2354                 if (rc)
2355                         goto active_err;
2356                 /* Modify mdtlov */
2357                 /* FIXME add to all MDT logs for CMD */
2358                 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
2359                         if (!test_bit(i, fsdb->fsdb_mdt_index_map))
2360                                 continue;
2361                         name_create_mdt(&logname, mti->mti_fsname, i);
2362                         rc = mgs_modify(obd, fsdb, mti, logname,
2363                                         mti->mti_svname, "add osc", flag);
2364                         name_destroy(&logname);
2365                         if (rc)
2366                                 goto active_err;
2367                 }
2368         active_err:
2369                 if (rc) {
2370                         LCONSOLE_ERROR_MSG(0x145, "Couldn't find %s in"
2371                                            "log (%d). No permanent "
2372                                            "changes were made to the "
2373                                            "config log.\n",
2374                                            mti->mti_svname, rc);
2375                         if (fsdb->fsdb_flags & FSDB_OLDLOG14)
2376                                 LCONSOLE_ERROR_MSG(0x146, "This may be"
2377                                                    " because the log"
2378                                                    "is in the old 1.4"
2379                                                    "style. Consider "
2380                                                    " --writeconf to "
2381                                                    "update the logs.\n");
2382                         GOTO(end, rc);
2383                 }
2384                 /* Fall through to osc proc for deactivating live OSC
2385                    on running MDT / clients. */
2386         }
2387         /* Below here, let obd's XXX_process_config methods handle it */
2388
2389         /* All lov. in proc */
2390         if (class_match_param(ptr, PARAM_LOV, NULL) == 0) {
2391                 char *mdtlovname;
2392
2393                 CDEBUG(D_MGS, "lov param %s\n", ptr);
2394                 if (!(mti->mti_flags & LDD_F_SV_TYPE_MDT)) {
2395                         LCONSOLE_ERROR_MSG(0x147, "LOV params must be "
2396                                            "set on the MDT, not %s. "
2397                                            "Ignoring.\n",
2398                                            mti->mti_svname);
2399                         GOTO(end, rc = 0);
2400                 }
2401
2402                 /* Modify mdtlov */
2403                 if (mgs_log_is_empty(obd, mti->mti_svname))
2404                         GOTO(end, rc = -ENODEV);
2405
2406                 name_create_mdt_and_lov(&logname, &mdtlovname, fsdb,
2407                                         mti->mti_stripe_index);
2408                 rc = mgs_wlp_lcfg(obd, fsdb, mti, mti->mti_svname,
2409                                   &bufs, mdtlovname, ptr);
2410                 name_destroy(&logname);
2411                 name_destroy(&mdtlovname);
2412                 if (rc)
2413                         GOTO(end, rc);
2414
2415                 /* Modify clilov */
2416                 name_create(&logname, mti->mti_fsname, "-client");
2417                 rc = mgs_wlp_lcfg(obd, fsdb, mti, logname, &bufs,
2418                                   fsdb->fsdb_clilov, ptr);
2419                 name_destroy(&logname);
2420                 GOTO(end, rc);
2421         }
2422
2423         /* All osc., mdc., llite. params in proc */
2424         if ((class_match_param(ptr, PARAM_OSC, NULL) == 0) ||
2425             (class_match_param(ptr, PARAM_MDC, NULL) == 0) ||
2426             (class_match_param(ptr, PARAM_LLITE, NULL) == 0)) {
2427                 char *cname;
2428                 if (memcmp(ptr, PARAM_LLITE, strlen(PARAM_LLITE)) == 0) {
2429                         name_create(&cname, mti->mti_fsname, "-client");
2430                         /* Add the client type to match the obdname in
2431                            class_config_llog_handler */
2432                 } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
2433                         /* COMPAT_146 */
2434                         if (fsdb->fsdb_mdc)
2435                                 name_create(&cname, fsdb->fsdb_mdc, "");
2436                         else
2437                                 name_create(&cname, mti->mti_svname,
2438                                             "-mdc");
2439                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
2440                         /* COMPAT_146 */
2441                         if (fsdb->fsdb_flags & FSDB_OLDLOG14) {
2442                                 LCONSOLE_ERROR_MSG(0x148, "Upgraded "
2443                                                    "client logs for %s"
2444                                                    " cannot be "
2445                                                    "modified. Consider"
2446                                                    " updating the "
2447                                                    "configuration with"
2448                                                    " --writeconf\n",
2449                                                    mti->mti_svname);
2450                                 /* We don't know the names of all the
2451                                    old oscs*/
2452                                 GOTO(end, rc = -EINVAL);
2453                         }
2454                         name_create(&cname, mti->mti_svname, "-osc");
2455                 } else {
2456                         GOTO(end, rc = -EINVAL);
2457                 }
2458
2459                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
2460
2461                 /* Modify client */
2462                 name_create(&logname, mti->mti_fsname, "-client");
2463                 rc = mgs_wlp_lcfg(obd, fsdb, mti, logname, &bufs,
2464                                   cname, ptr);
2465
2466                 /* osc params affect the MDT as well */
2467                 if (!rc && (mti->mti_flags & LDD_F_SV_TYPE_OST)) {
2468                         char mdt_index[16];
2469                         int i;
2470
2471                         for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
2472                                 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
2473                                         continue;
2474
2475                                 name_destroy(&cname);
2476                                 if (i == 0 && fsdb->fsdb_fl_oscname_18)
2477                                         sprintf(mdt_index, "-osc");
2478                                 else
2479                                         sprintf(mdt_index, "-osc-MDT%04x", i);
2480                                 name_create(&cname, mti->mti_svname, mdt_index);
2481
2482                                 name_destroy(&logname);
2483                                 name_create_mdt(&logname, mti->mti_fsname, i);
2484                                 if (!mgs_log_is_empty(obd, logname))
2485                                         rc = mgs_wlp_lcfg(obd, fsdb,
2486                                                           mti, logname,
2487                                                           &bufs, cname,
2488                                                           ptr);
2489                                 if (rc)
2490                                         break;
2491                         }
2492                 }
2493                 name_destroy(&logname);
2494                 name_destroy(&cname);
2495                 GOTO(end, rc);
2496         }
2497
2498         /* All mdt. params in proc */
2499         if (class_match_param(ptr, PARAM_MDT, NULL) == 0) {
2500                 int i;
2501                 __u32 idx;
2502
2503                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
2504                 if (strncmp(mti->mti_svname, mti->mti_fsname,
2505                             MTI_NAME_MAXLEN) == 0)
2506                         /* device is unspecified completely? */
2507                         rc = LDD_F_SV_TYPE_MDT | LDD_F_SV_ALL;
2508                 else
2509                         rc = server_name2index(mti->mti_svname, &idx, NULL);
2510                 if (rc < 0)
2511                         goto active_err;
2512                 if ((rc & LDD_F_SV_TYPE_MDT) == 0)
2513                         goto active_err;
2514                 if (rc & LDD_F_SV_ALL) {
2515                         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
2516                                 if (!test_bit(i,
2517                                               fsdb->fsdb_mdt_index_map))
2518                                         continue;
2519                                 name_create_mdt(&logname, mti->mti_fsname, i);
2520                                 rc = mgs_wlp_lcfg(obd, fsdb, mti,
2521                                                   logname, &bufs,
2522                                                   logname, ptr);
2523                                 name_destroy(&logname);
2524                                 if (rc)
2525                                         goto active_err;
2526                         }
2527                 } else {
2528                         rc = mgs_wlp_lcfg(obd, fsdb, mti,
2529                                           mti->mti_svname, &bufs,
2530                                           mti->mti_svname, ptr);
2531                         if (rc)
2532                                 goto active_err;
2533                 }
2534                 GOTO(end, rc);
2535         }
2536
2537         /* All mdd., ost. params in proc */
2538         if ((class_match_param(ptr, PARAM_MDD, NULL) == 0) ||
2539             (class_match_param(ptr, PARAM_OST, NULL) == 0)) {
2540                 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
2541                 if (mgs_log_is_empty(obd, mti->mti_svname))
2542                         GOTO(end, rc = -ENODEV);
2543
2544                 rc = mgs_wlp_lcfg(obd, fsdb, mti, mti->mti_svname,
2545                                   &bufs, mti->mti_svname, ptr);
2546                 GOTO(end, rc);
2547         }
2548
2549         LCONSOLE_WARN("Ignoring unrecognized param '%s'\n", ptr);
2550
2551 end:
2552         if (rc)
2553                 CERROR("err %d on param '%s'\n", rc, ptr);
2554
2555         RETURN(rc);
2556 }
2557
2558 /* Not implementing automatic failover nid addition at this time. */
2559 int mgs_check_failnid(struct obd_device *obd, struct mgs_target_info *mti)
2560 {
2561 #if 0
2562         struct fs_db *fsdb;
2563         int rc;
2564         ENTRY;
2565
2566         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb);
2567         if (rc)
2568                 RETURN(rc);
2569
2570         if (mgs_log_is_empty(obd, mti->mti_svname))
2571                 /* should never happen */
2572                 RETURN(-ENOENT);
2573
2574         CDEBUG(D_MGS, "Checking for new failnids for %s\n", mti->mti_svname);
2575
2576         /* FIXME We can just check mti->params to see if we're already in
2577            the failover list.  Modify mti->params for rewriting back at
2578            server_register_target(). */
2579
2580         down(&fsdb->fsdb_sem);
2581         rc = mgs_write_log_add_failnid(obd, fsdb, mti);
2582         up(&fsdb->fsdb_sem);
2583
2584         RETURN(rc);
2585 #endif
2586         return 0;
2587 }
2588
2589 int mgs_write_log_target(struct obd_device *obd,
2590                          struct mgs_target_info *mti)
2591 {
2592         struct fs_db *fsdb;
2593         int rc = -EINVAL;
2594         char *buf, *params;
2595         ENTRY;
2596
2597         /* set/check the new target index */
2598         rc = mgs_set_index(obd, mti);
2599         if (rc < 0) {
2600                 CERROR("Can't get index (%d)\n", rc);
2601                 RETURN(rc);
2602         }
2603
2604         /* COMPAT_146 */
2605         if (mti->mti_flags & LDD_F_UPGRADE14) {
2606                 if (rc == EALREADY) {
2607                         LCONSOLE_INFO("Found index %d for %s 1.4 log, "
2608                                       "upgrading\n", mti->mti_stripe_index,
2609                                       mti->mti_svname);
2610                 } else {
2611                         LCONSOLE_ERROR_MSG(0x149, "Failed to find %s in the old"
2612                                            " client log. Apparently it is not "
2613                                            "part of this filesystem, or the old"
2614                                            " log is wrong.\nUse 'writeconf' on "
2615                                            "the MDT to force log regeneration."
2616                                            "\n", mti->mti_svname);
2617                         /* Not in client log?  Upgrade anyhow...*/
2618                         /* Argument against upgrading: reformat MDT,
2619                            upgrade OST, then OST will start but will be SKIPped
2620                            in client logs.  Maybe error now is better. */
2621                         /* RETURN(-EINVAL); */
2622                 }
2623                 /* end COMPAT_146 */
2624         } else {
2625                 if (rc == EALREADY) {
2626                         LCONSOLE_WARN("Found index %d for %s, updating log\n",
2627                                       mti->mti_stripe_index, mti->mti_svname);
2628                         /* We would like to mark old log sections as invalid
2629                            and add new log sections in the client and mdt logs.
2630                            But if we add new sections, then live clients will
2631                            get repeat setup instructions for already running
2632                            osc's. So don't update the client/mdt logs. */
2633                         mti->mti_flags &= ~LDD_F_UPDATE;
2634                 }
2635         }
2636
2637         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb);
2638         if (rc) {
2639                 CERROR("Can't get db for %s\n", mti->mti_fsname);
2640                 RETURN(rc);
2641         }
2642
2643         down(&fsdb->fsdb_sem);
2644
2645         if (mti->mti_flags &
2646             (LDD_F_VIRGIN | LDD_F_UPGRADE14 | LDD_F_WRITECONF)) {
2647                 /* Generate a log from scratch */
2648                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
2649                         rc = mgs_write_log_mdt(obd, fsdb, mti);
2650                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
2651                         rc = mgs_write_log_ost(obd, fsdb, mti);
2652                 } else {
2653                         CERROR("Unknown target type %#x, can't create log for "
2654                                "%s\n", mti->mti_flags, mti->mti_svname);
2655                 }
2656                 if (rc) {
2657                         CERROR("Can't write logs for %s (%d)\n",
2658                                mti->mti_svname, rc);
2659                         GOTO(out_up, rc);
2660                 }
2661         } else {
2662                 /* Just update the params from tunefs in mgs_write_log_params */
2663                 CDEBUG(D_MGS, "Update params for %s\n", mti->mti_svname);
2664                 mti->mti_flags |= LDD_F_PARAM;
2665         }
2666
2667         /* allocate temporary buffer, where class_get_next_param will
2668            make copy of a current  parameter */
2669         OBD_ALLOC(buf, strlen(mti->mti_params) + 1);
2670         if (buf == NULL)
2671                 GOTO(out_up, rc = -ENOMEM);
2672         params = mti->mti_params;
2673         while (params != NULL) {
2674                 rc = class_get_next_param(&params, buf);
2675                 if (rc) {
2676                         if (rc == 1)
2677                                 /* there is no next parameter, that is
2678                                    not an error */
2679                                 rc = 0;
2680                         break;
2681                 }
2682                 CDEBUG(D_MGS, "remaining string: '%s', param: '%s'\n",
2683                        params, buf);
2684                 rc = mgs_write_log_param(obd, fsdb, mti, buf);
2685                 if (rc)
2686                         break;
2687         }
2688
2689         OBD_FREE(buf, strlen(mti->mti_params) + 1);
2690
2691 out_up:
2692         up(&fsdb->fsdb_sem);
2693         RETURN(rc);
2694 }
2695
2696 /* COMPAT_146 */
2697 /* verify that we can handle the old config logs */
2698 int mgs_upgrade_sv_14(struct obd_device *obd, struct mgs_target_info *mti)
2699 {
2700         struct fs_db *fsdb;
2701         int rc = 0;
2702         ENTRY;
2703
2704         /* Create ost log normally, as servers register.  Servers
2705            register with their old uuids (from last_rcvd), so old
2706            (MDT and client) logs should work.
2707          - new MDT won't know about old OSTs, only the ones that have
2708            registered, so we need the old MDT log to get the LOV right
2709            in order for old clients to work.
2710          - Old clients connect to the MDT, not the MGS, for their logs, and
2711            will therefore receive the old client log from the MDT /LOGS dir.
2712          - Old clients can continue to use and connect to old or new OSTs
2713          - New clients will contact the MGS for their log
2714         */
2715
2716         LCONSOLE_INFO("upgrading server %s from pre-1.6\n", mti->mti_svname);
2717         server_mti_print("upgrade", mti);
2718
2719         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb);
2720         if (rc)
2721                 RETURN(rc);
2722
2723         if (fsdb->fsdb_flags & FSDB_LOG_EMPTY) {
2724                 LCONSOLE_ERROR_MSG(0x14a, "The old client log %s-client is "
2725                                    "missing.  Was tunefs.lustre successful?\n",
2726                                    mti->mti_fsname);
2727                 RETURN(-ENOENT);
2728         }
2729
2730         if (fsdb->fsdb_gen == 0) {
2731                 /* There were no markers in the client log, meaning we have
2732                    not updated the logs for this fs */
2733                 CDEBUG(D_MGS, "found old, unupdated client log\n");
2734         }
2735
2736         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
2737                 if (mgs_log_is_empty(obd, mti->mti_svname)) {
2738                         LCONSOLE_ERROR_MSG(0x14b, "The old MDT log %s is "
2739                                            "missing. Was tunefs.lustre "
2740                                            "successful?\n",
2741                                            mti->mti_svname);
2742                         RETURN(-ENOENT);
2743                 }
2744                 /* We're starting with an old uuid.  Assume old name for lov
2745                    as well since the lov entry already exists in the log. */
2746                 CDEBUG(D_MGS, "old mds uuid %s\n", mti->mti_uuid);
2747                 if (strncmp(mti->mti_uuid, fsdb->fsdb_mdtlov + 4,
2748                             strlen(fsdb->fsdb_mdtlov) - 4) != 0) {
2749                         CERROR("old mds uuid %s doesn't match log %s (%s)\n",
2750                                mti->mti_uuid, fsdb->fsdb_mdtlov,
2751                                fsdb->fsdb_mdtlov + 4);
2752                         RETURN(-EINVAL);
2753                 }
2754         }
2755
2756         if (!(fsdb->fsdb_flags & FSDB_OLDLOG14)) {
2757                 LCONSOLE_ERROR_MSG(0x14c, "%s-client is supposedly an old "
2758                                    "log, but no old LOV or MDT was found. "
2759                                    "Consider updating the configuration with"
2760                                    " --writeconf.\n", mti->mti_fsname);
2761         }
2762
2763         RETURN(rc);
2764 }
2765 /* end COMPAT_146 */
2766
2767 int mgs_erase_log(struct obd_device *obd, char *name)
2768 {
2769         struct lvfs_run_ctxt saved;
2770         struct llog_ctxt *ctxt;
2771         struct llog_handle *llh;
2772         int rc = 0;
2773
2774         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
2775         LASSERT(ctxt != NULL);
2776
2777         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2778         rc = llog_create(ctxt, &llh, NULL, name);
2779         if (rc == 0) {
2780                 llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
2781                 rc = llog_destroy(llh);
2782                 llog_free_handle(llh);
2783         }
2784         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2785         llog_ctxt_put(ctxt);
2786
2787         if (rc)
2788                 CERROR("failed to clear log %s: %d\n", name, rc);
2789
2790         return(rc);
2791 }
2792
2793 /* erase all logs for the given fs */
2794 int mgs_erase_logs(struct obd_device *obd, char *fsname)
2795 {
2796         struct mgs_obd *mgs = &obd->u.mgs;
2797         static struct fs_db *fsdb;
2798         struct list_head dentry_list;
2799         struct l_linux_dirent *dirent, *n;
2800         int rc, len = strlen(fsname);
2801         ENTRY;
2802
2803         /* Find all the logs in the CONFIGS directory */
2804         rc = class_dentry_readdir(obd, mgs->mgs_configs_dir,
2805                                   mgs->mgs_vfsmnt, &dentry_list);
2806         if (rc) {
2807                 CERROR("Can't read %s dir\n", MOUNT_CONFIGS_DIR);
2808                 RETURN(rc);
2809         }
2810
2811         down(&mgs->mgs_sem);
2812
2813         /* Delete the fs db */
2814         fsdb = mgs_find_fsdb(obd, fsname);
2815         if (fsdb)
2816                 mgs_free_fsdb(obd, fsdb);
2817
2818         list_for_each_entry_safe(dirent, n, &dentry_list, lld_list) {
2819                 list_del(&dirent->lld_list);
2820                 if (strncmp(fsname, dirent->lld_name, len) == 0) {
2821                         CDEBUG(D_MGS, "Removing log %s\n", dirent->lld_name);
2822                         mgs_erase_log(obd, dirent->lld_name);
2823                 }
2824                 OBD_FREE(dirent, sizeof(*dirent));
2825         }
2826
2827         up(&mgs->mgs_sem);
2828
2829         RETURN(rc);
2830 }
2831
2832 /* from llog_swab */
2833 static void print_lustre_cfg(struct lustre_cfg *lcfg)
2834 {
2835         int i;
2836         ENTRY;
2837
2838         CDEBUG(D_MGS, "lustre_cfg: %p\n", lcfg);
2839         CDEBUG(D_MGS, "\tlcfg->lcfg_version: %#x\n", lcfg->lcfg_version);
2840
2841         CDEBUG(D_MGS, "\tlcfg->lcfg_command: %#x\n", lcfg->lcfg_command);
2842         CDEBUG(D_MGS, "\tlcfg->lcfg_num: %#x\n", lcfg->lcfg_num);
2843         CDEBUG(D_MGS, "\tlcfg->lcfg_flags: %#x\n", lcfg->lcfg_flags);
2844         CDEBUG(D_MGS, "\tlcfg->lcfg_nid: %s\n", libcfs_nid2str(lcfg->lcfg_nid));
2845
2846         CDEBUG(D_MGS, "\tlcfg->lcfg_bufcount: %d\n", lcfg->lcfg_bufcount);
2847         if (lcfg->lcfg_bufcount < LUSTRE_CFG_MAX_BUFCOUNT)
2848                 for (i = 0; i < lcfg->lcfg_bufcount; i++) {
2849                         CDEBUG(D_MGS, "\tlcfg->lcfg_buflens[%d]: %d %s\n",
2850                                i, lcfg->lcfg_buflens[i],
2851                                lustre_cfg_string(lcfg, i));
2852                 }
2853         EXIT;
2854 }
2855
2856 /* Set a permanent (config log) param for a target or fs */
2857 int mgs_setparam(struct obd_device *obd, struct lustre_cfg *lcfg, char *fsname)
2858 {
2859         struct fs_db *fsdb;
2860         struct mgs_target_info *mti;
2861         char *devname, *param;
2862         char *ptr, *tmp;
2863         __u32 index;
2864         int rc = 0;
2865         ENTRY;
2866
2867         print_lustre_cfg(lcfg);
2868
2869         /* lustre, lustre-mdtlov, lustre-client, lustre-MDT0000 */
2870         devname = lustre_cfg_string(lcfg, 0);
2871         param = lustre_cfg_string(lcfg, 1);
2872         if (!devname) {
2873                 /* Assume device name embedded in param:
2874                    lustre-OST0000.osc.max_dirty_mb=32 */
2875                 ptr = strchr(param, '.');
2876                 if (ptr) {
2877                         devname = param;
2878                         *ptr = 0;
2879                         param = ptr + 1;
2880                 }
2881         }
2882         if (!devname) {
2883                 LCONSOLE_ERROR_MSG(0x14d, "No target specified: %s\n", param);
2884                 RETURN(-ENOSYS);
2885         }
2886
2887         /* Extract fsname */
2888         ptr = strrchr(devname, '-');
2889         memset(fsname, 0, MTI_NAME_MAXLEN);
2890         if (ptr && (server_name2index(ptr, &index, NULL) >= 0)) {
2891                 /* param related to llite isn't allowed to set by OST or MDT */
2892                 if (strncmp(param, PARAM_LLITE, sizeof(PARAM_LLITE)) == 0)
2893                         RETURN(-EINVAL);
2894
2895                 strncpy(fsname, devname, ptr - devname);
2896         } else {
2897                 /* assume devname is the fsname */
2898                 strncpy(fsname, devname, MTI_NAME_MAXLEN);
2899         }
2900         fsname[MTI_NAME_MAXLEN - 1] = 0;
2901         CDEBUG(D_MGS, "setparam on fs %s device %s\n", fsname, devname);
2902
2903         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb);
2904         if (rc)
2905                 RETURN(rc);
2906         if (!fsdb->fsdb_fl_mgsself && fsdb->fsdb_flags & FSDB_LOG_EMPTY) {
2907                 CERROR("No filesystem targets for %s.  cfg_device from lctl "
2908                        "is '%s'\n", fsname, devname);
2909                 mgs_free_fsdb(obd, fsdb);
2910                 RETURN(-EINVAL);
2911         }
2912
2913         /* Create a fake mti to hold everything */
2914         OBD_ALLOC_PTR(mti);
2915         if (!mti)
2916                 GOTO(out, rc = -ENOMEM);
2917         strncpy(mti->mti_fsname, fsname, MTI_NAME_MAXLEN);
2918         strncpy(mti->mti_svname, devname, MTI_NAME_MAXLEN);
2919         strncpy(mti->mti_params, param, sizeof(mti->mti_params));
2920         rc = server_name2index(mti->mti_svname, &mti->mti_stripe_index, &tmp);
2921         if (rc < 0)
2922                 /* Not a valid server; may be only fsname */
2923                 rc = 0;
2924         else
2925                 /* Strip -osc or -mdc suffix from svname */
2926                 if (server_make_name(rc, mti->mti_stripe_index, mti->mti_fsname,
2927                                      mti->mti_svname))
2928                         GOTO(out, rc = -EINVAL);
2929
2930         mti->mti_flags = rc | LDD_F_PARAM;
2931
2932         down(&fsdb->fsdb_sem);
2933         /* this is lctl conf_param's single param path, there is not
2934            need to loop through parameters */
2935         rc = mgs_write_log_param(obd, fsdb, mti, mti->mti_params);
2936         up(&fsdb->fsdb_sem);
2937
2938 out:
2939         OBD_FREE_PTR(mti);
2940         RETURN(rc);
2941 }
2942
2943 static int mgs_write_log_pool(struct obd_device *obd, char *logname,
2944                               struct fs_db *fsdb, char *lovname,
2945                               enum lcfg_command_type cmd,
2946                               char *poolname, char *fsname,
2947                               char *ostname, char *comment)
2948 {
2949         struct llog_handle *llh = NULL;
2950         int rc;
2951
2952         rc = record_start_log(obd, &llh, logname);
2953         if (rc)
2954                 return rc;
2955         rc = record_marker(obd, llh, fsdb, CM_START, lovname, comment);
2956         record_base(obd, llh, lovname, 0, cmd, poolname, fsname, ostname, 0);
2957         rc = record_marker(obd, llh, fsdb, CM_END, lovname, comment);
2958         rc = record_end_log(obd, &llh);
2959
2960         return rc;
2961 }
2962
2963 int mgs_pool_cmd(struct obd_device *obd, enum lcfg_command_type cmd,
2964                  char *fsname, char *poolname, char *ostname)
2965 {
2966         struct fs_db *fsdb;
2967         char *lovname;
2968         char *logname;
2969         char *label = NULL, *canceled_label = NULL;
2970         int label_sz;
2971         struct mgs_target_info *mti = NULL;
2972         int rc, i;
2973         ENTRY;
2974
2975         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb);
2976         if (rc) {
2977                 CERROR("Can't get db for %s\n", fsname);
2978                 RETURN(rc);
2979         }
2980         if (fsdb->fsdb_flags & FSDB_LOG_EMPTY) {
2981                 CERROR("%s is not defined\n", fsname);
2982                 mgs_free_fsdb(obd, fsdb);
2983                 RETURN(-EINVAL);
2984         }
2985
2986         label_sz = 10 + strlen(fsname) + strlen(poolname);
2987
2988         /* check if ostname match fsname */
2989         if (ostname != NULL) {
2990                 char *ptr;
2991
2992                 ptr = strrchr(ostname, '-');
2993                 if ((ptr == NULL) ||
2994                     (strncmp(fsname, ostname, ptr-ostname) != 0))
2995                         RETURN(-EINVAL);
2996                 label_sz += strlen(ostname);
2997         }
2998
2999         OBD_ALLOC(label, label_sz);
3000         if (label == NULL)
3001                 GOTO(out, rc = -ENOMEM);
3002
3003         switch(cmd) {
3004         case LCFG_POOL_NEW: {
3005                 sprintf(label,
3006                         "new %s.%s", fsname, poolname);
3007                 break;
3008         }
3009         case LCFG_POOL_ADD: {
3010                 sprintf(label,
3011                         "add %s.%s.%s", fsname, poolname, ostname);
3012                 break;
3013         }
3014         case LCFG_POOL_REM: {
3015                 OBD_ALLOC(canceled_label, label_sz);
3016                 if (canceled_label == NULL)
3017                          GOTO(out, rc = -ENOMEM);
3018                 sprintf(label,
3019                         "rem %s.%s.%s", fsname, poolname, ostname);
3020                 sprintf(canceled_label,
3021                         "add %s.%s.%s", fsname, poolname, ostname);
3022                 break;
3023         }
3024         case LCFG_POOL_DEL: {
3025                 OBD_ALLOC(canceled_label, label_sz);
3026                 if (canceled_label == NULL)
3027                          GOTO(out, rc = -ENOMEM);
3028                 sprintf(label,
3029                         "del %s.%s", fsname, poolname);
3030                 sprintf(canceled_label,
3031                         "new %s.%s", fsname, poolname);
3032                 break;
3033         }
3034         default: {
3035                 break;
3036         }
3037         }
3038
3039         down(&fsdb->fsdb_sem);
3040
3041         if (canceled_label != NULL) {
3042                 OBD_ALLOC_PTR(mti);
3043                 if (mti == NULL)
3044                         GOTO(out, rc = -ENOMEM);
3045         }
3046
3047         /* write pool def to all MDT logs */
3048         for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
3049                  if (test_bit(i,  fsdb->fsdb_mdt_index_map)) {
3050                         name_create_mdt_and_lov(&logname, &lovname, fsdb, i);
3051
3052                         if (canceled_label != NULL) {
3053                                 strcpy(mti->mti_svname, "lov pool");
3054                                 mgs_modify(obd, fsdb, mti, logname, lovname,
3055                                            canceled_label, CM_SKIP);
3056                         }
3057
3058                         mgs_write_log_pool(obd, logname, fsdb, lovname,
3059                                            cmd, fsname, poolname, ostname,
3060                                            label);
3061                         name_destroy(&logname);
3062                         name_destroy(&lovname);
3063                 }
3064         }
3065
3066         name_create(&logname, fsname, "-client");
3067         if (canceled_label != NULL)
3068                 mgs_modify(obd, fsdb, mti, logname, fsdb->fsdb_clilov,
3069                            canceled_label, CM_SKIP);
3070
3071         mgs_write_log_pool(obd, logname, fsdb, fsdb->fsdb_clilov,
3072                            cmd, fsname, poolname, ostname, label);
3073         name_destroy(&logname);
3074
3075         up(&fsdb->fsdb_sem);
3076
3077         EXIT;
3078 out:
3079         if (label != NULL)
3080                 OBD_FREE(label, label_sz);
3081
3082         if (canceled_label != NULL)
3083                 OBD_FREE(canceled_label, label_sz);
3084
3085         if (mti != NULL)
3086                 OBD_FREE_PTR(mti);
3087
3088         return rc;
3089 }
3090
3091 #if 0
3092 /******************** unused *********************/
3093 static int mgs_backup_llog(struct obd_device *obd, char* fsname)
3094 {
3095         struct file *filp, *bak_filp;
3096         struct lvfs_run_ctxt saved;
3097         char *logname, *buf;
3098         loff_t soff = 0 , doff = 0;
3099         int count = 4096, len;
3100         int rc = 0;
3101
3102         OBD_ALLOC(logname, PATH_MAX);
3103         if (logname == NULL)
3104                 return -ENOMEM;
3105
3106         OBD_ALLOC(buf, count);
3107         if (!buf)
3108                 GOTO(out , rc = -ENOMEM);
3109
3110         len = snprintf(logname, PATH_MAX, "%s/%s.bak",
3111                        MOUNT_CONFIGS_DIR, fsname);
3112
3113         if (len >= PATH_MAX - 1) {
3114                 GOTO(out, -ENAMETOOLONG);
3115         }
3116
3117         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
3118
3119         bak_filp = l_filp_open(logname, O_RDWR|O_CREAT|O_TRUNC, 0660);
3120         if (IS_ERR(bak_filp)) {
3121                 rc = PTR_ERR(bak_filp);
3122                 CERROR("backup logfile open %s: %d\n", logname, rc);
3123                 GOTO(pop, rc);
3124         }
3125         sprintf(logname, "%s/%s", MOUNT_CONFIGS_DIR, fsname);
3126         filp = l_filp_open(logname, O_RDONLY, 0);
3127         if (IS_ERR(filp)) {
3128                 rc = PTR_ERR(filp);
3129                 CERROR("logfile open %s: %d\n", logname, rc);
3130                 GOTO(close1f, rc);
3131         }
3132
3133         while ((rc = lustre_fread(filp, buf, count, &soff)) > 0) {
3134                 rc = lustre_fwrite(bak_filp, buf, count, &doff);
3135                 break;
3136         }
3137
3138         filp_close(filp, 0);
3139 close1f:
3140         filp_close(bak_filp, 0);
3141 pop:
3142         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
3143 out:
3144         if (buf)
3145                 OBD_FREE(buf, count);
3146         OBD_FREE(logname, PATH_MAX);
3147         return rc;
3148 }
3149
3150 #endif