Whamcloud - gitweb
clarify error message
[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 "
1307                                        "upgraded client logs for %s. Consider "
1308                                        "updating the configuration with "
1309                                        "--writeconf.\n", 
1310                                        mti->mti_svname);
1311                         RETURN(-EINVAL);
1312                 }
1313                 name_create(&cliname, mti->mti_svname, "-osc");
1314         } else {
1315                 RETURN(-EINVAL);
1316         }
1317         
1318         /* Add failover nids to client log */
1319         name_create(&logname, mti->mti_fsname, "-client");
1320         rc = record_start_log(obd, &llh, logname);
1321         if (!rc) { 
1322                 /* FIXME this fn should be a single journal transaction */
1323                 rc = record_marker(obd, llh, fsdb, CM_START, mti->mti_svname,
1324                                    "add failnid");
1325                 rc = mgs_write_log_failnids(obd, mti, llh, cliname);
1326                 rc = record_marker(obd, llh, fsdb, CM_END, mti->mti_svname,
1327                                    "add failnid"); 
1328                 rc = record_end_log(obd, &llh);
1329         }
1330         name_destroy(&logname);
1331
1332         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1333                 /* Add OST failover nids to the MDT log as well */
1334                 name_create(&logname, mti->mti_fsname, "-MDT0000");
1335                 rc = record_start_log(obd, &llh, logname);
1336                 if (!rc) {
1337                         rc = record_marker(obd, llh, fsdb, CM_START, 
1338                                            mti->mti_svname, "add failnid");
1339                         rc = mgs_write_log_failnids(obd, mti, llh, cliname);
1340                         rc = record_marker(obd, llh, fsdb, CM_END, 
1341                                            mti->mti_svname, "add failnid"); 
1342                         rc = record_end_log(obd, &llh);
1343                 }
1344                 name_destroy(&logname);
1345         }
1346
1347         name_destroy(&cliname);
1348         RETURN(rc);
1349 }
1350
1351 static int mgs_wlp_lcfg(struct obd_device *obd, struct fs_db *fsdb, 
1352                         struct mgs_target_info *mti,
1353                         char *logname, struct lustre_cfg_bufs *bufs,
1354                         char *tgtname, char *ptr)
1355 {
1356         char comment[MTI_NAME_MAXLEN];
1357         char *tmp;
1358         struct lustre_cfg *lcfg;
1359         int rc;
1360         
1361         /* Erase any old settings of this same parameter */
1362         memcpy(comment, ptr, MTI_NAME_MAXLEN);
1363         comment[MTI_NAME_MAXLEN - 1] = 0;
1364         /* But don't try to match the value. */
1365         if ((tmp = strchr(comment, '=')))
1366             *tmp = 0;
1367         /* FIXME we should skip settings that are the same as old values */
1368         rc = mgs_modify(obd, fsdb, mti, logname, tgtname, comment, CM_SKIP);
1369         LCONSOLE_INFO("%sing parameter %s.%s in log %s\n", rc ?
1370                       "Sett" : "Modify", tgtname, comment, logname);
1371
1372         lustre_cfg_bufs_reset(bufs, tgtname);
1373         lustre_cfg_bufs_set_string(bufs, 1, ptr);
1374         lcfg = lustre_cfg_new(LCFG_PARAM, bufs);
1375         if (!lcfg) 
1376                 return -ENOMEM;
1377         rc = mgs_write_log_direct(obd, fsdb, logname, lcfg, tgtname, comment);
1378         lustre_cfg_free(lcfg);
1379         return rc;
1380 }
1381
1382 static int mgs_write_log_params(struct obd_device *obd, struct fs_db *fsdb,
1383                                 struct mgs_target_info *mti)
1384 {
1385         struct lustre_cfg_bufs bufs;
1386         struct lustre_cfg *lcfg;
1387         char *logname;
1388         char *ptr = mti->mti_params;
1389         char *endptr, *tmp;
1390         int rc = 0;
1391         ENTRY;
1392
1393         if (!mti->mti_params) 
1394                 RETURN(0);
1395
1396         /* For various parameter settings, we have to figure out which logs
1397            care about them (e.g. both mdt and client for lov settings) */
1398         while (ptr) {
1399                 while (*ptr == ' ') 
1400                         ptr++;
1401                 if (*ptr == '\0')
1402                         break;
1403                 endptr = strchr(ptr, ' ');
1404                 if (endptr) 
1405                         *endptr = '\0';
1406                 CDEBUG(D_MGS, "next param '%s'\n", ptr);
1407
1408                 /* The params are stored in MOUNT_DATA_FILE and modified 
1409                    via tunefs.lustre */
1410
1411                 /* Processed in lustre_start_mgc */
1412                 if (class_match_param(ptr, PARAM_MGSNODE, NULL) == 0) 
1413                         goto end_while;
1414
1415                 /* Processed in mgs_write_log_ost */
1416                 if (class_match_param(ptr, PARAM_FAILMODE, NULL) == 0) 
1417                         goto end_while;
1418
1419                 if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
1420                         /* Add a failover nidlist */
1421                         rc = 0;
1422                         /* We already processed failovers params for new
1423                            targets in mgs_write_log_target */
1424                         if (mti->mti_flags & LDD_F_PARAM_FNID) {
1425                                 CDEBUG(D_MGS, "Adding failnode\n");
1426                                 rc = mgs_write_log_add_failnid(obd, fsdb, mti);
1427                         }
1428                         goto end_while;
1429                 }
1430
1431                 if (class_match_param(ptr, PARAM_SYS_TIMEOUT, &tmp) == 0) {
1432                         /* Change obd timeout */
1433                         int timeout;
1434                         timeout = simple_strtoul(tmp, NULL, 0);
1435
1436                         CDEBUG(D_MGS, "obd timeout %d\n", timeout);
1437                         
1438                         lustre_cfg_bufs_reset(&bufs, NULL);
1439                         lcfg = lustre_cfg_new(LCFG_SET_TIMEOUT, &bufs);
1440                         lcfg->lcfg_num = timeout;
1441                         /* modify all servers and clients */
1442                         rc = mgs_write_log_direct_all(obd, fsdb, mti, lcfg,
1443                                                       mti->mti_fsname,
1444                                                       "timeout"); 
1445                         lustre_cfg_free(lcfg);
1446                         goto end_while;
1447                 }
1448
1449                 if (class_match_param(ptr, PARAM_OSC""PARAM_ACTIVE, &tmp) == 0){ 
1450                         /* active=0 means off, anything else means on */
1451                         int flag = (*tmp == '0') ? CM_EXCLUDE : 0;
1452                         if (!(mti->mti_flags & LDD_F_SV_TYPE_OST)) {
1453                                 LCONSOLE_ERROR("%s: Only OSCs can be (de)activ"
1454                                                "ated.\n", mti->mti_svname);
1455                                 rc = -EINVAL;
1456                                 goto end_while;
1457                         }
1458                         LCONSOLE_WARN("Permanently %sactivating %s\n",
1459                                       flag ? "de": "re", mti->mti_svname);
1460                         /* Modify clilov */
1461                         name_create(&logname, mti->mti_fsname, "-client");
1462                         rc = mgs_modify(obd, fsdb, mti, logname, 
1463                                         mti->mti_svname, "add osc", flag);
1464                         name_destroy(&logname);
1465                         if (rc) 
1466                                 goto active_err;
1467                         /* Modify mdtlov */
1468                         /* FIXME add to all MDT logs for CMD */
1469                         name_create(&logname, mti->mti_fsname, "-MDT0000");
1470                         rc = mgs_modify(obd, fsdb, mti, logname, 
1471                                         mti->mti_svname, "add osc", flag);
1472                         name_destroy(&logname);
1473 active_err:
1474                         if (rc) {
1475                                 LCONSOLE_ERROR("Couldn't find %s in log (%d). "
1476                                    "No permanent changes were made to the "
1477                                    "config log.\n", mti->mti_svname, rc);
1478                                 if (fsdb->fsdb_flags & FSDB_OLDLOG14) 
1479                                         LCONSOLE_ERROR("This may be because the"
1480                                         " log is in the old 1.4 style. Consider"
1481                                         " --writeconf to update the logs.\n");
1482                                 goto end_while;
1483                         }
1484                         /* Fall through to osc proc for deactivating 
1485                            live OSC on running MDT / clients. */
1486                 }
1487
1488                 /* Below here, let obd's XXX_process_config methods handle it */
1489
1490                 /* All lov. in proc */
1491                 if (class_match_param(ptr, PARAM_LOV, NULL) == 0) {
1492                         CDEBUG(D_MGS, "lov param %s\n", ptr);
1493                         if (!(mti->mti_flags & LDD_F_SV_TYPE_MDT)) {
1494                                 LCONSOLE_ERROR("LOV params must be set on the "
1495                                                "MDT, not %s. Ignoring.\n",
1496                                                mti->mti_svname);
1497                                 rc = 0;
1498                                 goto end_while;
1499                         }
1500
1501                         /* Modify mdtlov */
1502                         if (mgs_log_is_empty(obd, mti->mti_svname)) {
1503                                 rc = -ENODEV;
1504                                 goto end_while;
1505                         }
1506                         rc = mgs_wlp_lcfg(obd, fsdb, mti, mti->mti_svname, 
1507                                           &bufs, fsdb->fsdb_mdtlov, ptr);
1508                         if (rc) 
1509                                 goto end_while;
1510
1511                         /* Modify clilov */
1512                         name_create(&logname, mti->mti_fsname, "-client");
1513                         rc = mgs_wlp_lcfg(obd, fsdb, mti, logname, &bufs,
1514                                           fsdb->fsdb_clilov, ptr);
1515                         name_destroy(&logname);
1516                         goto end_while;
1517                 }
1518
1519                 /* All osc., mdc., llite. params in proc */
1520                 if ((class_match_param(ptr, PARAM_OSC, NULL) == 0) || 
1521                     (class_match_param(ptr, PARAM_MDC, NULL) == 0) || 
1522                     (class_match_param(ptr, PARAM_LLITE, NULL) == 0)) {
1523                         char *cname;
1524                         if (memcmp(ptr, PARAM_LLITE, strlen(PARAM_LLITE)) == 0) {
1525                                 name_create(&cname, mti->mti_fsname, "-client");
1526                         /* Add the client type to match the obdname 
1527                            in class_config_llog_handler */
1528                         } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
1529                                 /* COMPAT_146 */
1530                                 if (fsdb->fsdb_mdc)
1531                                         name_create(&cname, fsdb->fsdb_mdc, "");
1532                                 else
1533                                         name_create(&cname, mti->mti_svname, 
1534                                                     "-mdc");
1535                         } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1536                                 /* COMPAT_146 */
1537                                 if (fsdb->fsdb_flags & FSDB_OLDLOG14) {
1538                                       LCONSOLE_ERROR("Upgraded client logs "
1539                                            "for %s cannot be modified. "
1540                                            "Consider updating the "
1541                                            "configuration with --writeconf\n",
1542                                            mti->mti_svname);
1543                                         /* We don't know the names of all the
1544                                            old oscs*/
1545                                         rc = -EINVAL;
1546                                         goto end_while;
1547                                 }
1548                                 name_create(&cname, mti->mti_svname, "-osc");
1549                         } else {       
1550                                 rc = -EINVAL;
1551                                 goto end_while;
1552                         }
1553
1554                         CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
1555                         
1556                         /* Modify client */
1557                         name_create(&logname, mti->mti_fsname, "-client");
1558                         rc = mgs_wlp_lcfg(obd, fsdb, mti, logname, &bufs, 
1559                                           cname, ptr);
1560                         name_destroy(&logname);
1561                         
1562                         /* osc params affect the MDT as well */
1563                         if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1564                                 /* FIXME add to all MDT logs for CMD */
1565                                 name_create(&logname, mti->mti_fsname,
1566                                             "-MDT0000");
1567                                 if (!mgs_log_is_empty(obd, logname))
1568                                         rc = mgs_wlp_lcfg(obd, fsdb, mti,
1569                                                           logname, &bufs, 
1570                                                           cname, ptr);
1571                                 name_destroy(&logname);
1572                         }
1573                         name_destroy(&cname);
1574                         goto end_while;
1575                 }
1576
1577                 /* All mdt., ost. params in proc */
1578                 if ((class_match_param(ptr, PARAM_MDT, NULL) == 0) || 
1579                     (class_match_param(ptr, PARAM_OST, NULL) == 0)) {
1580                         CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
1581                         if (mgs_log_is_empty(obd, mti->mti_svname)) {
1582                                 rc = -ENODEV;
1583                                 goto end_while;
1584                         }
1585                         rc = mgs_wlp_lcfg(obd, fsdb, mti, mti->mti_svname,
1586                                           &bufs, mti->mti_svname, ptr);
1587                         goto end_while;
1588                 }
1589
1590                 LCONSOLE_WARN("Ignoring unrecognized param '%s'\n", ptr);
1591
1592 end_while:
1593                 if (rc) {
1594                         CERROR("err %d on param '%s\n", rc, ptr);
1595                         break;
1596                 }
1597                 
1598                 if (!endptr)
1599                         /* last param */
1600                         break;
1601                  
1602                 *endptr = ' ';
1603                 ptr = endptr + 1;
1604         }
1605
1606         RETURN(rc);
1607 }
1608
1609 int mgs_check_failnid(struct obd_device *obd, struct mgs_target_info *mti)
1610 {
1611         /* Not implementing automatic failover nid addition at this time. */
1612         return 0;
1613 #if 0
1614         struct fs_db *fsdb;
1615         int rc;
1616         ENTRY;
1617
1618         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb); 
1619         if (rc) 
1620                 RETURN(rc);
1621
1622         if (mgs_log_is_empty(obd, mti->mti_svname)) 
1623                 /* should never happen */
1624                 RETURN(-ENOENT);
1625
1626         CDEBUG(D_MGS, "Checking for new failnids for %s\n", mti->mti_svname);
1627
1628         /* FIXME We can just check mti->params to see if we're already in
1629            the failover list.  Modify mti->params for rewriting back at 
1630            server_register_target(). */
1631         
1632         down(&fsdb->fsdb_sem);
1633         rc = mgs_write_log_add_failnid(obd, fsdb, mti);
1634         up(&fsdb->fsdb_sem);
1635
1636         RETURN(rc);
1637 #endif
1638 }
1639
1640 int mgs_write_log_target(struct obd_device *obd,
1641                          struct mgs_target_info *mti)
1642 {
1643         struct fs_db *fsdb;
1644         int rc = -EINVAL;
1645         ENTRY;
1646
1647         /* set/check the new target index */
1648         rc = mgs_set_index(obd, mti);
1649         if (rc < 0) {
1650                 CERROR("Can't get index (%d)\n", rc);
1651                 RETURN(rc);
1652         }
1653         /* COMPAT_146 */
1654         if (mti->mti_flags & LDD_F_UPGRADE14) {
1655                 if (rc == EALREADY) {
1656                         LCONSOLE_INFO("Found index %d for %s 1.4 log, "
1657                                       "upgrading\n", mti->mti_stripe_index, 
1658                                       mti->mti_svname);
1659                 } else {
1660                         LCONSOLE_ERROR("Failed to find %s in the old client "
1661                                        "log. Apparently it is not part of this "
1662                                        "filesystem, or the old log is wrong.\n"
1663                                        "Use 'writeconf' on the MDT to force log"
1664                                        " regeneration.\n", mti->mti_svname);
1665                         /* Not in client log?  Upgrade anyhow...*/
1666                         /* Argument against upgrading: reformat MDT,
1667                            upgrade OST, then OST will start but will be SKIPped
1668                            in client logs.  Maybe error now is better. */
1669                         /* RETURN(-EINVAL); */
1670                 }
1671                 /* end COMPAT_146 */
1672         } else {
1673                 if (rc == EALREADY) {
1674                         /* This might be a params update, or a 
1675                            local writeconf. (For "full" writeconf, the client
1676                            log won't have an entry for this target, so we 
1677                            won't get here.) */
1678                         LCONSOLE_WARN("Found index %d for %s, updating log\n", 
1679                                       mti->mti_stripe_index, mti->mti_svname);
1680                         /* We would like to mark old log sections as invalid 
1681                            and add new log sections in the client and mdt logs.
1682                            But if we add new sections, then live clients will
1683                            get repeat setup instructions for already running
1684                            osc's. So don't update the client/mdt logs. */
1685                         mti->mti_flags &= ~LDD_F_UPDATE;
1686                 }
1687         }
1688
1689         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb); 
1690         if (rc) {
1691                 CERROR("Can't get db for %s\n", mti->mti_fsname);
1692                 RETURN(rc);
1693         }
1694
1695         down(&fsdb->fsdb_sem);
1696
1697         if (mti->mti_flags & 
1698             (LDD_F_VIRGIN | LDD_F_UPGRADE14 | LDD_F_WRITECONF)) {
1699                 /* Generate a log from scratch */
1700                 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
1701                         rc = mgs_write_log_mdt(obd, fsdb, mti);
1702                 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
1703                         rc = mgs_write_log_ost(obd, fsdb, mti);
1704                 } else {
1705                         CERROR("Unknown target type %#x, can't create log for "
1706                                "%s\n", mti->mti_flags, mti->mti_svname);
1707                 }
1708                 if (rc) {
1709                         CERROR("Can't write logs for %s (%d)\n",
1710                                mti->mti_svname, rc);
1711                         GOTO(out_up, rc);
1712                 }
1713         } else {
1714                 /* Just update the params from tunefs in mgs_write_log_params */
1715                 CDEBUG(D_MGS, "Update params for %s\n", mti->mti_svname);
1716                 mti->mti_flags |= LDD_F_PARAM_FNID;
1717         }
1718         
1719         rc = mgs_write_log_params(obd, fsdb, mti);
1720
1721 out_up:
1722         up(&fsdb->fsdb_sem);
1723         RETURN(rc);
1724 }
1725
1726 /* COMPAT_146 */
1727 /* verify that we can handle the old config logs */ 
1728 int mgs_upgrade_sv_14(struct obd_device *obd, struct mgs_target_info *mti)
1729 {
1730         struct fs_db *fsdb;
1731         int rc = 0;
1732         ENTRY;
1733
1734         /* Create ost log normally, as servers register.  Servers 
1735            register with their old uuids (from last_rcvd), so old
1736            (MDT and client) logs should work.
1737          - new MDT won't know about old OSTs, only the ones that have 
1738            registered, so we need the old MDT log to get the LOV right 
1739            in order for old clients to work. 
1740          - Old clients connect to the MDT, not the MGS, for their logs, and 
1741            will therefore receive the old client log from the MDT /LOGS dir. 
1742          - Old clients can continue to use and connect to old or new OSTs
1743          - New clients will contact the MGS for their log 
1744         */
1745
1746         LCONSOLE_INFO("upgrading server %s from pre-1.6\n", mti->mti_svname); 
1747         server_mti_print("upgrade", mti);
1748         
1749         rc = mgs_find_or_make_fsdb(obd, mti->mti_fsname, &fsdb);
1750         if (rc) 
1751                 RETURN(rc);
1752         
1753         if (fsdb->fsdb_flags & FSDB_LOG_EMPTY) {
1754                 LCONSOLE_ERROR("The old client log %s-client is missing.  Was "
1755                                "tunefs.lustre successful?\n",
1756                                mti->mti_fsname);
1757                 RETURN(-ENOENT);
1758         }
1759
1760         if (fsdb->fsdb_gen == 0) {
1761                 /* There were no markers in the client log, meaning we have 
1762                    not updated the logs for this fs */
1763                 CDEBUG(D_MGS, "found old, unupdated client log\n");
1764         }
1765
1766         if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
1767                 if (mgs_log_is_empty(obd, mti->mti_svname)) {
1768                         LCONSOLE_ERROR("The old MDT log %s is missing.  Was "
1769                                        "tunefs.lustre successful?\n",
1770                                        mti->mti_svname);
1771                         RETURN(-ENOENT);
1772                 }
1773
1774                 /* We're starting with an old uuid.  Assume old name for lov
1775                    as well since the lov entry already exists in the log. */
1776                 CDEBUG(D_MGS, "old mds uuid %s\n", mti->mti_uuid);
1777                 if (strncmp(mti->mti_uuid, fsdb->fsdb_mdtlov + 4, 
1778                             strlen(fsdb->fsdb_mdtlov) - 4) != 0) {
1779                         CERROR("old mds uuid %s doesn't match log %s (%s)\n",
1780                                mti->mti_uuid, fsdb->fsdb_mdtlov, 
1781                                fsdb->fsdb_mdtlov + 4);
1782                         RETURN(-EINVAL);
1783                 }
1784         }
1785
1786         if (!(fsdb->fsdb_flags & FSDB_OLDLOG14)) {
1787                 LCONSOLE_ERROR("%s-client is supposedly an old log, but no old "
1788                                "LOV or MDT was found. Consider updating the "
1789                                "configuration with --writeconf.\n",
1790                                mti->mti_fsname);
1791         }
1792
1793         RETURN(rc);
1794 }
1795 /* end COMPAT_146 */
1796
1797 int mgs_erase_log(struct obd_device *obd, char *name)
1798 {
1799         struct lvfs_run_ctxt saved;
1800         struct llog_handle *llh;
1801         int rc = 0;
1802
1803         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
1804         rc = llog_create(llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT),
1805                          &llh, NULL, name);
1806         if (rc == 0) {
1807                 llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
1808                 rc = llog_destroy(llh);
1809                 llog_free_handle(llh);
1810         }
1811         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
1812
1813         if (rc)
1814                 CERROR("failed to clear log %s: %d\n", name, rc);
1815
1816         return(rc);
1817 }
1818
1819 /* erase all logs for the given fs */
1820 int mgs_erase_logs(struct obd_device *obd, char *fsname)
1821 {
1822         struct mgs_obd *mgs = &obd->u.mgs;
1823         static struct fs_db *fsdb;
1824         struct list_head dentry_list;
1825         struct l_linux_dirent *dirent, *n;
1826         int rc, len = strlen(fsname);
1827         ENTRY;
1828         
1829         /* Find all the logs in the CONFIGS directory */
1830         rc = class_dentry_readdir(obd, mgs->mgs_configs_dir,
1831                                   mgs->mgs_vfsmnt, &dentry_list);
1832         if (rc) {
1833                 CERROR("Can't read %s dir\n", MOUNT_CONFIGS_DIR);
1834                 RETURN(rc);
1835         }
1836                                                                                 
1837         down(&mgs->mgs_sem);
1838         
1839         /* Delete the fs db */
1840         fsdb = mgs_find_fsdb(obd, fsname);
1841         if (fsdb) 
1842                 mgs_free_fsdb(obd, fsdb);
1843
1844         list_for_each_entry_safe(dirent, n, &dentry_list, lld_list) {
1845                 list_del(&dirent->lld_list);
1846                 if (strncmp(fsname, dirent->lld_name, len) == 0) {
1847                         CDEBUG(D_MGS, "Removing log %s\n", dirent->lld_name);
1848                         mgs_erase_log(obd, dirent->lld_name);
1849                 }
1850                 OBD_FREE(dirent, sizeof(*dirent));
1851         }
1852         
1853         up(&mgs->mgs_sem);
1854
1855         RETURN(rc);
1856 }
1857
1858 /* from llog_swab */
1859 static void print_lustre_cfg(struct lustre_cfg *lcfg)
1860 {
1861         int i;
1862         ENTRY;
1863
1864         CDEBUG(D_MGS, "lustre_cfg: %p\n", lcfg);
1865         CDEBUG(D_MGS, "\tlcfg->lcfg_version: %#x\n", lcfg->lcfg_version);
1866
1867         CDEBUG(D_MGS, "\tlcfg->lcfg_command: %#x\n", lcfg->lcfg_command);
1868         CDEBUG(D_MGS, "\tlcfg->lcfg_num: %#x\n", lcfg->lcfg_num);
1869         CDEBUG(D_MGS, "\tlcfg->lcfg_flags: %#x\n", lcfg->lcfg_flags);
1870         CDEBUG(D_MGS, "\tlcfg->lcfg_nid: %s\n", libcfs_nid2str(lcfg->lcfg_nid));
1871
1872         CDEBUG(D_MGS, "\tlcfg->lcfg_bufcount: %d\n", lcfg->lcfg_bufcount);
1873         if (lcfg->lcfg_bufcount < LUSTRE_CFG_MAX_BUFCOUNT)
1874                 for (i = 0; i < lcfg->lcfg_bufcount; i++) {
1875                         CDEBUG(D_MGS, "\tlcfg->lcfg_buflens[%d]: %d %s\n",
1876                                i, lcfg->lcfg_buflens[i], 
1877                                lustre_cfg_string(lcfg, i));
1878                 }
1879         EXIT;
1880 }
1881
1882 /* Set a permanent (config log) param for a target or fs */
1883 int mgs_setparam(struct obd_device *obd, struct lustre_cfg *lcfg, char *fsname)
1884 {
1885         struct fs_db *fsdb;
1886         struct mgs_target_info *mti;
1887         char *devname, *param;
1888         char *ptr, *tmp;
1889         int rc = 0;
1890         ENTRY;
1891
1892         print_lustre_cfg(lcfg);
1893         
1894         /* lustre, lustre-mdtlov, lustre-client, lustre-MDT0000 */
1895         devname = lustre_cfg_string(lcfg, 0);
1896         param = lustre_cfg_string(lcfg, 1);
1897         if (!devname) {
1898                 /* Assume device name embedded in param:
1899                    lustre-OST0000.osc.max_dirty_mb=32 */
1900                 ptr = strchr(param, '.');
1901                 if (ptr) {
1902                         devname = param;
1903                         *ptr = 0;
1904                         param = ptr + 1;
1905                 }
1906         }
1907         if (!devname) {
1908                 LCONSOLE_ERROR("No target specified: %s\n", param);
1909                 RETURN(-ENOSYS);
1910         }
1911
1912         /* Extract fsname */
1913         ptr = strchr(devname, '-');
1914         memset(fsname, 0, MTI_NAME_MAXLEN);
1915         if (!ptr) {
1916                 /* assume devname is the fsname */
1917                 strncpy(fsname, devname, MTI_NAME_MAXLEN);
1918         } else {  
1919                 strncpy(fsname, devname, ptr - devname);
1920         }
1921         fsname[MTI_NAME_MAXLEN - 1] = 0;
1922         CDEBUG(D_MGS, "setparam on fs %s device %s\n", fsname, devname);
1923
1924         rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb); 
1925         if (rc) 
1926                 RETURN(rc);
1927         if (fsdb->fsdb_flags & FSDB_LOG_EMPTY) {
1928                 CERROR("No filesystem targets for %s.  cfg_device from lctl "
1929                        "is '%s'\n", fsname, devname);
1930                 mgs_free_fsdb(obd, fsdb);
1931                 RETURN(-EINVAL);
1932         }
1933
1934         /* Create a fake mti to hold everything */
1935         OBD_ALLOC_PTR(mti);
1936         if (!mti) 
1937                 GOTO(out, rc = -ENOMEM);
1938         strncpy(mti->mti_fsname, fsname, MTI_NAME_MAXLEN);
1939         strncpy(mti->mti_svname, devname, MTI_NAME_MAXLEN);
1940         strncpy(mti->mti_params, param, sizeof(mti->mti_params));
1941         rc = server_name2index(mti->mti_svname, &mti->mti_stripe_index, &tmp);
1942         if (rc < 0) 
1943                 /* Not a valid server; may be only fsname */
1944                 rc = 0;
1945         else
1946                 /* Strip -osc or -mdc suffix from svname */
1947                 if (server_make_name(rc, mti->mti_stripe_index, mti->mti_fsname, 
1948                                      mti->mti_svname)) 
1949                         GOTO(out, rc = -EINVAL);
1950
1951         mti->mti_flags = rc | LDD_F_PARAM_FNID;
1952
1953         down(&fsdb->fsdb_sem);
1954         rc = mgs_write_log_params(obd, fsdb, mti); 
1955         up(&fsdb->fsdb_sem);
1956
1957 out:
1958         OBD_FREE_PTR(mti);
1959         RETURN(rc);
1960 }
1961
1962
1963 #if 0
1964 /******************** unused *********************/
1965 static int mgs_backup_llog(struct obd_device *obd, char* fsname)
1966 {
1967         struct file *filp, *bak_filp;
1968         struct lvfs_run_ctxt saved;
1969         char *logname, *buf;
1970         loff_t soff = 0 , doff = 0;
1971         int count = 4096, len;
1972         int rc = 0;
1973
1974         OBD_ALLOC(logname, PATH_MAX);
1975         if (logname == NULL)
1976                 return -ENOMEM;
1977
1978         OBD_ALLOC(buf, count);
1979         if (!buf)
1980                 GOTO(out , rc = -ENOMEM);
1981
1982         len = snprintf(logname, PATH_MAX, "%s/%s.bak",
1983                        MOUNT_CONFIGS_DIR, fsname);
1984
1985         if (len >= PATH_MAX - 1) {
1986                 GOTO(out, -ENAMETOOLONG);
1987         } 
1988
1989         push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
1990                 
1991         bak_filp = l_filp_open(logname, O_RDWR|O_CREAT|O_TRUNC, 0660);
1992         if (IS_ERR(bak_filp)) {
1993                 rc = PTR_ERR(bak_filp);
1994                 CERROR("backup logfile open %s: %d\n", logname, rc);
1995                 GOTO(pop, rc);
1996         }
1997         sprintf(logname, "%s/%s", MOUNT_CONFIGS_DIR, fsname);
1998         filp = l_filp_open(logname, O_RDONLY, 0);
1999         if (IS_ERR(filp)) {
2000                 rc = PTR_ERR(filp);
2001                 CERROR("logfile open %s: %d\n", logname, rc);
2002                 GOTO(close1f, rc);
2003         }
2004
2005         while ((rc = lustre_fread(filp, buf, count, &soff)) > 0) {
2006                 rc = lustre_fwrite(bak_filp, buf, count, &doff);
2007                 break;
2008         }
2009
2010         filp_close(filp, 0);
2011 close1f:
2012         filp_close(bak_filp, 0);
2013 pop:
2014         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
2015 out:
2016         if (buf)
2017                 OBD_FREE(buf, count);
2018         OBD_FREE(logname, PATH_MAX);
2019         return rc;
2020 }
2021
2022
2023
2024 #endif