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