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