Whamcloud - gitweb
b=17710
[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 "mgs_internal.h"
66
67 /******************** Class functions *********************/
68
69 /* Caller must list_del and OBD_FREE each dentry from the list */
70 int class_dentry_readdir(struct obd_device *obd, struct dentry *dir,
71                          struct vfsmount *inmnt, 
72                          struct list_head *dentry_list){
73         /* see mds_cleanup_pending */
74         struct lvfs_run_ctxt saved;
75         struct file *file;
76         struct dentry *dentry;
77         struct vfsmount *mnt;
78         int rc = 0;
79         ENTRY;
80
81         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
82         dentry = dget(dir);
83         if (IS_ERR(dentry))
84                 GOTO(out_pop, rc = PTR_ERR(dentry));
85         mnt = mntget(inmnt);
86         if (IS_ERR(mnt)) {
87                 l_dput(dentry);
88                 GOTO(out_pop, rc = PTR_ERR(mnt));
89         }
90
91         file = dentry_open(dentry, mnt, O_RDONLY);
92         if (IS_ERR(file))
93                 /* dentry_open_it() drops the dentry, mnt refs */
94                 GOTO(out_pop, rc = PTR_ERR(file));
95
96         INIT_LIST_HEAD(dentry_list);
97         rc = l_readdir(file, dentry_list);
98         filp_close(file, 0);
99         /*  filp_close->fput() drops the dentry, mnt refs */
100
101 out_pop:
102         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
103         RETURN(rc);
104 }
105
106 /******************** DB functions *********************/
107
108 static inline int name_create(char **newname, char *prefix, char *suffix)
109 {
110         LASSERT(newname);
111         OBD_ALLOC(*newname, strlen(prefix) + strlen(suffix) + 1);
112         if (!*newname) 
113                 return -ENOMEM;
114         sprintf(*newname, "%s%s", prefix, suffix);
115         return 0;
116 }
117
118 static inline void name_destroy(char **name)
119 {        
120         if (*name)
121                 OBD_FREE(*name, strlen(*name) + 1);
122         *name = NULL;
123 }
124
125 /* from the (client) config log, figure out:
126         1. which ost's/mdt's are configured (by index)
127         2. what the last config step is
128         3. COMPAT_146 lov name
129         4. COMPAT_146 mdt lov name
130         5. COMPAT_146 mdc name 
131 */
132 /* It might be better to have a separate db file, instead of parsing the info
133    out of the client log.  This is slow and potentially error-prone. */
134 static int mgs_fsdb_handler(struct llog_handle *llh, struct llog_rec_hdr *rec, 
135                             void *data)
136 {
137         struct fs_db *fsdb = (struct fs_db *)data;
138         int cfg_len = rec->lrh_len;
139         char *cfg_buf = (char*) (rec + 1);
140         struct lustre_cfg *lcfg;
141         __u32 index;
142         int rc = 0;
143         ENTRY;
144
145         if (rec->lrh_type != OBD_CFG_REC) {
146                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
147                 RETURN(-EINVAL);
148         }
149
150         rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
151         if (rc) {
152                 CERROR("Insane cfg\n");
153                 RETURN(rc);
154         }
155
156         lcfg = (struct lustre_cfg *)cfg_buf;
157
158         CDEBUG(D_INFO, "cmd %x %s %s\n", lcfg->lcfg_command, 
159                lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
160
161         /* Figure out ost indicies */ 
162         /* lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1 */
163         if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD ||
164             lcfg->lcfg_command == LCFG_LOV_DEL_OBD) {
165                 index = simple_strtoul(lustre_cfg_string(lcfg, 2),
166                                        NULL, 10);
167                 CDEBUG(D_MGS, "OST index for %s is %u (%s)\n",
168                        lustre_cfg_string(lcfg, 1), index, 
169                        lustre_cfg_string(lcfg, 2));
170                 set_bit(index, fsdb->fsdb_ost_index_map);
171         }
172         
173         /* Figure out mdt indicies */
174         /* attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f */
175         if ((lcfg->lcfg_command == LCFG_ATTACH) &&
176             (strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_MDC_NAME) == 0)) {
177                 rc = server_name2index(lustre_cfg_string(lcfg, 0),
178                                        &index, NULL);
179                 if (rc != LDD_F_SV_TYPE_MDT) {
180                         CWARN("Unparsable MDC name %s, assuming index 0\n",
181                               lustre_cfg_string(lcfg, 0));
182                         index = 0;
183                 }
184                 rc = 0;
185                 CDEBUG(D_MGS, "MDT index is %u\n", index);
186                 set_bit(index, fsdb->fsdb_mdt_index_map);
187         }
188
189         /* COMPAT_146 */
190         /* figure out the old LOV name. fsdb_gen = 0 means old log */
191         /* #01 L attach 0:lov_mdsA 1:lov 2:cdbe9_lov_mdsA_dc8cf7f3bb */
192         if ((fsdb->fsdb_gen == 0) && (lcfg->lcfg_command == LCFG_ATTACH) &&
193             (strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_LOV_NAME) == 0)) {
194                 fsdb->fsdb_flags |= FSDB_OLDLOG14;
195                 name_destroy(&fsdb->fsdb_clilov);
196                 rc = name_create(&fsdb->fsdb_clilov, 
197                                  lustre_cfg_string(lcfg, 0), "");
198                 if (rc) 
199                         RETURN(rc);
200                 CDEBUG(D_MGS, "client lov name is %s\n", fsdb->fsdb_clilov);
201         }
202
203         /* figure out the old MDT lov name from the MDT uuid */
204         if ((fsdb->fsdb_gen == 0) && (lcfg->lcfg_command == LCFG_SETUP) &&
205             (strncmp(lustre_cfg_string(lcfg, 0), "MDC_", 4) == 0)) {
206                 char *ptr;
207                 fsdb->fsdb_flags |= FSDB_OLDLOG14;
208                 ptr = strstr(lustre_cfg_string(lcfg, 1), "_UUID");
209                 if (!ptr) {
210                         CERROR("Can't parse MDT uuid %s\n", 
211                                lustre_cfg_string(lcfg, 1));
212                         RETURN(-EINVAL);
213                 }
214                 *ptr = '\0';
215                 name_destroy(&fsdb->fsdb_mdtlov);
216                 rc = name_create(&fsdb->fsdb_mdtlov, 
217                                  "lov_", lustre_cfg_string(lcfg, 1));
218                 if (rc) 
219                         RETURN(rc);
220                 name_destroy(&fsdb->fsdb_mdc);
221                 rc = name_create(&fsdb->fsdb_mdc, 
222                                  lustre_cfg_string(lcfg, 0), "");
223                 if (rc) 
224                         RETURN(rc);
225                 CDEBUG(D_MGS, "MDT lov name is %s\n", fsdb->fsdb_mdtlov);
226         }
227         /* end COMPAT_146 */
228
229         /* Keep track of the latest marker step */
230         if (lcfg->lcfg_command == LCFG_MARKER) {
231                 struct cfg_marker *marker;
232                 marker = lustre_cfg_buf(lcfg, 1);
233                 fsdb->fsdb_gen = max(fsdb->fsdb_gen, marker->cm_step);
234         }
235
236         RETURN(rc);
237 }
238
239 static int mgs_get_fsdb_from_llog(struct obd_device *obd, struct fs_db *fsdb)
240 {
241         char *logname;
242         struct llog_handle *loghandle;
243         struct lvfs_run_ctxt saved;
244         struct llog_ctxt *ctxt;
245         int rc, rc2;
246         ENTRY;
247
248         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
249         LASSERT(ctxt != NULL);
250         name_create(&logname, fsdb->fsdb_name, "-client");
251         down(&fsdb->fsdb_sem);
252         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
253         rc = llog_create(ctxt, &loghandle, NULL, logname);
254         if (rc)
255                 GOTO(out_pop, rc);
256
257         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
258         if (rc)
259                 GOTO(out_close, rc);
260
261         if (llog_get_size(loghandle) <= 1)
262                 fsdb->fsdb_flags |= FSDB_LOG_EMPTY;
263
264         rc = llog_process(loghandle, mgs_fsdb_handler, (void *)fsdb, NULL);
265         CDEBUG(D_INFO, "get_db = %d\n", rc);
266 out_close:
267         rc2 = llog_close(loghandle);
268         if (!rc)
269                 rc = rc2;
270 out_pop:
271         llog_ctxt_put(ctxt);
272         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
273         up(&fsdb->fsdb_sem);
274         name_destroy(&logname);
275
276         RETURN(rc);
277 }
278
279 static struct fs_db *mgs_find_fsdb(struct obd_device *obd, char *fsname)
280 {
281         struct mgs_obd *mgs = &obd->u.mgs;
282         struct fs_db *fsdb;
283         struct list_head *tmp;
284
285         list_for_each(tmp, &mgs->mgs_fs_db_list) {
286                 fsdb = list_entry(tmp, struct fs_db, fsdb_list);
287                 if (strcmp(fsdb->fsdb_name, fsname) == 0)
288                         return fsdb;
289         }
290         return NULL;
291 }
292
293 /* caller must hold the mgs->mgs_fs_db_lock */
294 static struct fs_db *mgs_new_fsdb(struct obd_device *obd, char *fsname)
295 {
296         struct mgs_obd *mgs = &obd->u.mgs;
297         struct fs_db *fsdb;
298         int rc;
299         ENTRY;
300         
301         OBD_ALLOC_PTR(fsdb);
302         if (!fsdb) 
303                 RETURN(NULL);
304
305         OBD_ALLOC(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
306         OBD_ALLOC(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
307         if (!fsdb->fsdb_ost_index_map || !fsdb->fsdb_mdt_index_map) {
308                 CERROR("No memory for index maps\n");
309                 GOTO(err, 0);
310         }
311         
312         strncpy(fsdb->fsdb_name, fsname, sizeof(fsdb->fsdb_name));
313         fsdb->fsdb_name[sizeof(fsdb->fsdb_name) - 1] = 0;
314         rc = name_create(&fsdb->fsdb_mdtlov, fsname, "-mdtlov");
315         if (rc) 
316                 GOTO(err, rc);
317         rc = name_create(&fsdb->fsdb_clilov, fsname, "-clilov");
318         if (rc) 
319                 GOTO(err, rc);
320
321         sema_init(&fsdb->fsdb_sem, 1);
322         list_add(&fsdb->fsdb_list, &mgs->mgs_fs_db_list);
323         lproc_mgs_add_live(obd, fsdb);
324
325         RETURN(fsdb);
326 err:
327         if (fsdb->fsdb_ost_index_map) 
328                 OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
329         if (fsdb->fsdb_mdt_index_map) 
330                 OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
331         name_destroy(&fsdb->fsdb_clilov); 
332         name_destroy(&fsdb->fsdb_mdtlov); 
333         OBD_FREE_PTR(fsdb);
334         RETURN(NULL);
335 }
336
337 static void mgs_free_fsdb(struct obd_device *obd, struct fs_db *fsdb)
338 {
339         /* wait for anyone with the sem */
340         down(&fsdb->fsdb_sem);
341         lproc_mgs_del_live(obd, fsdb);
342         list_del(&fsdb->fsdb_list);
343         OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
344         OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
345         name_destroy(&fsdb->fsdb_clilov); 
346         name_destroy(&fsdb->fsdb_mdtlov); 
347         name_destroy(&fsdb->fsdb_mdc); 
348         OBD_FREE_PTR(fsdb);
349 }
350
351 int mgs_init_fsdb_list(struct obd_device *obd)
352 {
353         struct mgs_obd *mgs = &obd->u.mgs;
354         INIT_LIST_HEAD(&mgs->mgs_fs_db_list);
355         return 0;
356 }
357
358 int mgs_cleanup_fsdb_list(struct obd_device *obd)
359 {
360         struct mgs_obd *mgs = &obd->u.mgs;
361         struct fs_db *fsdb;
362         struct list_head *tmp, *tmp2;
363         down(&mgs->mgs_sem);
364         list_for_each_safe(tmp, tmp2, &mgs->mgs_fs_db_list) {
365                 fsdb = list_entry(tmp, struct fs_db, fsdb_list);
366                 mgs_free_fsdb(obd, fsdb);
367         }
368         up(&mgs->mgs_sem);
369         return 0;
370 }
371
372 static int mgs_find_or_make_fsdb(struct obd_device *obd, char *name, 
373                                struct fs_db **dbh)
374 {
375         struct mgs_obd *mgs = &obd->u.mgs;
376         struct fs_db *fsdb;
377         int rc = 0;
378
379         down(&mgs->mgs_sem);
380         fsdb = mgs_find_fsdb(obd, name);
381         if (fsdb) {
382                 up(&mgs->mgs_sem);
383                 *dbh = fsdb;
384                 return 0;
385         }
386
387         CDEBUG(D_MGS, "Creating new db\n");
388         fsdb = mgs_new_fsdb(obd, name);
389         up(&mgs->mgs_sem);
390         if (!fsdb) 
391                 return -ENOMEM;
392
393         /* populate the db from the client llog */
394         rc = mgs_get_fsdb_from_llog(obd, fsdb);
395         if (rc) {
396                 CERROR("Can't get db from client log %d\n", rc);
397                 mgs_free_fsdb(obd, fsdb);
398                 return rc;
399         }
400
401         *dbh = fsdb;
402         
403         return 0;
404 }
405
406 /* 1 = index in use
407    0 = index unused 
408    -1= empty client log */
409 int mgs_check_index(struct obd_device *obd, struct mgs_target_info *mti)
410 {
411         struct fs_db *fsdb;
412         void *imap;
413         int rc = 0;
414         ENTRY;
415
416         LASSERT(!(mti->mti_flags & LDD_F_NEED_INDEX));
417
418         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb); 
419         if (rc) {
420                 CERROR("Can't get db for %s\n", mti->mti_fsname);
421                 RETURN(rc);
422         }
423
424         if (fsdb->fsdb_flags & FSDB_LOG_EMPTY) 
425                 RETURN(-1);
426
427         if (mti->mti_flags & LDD_F_SV_TYPE_OST) 
428                 imap = fsdb->fsdb_ost_index_map;
429         else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) 
430                 imap = fsdb->fsdb_mdt_index_map;
431         else
432                 RETURN(-EINVAL);
433
434         if (test_bit(mti->mti_stripe_index, imap)) 
435                 RETURN(1);
436         RETURN(0);
437 }
438
439 static __inline__ int next_index(void *index_map, int map_len)
440 {
441         int i;
442         for (i = 0; i < map_len * 8; i++)
443                  if (!test_bit(i, index_map)) {
444                          return i;
445                  }
446         CERROR("max index %d exceeded.\n", i);
447         return -1;
448 }
449
450 /* Return codes:
451         0  newly marked as in use
452         <0 err
453         +EALREADY for update of an old index */
454 int mgs_set_index(struct obd_device *obd, struct mgs_target_info *mti)
455 {
456         struct fs_db *fsdb;
457         void *imap;
458         int rc = 0;
459         ENTRY;
460
461         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb); 
462         if (rc) {
463                 CERROR("Can't get db for %s\n", mti->mti_fsname);
464                 RETURN(rc);
465         }
466
467         if (mti->mti_flags & LDD_F_SV_TYPE_OST) 
468                 imap = fsdb->fsdb_ost_index_map;
469         else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) 
470                 imap = fsdb->fsdb_mdt_index_map;
471         else
472                 RETURN(-EINVAL);
473
474         if (mti->mti_flags & LDD_F_NEED_INDEX) {
475                 rc = next_index(imap, INDEX_MAP_SIZE);
476                 if (rc == -1)
477                         RETURN(-ERANGE);
478                 mti->mti_stripe_index = rc;
479         }
480
481         /* Remove after CMD */
482         if ((mti->mti_flags & LDD_F_SV_TYPE_MDT) && 
483             (mti->mti_stripe_index > 0)) {
484                 LCONSOLE_ERROR_MSG(0x13e, "MDT index must = 0 (until Clustered "
485                                    "MetaData feature is ready.)\n");
486                 mti->mti_stripe_index = 0;
487         }
488
489         if (mti->mti_stripe_index >= INDEX_MAP_SIZE * 8) {
490                 LCONSOLE_ERROR_MSG(0x13f, "Server %s requested index %d, but the"
491                                    "max index is %d.\n", 
492                                    mti->mti_svname, mti->mti_stripe_index,
493                                    INDEX_MAP_SIZE * 8);
494                 RETURN(-ERANGE);
495         }
496
497         if (test_bit(mti->mti_stripe_index, imap)) {
498                 if ((mti->mti_flags & LDD_F_VIRGIN) &&
499                     !(mti->mti_flags & LDD_F_WRITECONF)) {
500                         LCONSOLE_ERROR_MSG(0x140, "Server %s requested index "
501                                            "%d, but that index is already in "
502                                            "use. Use --writeconf to force\n",
503                                            mti->mti_svname,
504                                            mti->mti_stripe_index);
505                         RETURN(-EADDRINUSE);
506                 } else {
507                         CDEBUG(D_MGS, "Server %s updating index %d\n",
508                                mti->mti_svname, mti->mti_stripe_index);
509                         RETURN(EALREADY);
510                 }
511         }
512
513         set_bit(mti->mti_stripe_index, imap);
514         fsdb->fsdb_flags &= ~FSDB_LOG_EMPTY;
515         server_make_name(mti->mti_flags, mti->mti_stripe_index,
516                          mti->mti_fsname, mti->mti_svname);
517
518         CDEBUG(D_MGS, "Set index for %s to %d\n", mti->mti_svname, 
519                mti->mti_stripe_index);
520
521         RETURN(0);
522 }
523
524 struct mgs_modify_lookup {
525         struct cfg_marker mml_marker;
526         int               mml_modified;
527 };
528
529 static int mgs_modify_handler(struct llog_handle *llh, struct llog_rec_hdr *rec, 
530                               void *data)
531 {
532         struct mgs_modify_lookup *mml = (struct mgs_modify_lookup *)data;
533         struct cfg_marker *marker;
534         struct lustre_cfg *lcfg = (struct lustre_cfg *)(rec + 1);
535         int cfg_len = rec->lrh_len - sizeof(struct llog_rec_hdr) - 
536                 sizeof(struct llog_rec_tail);
537         int rc;
538         ENTRY;
539
540         if (rec->lrh_type != OBD_CFG_REC) {
541                 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
542                 RETURN(-EINVAL);
543         }
544
545         rc = lustre_cfg_sanity_check(lcfg, cfg_len);
546         if (rc) {
547                 CERROR("Insane cfg\n");
548                 RETURN(rc);
549         }
550
551         /* We only care about markers */
552         if (lcfg->lcfg_command != LCFG_MARKER)
553                 RETURN(0); 
554         
555         marker = lustre_cfg_buf(lcfg, 1);
556         if ((strcmp(mml->mml_marker.cm_comment, marker->cm_comment) == 0) && 
557             (strcmp(mml->mml_marker.cm_tgtname, marker->cm_tgtname) == 0) &&
558             !(marker->cm_flags & CM_SKIP)) {
559                 /* Found a non-skipped marker match */
560                 CDEBUG(D_MGS, "Changing rec %u marker %d %x->%x: %s %s\n",
561                        rec->lrh_index, marker->cm_step, 
562                        marker->cm_flags, mml->mml_marker.cm_flags,
563                        marker->cm_tgtname, marker->cm_comment);
564                 /* Overwrite the old marker llog entry */
565                 marker->cm_flags &= ~CM_EXCLUDE; /* in case we're unexcluding */
566                 marker->cm_flags |= mml->mml_marker.cm_flags;
567                 marker->cm_canceltime = mml->mml_marker.cm_canceltime;
568                 /* Header and tail are added back to lrh_len in 
569                    llog_lvfs_write_rec */
570                 rec->lrh_len = cfg_len; 
571                 rc = llog_write_rec(llh, rec, NULL, 0, (void *)lcfg, 
572                                     rec->lrh_index);
573                 if (!rc) 
574                          mml->mml_modified++;
575         }
576
577         RETURN(rc);
578 }
579
580 /* Modify an existing config log record (for CM_SKIP or CM_EXCLUDE) */
581 static int mgs_modify(struct obd_device *obd, struct fs_db *fsdb,
582                       struct mgs_target_info *mti, char *logname, 
583                       char *devname, char *comment, int flags)
584 {
585         struct llog_handle *loghandle;
586         struct lvfs_run_ctxt saved;
587         struct llog_ctxt *ctxt;
588         struct mgs_modify_lookup *mml;
589         int rc, rc2;
590         ENTRY;
591
592         CDEBUG(D_MGS, "modify %s/%s/%s\n", logname, devname, comment);
593
594         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
595        
596         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
597         LASSERT(ctxt != NULL);
598         rc = llog_create(ctxt, &loghandle, NULL, logname);
599         if (rc)
600                 GOTO(out_pop, rc);
601
602         rc = llog_init_handle(loghandle, LLOG_F_IS_PLAIN, NULL);
603         if (rc)
604                 GOTO(out_close, rc);
605
606         if (llog_get_size(loghandle) <= 1)
607                 GOTO(out_close, rc = 0);
608
609         OBD_ALLOC_PTR(mml);
610         if (!mml) 
611                 GOTO(out_close, rc = -ENOMEM);
612         strcpy(mml->mml_marker.cm_comment, comment);
613         strcpy(mml->mml_marker.cm_tgtname, devname);
614         /* Modify mostly means cancel */
615         mml->mml_marker.cm_flags = flags;
616         mml->mml_marker.cm_canceltime = flags ? cfs_time_current_sec() : 0;
617         mml->mml_modified = 0;
618         rc = llog_process(loghandle, mgs_modify_handler, (void *)mml, NULL);
619         if (!rc && !mml->mml_modified) 
620                 rc = -ENODEV;
621         OBD_FREE_PTR(mml);
622
623 out_close:
624         rc2 = llog_close(loghandle);
625         if (!rc)
626                 rc = rc2;
627 out_pop:
628         llog_ctxt_put(ctxt);
629         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
630         if (rc && rc != -ENODEV) 
631                 CERROR("modify %s/%s failed %d\n",
632                        mti->mti_svname, comment, rc);
633
634         RETURN(rc);
635 }
636
637                            
638 /******************** config log recording functions *********************/
639
640 static int record_lcfg(struct obd_device *obd, struct llog_handle *llh,
641                          struct lustre_cfg *lcfg)
642 {
643         struct lvfs_run_ctxt   saved;
644         struct llog_rec_hdr    rec;
645         int buflen, rc;
646
647         if (!lcfg || !llh) 
648                 return -ENOMEM;
649
650         LASSERT(llh->lgh_ctxt);        
651
652         buflen = lustre_cfg_len(lcfg->lcfg_bufcount,
653                                 lcfg->lcfg_buflens);
654         rec.lrh_len = llog_data_len(buflen);
655         rec.lrh_type = OBD_CFG_REC;
656         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
657         /* idx = -1 means append */
658         rc = llog_write_rec(llh, &rec, NULL, 0, (void *)lcfg, -1);
659         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
660         if (rc) 
661                 CERROR("failed %d\n", rc);
662         return rc;
663 }
664
665 static int record_base(struct obd_device *obd, struct llog_handle *llh,
666                      char *cfgname, lnet_nid_t nid, int cmd,
667                      char *s1, char *s2, char *s3, char *s4)
668 {
669         struct lustre_cfg_bufs bufs;
670         struct lustre_cfg     *lcfg;
671         int rc;
672                
673         CDEBUG(D_MGS, "lcfg %s %#x %s %s %s %s\n", cfgname,
674                cmd, s1, s2, s3, s4); 
675
676         lustre_cfg_bufs_reset(&bufs, cfgname);
677         if (s1) 
678                 lustre_cfg_bufs_set_string(&bufs, 1, s1);
679         if (s2) 
680                 lustre_cfg_bufs_set_string(&bufs, 2, s2);
681         if (s3) 
682                 lustre_cfg_bufs_set_string(&bufs, 3, s3);
683         if (s4) 
684                 lustre_cfg_bufs_set_string(&bufs, 4, s4);
685
686         lcfg = lustre_cfg_new(cmd, &bufs);
687         if (!lcfg) 
688                 return -ENOMEM;
689         lcfg->lcfg_nid = nid;
690
691         rc = record_lcfg(obd, llh, lcfg);
692         
693         lustre_cfg_free(lcfg);
694         
695         if (rc) {
696                 CERROR("error %d: lcfg %s %#x %s %s %s %s\n", rc, cfgname,
697                        cmd, s1, s2, s3, s4); 
698         }
699         return(rc);
700 }
701
702
703 static inline int record_add_uuid(struct obd_device *obd, 
704                                   struct llog_handle *llh, 
705                                   __u64 nid, char *uuid)
706 {
707         return record_base(obd,llh,NULL,nid,LCFG_ADD_UUID,uuid,0,0,0);
708
709 }
710
711 static inline int record_add_conn(struct obd_device *obd, 
712                                   struct llog_handle *llh,
713                                   char *devname,
714                                   char *uuid)
715 {
716         return record_base(obd,llh,devname,0,LCFG_ADD_CONN,uuid,0,0,0);
717 }
718
719 static inline int record_attach(struct obd_device *obd, struct llog_handle *llh,
720                                 char *devname, char *type, char *uuid)
721 {
722         return record_base(obd,llh,devname,0,LCFG_ATTACH,type,uuid,0,0);
723 }
724
725 static inline int record_setup(struct obd_device *obd, struct llog_handle *llh,
726                                char *devname, 
727                                char *s1, char *s2, char *s3, char *s4)
728 {
729         return record_base(obd,llh,devname,0,LCFG_SETUP,s1,s2,s3,s4);
730 }
731
732 static int record_lov_setup(struct obd_device *obd, struct llog_handle *llh,
733                             char *devname, struct lov_desc *desc)
734 {
735         struct lustre_cfg_bufs bufs;
736         struct lustre_cfg *lcfg;
737         int rc;
738
739         lustre_cfg_bufs_reset(&bufs, devname);
740         lustre_cfg_bufs_set(&bufs, 1, desc, sizeof(*desc));
741         lcfg = lustre_cfg_new(LCFG_SETUP, &bufs);
742         if (!lcfg) 
743                 return -ENOMEM;
744         rc = record_lcfg(obd, llh, lcfg);
745
746         lustre_cfg_free(lcfg);
747         return rc;
748 }
749
750 static inline int record_lov_add(struct obd_device *obd,
751                                  struct llog_handle *llh,
752                                  char *lov_name, char *ost_uuid,
753                                  char *index, char *gen)
754 {
755         return record_base(obd,llh,lov_name,0,LCFG_LOV_ADD_OBD,
756                            ost_uuid,index,gen,0);
757 }                                  
758
759 static inline int record_mount_opt(struct obd_device *obd, 
760                                    struct llog_handle *llh,
761                                    char *profile, char *lov_name,
762                                    char *mdc_name)
763 {
764         return record_base(obd,llh,NULL,0,LCFG_MOUNTOPT,
765                            profile,lov_name,mdc_name,0);
766 }                
767
768 static int record_marker(struct obd_device *obd, struct llog_handle *llh,
769                          struct fs_db *fsdb, __u32 flags,
770                          char *tgtname, char *comment)
771 {
772         struct cfg_marker marker;
773         struct lustre_cfg_bufs bufs;
774         struct lustre_cfg *lcfg;
775         int rc;
776
777         if (flags & CM_START) 
778                 fsdb->fsdb_gen++;
779         marker.cm_step = fsdb->fsdb_gen;
780         marker.cm_flags = flags;
781         marker.cm_vers = LUSTRE_VERSION_CODE;
782         strncpy(marker.cm_tgtname, tgtname, sizeof(marker.cm_tgtname)); 
783         strncpy(marker.cm_comment, comment, sizeof(marker.cm_comment)); 
784         marker.cm_createtime = cfs_time_current_sec();
785         marker.cm_canceltime = 0;
786         lustre_cfg_bufs_reset(&bufs, NULL);
787         lustre_cfg_bufs_set(&bufs, 1, &marker, sizeof(marker));
788         lcfg = lustre_cfg_new(LCFG_MARKER, &bufs);
789         if (!lcfg) 
790                 return -ENOMEM;
791         rc = record_lcfg(obd, llh, lcfg);
792
793         lustre_cfg_free(lcfg);
794         return rc;
795 }
796
797 static int record_start_log(struct obd_device *obd, 
798                             struct llog_handle **llh, char *name)
799 {
800         static struct obd_uuid cfg_uuid = { .uuid = "config_uuid" };
801         struct lvfs_run_ctxt saved;
802         struct llog_ctxt *ctxt;
803         int rc = 0;
804         
805         if (*llh) 
806                 GOTO(out, rc = -EBUSY);
807
808         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
809         if (!ctxt)
810                 GOTO(out, rc = -ENODEV);
811         
812         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
813         rc = llog_create(ctxt, llh, NULL, name);
814         if (rc == 0)
815                 llog_init_handle(*llh, LLOG_F_IS_PLAIN, &cfg_uuid);
816         else
817                 *llh = NULL;
818
819         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
820         llog_ctxt_put(ctxt);
821
822 out:
823         if (rc) {
824                 CERROR("Can't start log %s: %d\n", name, rc);
825         }
826         RETURN(rc);
827 }
828
829 static int record_end_log(struct obd_device *obd, struct llog_handle **llh)
830 {
831         struct lvfs_run_ctxt saved;
832         int rc = 0;
833
834         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
835         
836         rc = llog_close(*llh);
837         *llh = NULL;
838         
839         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
840         RETURN(rc);
841 }
842
843 static int mgs_log_is_empty(struct obd_device *obd, char *name)
844 {
845         struct lvfs_run_ctxt saved;
846         struct llog_handle *llh;
847         struct llog_ctxt *ctxt;
848         int rc = 0;
849
850         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
851         LASSERT(ctxt != NULL);
852         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
853         rc = llog_create(ctxt, &llh, NULL, name);
854         if (rc == 0) {
855                 llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
856                 rc = llog_get_size(llh);
857                 llog_close(llh);
858         }
859         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
860         llog_ctxt_put(ctxt);
861         /* header is record 1 */
862         return(rc <= 1);
863 }
864
865 /******************** config "macros" *********************/
866
867 /* write an lcfg directly into a log (with markers) */
868 static int mgs_write_log_direct(struct obd_device *obd, struct fs_db *fsdb,
869                                 char *logname, struct lustre_cfg *lcfg, 
870                                 char *devname, char *comment)
871 {
872         struct llog_handle *llh = NULL;
873         int rc;
874         ENTRY;
875
876         if (!lcfg) 
877                 RETURN(-ENOMEM);
878
879         rc = record_start_log(obd, &llh, logname);
880         if (rc) 
881                 RETURN(rc);
882         
883         /* FIXME These should be a single journal transaction */
884         rc = record_marker(obd, llh, fsdb, CM_START, devname, comment); 
885         
886         rc = record_lcfg(obd, llh, lcfg);
887
888         rc = record_marker(obd, llh, fsdb, CM_END, devname, comment); 
889         rc = record_end_log(obd, &llh);
890         
891         RETURN(rc);
892 }
893
894 /* write the lcfg in all logs for the given fs */
895 int mgs_write_log_direct_all(struct obd_device *obd, struct fs_db *fsdb,
896                              struct mgs_target_info *mti, 
897                              struct lustre_cfg *lcfg,
898                              char *devname, char *comment)
899 {
900         struct mgs_obd *mgs = &obd->u.mgs;
901         struct list_head dentry_list;
902         struct l_linux_dirent *dirent, *n;
903         char *fsname = mti->mti_fsname;
904         char *logname;
905         int rc = 0, len = strlen(fsname);
906         ENTRY;
907         
908         /* We need to set params for any future logs 
909            as well. FIXME Append this file to every new log. 
910            Actually, we should store as params (text), not llogs.  Or
911            in a database. */
912         name_create(&logname, fsname, "-params");
913         if (mgs_log_is_empty(obd, logname)) {
914                 struct llog_handle *llh = NULL;
915                 rc = record_start_log(obd, &llh, logname);
916                 record_end_log(obd, &llh);
917         }
918         name_destroy(&logname);
919         if (rc) 
920                 RETURN(rc);
921
922         /* Find all the logs in the CONFIGS directory */
923         rc = class_dentry_readdir(obd, mgs->mgs_configs_dir,
924                                   mgs->mgs_vfsmnt, &dentry_list);
925         if (rc) {
926                 CERROR("Can't read %s dir\n", MOUNT_CONFIGS_DIR);
927                 RETURN(rc);
928         }
929                                                                                 
930         /* Could use fsdb index maps instead of directory listing */
931         list_for_each_entry_safe(dirent, n, &dentry_list, lld_list) {
932                 list_del(&dirent->lld_list);
933                 if (strncmp(fsname, dirent->lld_name, len) == 0) {
934                         CDEBUG(D_MGS, "Changing log %s\n", dirent->lld_name);
935                         /* Erase any old settings of this same parameter */
936                         mgs_modify(obd, fsdb, mti, dirent->lld_name, devname, 
937                                    comment, CM_SKIP);
938                         /* Write the new one */
939                         rc = mgs_write_log_direct(obd, fsdb, dirent->lld_name,
940                                                   lcfg, devname, comment);
941                         if (rc)
942                                 CERROR("err %d writing log %s\n", rc, 
943                                        dirent->lld_name);
944                 }
945                 OBD_FREE(dirent, sizeof(*dirent));
946         }
947         
948         RETURN(rc);
949 }
950
951 /* lov is the first thing in the mdt and client logs */
952 static int mgs_write_log_lov(struct obd_device *obd, struct fs_db *fsdb, 
953                              struct mgs_target_info *mti,
954                              char *logname, char *lovname)
955 {
956         struct llog_handle *llh = NULL;
957         struct lov_desc *lovdesc;
958         char *uuid;
959         int rc = 0;
960         ENTRY;
961
962         CDEBUG(D_MGS, "Writing log %s\n", logname);
963
964         /*
965         #01 L attach   0:lov_mdsA  1:lov  2:71ccb_lov_mdsA_19f961a9e1
966         #02 L lov_setup 0:lov_mdsA 1:(struct lov_desc)
967               uuid=lov1_UUID, stripe count=1, size=1048576, offset=0, pattern=0
968         */
969
970         /* FIXME just make lov_setup accept empty desc (put uuid in buf 2) */
971         OBD_ALLOC(lovdesc, sizeof(*lovdesc));
972         if (lovdesc == NULL)
973                 RETURN(-ENOMEM);
974         lovdesc->ld_magic = LOV_DESC_MAGIC;
975         lovdesc->ld_tgt_count = 0;
976         /* Defaults.  Can be changed later by lcfg config_param */ 
977         lovdesc->ld_default_stripe_count = 1;
978         lovdesc->ld_pattern = LOV_PATTERN_RAID0;
979         lovdesc->ld_default_stripe_size = 1024 * 1024;
980         lovdesc->ld_default_stripe_offset = 0;
981         lovdesc->ld_qos_maxage = QOS_DEFAULT_MAXAGE;
982         sprintf((char*)lovdesc->ld_uuid.uuid, "%s_UUID", lovname);
983         /* can these be the same? */
984         uuid = (char *)lovdesc->ld_uuid.uuid;
985
986         /* This should always be the first entry in a log.
987         rc = mgs_clear_log(obd, logname); */
988         rc = record_start_log(obd, &llh, logname);
989         if (rc) 
990                 GOTO(out, rc);
991         /* FIXME these should be a single journal transaction */
992         rc = record_marker(obd, llh, fsdb, CM_START, lovname, "lov setup"); 
993         rc = record_attach(obd, llh, lovname, "lov", uuid);
994         rc = record_lov_setup(obd, llh, lovname, lovdesc);
995         rc = record_marker(obd, llh, fsdb, CM_END, lovname, "lov setup"); 
996         rc = record_end_log(obd, &llh);
997 out:        
998         OBD_FREE(lovdesc, sizeof(*lovdesc));
999         RETURN(rc);
1000 }
1001
1002 /* add failnids to open log */
1003 static int mgs_write_log_failnids(struct obd_device *obd,
1004                                   struct mgs_target_info *mti,
1005                                   struct llog_handle *llh,
1006                                   char *cliname)
1007 {
1008         char *failnodeuuid = NULL;
1009         char *ptr = mti->mti_params;
1010         lnet_nid_t nid;
1011         int rc = 0;
1012
1013         /*
1014         #03 L add_uuid  nid=uml1@tcp(0x20000c0a80201) nal=90 0:  1:uml1_UUID
1015         #04 L add_uuid  nid=1@elan(0x1000000000001)   nal=90 0:  1:uml1_UUID
1016         #05 L setup    0:OSC_uml1_ost1_mdsA  1:ost1_UUID  2:uml1_UUID
1017         #06 L add_uuid  nid=uml2@tcp(0x20000c0a80202) nal=90 0:  1:uml2_UUID
1018         #0x L add_uuid  nid=2@elan(0x1000000000002)   nal=90 0:  1:uml2_UUID
1019         #07 L add_conn 0:OSC_uml1_ost1_mdsA  1:uml2_UUID
1020         */
1021
1022         /* Pull failnid info out of params string */
1023         while (class_find_param(ptr, PARAM_FAILNODE, &ptr) == 0) {
1024                 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
1025                         if (failnodeuuid == NULL) {
1026                                 /* We don't know the failover node name, 
1027                                    so just use the first nid as the uuid */
1028                                 rc = name_create(&failnodeuuid,
1029                                                  libcfs_nid2str(nid), "");
1030                                 if (rc) 
1031                                         return rc;
1032                         }
1033                         CDEBUG(D_MGS, "add nid %s for failover uuid %s, "
1034                                "client %s\n", libcfs_nid2str(nid),
1035                                failnodeuuid, cliname);
1036                         rc = record_add_uuid(obd, llh, nid, failnodeuuid);
1037                 }
1038                 if (failnodeuuid) {
1039                         rc = record_add_conn(obd, llh, cliname, failnodeuuid);
1040                         name_destroy(&failnodeuuid);
1041                         failnodeuuid = NULL;
1042                 }
1043         }
1044
1045         return rc;
1046 }
1047
1048 static int mgs_write_log_mdt(struct obd_device *obd, struct fs_db *fsdb,
1049                              struct mgs_target_info *mti)
1050 {
1051         struct llog_handle *llh = NULL;
1052         char *cliname, *mdcname, *nodeuuid, *mdcuuid;
1053         int rc, i, first_log = 0;
1054         ENTRY;
1055
1056         CDEBUG(D_MGS, "writing new mdt %s\n", mti->mti_svname);
1057         
1058         if (mti->mti_uuid[0] == '\0') {
1059                 /* Make up our own uuid */
1060                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
1061                          "%s_UUID", mti->mti_svname);
1062         }
1063
1064         /* Append mdt info to mdt log */
1065         if (mgs_log_is_empty(obd, mti->mti_svname)) {
1066                 /* This is the first time for all logs for this fs, 
1067                    since any ost should have already started the mdt log. */
1068                 first_log++;
1069                 rc = mgs_write_log_lov(obd, fsdb, mti, mti->mti_svname,
1070                                        fsdb->fsdb_mdtlov);
1071         } 
1072         /* else there's already some ost entries in the mdt log. */
1073
1074         /* We added the lov, maybe some osc's, now for the mdt.
1075            We might add more ost's after this. Note that during the parsing
1076            of this log, this is when the mdt will start. (This was not 
1077            formerly part of the old mds log, it was directly executed by
1078            lconf.) */ 
1079         /*
1080         mount_option 0:  1:mdsA  2:lov_mdsA
1081         attach mds mdsA mdsA_UUID
1082         setup /dev/loop2 ldiskfs mdsA errors=remount-ro,user_xattr
1083         */
1084         rc = record_start_log(obd, &llh, mti->mti_svname);
1085         if (rc) 
1086                 RETURN(rc);
1087         /* FIXME this whole fn should be a single journal transaction */
1088         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,"add mdt"); 
1089         rc = record_mount_opt(obd, llh, mti->mti_svname, fsdb->fsdb_mdtlov, 0);
1090         rc = record_attach(obd, llh, mti->mti_svname, LUSTRE_MDS_NAME, 
1091                            mti->mti_uuid);
1092         rc = record_setup(obd, llh, mti->mti_svname,
1093                           mti->mti_uuid /* Ignored. Compatible with future. */,
1094                           "0" /* MDT Index, default to zero. */,
1095                           mti->mti_svname,
1096                           0 /* options */);
1097         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname, "add mdt"); 
1098         rc = record_end_log(obd, &llh);
1099
1100         /* Append the mdt info to the client log */
1101         name_create(&cliname, mti->mti_fsname, "-client");
1102         if (first_log) { 
1103                 /* Start client log */
1104                 rc = mgs_write_log_lov(obd, fsdb, mti, cliname,
1105                                        fsdb->fsdb_clilov);
1106         }
1107
1108         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]),/*"_UUID"*/"");
1109         name_create(&mdcname, mti->mti_svname, "-mdc");
1110         name_create(&mdcuuid, mdcname, "_UUID");
1111         /* 
1112         #09 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
1113         #10 L attach   0:MDC_uml1_mdsA_MNT_client  1:mdc  2:1d834_MNT_client_03f
1114         #11 L setup    0:MDC_uml1_mdsA_MNT_client  1:mdsA_UUID  2:uml1_UUID
1115         #12 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
1116         #13 L add_conn 0:MDC_uml1_mdsA_MNT_client  1:uml2_UUID
1117         #14 L mount_option 0:  1:client  2:lov1  3:MDC_uml1_mdsA_MNT_client
1118         */
1119         rc = record_start_log(obd, &llh, cliname);
1120         if (rc) 
1121                 GOTO(out, rc);
1122         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,"add mdc");
1123         /* COMPAT_146 */
1124         if (fsdb->fsdb_flags & FSDB_OLDLOG14) {
1125                 /* Old client log already has MDC entry, but needs mount opt 
1126                    for new client name (lustre-client) */
1127                 /* FIXME Old MDT log already has an old mount opt 
1128                    which we should remove (currently handled by
1129                    class_del_profiles()) */
1130                 rc = record_mount_opt(obd, llh, cliname, fsdb->fsdb_clilov,
1131                                       fsdb->fsdb_mdc);
1132                 /* Only add failnids with --writeconf 
1133                 rc = mgs_write_log_failnids(obd, mti, llh, fsdb->fsdb_mdc);
1134                 */
1135                 /* end COMPAT_146 */
1136         } else {
1137                 for (i = 0; i < mti->mti_nid_count; i++) {
1138                         CDEBUG(D_MGS, "add nid %s\n",
1139                                libcfs_nid2str(mti->mti_nids[i]));
1140                         rc = record_add_uuid(obd, llh, mti->mti_nids[i],
1141                                              nodeuuid);
1142                 }
1143                 rc = record_attach(obd, llh, mdcname, LUSTRE_MDC_NAME, mdcuuid);
1144                 rc = record_setup(obd, llh, mdcname, mti->mti_uuid,nodeuuid,
1145                                   0, 0);
1146                 rc = mgs_write_log_failnids(obd, mti, llh, mdcname);
1147                 rc = record_mount_opt(obd, llh, cliname, fsdb->fsdb_clilov,
1148                                       mdcname);
1149         }
1150         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname, "add mdc"); 
1151         rc = record_end_log(obd, &llh);
1152 out:
1153         name_destroy(&mdcuuid);
1154         name_destroy(&mdcname);
1155         name_destroy(&nodeuuid);
1156         name_destroy(&cliname);
1157         RETURN(rc);
1158 }
1159
1160 /* Add the ost info to the client/mdt lov */
1161 static int mgs_write_log_osc(struct obd_device *obd, struct fs_db *fsdb,
1162                              struct mgs_target_info *mti,
1163                              char *logname, char *lovname, int flags)
1164 {
1165         struct llog_handle *llh = NULL;
1166         char *nodeuuid, *oscname, *oscuuid, *lovuuid;
1167         char index[5];
1168         int i, rc;
1169
1170         if (mgs_log_is_empty(obd, logname)) {
1171                 /* The first item in the log must be the lov, so we have
1172                    somewhere to add our osc. */
1173                 rc = mgs_write_log_lov(obd, fsdb, mti, logname, lovname);
1174         }
1175   
1176         CDEBUG(D_MGS, "adding osc for %s to log %s\n",
1177                mti->mti_svname, logname);
1178
1179         name_create(&nodeuuid, libcfs_nid2str(mti->mti_nids[0]), "");
1180         name_create(&oscname, mti->mti_svname, "-osc");
1181         name_create(&oscuuid, oscname, "_UUID");
1182         name_create(&lovuuid, lovname, "_UUID");
1183
1184         /*
1185         #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0:  1:uml1_UUID
1186         multihomed (#4)
1187         #04 L add_uuid  nid=1@elan(0x1000000000001)  nal=90 0:  1:uml1_UUID
1188         #04 L attach   0:OSC_uml1_ost1_MNT_client  1:osc  2:89070_lov1_a41dff51a
1189         #05 L setup    0:OSC_uml1_ost1_MNT_client  1:ost1_UUID  2:uml1_UUID
1190         failover (#6,7)
1191         #06 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0:  1:uml2_UUID
1192         #07 L add_conn 0:OSC_uml1_ost1_MNT_client  1:uml2_UUID
1193         #08 L lov_modify_tgts add 0:lov1  1:ost1_UUID  2(index):0  3(gen):1
1194         */
1195         rc = record_start_log(obd, &llh, logname);
1196         if (rc) 
1197                 GOTO(out, rc);
1198         /* FIXME these should be a single journal transaction */
1199         rc = record_marker(obd, llh, fsdb, CM_START | flags, mti->mti_svname,
1200                            "add osc"); 
1201         for (i = 0; i < mti->mti_nid_count; i++) {
1202                 CDEBUG(D_MGS, "add nid %s\n", libcfs_nid2str(mti->mti_nids[i]));
1203                 rc = record_add_uuid(obd, llh, mti->mti_nids[i], nodeuuid);
1204         }
1205         rc = record_attach(obd, llh, oscname, LUSTRE_OSC_NAME, lovuuid);
1206         rc = record_setup(obd, llh, oscname, mti->mti_uuid, nodeuuid, 0, 0);
1207         rc = mgs_write_log_failnids(obd, mti, llh, oscname);
1208         snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
1209         rc = record_lov_add(obd, llh, lovname, mti->mti_uuid, index, "1");
1210         rc = record_marker(obd, llh, fsdb, CM_END | flags, mti->mti_svname,
1211                            "add osc"); 
1212         rc = record_end_log(obd, &llh);
1213 out:        
1214         name_destroy(&lovuuid);
1215         name_destroy(&oscuuid);
1216         name_destroy(&oscname);
1217         name_destroy(&nodeuuid);
1218         return rc;
1219 }
1220
1221 static int mgs_write_log_ost(struct obd_device *obd, struct fs_db *fsdb,
1222                              struct mgs_target_info *mti)
1223 {
1224         struct llog_handle *llh = NULL;
1225         char *logname;
1226         char *ptr = mti->mti_params;
1227         int rc, flags = 0, failout = 0;
1228         ENTRY;
1229         
1230         CDEBUG(D_MGS, "writing new ost %s\n", mti->mti_svname);
1231
1232         /* The ost startup log */
1233
1234         /* If the ost log already exists, that means that someone reformatted
1235            the ost and it called target_add again. */
1236         if (!mgs_log_is_empty(obd, mti->mti_svname)) {
1237                 LCONSOLE_ERROR_MSG(0x141, "The config log for %s already "
1238                                    "exists, yet the server claims it never "
1239                                    "registered. It may have been reformatted, "
1240                                    "or the index changed. writeconf the MDT to "
1241                                    "regenerate all logs.\n", mti->mti_svname);
1242                 RETURN(-EALREADY);
1243         }
1244         /*
1245         attach obdfilter ost1 ost1_UUID
1246         setup /dev/loop2 ldiskfs f|n errors=remount-ro,user_xattr
1247         */
1248         if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0) 
1249                 failout = (strncmp(ptr, "failout", 7) == 0);
1250         rc = record_start_log(obd, &llh, mti->mti_svname);
1251         if (rc) 
1252                 RETURN(rc);
1253         /* FIXME these should be a single journal transaction */
1254         rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,"add ost"); 
1255         if (*mti->mti_uuid == '\0') 
1256                 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
1257                          "%s_UUID", mti->mti_svname);
1258         rc = record_attach(obd, llh, mti->mti_svname,
1259                            "obdfilter"/*LUSTRE_OST_NAME*/, mti->mti_uuid);
1260         rc = record_setup(obd, llh, mti->mti_svname,
1261                           "dev"/*ignored*/, "type"/*ignored*/,
1262                           failout ? "n" : "f", 0/*options*/);
1263         rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname, "add ost"); 
1264         rc = record_end_log(obd, &llh);
1265
1266         /* We also have to update the other logs where this osc is part of 
1267            the lov */
1268
1269         if (fsdb->fsdb_flags & FSDB_OLDLOG14) {
1270                 /* If we're upgrading, the old mdt log already has our
1271                    entry. Let's do a fake one for fun. */
1272                 /* Note that we can't add any new failnids, since we don't
1273                    know the old osc names. */
1274                 flags = CM_SKIP | CM_UPGRADE146;
1275         } else if ((mti->mti_flags & LDD_F_UPDATE) != LDD_F_UPDATE) {
1276                 /* If the update flag isn't set, don't really update
1277                    client/mdt logs. */
1278                 flags |= CM_SKIP;
1279                 LCONSOLE_WARN("Client log for %s was not updated; writeconf "
1280                               "the MDT first to regenerate it.\n",
1281                               mti->mti_svname);
1282         }
1283         
1284         /* Append ost info to mdt log */
1285         /* FIXME add to all MDT logs for CMD */
1286         /* FIXME need real MDT name, but MDT may not have registered yet! */
1287         name_create(&logname, mti->mti_fsname, "-MDT0000");
1288         rc = mgs_write_log_osc(obd, fsdb, mti, logname, fsdb->fsdb_mdtlov,
1289                                flags);
1290         name_destroy(&logname);
1291         
1292         /* Append ost info to the client log */
1293         name_create(&logname, mti->mti_fsname, "-client");
1294         rc = mgs_write_log_osc(obd, fsdb, mti, logname, fsdb->fsdb_clilov, 
1295                                flags);
1296         name_destroy(&logname);
1297         
1298         RETURN(rc);
1299 }
1300
1301 /* Add additional failnids to an existing log.  
1302    The mdc/osc must have been added to logs first */
1303 /* tcp nids must be in dotted-quad ascii -
1304    we can't resolve hostnames from the kernel. */
1305 static int mgs_write_log_add_failnid(struct obd_device *obd, struct fs_db *fsdb,
1306                                      struct mgs_target_info *mti)
1307 {
1308         char *logname, *cliname;
1309         struct llog_handle *llh = NULL;
1310         int rc;
1311         ENTRY;
1312
1313         /* FIXME how do we delete a failnid? Currently --writeconf is the
1314            only way.  Maybe make --erase-params pass a flag to really 
1315            erase all params from logs - except it can't erase the failnids
1316            given when a target first registers, since they aren't processed
1317            as params... */
1318
1319         /* Verify that we know about this target */
1320         if (mgs_log_is_empty(obd, mti->mti_svname)) {
1321                 LCONSOLE_ERROR_MSG(0x142, "The target %s has not registered "
1322                                    "yet. It must be started before failnids can"
1323                                    " be added.\n", mti->mti_svname);
1324                 RETURN(-ENOENT);
1325         }
1326
1327         /* Create mdc/osc client name (e.g. lustre-OST0001-osc) */
1328         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
1329                 /* COMPAT_146 */ 
1330                 if (fsdb->fsdb_mdc)
1331                         name_create(&cliname, fsdb->fsdb_mdc, "");
1332                 else 
1333                         name_create(&cliname, mti->mti_svname, "-mdc");
1334         } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1335                 /* COMPAT_146 */
1336                 if (fsdb->fsdb_flags & FSDB_OLDLOG14) {
1337                         LCONSOLE_ERROR_MSG(0x143, "Failover NIDs cannot be "
1338                                            "added to upgraded client logs for "
1339                                            "%s. Consider updating the "
1340                                            "configuration with --writeconf.\n", 
1341                                            mti->mti_svname);
1342                         RETURN(-EINVAL);
1343                 }
1344                 name_create(&cliname, mti->mti_svname, "-osc");
1345         } else {
1346                 RETURN(-EINVAL);
1347         }
1348         
1349         /* Add failover nids to client log */
1350         name_create(&logname, mti->mti_fsname, "-client");
1351         rc = record_start_log(obd, &llh, logname);
1352         if (!rc) { 
1353                 /* FIXME this fn should be a single journal transaction */
1354                 rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,
1355                                    "add failnid");
1356                 rc = mgs_write_log_failnids(obd, mti, llh, cliname);
1357                 rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname,
1358                                    "add failnid"); 
1359                 rc = record_end_log(obd, &llh);
1360         }
1361         name_destroy(&logname);
1362
1363         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1364                 /* Add OST failover nids to the MDT log as well */
1365                 name_create(&logname, mti->mti_fsname, "-MDT0000");
1366                 rc = record_start_log(obd, &llh, logname);
1367                 if (!rc) {
1368                         rc = record_marker(obd, llh, fsdb, CM_START, 
1369                                            mti->mti_svname, "add failnid");
1370                         rc = mgs_write_log_failnids(obd, mti, llh, cliname);
1371                         rc = record_marker(obd, llh, fsdb, CM_END, 
1372                                            mti->mti_svname, "add failnid"); 
1373                         rc = record_end_log(obd, &llh);
1374                 }
1375                 name_destroy(&logname);
1376         }
1377
1378         name_destroy(&cliname);
1379         RETURN(rc);
1380 }
1381
1382 static int mgs_wlp_lcfg(struct obd_device *obd, struct fs_db *fsdb, 
1383                         struct mgs_target_info *mti,
1384                         char *logname, struct lustre_cfg_bufs *bufs,
1385                         char *tgtname, char *ptr)
1386 {
1387         char comment[MTI_NAME_MAXLEN];
1388         char *tmp;
1389         struct lustre_cfg *lcfg;
1390         int rc;
1391         
1392         /* Erase any old settings of this same parameter */
1393         memcpy(comment, ptr, MTI_NAME_MAXLEN);
1394         comment[MTI_NAME_MAXLEN - 1] = 0;
1395         /* But don't try to match the value. */
1396         if ((tmp = strchr(comment, '=')))
1397             *tmp = 0;
1398         /* FIXME we should skip settings that are the same as old values */
1399         rc = mgs_modify(obd, fsdb, mti, logname, tgtname, comment, CM_SKIP);
1400         LCONSOLE_INFO("%sing parameter %s.%s in log %s\n", rc ?
1401                       "Sett" : "Modify", tgtname, comment, logname);
1402
1403         lustre_cfg_bufs_reset(bufs, tgtname);
1404         lustre_cfg_bufs_set_string(bufs, 1, ptr);
1405         lcfg = lustre_cfg_new(LCFG_PARAM, bufs);
1406         if (!lcfg) 
1407                 return -ENOMEM;
1408         rc = mgs_write_log_direct(obd, fsdb, logname, lcfg, tgtname, comment);
1409         lustre_cfg_free(lcfg);
1410         return rc;
1411 }
1412
1413 static int mgs_write_log_params(struct obd_device *obd, struct fs_db *fsdb,
1414                                 struct mgs_target_info *mti)
1415 {
1416         struct lustre_cfg_bufs bufs;
1417         struct lustre_cfg *lcfg;
1418         char *logname;
1419         char *ptr = mti->mti_params;
1420         char *endptr, *tmp;
1421         int rc = 0;
1422         ENTRY;
1423
1424         if (!mti->mti_params) 
1425                 RETURN(0);
1426
1427         /* For various parameter settings, we have to figure out which logs
1428            care about them (e.g. both mdt and client for lov settings) */
1429         while (ptr) {
1430                 while (*ptr == ' ') 
1431                         ptr++;
1432                 if (*ptr == '\0')
1433                         break;
1434                 endptr = strchr(ptr, ' ');
1435                 if (endptr) 
1436                         *endptr = '\0';
1437                 CDEBUG(D_MGS, "next param '%s'\n", ptr);
1438
1439                 /* The params are stored in MOUNT_DATA_FILE and modified 
1440                    via tunefs.lustre */
1441
1442                 /* Processed in lustre_start_mgc */
1443                 if (class_match_param(ptr, PARAM_MGSNODE, NULL) == 0) 
1444                         goto end_while;
1445
1446                 /* Processed in mgs_write_log_ost */
1447                 if (class_match_param(ptr, PARAM_FAILMODE, NULL) == 0) {
1448                         if (mti->mti_flags & LDD_F_PARAM) {
1449                                 LCONSOLE_ERROR_MSG(0x169, "%s can only be "
1450                                                    "changed with tunefs.lustre "
1451                                                    "and --writeconf\n", ptr);
1452                                 rc = -EPERM;
1453                         }
1454                         goto end_while;
1455                 }
1456
1457                 if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
1458                         /* Add a failover nidlist */
1459                         rc = 0;
1460                         /* We already processed failovers params for new
1461                            targets in mgs_write_log_target */
1462                         if (mti->mti_flags & LDD_F_PARAM) {
1463                                 CDEBUG(D_MGS, "Adding failnode\n");
1464                                 rc = mgs_write_log_add_failnid(obd, fsdb, mti);
1465                         }
1466                         goto end_while;
1467                 }
1468
1469                 if (class_match_param(ptr, PARAM_SYS_TIMEOUT, &tmp) == 0) {
1470                         /* Change obd timeout */
1471                         int timeout;
1472                         timeout = simple_strtoul(tmp, NULL, 0);
1473
1474                         CDEBUG(D_MGS, "obd timeout %d\n", timeout);
1475                         
1476                         lustre_cfg_bufs_reset(&bufs, NULL);
1477                         lcfg = lustre_cfg_new(LCFG_SET_TIMEOUT, &bufs);
1478                         lcfg->lcfg_num = timeout;
1479                         /* modify all servers and clients */
1480                         rc = mgs_write_log_direct_all(obd, fsdb, mti, lcfg,
1481                                                       mti->mti_fsname,
1482                                                       "timeout"); 
1483                         lustre_cfg_free(lcfg);
1484                         goto end_while;
1485                 }
1486
1487                 if (class_match_param(ptr, PARAM_LDLM_TIMEOUT, &tmp) == 0) {
1488                         /* Change ldlm timeout */
1489                         int timeout;
1490                         timeout = simple_strtoul(tmp, NULL, 0);
1491
1492                         CDEBUG(D_MGS, "ldlm timeout %d\n", timeout);
1493                         
1494                         lustre_cfg_bufs_reset(&bufs, NULL);
1495                         lcfg = lustre_cfg_new(LCFG_SET_LDLM_TIMEOUT, &bufs);
1496                         lcfg->lcfg_num = timeout;
1497                         /* modify all servers and clients */
1498                         rc = mgs_write_log_direct_all(obd, fsdb, mti, lcfg,
1499                                                       mti->mti_fsname,
1500                                                       "ldlm_timeout"); 
1501                         lustre_cfg_free(lcfg);
1502                         goto end_while;
1503                 }
1504
1505                 if (class_match_param(ptr, PARAM_OSC""PARAM_ACTIVE, &tmp) == 0){ 
1506                         /* active=0 means off, anything else means on */
1507                         int flag = (*tmp == '0') ? CM_EXCLUDE : 0;
1508                         if (!(mti->mti_flags & LDD_F_SV_TYPE_OST)) {
1509                                 LCONSOLE_ERROR_MSG(0x144, "%s: Only OSCs can be"
1510                                                    " (de)activated.\n", 
1511                                                    mti->mti_svname);
1512                                 rc = -EINVAL;
1513                                 goto end_while;
1514                         }
1515                         LCONSOLE_WARN("Permanently %sactivating %s\n",
1516                                       flag ? "de": "re", mti->mti_svname);
1517                         /* Modify clilov */
1518                         name_create(&logname, mti->mti_fsname, "-client");
1519                         rc = mgs_modify(obd, fsdb, mti, logname, 
1520                                         mti->mti_svname, "add osc", flag);
1521                         name_destroy(&logname);
1522                         if (rc) 
1523                                 goto active_err;
1524                         /* Modify mdtlov */
1525                         /* FIXME add to all MDT logs for CMD */
1526                         name_create(&logname, mti->mti_fsname, "-MDT0000");
1527                         rc = mgs_modify(obd, fsdb, mti, logname, 
1528                                         mti->mti_svname, "add osc", flag);
1529                         name_destroy(&logname);
1530 active_err:
1531                         if (rc) {
1532                                 LCONSOLE_ERROR_MSG(0x145, "Couldn't find %s in "
1533                                                   "log (%d). No permanent "
1534                                                   "changes were made to the "
1535                                                   "config log.\n", 
1536                                                   mti->mti_svname, rc);
1537                                 if (fsdb->fsdb_flags & FSDB_OLDLOG14) 
1538                                         LCONSOLE_ERROR_MSG(0x146, "This may be "
1539                                         "because the log is in the old 1.4 "
1540                                         "style. Consider --writeconf to "
1541                                         "update the logs.\n");
1542                                 goto end_while;
1543                         }
1544                         /* Fall through to osc proc for deactivating 
1545                            live OSC on running MDT / clients. */
1546                 }
1547
1548                 /* Below here, let obd's XXX_process_config methods handle it */
1549
1550                 /* All lov. in proc */
1551                 if (class_match_param(ptr, PARAM_LOV, NULL) == 0) {
1552                         CDEBUG(D_MGS, "lov param %s\n", ptr);
1553                         if (!(mti->mti_flags & LDD_F_SV_TYPE_MDT)) {
1554                                 LCONSOLE_ERROR_MSG(0x147, "LOV params must be "
1555                                                    "set on the MDT, not %s. "
1556                                                    "Ignoring.\n", 
1557                                                    mti->mti_svname);
1558                                 rc = 0;
1559                                 goto end_while;
1560                         }
1561
1562                         /* Modify mdtlov */
1563                         if (mgs_log_is_empty(obd, mti->mti_svname)) {
1564                                 rc = -ENODEV;
1565                                 goto end_while;
1566                         }
1567                         rc = mgs_wlp_lcfg(obd, fsdb, mti, mti->mti_svname, 
1568                                           &bufs, fsdb->fsdb_mdtlov, ptr);
1569                         if (rc) 
1570                                 goto end_while;
1571
1572                         /* Modify clilov */
1573                         name_create(&logname, mti->mti_fsname, "-client");
1574                         rc = mgs_wlp_lcfg(obd, fsdb, mti, logname, &bufs,
1575                                           fsdb->fsdb_clilov, ptr);
1576                         name_destroy(&logname);
1577                         goto end_while;
1578                 }
1579
1580                 /* All osc., mdc., llite. params in proc */
1581                 if ((class_match_param(ptr, PARAM_OSC, NULL) == 0) || 
1582                     (class_match_param(ptr, PARAM_MDC, NULL) == 0) || 
1583                     (class_match_param(ptr, PARAM_LLITE, NULL) == 0)) {
1584                         char *cname;
1585                         if (memcmp(ptr, PARAM_LLITE, strlen(PARAM_LLITE)) == 0) {
1586                                 name_create(&cname, mti->mti_fsname, "-client");
1587                         /* Add the client type to match the obdname 
1588                            in class_config_llog_handler */
1589                         } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
1590                                 /* COMPAT_146 */
1591                                 if (fsdb->fsdb_mdc)
1592                                         name_create(&cname, fsdb->fsdb_mdc, "");
1593                                 else
1594                                         name_create(&cname, mti->mti_svname, 
1595                                                     "-mdc");
1596                         } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1597                                 /* COMPAT_146 */
1598                                 if (fsdb->fsdb_flags & FSDB_OLDLOG14) {
1599                                       LCONSOLE_ERROR_MSG(0x148, "Upgraded client"
1600                                            " logs for %s cannot be modified. "
1601                                            "Consider updating the "
1602                                            "configuration with --writeconf\n",
1603                                            mti->mti_svname);
1604                                         /* We don't know the names of all the
1605                                            old oscs*/
1606                                         rc = -EINVAL;
1607                                         goto end_while;
1608                                 }
1609                                 name_create(&cname, mti->mti_svname, "-osc");
1610                         } else {       
1611                                 rc = -EINVAL;
1612                                 goto end_while;
1613                         }
1614
1615                         CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
1616                         
1617                         /* Modify client */
1618                         name_create(&logname, mti->mti_fsname, "-client");
1619                         rc = mgs_wlp_lcfg(obd, fsdb, mti, logname, &bufs, 
1620                                           cname, ptr);
1621                         name_destroy(&logname);
1622                         
1623                         /* osc params affect the MDT as well */
1624                         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1625                                 /* FIXME add to all MDT logs for CMD */
1626                                 name_create(&logname, mti->mti_fsname,
1627                                             "-MDT0000");
1628                                 if (!mgs_log_is_empty(obd, logname))
1629                                         rc = mgs_wlp_lcfg(obd, fsdb, mti,
1630                                                           logname, &bufs, 
1631                                                           cname, ptr);
1632                                 name_destroy(&logname);
1633                         }
1634                         name_destroy(&cname);
1635                         goto end_while;
1636                 }
1637
1638                 /* All mdt., ost. params in proc */
1639                 if ((class_match_param(ptr, PARAM_MDT, NULL) == 0) || 
1640                     (class_match_param(ptr, PARAM_OST, NULL) == 0)) {
1641                         CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
1642                         if (mgs_log_is_empty(obd, mti->mti_svname)) {
1643                                 rc = -ENODEV;
1644                                 goto end_while;
1645                         }
1646                         rc = mgs_wlp_lcfg(obd, fsdb, mti, mti->mti_svname,
1647                                           &bufs, mti->mti_svname, ptr);
1648                         goto end_while;
1649                 }
1650
1651                 LCONSOLE_WARN("Ignoring unrecognized param '%s'\n", ptr);
1652
1653 end_while:
1654                 if (rc) {
1655                         CERROR("err %d on param '%s\n", rc, ptr);
1656                         break;
1657                 }
1658                 
1659                 if (!endptr)
1660                         /* last param */
1661                         break;
1662                  
1663                 *endptr = ' ';
1664                 ptr = endptr + 1;
1665         }
1666
1667         RETURN(rc);
1668 }
1669
1670 int mgs_check_failnid(struct obd_device *obd, struct mgs_target_info *mti)
1671 {
1672         /* Not implementing automatic failover nid addition at this time. */
1673         return 0;
1674 #if 0
1675         struct fs_db *fsdb;
1676         int rc;
1677         ENTRY;
1678
1679         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb); 
1680         if (rc) 
1681                 RETURN(rc);
1682
1683         if (mgs_log_is_empty(obd, mti->mti_svname)) 
1684                 /* should never happen */
1685                 RETURN(-ENOENT);
1686
1687         CDEBUG(D_MGS, "Checking for new failnids for %s\n", mti->mti_svname);
1688
1689         /* FIXME We can just check mti->params to see if we're already in
1690            the failover list.  Modify mti->params for rewriting back at 
1691            server_register_target(). */
1692         
1693         down(&fsdb->fsdb_sem);
1694         rc = mgs_write_log_add_failnid(obd, fsdb, mti);
1695         up(&fsdb->fsdb_sem);
1696
1697         RETURN(rc);
1698 #endif
1699 }
1700
1701 int mgs_write_log_target(struct obd_device *obd,
1702                          struct mgs_target_info *mti)
1703 {
1704         struct fs_db *fsdb;
1705         int rc = -EINVAL;
1706         ENTRY;
1707
1708         /* set/check the new target index */
1709         rc = mgs_set_index(obd, mti);
1710         if (rc < 0) {
1711                 CERROR("Can't get index (%d)\n", rc);
1712                 RETURN(rc);
1713         }
1714         /* COMPAT_146 */
1715         if (mti->mti_flags & LDD_F_UPGRADE14) {
1716                 if (rc == EALREADY) {
1717                         LCONSOLE_INFO("Found index %d for %s 1.4 log, "
1718                                       "upgrading\n", mti->mti_stripe_index, 
1719                                       mti->mti_svname);
1720                 } else {
1721                         LCONSOLE_ERROR_MSG(0x149, "Failed to find %s in the old"
1722                                            " client log. Apparently it is not "
1723                                            "part of this filesystem, or the old"
1724                                            " log is wrong.\nUse 'writeconf' on "
1725                                            "the MDT to force log regeneration."
1726                                            "\n", mti->mti_svname);
1727                         /* Not in client log?  Upgrade anyhow...*/
1728                         /* Argument against upgrading: reformat MDT,
1729                            upgrade OST, then OST will start but will be SKIPped
1730                            in client logs.  Maybe error now is better. */
1731                         /* RETURN(-EINVAL); */
1732                 }
1733                 /* end COMPAT_146 */
1734         } else {
1735                 if (rc == EALREADY) {
1736                         /* This might be a params update, or a 
1737                            local writeconf. (For "full" writeconf, the client
1738                            log won't have an entry for this target, so we 
1739                            won't get here.) */
1740                         LCONSOLE_WARN("Found index %d for %s, updating log\n", 
1741                                       mti->mti_stripe_index, mti->mti_svname);
1742                         /* We would like to mark old log sections as invalid 
1743                            and add new log sections in the client and mdt logs.
1744                            But if we add new sections, then live clients will
1745                            get repeat setup instructions for already running
1746                            osc's. So don't update the client/mdt logs. */
1747                         mti->mti_flags &= ~LDD_F_UPDATE;
1748                 }
1749         }
1750
1751         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb); 
1752         if (rc) {
1753                 CERROR("Can't get db for %s\n", mti->mti_fsname);
1754                 RETURN(rc);
1755         }
1756
1757         down(&fsdb->fsdb_sem);
1758
1759         if (mti->mti_flags & 
1760             (LDD_F_VIRGIN | LDD_F_UPGRADE14 | LDD_F_WRITECONF)) {
1761                 /* Generate a log from scratch */
1762                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
1763                         rc = mgs_write_log_mdt(obd, fsdb, mti);
1764                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1765                         rc = mgs_write_log_ost(obd, fsdb, mti);
1766                 } else {
1767                         CERROR("Unknown target type %#x, can't create log for "
1768                                "%s\n", mti->mti_flags, mti->mti_svname);
1769                 }
1770                 if (rc) {
1771                         CERROR("Can't write logs for %s (%d)\n",
1772                                mti->mti_svname, rc);
1773                         GOTO(out_up, rc);
1774                 }
1775         } else {
1776                 /* Just update the params from tunefs in mgs_write_log_params */
1777                 CDEBUG(D_MGS, "Update params for %s\n", mti->mti_svname);
1778                 mti->mti_flags |= LDD_F_PARAM;
1779         }
1780         
1781         rc = mgs_write_log_params(obd, fsdb, mti);
1782
1783 out_up:
1784         up(&fsdb->fsdb_sem);
1785         RETURN(rc);
1786 }
1787
1788 /* COMPAT_146 */
1789 /* verify that we can handle the old config logs */ 
1790 int mgs_upgrade_sv_14(struct obd_device *obd, struct mgs_target_info *mti)
1791 {
1792         struct fs_db *fsdb;
1793         int rc = 0;
1794         ENTRY;
1795
1796         /* Create ost log normally, as servers register.  Servers 
1797            register with their old uuids (from last_rcvd), so old
1798            (MDT and client) logs should work.
1799          - new MDT won't know about old OSTs, only the ones that have 
1800            registered, so we need the old MDT log to get the LOV right 
1801            in order for old clients to work. 
1802          - Old clients connect to the MDT, not the MGS, for their logs, and 
1803            will therefore receive the old client log from the MDT /LOGS dir. 
1804          - Old clients can continue to use and connect to old or new OSTs
1805          - New clients will contact the MGS for their log 
1806         */
1807
1808         LCONSOLE_INFO("upgrading server %s from pre-1.6\n", mti->mti_svname); 
1809         server_mti_print("upgrade", mti);
1810         
1811         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb);
1812         if (rc) 
1813                 RETURN(rc);
1814         
1815         if (fsdb->fsdb_flags & FSDB_LOG_EMPTY) {
1816                 LCONSOLE_ERROR_MSG(0x14a, "The old client log %s-client is "
1817                                    "missing.  Was tunefs.lustre successful?\n",
1818                                    mti->mti_fsname);
1819                 RETURN(-ENOENT);
1820         }
1821
1822         if (fsdb->fsdb_gen == 0) {
1823                 /* There were no markers in the client log, meaning we have 
1824                    not updated the logs for this fs */
1825                 CDEBUG(D_MGS, "found old, unupdated client log\n");
1826         }
1827
1828         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
1829                 if (mgs_log_is_empty(obd, mti->mti_svname)) {
1830                         LCONSOLE_ERROR_MSG(0x14b, "The old MDT log %s is "
1831                                            "missing. Was tunefs.lustre "
1832                                            "successful?\n",
1833                                            mti->mti_svname);
1834                         RETURN(-ENOENT);
1835                 }
1836
1837                 /* We're starting with an old uuid.  Assume old name for lov
1838                    as well since the lov entry already exists in the log. */
1839                 CDEBUG(D_MGS, "old mds uuid %s\n", mti->mti_uuid);
1840                 if (strncmp(mti->mti_uuid, fsdb->fsdb_mdtlov + 4, 
1841                             strlen(fsdb->fsdb_mdtlov) - 4) != 0) {
1842                         CERROR("old mds uuid %s doesn't match log %s (%s)\n",
1843                                mti->mti_uuid, fsdb->fsdb_mdtlov, 
1844                                fsdb->fsdb_mdtlov + 4);
1845                         RETURN(-EINVAL);
1846                 }
1847         }
1848
1849         if (!(fsdb->fsdb_flags & FSDB_OLDLOG14)) {
1850                 LCONSOLE_ERROR_MSG(0x14c, "%s-client is supposedly an old log, "
1851                                    "but no old LOV or MDT was found. Consider "
1852                                    "updating the configuration with "
1853                                    "--writeconf.\n", mti->mti_fsname);
1854         }
1855
1856         RETURN(rc);
1857 }
1858 /* end COMPAT_146 */
1859
1860 int mgs_erase_log(struct obd_device *obd, char *name)
1861 {
1862         struct lvfs_run_ctxt saved;
1863         struct llog_ctxt *ctxt;
1864         struct llog_handle *llh;
1865         int rc = 0;
1866
1867         ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
1868         LASSERT(ctxt != NULL);
1869
1870         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
1871         rc = llog_create(ctxt, &llh, NULL, name);
1872         if (rc == 0) {
1873                 llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
1874                 rc = llog_destroy(llh);
1875                 llog_free_handle(llh);
1876         }
1877         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
1878         llog_ctxt_put(ctxt);
1879
1880         if (rc)
1881                 CERROR("failed to clear log %s: %d\n", name, rc);
1882
1883         return(rc);
1884 }
1885
1886 /* erase all logs for the given fs */
1887 int mgs_erase_logs(struct obd_device *obd, char *fsname)
1888 {
1889         struct mgs_obd *mgs = &obd->u.mgs;
1890         static struct fs_db *fsdb;
1891         struct list_head dentry_list;
1892         struct l_linux_dirent *dirent, *n;
1893         int rc, len = strlen(fsname);
1894         ENTRY;
1895         
1896         /* Find all the logs in the CONFIGS directory */
1897         rc = class_dentry_readdir(obd, mgs->mgs_configs_dir,
1898                                   mgs->mgs_vfsmnt, &dentry_list);
1899         if (rc) {
1900                 CERROR("Can't read %s dir\n", MOUNT_CONFIGS_DIR);
1901                 RETURN(rc);
1902         }
1903                                                                                 
1904         down(&mgs->mgs_sem);
1905         
1906         /* Delete the fs db */
1907         fsdb = mgs_find_fsdb(obd, fsname);
1908         if (fsdb) 
1909                 mgs_free_fsdb(obd, fsdb);
1910
1911         list_for_each_entry_safe(dirent, n, &dentry_list, lld_list) {
1912                 list_del(&dirent->lld_list);
1913                 if (strncmp(fsname, dirent->lld_name, len) == 0) {
1914                         CDEBUG(D_MGS, "Removing log %s\n", dirent->lld_name);
1915                         mgs_erase_log(obd, dirent->lld_name);
1916                 }
1917                 OBD_FREE(dirent, sizeof(*dirent));
1918         }
1919         
1920         up(&mgs->mgs_sem);
1921
1922         RETURN(rc);
1923 }
1924
1925 /* from llog_swab */
1926 static void print_lustre_cfg(struct lustre_cfg *lcfg)
1927 {
1928         int i;
1929         ENTRY;
1930
1931         CDEBUG(D_MGS, "lustre_cfg: %p\n", lcfg);
1932         CDEBUG(D_MGS, "\tlcfg->lcfg_version: %#x\n", lcfg->lcfg_version);
1933
1934         CDEBUG(D_MGS, "\tlcfg->lcfg_command: %#x\n", lcfg->lcfg_command);
1935         CDEBUG(D_MGS, "\tlcfg->lcfg_num: %#x\n", lcfg->lcfg_num);
1936         CDEBUG(D_MGS, "\tlcfg->lcfg_flags: %#x\n", lcfg->lcfg_flags);
1937         CDEBUG(D_MGS, "\tlcfg->lcfg_nid: %s\n", libcfs_nid2str(lcfg->lcfg_nid));
1938
1939         CDEBUG(D_MGS, "\tlcfg->lcfg_bufcount: %d\n", lcfg->lcfg_bufcount);
1940         if (lcfg->lcfg_bufcount < LUSTRE_CFG_MAX_BUFCOUNT)
1941                 for (i = 0; i < lcfg->lcfg_bufcount; i++) {
1942                         CDEBUG(D_MGS, "\tlcfg->lcfg_buflens[%d]: %d %s\n",
1943                                i, lcfg->lcfg_buflens[i], 
1944                                lustre_cfg_string(lcfg, i));
1945                 }
1946         EXIT;
1947 }
1948
1949 /* Set a permanent (config log) param for a target or fs */
1950 int mgs_setparam(struct obd_device *obd, struct lustre_cfg *lcfg, char *fsname)
1951 {
1952         struct fs_db *fsdb;
1953         struct mgs_target_info *mti;
1954         char *devname, *param;
1955         char *ptr, *tmp;
1956         __u32 index;
1957         int rc = 0;
1958         ENTRY;
1959
1960         print_lustre_cfg(lcfg);
1961         
1962         /* lustre, lustre-mdtlov, lustre-client, lustre-MDT0000 */
1963         devname = lustre_cfg_string(lcfg, 0);
1964         param = lustre_cfg_string(lcfg, 1);
1965         if (!devname) {
1966                 /* Assume device name embedded in param:
1967                    lustre-OST0000.osc.max_dirty_mb=32 */
1968                 ptr = strchr(param, '.');
1969                 if (ptr) {
1970                         devname = param;
1971                         *ptr = 0;
1972                         param = ptr + 1;
1973                 }
1974         }
1975         if (!devname) {
1976                 LCONSOLE_ERROR_MSG(0x14d, "No target specified: %s\n", param);
1977                 RETURN(-ENOSYS);
1978         }
1979
1980         /* Extract fsname */
1981         ptr = strrchr(devname, '-');
1982         memset(fsname, 0, MTI_NAME_MAXLEN);
1983         if (ptr && (server_name2index(ptr, &index, NULL) >= 0)) {
1984                 /* param related to llite isn't allowed to set by OST or MDT */
1985                 if (strncmp(param, PARAM_LLITE, sizeof(PARAM_LLITE)) == 0)
1986                         RETURN(-EINVAL);
1987
1988                 strncpy(fsname, devname, ptr - devname);
1989         } else {
1990                 /* assume devname is the fsname */
1991                 strncpy(fsname, devname, MTI_NAME_MAXLEN);
1992         }
1993         fsname[MTI_NAME_MAXLEN - 1] = 0;
1994         CDEBUG(D_MGS, "setparam on fs %s device %s\n", fsname, devname);
1995
1996         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb); 
1997         if (rc) 
1998                 RETURN(rc);
1999         if (fsdb->fsdb_flags & FSDB_LOG_EMPTY) {
2000                 CERROR("No filesystem targets for %s.  cfg_device from lctl "
2001                        "is '%s'\n", fsname, devname);
2002                 mgs_free_fsdb(obd, fsdb);
2003                 RETURN(-EINVAL);
2004         }
2005
2006         /* Create a fake mti to hold everything */
2007         OBD_ALLOC_PTR(mti);
2008         if (!mti) 
2009                 GOTO(out, rc = -ENOMEM);
2010         strncpy(mti->mti_fsname, fsname, MTI_NAME_MAXLEN);
2011         strncpy(mti->mti_svname, devname, MTI_NAME_MAXLEN);
2012         strncpy(mti->mti_params, param, sizeof(mti->mti_params));
2013         rc = server_name2index(mti->mti_svname, &mti->mti_stripe_index, &tmp);
2014         if (rc < 0) 
2015                 /* Not a valid server; may be only fsname */
2016                 rc = 0;
2017         else
2018                 /* Strip -osc or -mdc suffix from svname */
2019                 if (server_make_name(rc, mti->mti_stripe_index, mti->mti_fsname, 
2020                                      mti->mti_svname)) 
2021                         GOTO(out, rc = -EINVAL);
2022
2023         mti->mti_flags = rc | LDD_F_PARAM;
2024
2025         down(&fsdb->fsdb_sem);
2026         rc = mgs_write_log_params(obd, fsdb, mti); 
2027         up(&fsdb->fsdb_sem);
2028
2029 out:
2030         OBD_FREE_PTR(mti);
2031         RETURN(rc);
2032 }
2033
2034
2035 static int mgs_write_log_pool(struct obd_device *obd, char *logname, struct fs_db *fsdb,
2036                        char *lovname,
2037                        enum lcfg_command_type cmd,
2038                        char *poolname, char *fsname,
2039                        char *ostname, char *comment)
2040 {
2041         struct llog_handle *llh = NULL;
2042         int rc;
2043
2044         rc = record_start_log(obd, &llh, logname);
2045         if (rc)
2046                 RETURN(rc);
2047         rc = record_marker(obd, llh, fsdb, CM_START, lovname, comment);
2048         record_base(obd, llh, lovname, 0, cmd, poolname, fsname, ostname, 0);
2049         rc = record_marker(obd, llh, fsdb, CM_END, lovname, comment);
2050         rc = record_end_log(obd, &llh);
2051
2052         return(rc);
2053 }
2054
2055 int mgs_pool_cmd(struct obd_device *obd, enum lcfg_command_type cmd,
2056                  char *fsname, char *poolname, char *ostname)
2057 {
2058         struct fs_db *fsdb;
2059         char mdt_index[16];
2060         char *lovname;
2061         char *logname;
2062         char *label, *canceled_label = NULL;
2063         int label_sz;
2064         struct mgs_target_info *mti;
2065         int rc;
2066         ENTRY;
2067
2068         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb);
2069         if (rc) {
2070                 CERROR("Can't get db for %s\n", fsname);
2071                 RETURN(rc);
2072         }
2073         if (fsdb->fsdb_flags & FSDB_LOG_EMPTY) {
2074                 CERROR("%s is not defined\n", fsname);
2075                 mgs_free_fsdb(obd, fsdb);
2076                 RETURN(-EINVAL);
2077         }
2078
2079         label_sz = 10 + strlen(fsname) + strlen(poolname);
2080
2081         /* check if ostname match fsname */
2082         if (ostname != NULL) {
2083                 char *ptr;
2084
2085                 ptr = strrchr(ostname, '-');
2086                 if ((ptr == NULL) ||
2087                     (strncmp(fsname, ostname, ptr-ostname) != 0))
2088                         RETURN(-EINVAL);
2089                 label_sz += strlen(ostname);
2090         }
2091
2092         OBD_ALLOC(label, label_sz);
2093         if (label == NULL)
2094                 RETURN(-ENOMEM);
2095
2096         switch(cmd) {
2097         case LCFG_POOL_NEW: {
2098                 sprintf(label,
2099                         "new %s.%s", fsname, poolname);
2100                 break;
2101         }
2102         case LCFG_POOL_ADD: {
2103                 sprintf(label,
2104                         "add %s.%s.%s", fsname, poolname, ostname);
2105                 break;
2106         }
2107         case LCFG_POOL_REM: {
2108                 OBD_ALLOC(canceled_label, label_sz);
2109                 if (canceled_label == NULL)
2110                          RETURN(-ENOMEM);
2111                 sprintf(label,
2112                         "rem %s.%s.%s", fsname, poolname, ostname);
2113                 sprintf(canceled_label,
2114                         "add %s.%s.%s", fsname, poolname, ostname);
2115                 break;
2116         }
2117         case LCFG_POOL_DEL: {
2118                 OBD_ALLOC(canceled_label, label_sz);
2119                 if (canceled_label == NULL)
2120                          RETURN(-ENOMEM);
2121                 sprintf(label,
2122                         "del %s.%s", fsname, poolname);
2123                 sprintf(canceled_label,
2124                         "new %s.%s", fsname, poolname);
2125                 break;
2126         }
2127         default: {
2128                 break;
2129         }
2130         }
2131
2132         down(&fsdb->fsdb_sem);
2133
2134         sprintf(mdt_index, "-MDT%04x", 0);
2135         name_create(&logname, fsname, mdt_index);
2136         name_create(&lovname, fsdb->fsdb_mdtlov, "");
2137
2138         mti = NULL;
2139         if (canceled_label != NULL) {
2140                 OBD_ALLOC(mti, sizeof(*mti));
2141                 if (mti != NULL) {
2142                         strcpy(mti->mti_svname, "lov pool");
2143                         mgs_modify(obd, fsdb, mti, logname, lovname,
2144                                    canceled_label, CM_SKIP);
2145                 }
2146         }
2147
2148         mgs_write_log_pool(obd, logname, fsdb, lovname,
2149                            cmd, fsname, poolname, ostname, label);
2150         name_destroy(&logname);
2151
2152         name_create(&logname, fsname, "-client");
2153         if (canceled_label != NULL) {
2154                 mgs_modify(obd, fsdb, mti, logname, lovname,
2155                            canceled_label, CM_SKIP);
2156         }
2157         mgs_write_log_pool(obd, logname, fsdb, fsdb->fsdb_clilov,
2158                            cmd, fsname, poolname, ostname, label);
2159         name_destroy(&logname);
2160         name_destroy(&lovname);
2161
2162         up(&fsdb->fsdb_sem);
2163
2164         OBD_FREE(label, label_sz);
2165         if (canceled_label != NULL)
2166                 OBD_FREE(canceled_label, label_sz);
2167
2168         if (mti != NULL)
2169                 OBD_FREE(mti, sizeof(*mti));
2170
2171         RETURN(rc);
2172 }
2173
2174 #if 0
2175 /******************** unused *********************/
2176 static int mgs_backup_llog(struct obd_device *obd, char* fsname)
2177 {
2178         struct file *filp, *bak_filp;
2179         struct lvfs_run_ctxt saved;
2180         char *logname, *buf;
2181         loff_t soff = 0 , doff = 0;
2182         int count = 4096, len;
2183         int rc = 0;
2184
2185         OBD_ALLOC(logname, PATH_MAX);
2186         if (logname == NULL)
2187                 return -ENOMEM;
2188
2189         OBD_ALLOC(buf, count);
2190         if (!buf)
2191                 GOTO(out , rc = -ENOMEM);
2192
2193         len = snprintf(logname, PATH_MAX, "%s/%s.bak",
2194                        MOUNT_CONFIGS_DIR, fsname);
2195
2196         if (len >= PATH_MAX - 1) {
2197                 GOTO(out, -ENAMETOOLONG);
2198         } 
2199
2200         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2201                 
2202         bak_filp = l_filp_open(logname, O_RDWR|O_CREAT|O_TRUNC, 0660);
2203         if (IS_ERR(bak_filp)) {
2204                 rc = PTR_ERR(bak_filp);
2205                 CERROR("backup logfile open %s: %d\n", logname, rc);
2206                 GOTO(pop, rc);
2207         }
2208         sprintf(logname, "%s/%s", MOUNT_CONFIGS_DIR, fsname);
2209         filp = l_filp_open(logname, O_RDONLY, 0);
2210         if (IS_ERR(filp)) {
2211                 rc = PTR_ERR(filp);
2212                 CERROR("logfile open %s: %d\n", logname, rc);
2213                 GOTO(close1f, rc);
2214         }
2215
2216         while ((rc = lustre_fread(filp, buf, count, &soff)) > 0) {
2217                 rc = lustre_fwrite(bak_filp, buf, count, &doff);
2218                 break;
2219         }
2220
2221         filp_close(filp, 0);
2222 close1f:
2223         filp_close(bak_filp, 0);
2224 pop:
2225         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2226 out:
2227         if (buf)
2228                 OBD_FREE(buf, count);
2229         OBD_FREE(logname, PATH_MAX);
2230         return rc;
2231 }
2232
2233
2234
2235 #endif