4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.gnu.org/licenses/gpl-2.0.html
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Use is subject to license terms.
26 * Copyright (c) 2011, 2016, Intel Corporation.
29 * This file is part of Lustre, http://www.lustre.org/
30 * Lustre is a trademark of Sun Microsystems, Inc.
32 * lustre/mgs/mgs_llog.c
34 * Lustre Management Server (mgs) config llog creation
36 * Author: Nathan Rutman <nathan@clusterfs.com>
37 * Author: Alex Zhuravlev <bzzz@whamcloud.com>
38 * Author: Mikhail Pershin <tappro@whamcloud.com>
41 #define DEBUG_SUBSYSTEM S_MGS
42 #define D_MGS D_CONFIG
45 #include <lustre_ioctl.h>
46 #include <lustre_param.h>
47 #include <lustre_sec.h>
48 #include <lustre_quota.h>
50 #include "mgs_internal.h"
52 /********************** Class functions ********************/
54 /* Find all logs in CONFIG directory and link then into list */
55 int class_dentry_readdir(const struct lu_env *env,
56 struct mgs_device *mgs, struct list_head *log_list)
58 struct dt_object *dir = mgs->mgs_configs_dir;
59 const struct dt_it_ops *iops;
61 struct mgs_direntry *de;
65 INIT_LIST_HEAD(log_list);
68 LASSERT(dir->do_index_ops);
70 iops = &dir->do_index_ops->dio_it;
71 it = iops->init(env, dir, LUDA_64BITHASH);
75 rc = iops->load(env, it, 0);
81 key = (void *)iops->key(env, it);
83 CERROR("%s: key failed when listing %s: rc = %d\n",
84 mgs->mgs_obd->obd_name, MOUNT_CONFIGS_DIR,
88 key_sz = iops->key_size(env, it);
91 /* filter out "." and ".." entries */
95 if (key_sz == 2 && key[1] == '.')
99 /* filter out ".bak" files */
100 /* sizeof(".bak") - 1 == 3 */
102 !memcmp(".bak", key + key_sz - 3, 3)) {
103 CDEBUG(D_MGS, "Skipping backup file %.*s\n",
108 de = mgs_direntry_alloc(key_sz + 1);
114 memcpy(de->mde_name, key, key_sz);
115 de->mde_name[key_sz] = 0;
117 list_add(&de->mde_list, log_list);
120 rc = iops->next(env, it);
130 CERROR("%s: key failed when listing %s: rc = %d\n",
131 mgs->mgs_obd->obd_name, MOUNT_CONFIGS_DIR, rc);
135 /******************** DB functions *********************/
137 static inline int name_create(char **newname, char *prefix, char *suffix)
140 OBD_ALLOC(*newname, strlen(prefix) + strlen(suffix) + 1);
143 sprintf(*newname, "%s%s", prefix, suffix);
147 static inline void name_destroy(char **name)
150 OBD_FREE(*name, strlen(*name) + 1);
154 struct mgs_fsdb_handler_data
160 /* from the (client) config log, figure out:
161 1. which ost's/mdt's are configured (by index)
162 2. what the last config step is
163 3. COMPAT_18 osc name
165 /* It might be better to have a separate db file, instead of parsing the info
166 out of the client log. This is slow and potentially error-prone. */
167 static int mgs_fsdb_handler(const struct lu_env *env, struct llog_handle *llh,
168 struct llog_rec_hdr *rec, void *data)
170 struct mgs_fsdb_handler_data *d = data;
171 struct fs_db *fsdb = d->fsdb;
172 int cfg_len = rec->lrh_len;
173 char *cfg_buf = (char*) (rec + 1);
174 struct lustre_cfg *lcfg;
179 if (rec->lrh_type != OBD_CFG_REC) {
180 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
184 rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
186 CERROR("Insane cfg\n");
190 lcfg = (struct lustre_cfg *)cfg_buf;
192 CDEBUG(D_INFO, "cmd %x %s %s\n", lcfg->lcfg_command,
193 lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
195 /* Figure out ost indicies */
196 /* lov_modify_tgts add 0:lov1 1:ost1_UUID 2(index):0 3(gen):1 */
197 if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD ||
198 lcfg->lcfg_command == LCFG_LOV_DEL_OBD) {
199 index = simple_strtoul(lustre_cfg_string(lcfg, 2),
201 CDEBUG(D_MGS, "OST index for %s is %u (%s)\n",
202 lustre_cfg_string(lcfg, 1), index,
203 lustre_cfg_string(lcfg, 2));
204 set_bit(index, fsdb->fsdb_ost_index_map);
207 /* Figure out mdt indicies */
208 /* attach 0:MDC_uml1_mdsA_MNT_client 1:mdc 2:1d834_MNT_client_03f */
209 if ((lcfg->lcfg_command == LCFG_ATTACH) &&
210 (strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_MDC_NAME) == 0)) {
211 rc = server_name2index(lustre_cfg_string(lcfg, 0),
213 if (rc != LDD_F_SV_TYPE_MDT) {
214 CWARN("Unparsable MDC name %s, assuming index 0\n",
215 lustre_cfg_string(lcfg, 0));
219 CDEBUG(D_MGS, "MDT index is %u\n", index);
220 set_bit(index, fsdb->fsdb_mdt_index_map);
221 fsdb->fsdb_mdt_count ++;
225 * figure out the old config. fsdb_gen = 0 means old log
226 * It is obsoleted and not supported anymore
228 if (fsdb->fsdb_gen == 0) {
229 CERROR("Old config format is not supported\n");
234 * compat to 1.8, check osc name used by MDT0 to OSTs, bz18548.
236 if (!test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags) &&
237 lcfg->lcfg_command == LCFG_ATTACH &&
238 strcmp(lustre_cfg_string(lcfg, 1), LUSTRE_OSC_NAME) == 0) {
239 if (OBD_OCD_VERSION_MAJOR(d->ver) == 1 &&
240 OBD_OCD_VERSION_MINOR(d->ver) <= 8) {
241 CWARN("MDT using 1.8 OSC name scheme\n");
242 set_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags);
246 if (lcfg->lcfg_command == LCFG_MARKER) {
247 struct cfg_marker *marker;
248 marker = lustre_cfg_buf(lcfg, 1);
250 d->ver = marker->cm_vers;
252 /* Keep track of the latest marker step */
253 fsdb->fsdb_gen = max(fsdb->fsdb_gen, marker->cm_step);
259 /* fsdb->fsdb_mutex is already held in mgs_find_or_make_fsdb*/
260 static int mgs_get_fsdb_from_llog(const struct lu_env *env,
261 struct mgs_device *mgs,
265 struct llog_handle *loghandle;
266 struct llog_ctxt *ctxt;
267 struct mgs_fsdb_handler_data d = {
274 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
275 LASSERT(ctxt != NULL);
276 rc = name_create(&logname, fsdb->fsdb_name, "-client");
279 rc = llog_open_create(env, ctxt, &loghandle, NULL, logname);
283 rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
287 if (llog_get_size(loghandle) <= 1)
288 set_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags);
290 rc = llog_process(env, loghandle, mgs_fsdb_handler, (void *)&d, NULL);
291 CDEBUG(D_INFO, "get_db = %d\n", rc);
293 llog_close(env, loghandle);
295 name_destroy(&logname);
302 static void mgs_free_fsdb_srpc(struct fs_db *fsdb)
304 struct mgs_tgt_srpc_conf *tgtconf;
306 /* free target-specific rules */
307 while (fsdb->fsdb_srpc_tgt) {
308 tgtconf = fsdb->fsdb_srpc_tgt;
309 fsdb->fsdb_srpc_tgt = tgtconf->mtsc_next;
311 LASSERT(tgtconf->mtsc_tgt);
313 sptlrpc_rule_set_free(&tgtconf->mtsc_rset);
314 OBD_FREE(tgtconf->mtsc_tgt, strlen(tgtconf->mtsc_tgt) + 1);
315 OBD_FREE_PTR(tgtconf);
318 /* free general rules */
319 sptlrpc_rule_set_free(&fsdb->fsdb_srpc_gen);
322 struct fs_db *mgs_find_fsdb(struct mgs_device *mgs, char *fsname)
325 struct list_head *tmp;
327 list_for_each(tmp, &mgs->mgs_fs_db_list) {
328 fsdb = list_entry(tmp, struct fs_db, fsdb_list);
329 if (strcmp(fsdb->fsdb_name, fsname) == 0)
335 /* caller must hold the mgs->mgs_fs_db_lock */
336 static struct fs_db *mgs_new_fsdb(const struct lu_env *env,
337 struct mgs_device *mgs, char *fsname)
343 if (strlen(fsname) >= sizeof(fsdb->fsdb_name)) {
344 CERROR("fsname %s is too long\n", fsname);
345 RETURN(ERR_PTR(-EINVAL));
350 RETURN(ERR_PTR(-ENOMEM));
352 strcpy(fsdb->fsdb_name, fsname);
353 mutex_init(&fsdb->fsdb_mutex);
354 set_bit(FSDB_UDESC, &fsdb->fsdb_flags);
357 if (strcmp(fsname, MGSSELF_NAME) == 0) {
358 set_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags);
359 fsdb->fsdb_mgs = mgs;
361 OBD_ALLOC(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
362 OBD_ALLOC(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
363 if (!fsdb->fsdb_ost_index_map || !fsdb->fsdb_mdt_index_map) {
364 CERROR("No memory for index maps\n");
365 GOTO(err, rc = -ENOMEM);
368 rc = name_create(&fsdb->fsdb_clilov, fsname, "-clilov");
371 rc = name_create(&fsdb->fsdb_clilmv, fsname, "-clilmv");
375 /* initialise data for NID table */
376 mgs_ir_init_fs(env, mgs, fsdb);
378 lproc_mgs_add_live(mgs, fsdb);
381 list_add(&fsdb->fsdb_list, &mgs->mgs_fs_db_list);
385 if (fsdb->fsdb_ost_index_map)
386 OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
387 if (fsdb->fsdb_mdt_index_map)
388 OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
389 name_destroy(&fsdb->fsdb_clilov);
390 name_destroy(&fsdb->fsdb_clilmv);
395 static void mgs_free_fsdb(struct mgs_device *mgs, struct fs_db *fsdb)
397 /* wait for anyone with the sem */
398 mutex_lock(&fsdb->fsdb_mutex);
399 lproc_mgs_del_live(mgs, fsdb);
400 list_del(&fsdb->fsdb_list);
402 /* deinitialize fsr */
403 mgs_ir_fini_fs(mgs, fsdb);
405 if (fsdb->fsdb_ost_index_map)
406 OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
407 if (fsdb->fsdb_mdt_index_map)
408 OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
409 name_destroy(&fsdb->fsdb_clilov);
410 name_destroy(&fsdb->fsdb_clilmv);
411 mgs_free_fsdb_srpc(fsdb);
412 mutex_unlock(&fsdb->fsdb_mutex);
416 int mgs_init_fsdb_list(struct mgs_device *mgs)
418 INIT_LIST_HEAD(&mgs->mgs_fs_db_list);
422 int mgs_cleanup_fsdb_list(struct mgs_device *mgs)
425 struct list_head *tmp, *tmp2;
427 mutex_lock(&mgs->mgs_mutex);
428 list_for_each_safe(tmp, tmp2, &mgs->mgs_fs_db_list) {
429 fsdb = list_entry(tmp, struct fs_db, fsdb_list);
430 mgs_free_fsdb(mgs, fsdb);
432 mutex_unlock(&mgs->mgs_mutex);
436 int mgs_find_or_make_fsdb(const struct lu_env *env,
437 struct mgs_device *mgs, char *name,
444 mutex_lock(&mgs->mgs_mutex);
445 fsdb = mgs_find_fsdb(mgs, name);
447 mutex_unlock(&mgs->mgs_mutex);
452 CDEBUG(D_MGS, "Creating new db\n");
453 fsdb = mgs_new_fsdb(env, mgs, name);
454 /* lock fsdb_mutex until the db is loaded from llogs */
456 mutex_lock(&fsdb->fsdb_mutex);
457 mutex_unlock(&mgs->mgs_mutex);
459 RETURN(PTR_ERR(fsdb));
461 if (!test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
462 /* populate the db from the client llog */
463 rc = mgs_get_fsdb_from_llog(env, mgs, fsdb);
465 CERROR("Can't get db from client log %d\n", rc);
470 /* populate srpc rules from params llog */
471 rc = mgs_get_fsdb_srpc_from_llog(env, mgs, fsdb);
473 CERROR("Can't get db from params log %d\n", rc);
477 mutex_unlock(&fsdb->fsdb_mutex);
483 mutex_unlock(&fsdb->fsdb_mutex);
484 mgs_free_fsdb(mgs, fsdb);
490 -1= empty client log */
491 int mgs_check_index(const struct lu_env *env,
492 struct mgs_device *mgs,
493 struct mgs_target_info *mti)
500 LASSERT(!(mti->mti_flags & LDD_F_NEED_INDEX));
502 rc = mgs_find_or_make_fsdb(env, mgs, mti->mti_fsname, &fsdb);
504 CERROR("Can't get db for %s\n", mti->mti_fsname);
508 if (test_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags))
511 if (mti->mti_flags & LDD_F_SV_TYPE_OST)
512 imap = fsdb->fsdb_ost_index_map;
513 else if (mti->mti_flags & LDD_F_SV_TYPE_MDT)
514 imap = fsdb->fsdb_mdt_index_map;
518 if (test_bit(mti->mti_stripe_index, imap))
523 static __inline__ int next_index(void *index_map, int map_len)
526 for (i = 0; i < map_len * 8; i++)
527 if (!test_bit(i, index_map)) {
530 CERROR("max index %d exceeded.\n", i);
535 0 newly marked as in use
537 +EALREADY for update of an old index */
538 static int mgs_set_index(const struct lu_env *env,
539 struct mgs_device *mgs,
540 struct mgs_target_info *mti)
547 rc = mgs_find_or_make_fsdb(env, mgs, mti->mti_fsname, &fsdb);
549 CERROR("Can't get db for %s\n", mti->mti_fsname);
553 mutex_lock(&fsdb->fsdb_mutex);
554 if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
555 imap = fsdb->fsdb_ost_index_map;
556 } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
557 imap = fsdb->fsdb_mdt_index_map;
559 GOTO(out_up, rc = -EINVAL);
562 if (mti->mti_flags & LDD_F_NEED_INDEX) {
563 rc = next_index(imap, INDEX_MAP_SIZE);
565 GOTO(out_up, rc = -ERANGE);
566 mti->mti_stripe_index = rc;
567 if (mti->mti_flags & LDD_F_SV_TYPE_MDT)
568 fsdb->fsdb_mdt_count ++;
571 /* the last index(0xffff) is reserved for default value. */
572 if (mti->mti_stripe_index >= INDEX_MAP_SIZE * 8 - 1) {
573 LCONSOLE_ERROR_MSG(0x13f, "Server %s requested index %u, "
574 "but index must be less than %u.\n",
575 mti->mti_svname, mti->mti_stripe_index,
576 INDEX_MAP_SIZE * 8 - 1);
577 GOTO(out_up, rc = -ERANGE);
580 if (test_bit(mti->mti_stripe_index, imap)) {
581 if ((mti->mti_flags & LDD_F_VIRGIN) &&
582 !(mti->mti_flags & LDD_F_WRITECONF)) {
583 LCONSOLE_ERROR_MSG(0x140, "Server %s requested index "
584 "%d, but that index is already in "
585 "use. Use --writeconf to force\n",
587 mti->mti_stripe_index);
588 GOTO(out_up, rc = -EADDRINUSE);
590 CDEBUG(D_MGS, "Server %s updating index %d\n",
591 mti->mti_svname, mti->mti_stripe_index);
592 GOTO(out_up, rc = EALREADY);
596 set_bit(mti->mti_stripe_index, imap);
597 clear_bit(FSDB_LOG_EMPTY, &fsdb->fsdb_flags);
598 mutex_unlock(&fsdb->fsdb_mutex);
599 if (server_make_name(mti->mti_flags & ~(LDD_F_VIRGIN | LDD_F_WRITECONF),
600 mti->mti_stripe_index, mti->mti_fsname,
602 CERROR("unknown server type %#x\n", mti->mti_flags);
606 CDEBUG(D_MGS, "Set index for %s to %d\n", mti->mti_svname,
607 mti->mti_stripe_index);
611 mutex_unlock(&fsdb->fsdb_mutex);
615 struct mgs_modify_lookup {
616 struct cfg_marker mml_marker;
620 static int mgs_check_record_match(const struct lu_env *env,
621 struct llog_handle *llh,
622 struct llog_rec_hdr *rec, void *data)
624 struct cfg_marker *mc_marker = data;
625 struct cfg_marker *marker;
626 struct lustre_cfg *lcfg = REC_DATA(rec);
627 int cfg_len = REC_DATA_LEN(rec);
632 if (rec->lrh_type != OBD_CFG_REC) {
633 CDEBUG(D_ERROR, "Unhandled lrh_type: %#x\n", rec->lrh_type);
637 rc = lustre_cfg_sanity_check(lcfg, cfg_len);
639 CDEBUG(D_ERROR, "Insane cfg\n");
643 /* We only care about markers */
644 if (lcfg->lcfg_command != LCFG_MARKER)
647 marker = lustre_cfg_buf(lcfg, 1);
649 if (marker->cm_flags & CM_SKIP)
652 if ((strcmp(mc_marker->cm_comment, marker->cm_comment) == 0) &&
653 (strcmp(mc_marker->cm_tgtname, marker->cm_tgtname) == 0)) {
654 /* Found a non-skipped marker match */
655 CDEBUG(D_MGS, "Matched rec %u marker %d flag %x %s %s\n",
656 rec->lrh_index, marker->cm_step,
657 marker->cm_flags, marker->cm_tgtname,
659 rc = LLOG_PROC_BREAK;
666 * Check an existing config log record with matching comment and device
668 * 0 - checked successfully,
669 * LLOG_PROC_BREAK - record matches
672 static int mgs_check_marker(const struct lu_env *env, struct mgs_device *mgs,
673 struct fs_db *fsdb, struct mgs_target_info *mti,
674 char *logname, char *devname, char *comment)
676 struct llog_handle *loghandle;
677 struct llog_ctxt *ctxt;
678 struct cfg_marker *mc_marker;
683 LASSERT(mutex_is_locked(&fsdb->fsdb_mutex));
684 CDEBUG(D_MGS, "mgs check %s/%s/%s\n", logname, devname, comment);
686 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
687 LASSERT(ctxt != NULL);
688 rc = llog_open(env, ctxt, &loghandle, NULL, logname, LLOG_OPEN_EXISTS);
695 rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
699 if (llog_get_size(loghandle) <= 1)
700 GOTO(out_close, rc = 0);
702 OBD_ALLOC_PTR(mc_marker);
704 GOTO(out_close, rc = -ENOMEM);
705 if (strlcpy(mc_marker->cm_comment, comment,
706 sizeof(mc_marker->cm_comment)) >=
707 sizeof(mc_marker->cm_comment))
708 GOTO(out_free, rc = -E2BIG);
709 if (strlcpy(mc_marker->cm_tgtname, devname,
710 sizeof(mc_marker->cm_tgtname)) >=
711 sizeof(mc_marker->cm_tgtname))
712 GOTO(out_free, rc = -E2BIG);
714 rc = llog_process(env, loghandle, mgs_check_record_match,
715 (void *)mc_marker, NULL);
718 OBD_FREE_PTR(mc_marker);
721 llog_close(env, loghandle);
723 if (rc && rc != LLOG_PROC_BREAK)
724 CDEBUG(D_ERROR, "%s: mgs check %s/%s failed: rc = %d\n",
725 mgs->mgs_obd->obd_name, mti->mti_svname, comment, rc);
730 static int mgs_modify_handler(const struct lu_env *env,
731 struct llog_handle *llh,
732 struct llog_rec_hdr *rec, void *data)
734 struct mgs_modify_lookup *mml = data;
735 struct cfg_marker *marker;
736 struct lustre_cfg *lcfg = REC_DATA(rec);
737 int cfg_len = REC_DATA_LEN(rec);
741 if (rec->lrh_type != OBD_CFG_REC) {
742 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
746 rc = lustre_cfg_sanity_check(lcfg, cfg_len);
748 CERROR("Insane cfg\n");
752 /* We only care about markers */
753 if (lcfg->lcfg_command != LCFG_MARKER)
756 marker = lustre_cfg_buf(lcfg, 1);
757 if ((strcmp(mml->mml_marker.cm_comment, marker->cm_comment) == 0) &&
758 (strcmp(mml->mml_marker.cm_tgtname, marker->cm_tgtname) == 0) &&
759 !(marker->cm_flags & CM_SKIP)) {
760 /* Found a non-skipped marker match */
761 CDEBUG(D_MGS, "Changing rec %u marker %d %x->%x: %s %s\n",
762 rec->lrh_index, marker->cm_step,
763 marker->cm_flags, mml->mml_marker.cm_flags,
764 marker->cm_tgtname, marker->cm_comment);
765 /* Overwrite the old marker llog entry */
766 marker->cm_flags &= ~CM_EXCLUDE; /* in case we're unexcluding */
767 marker->cm_flags |= mml->mml_marker.cm_flags;
768 marker->cm_canceltime = mml->mml_marker.cm_canceltime;
769 rc = llog_write(env, llh, rec, rec->lrh_index);
778 * Modify an existing config log record (for CM_SKIP or CM_EXCLUDE)
780 * 0 - modified successfully,
781 * 1 - no modification was done
784 static int mgs_modify(const struct lu_env *env, struct mgs_device *mgs,
785 struct fs_db *fsdb, struct mgs_target_info *mti,
786 char *logname, char *devname, char *comment, int flags)
788 struct llog_handle *loghandle;
789 struct llog_ctxt *ctxt;
790 struct mgs_modify_lookup *mml;
795 LASSERT(mutex_is_locked(&fsdb->fsdb_mutex));
796 CDEBUG(D_MGS, "modify %s/%s/%s fl=%x\n", logname, devname, comment,
799 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
800 LASSERT(ctxt != NULL);
801 rc = llog_open(env, ctxt, &loghandle, NULL, logname, LLOG_OPEN_EXISTS);
808 rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
812 if (llog_get_size(loghandle) <= 1)
813 GOTO(out_close, rc = 0);
817 GOTO(out_close, rc = -ENOMEM);
818 if (strlcpy(mml->mml_marker.cm_comment, comment,
819 sizeof(mml->mml_marker.cm_comment)) >=
820 sizeof(mml->mml_marker.cm_comment))
821 GOTO(out_free, rc = -E2BIG);
822 if (strlcpy(mml->mml_marker.cm_tgtname, devname,
823 sizeof(mml->mml_marker.cm_tgtname)) >=
824 sizeof(mml->mml_marker.cm_tgtname))
825 GOTO(out_free, rc = -E2BIG);
826 /* Modify mostly means cancel */
827 mml->mml_marker.cm_flags = flags;
828 mml->mml_marker.cm_canceltime = flags ? cfs_time_current_sec() : 0;
829 mml->mml_modified = 0;
830 rc = llog_process(env, loghandle, mgs_modify_handler, (void *)mml,
832 if (!rc && !mml->mml_modified)
839 llog_close(env, loghandle);
842 CERROR("%s: modify %s/%s failed: rc = %d\n",
843 mgs->mgs_obd->obd_name, mti->mti_svname, comment, rc);
848 /** This structure is passed to mgs_replace_handler */
849 struct mgs_replace_uuid_lookup {
850 /* Nids are replaced for this target device */
851 struct mgs_target_info target;
852 /* Temporary modified llog */
853 struct llog_handle *temp_llh;
854 /* Flag is set if in target block*/
855 int in_target_device;
856 /* Nids already added. Just skip (multiple nids) */
857 int device_nids_added;
858 /* Flag is set if this block should not be copied */
863 * Check: a) if block should be skipped
864 * b) is it target block
869 * \retval 0 should not to be skipped
870 * \retval 1 should to be skipped
872 static int check_markers(struct lustre_cfg *lcfg,
873 struct mgs_replace_uuid_lookup *mrul)
875 struct cfg_marker *marker;
877 /* Track markers. Find given device */
878 if (lcfg->lcfg_command == LCFG_MARKER) {
879 marker = lustre_cfg_buf(lcfg, 1);
880 /* Clean llog from records marked as CM_EXCLUDE.
881 CM_SKIP records are used for "active" command
882 and can be restored if needed */
883 if ((marker->cm_flags & (CM_EXCLUDE | CM_START)) ==
884 (CM_EXCLUDE | CM_START)) {
889 if ((marker->cm_flags & (CM_EXCLUDE | CM_END)) ==
890 (CM_EXCLUDE | CM_END)) {
895 if (strcmp(mrul->target.mti_svname, marker->cm_tgtname) == 0) {
896 LASSERT(!(marker->cm_flags & CM_START) ||
897 !(marker->cm_flags & CM_END));
898 if (marker->cm_flags & CM_START) {
899 mrul->in_target_device = 1;
900 mrul->device_nids_added = 0;
901 } else if (marker->cm_flags & CM_END)
902 mrul->in_target_device = 0;
909 static int record_base(const struct lu_env *env, struct llog_handle *llh,
910 char *cfgname, lnet_nid_t nid, int cmd,
911 char *s1, char *s2, char *s3, char *s4)
913 struct mgs_thread_info *mgi = mgs_env_info(env);
914 struct llog_cfg_rec *lcr;
917 CDEBUG(D_MGS, "lcfg %s %#x %s %s %s %s\n", cfgname,
918 cmd, s1, s2, s3, s4);
920 lustre_cfg_bufs_reset(&mgi->mgi_bufs, cfgname);
922 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, s1);
924 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 2, s2);
926 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 3, s3);
928 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 4, s4);
930 lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
934 lcr->lcr_cfg.lcfg_nid = nid;
935 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
937 lustre_cfg_rec_free(lcr);
941 "failed to write lcfg %s %#x %s %s %s %s: rc = %d\n",
942 cfgname, cmd, s1, s2, s3, s4, rc);
946 static inline int record_add_uuid(const struct lu_env *env,
947 struct llog_handle *llh,
948 uint64_t nid, char *uuid)
950 return record_base(env, llh, NULL, nid, LCFG_ADD_UUID, uuid,
954 static inline int record_add_conn(const struct lu_env *env,
955 struct llog_handle *llh,
956 char *devname, char *uuid)
958 return record_base(env, llh, devname, 0, LCFG_ADD_CONN, uuid,
962 static inline int record_attach(const struct lu_env *env,
963 struct llog_handle *llh, char *devname,
964 char *type, char *uuid)
966 return record_base(env, llh, devname, 0, LCFG_ATTACH, type, uuid,
970 static inline int record_setup(const struct lu_env *env,
971 struct llog_handle *llh, char *devname,
972 char *s1, char *s2, char *s3, char *s4)
974 return record_base(env, llh, devname, 0, LCFG_SETUP, s1, s2, s3, s4);
978 * \retval <0 record processing error
979 * \retval n record is processed. No need copy original one.
980 * \retval 0 record is not processed.
982 static int process_command(const struct lu_env *env, struct lustre_cfg *lcfg,
983 struct mgs_replace_uuid_lookup *mrul)
990 if (lcfg->lcfg_command == LCFG_ADD_UUID) {
991 /* LCFG_ADD_UUID command found. Let's skip original command
992 and add passed nids */
993 ptr = mrul->target.mti_params;
994 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
995 CDEBUG(D_MGS, "add nid %s with uuid %s, "
996 "device %s\n", libcfs_nid2str(nid),
997 mrul->target.mti_params,
998 mrul->target.mti_svname);
999 rc = record_add_uuid(env,
1000 mrul->temp_llh, nid,
1001 mrul->target.mti_params);
1006 if (nids_added == 0) {
1007 CERROR("No new nids were added, nid %s with uuid %s, "
1008 "device %s\n", libcfs_nid2str(nid),
1009 mrul->target.mti_params,
1010 mrul->target.mti_svname);
1013 mrul->device_nids_added = 1;
1019 if (mrul->device_nids_added && lcfg->lcfg_command == LCFG_SETUP) {
1020 /* LCFG_SETUP command found. UUID should be changed */
1021 rc = record_setup(env,
1023 /* devname the same */
1024 lustre_cfg_string(lcfg, 0),
1025 /* s1 is not changed */
1026 lustre_cfg_string(lcfg, 1),
1027 /* new uuid should be
1029 mrul->target.mti_params,
1030 /* s3 is not changed */
1031 lustre_cfg_string(lcfg, 3),
1032 /* s4 is not changed */
1033 lustre_cfg_string(lcfg, 4));
1037 /* Another commands in target device block */
1042 * Handler that called for every record in llog.
1043 * Records are processed in order they placed in llog.
1045 * \param[in] llh log to be processed
1046 * \param[in] rec current record
1047 * \param[in] data mgs_replace_uuid_lookup structure
1051 static int mgs_replace_handler(const struct lu_env *env,
1052 struct llog_handle *llh,
1053 struct llog_rec_hdr *rec,
1056 struct mgs_replace_uuid_lookup *mrul;
1057 struct lustre_cfg *lcfg = REC_DATA(rec);
1058 int cfg_len = REC_DATA_LEN(rec);
1062 mrul = (struct mgs_replace_uuid_lookup *)data;
1064 if (rec->lrh_type != OBD_CFG_REC) {
1065 CERROR("unhandled lrh_type: %#x, cmd %x %s %s\n",
1066 rec->lrh_type, lcfg->lcfg_command,
1067 lustre_cfg_string(lcfg, 0),
1068 lustre_cfg_string(lcfg, 1));
1072 rc = lustre_cfg_sanity_check(lcfg, cfg_len);
1074 /* Do not copy any invalidated records */
1075 GOTO(skip_out, rc = 0);
1078 rc = check_markers(lcfg, mrul);
1079 if (rc || mrul->skip_it)
1080 GOTO(skip_out, rc = 0);
1082 /* Write to new log all commands outside target device block */
1083 if (!mrul->in_target_device)
1084 GOTO(copy_out, rc = 0);
1086 /* Skip all other LCFG_ADD_UUID and LCFG_ADD_CONN records
1087 (failover nids) for this target, assuming that if then
1088 primary is changing then so is the failover */
1089 if (mrul->device_nids_added &&
1090 (lcfg->lcfg_command == LCFG_ADD_UUID ||
1091 lcfg->lcfg_command == LCFG_ADD_CONN))
1092 GOTO(skip_out, rc = 0);
1094 rc = process_command(env, lcfg, mrul);
1101 /* Record is placed in temporary llog as is */
1102 rc = llog_write(env, mrul->temp_llh, rec, LLOG_NEXT_IDX);
1104 CDEBUG(D_MGS, "Copied idx=%d, rc=%d, len=%d, cmd %x %s %s\n",
1105 rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
1106 lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
1110 CDEBUG(D_MGS, "Skipped idx=%d, rc=%d, len=%d, cmd %x %s %s\n",
1111 rec->lrh_index, rc, rec->lrh_len, lcfg->lcfg_command,
1112 lustre_cfg_string(lcfg, 0), lustre_cfg_string(lcfg, 1));
1116 static int mgs_log_is_empty(const struct lu_env *env,
1117 struct mgs_device *mgs, char *name)
1119 struct llog_ctxt *ctxt;
1122 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
1123 LASSERT(ctxt != NULL);
1125 rc = llog_is_empty(env, ctxt, name);
1126 llog_ctxt_put(ctxt);
1130 static int mgs_replace_nids_log(const struct lu_env *env,
1131 struct obd_device *mgs, struct fs_db *fsdb,
1132 char *logname, char *devname, char *nids)
1134 struct llog_handle *orig_llh, *backup_llh;
1135 struct llog_ctxt *ctxt;
1136 struct mgs_replace_uuid_lookup *mrul;
1137 struct mgs_device *mgs_dev = lu2mgs_dev(mgs->obd_lu_dev);
1138 static struct obd_uuid cfg_uuid = { .uuid = "config_uuid" };
1143 CDEBUG(D_MGS, "Replace nids for %s in %s\n", devname, logname);
1145 ctxt = llog_get_context(mgs, LLOG_CONFIG_ORIG_CTXT);
1146 LASSERT(ctxt != NULL);
1148 if (mgs_log_is_empty(env, mgs_dev, logname)) {
1149 /* Log is empty. Nothing to replace */
1150 GOTO(out_put, rc = 0);
1153 OBD_ALLOC(backup, strlen(logname) + strlen(".bak") + 1);
1155 GOTO(out_put, rc = -ENOMEM);
1157 sprintf(backup, "%s.bak", logname);
1159 rc = llog_backup(env, mgs, ctxt, ctxt, logname, backup);
1161 /* Now erase original log file. Connections are not allowed.
1162 Backup is already saved */
1163 rc = llog_erase(env, ctxt, NULL, logname);
1166 } else if (rc != -ENOENT) {
1167 CERROR("%s: can't make backup for %s: rc = %d\n",
1168 mgs->obd_name, logname, rc);
1172 /* open local log */
1173 rc = llog_open_create(env, ctxt, &orig_llh, NULL, logname);
1175 GOTO(out_restore, rc);
1177 rc = llog_init_handle(env, orig_llh, LLOG_F_IS_PLAIN, &cfg_uuid);
1179 GOTO(out_closel, rc);
1181 /* open backup llog */
1182 rc = llog_open(env, ctxt, &backup_llh, NULL, backup,
1185 GOTO(out_closel, rc);
1187 rc = llog_init_handle(env, backup_llh, LLOG_F_IS_PLAIN, NULL);
1189 GOTO(out_close, rc);
1191 if (llog_get_size(backup_llh) <= 1)
1192 GOTO(out_close, rc = 0);
1194 OBD_ALLOC_PTR(mrul);
1196 GOTO(out_close, rc = -ENOMEM);
1197 /* devname is only needed information to replace UUID records */
1198 strlcpy(mrul->target.mti_svname, devname,
1199 sizeof(mrul->target.mti_svname));
1200 /* parse nids later */
1201 strlcpy(mrul->target.mti_params, nids, sizeof(mrul->target.mti_params));
1202 /* Copy records to this temporary llog */
1203 mrul->temp_llh = orig_llh;
1205 rc = llog_process(env, backup_llh, mgs_replace_handler,
1206 (void *)mrul, NULL);
1209 rc2 = llog_close(NULL, backup_llh);
1213 rc2 = llog_close(NULL, orig_llh);
1219 CERROR("%s: llog should be restored: rc = %d\n",
1221 rc2 = llog_backup(env, mgs, ctxt, ctxt, backup,
1224 CERROR("%s: can't restore backup %s: rc = %d\n",
1225 mgs->obd_name, logname, rc2);
1229 OBD_FREE(backup, strlen(backup) + 1);
1232 llog_ctxt_put(ctxt);
1235 CERROR("%s: failed to replace nids in log %s: rc = %d\n",
1236 mgs->obd_name, logname, rc);
1242 * Parse device name and get file system name and/or device index
1244 * \param[in] devname device name (ex. lustre-MDT0000)
1245 * \param[out] fsname file system name(optional)
1246 * \param[out] index device index(optional)
1250 static int mgs_parse_devname(char *devname, char *fsname, __u32 *index)
1255 /* Extract fsname */
1257 rc = server_name2fsname(devname, fsname, NULL);
1259 CDEBUG(D_MGS, "Device name %s without fsname\n",
1266 rc = server_name2index(devname, index, NULL);
1268 CDEBUG(D_MGS, "Device name %s with wrong index\n",
1277 /* This is only called during replace_nids */
1278 static int only_mgs_is_running(struct obd_device *mgs_obd)
1280 /* TDB: Is global variable with devices count exists? */
1281 int num_devices = get_devices_count();
1282 int num_exports = 0;
1283 struct obd_export *exp;
1285 spin_lock(&mgs_obd->obd_dev_lock);
1286 list_for_each_entry(exp, &mgs_obd->obd_exports, exp_obd_chain) {
1287 /* skip self export */
1288 if (exp == mgs_obd->obd_self_export)
1290 if (exp_connect_flags(exp) & OBD_CONNECT_MDS_MDS)
1295 CERROR("%s: node %s still connected during replace_nids "
1296 "connect_flags:%llx\n",
1298 libcfs_nid2str(exp->exp_nid_stats->nid),
1299 exp_connect_flags(exp));
1302 spin_unlock(&mgs_obd->obd_dev_lock);
1304 /* osd, MGS and MGC + self_export
1305 (wc -l /proc/fs/lustre/devices <= 2) && (non self exports == 0) */
1306 return (num_devices <= 3) && (num_exports == 0);
1309 static int name_create_mdt(char **logname, char *fsname, int i)
1313 sprintf(mdt_index, "-MDT%04x", i);
1314 return name_create(logname, fsname, mdt_index);
1318 * Replace nids for \a device to \a nids values
1320 * \param obd MGS obd device
1321 * \param devname nids need to be replaced for this device
1322 * (ex. lustre-OST0000)
1323 * \param nids nids list (ex. nid1,nid2,nid3)
1327 int mgs_replace_nids(const struct lu_env *env,
1328 struct mgs_device *mgs,
1329 char *devname, char *nids)
1331 /* Assume fsname is part of device name */
1332 char fsname[MTI_NAME_MAXLEN];
1339 struct obd_device *mgs_obd = mgs->mgs_obd;
1342 /* We can only change NIDs if no other nodes are connected */
1343 spin_lock(&mgs_obd->obd_dev_lock);
1344 conn_state = mgs_obd->obd_no_conn;
1345 mgs_obd->obd_no_conn = 1;
1346 spin_unlock(&mgs_obd->obd_dev_lock);
1348 /* We can not change nids if not only MGS is started */
1349 if (!only_mgs_is_running(mgs_obd)) {
1350 CERROR("Only MGS is allowed to be started\n");
1351 GOTO(out, rc = -EINPROGRESS);
1354 /* Get fsname and index*/
1355 rc = mgs_parse_devname(devname, fsname, &index);
1359 rc = mgs_find_or_make_fsdb(env, mgs, fsname, &fsdb);
1361 CERROR("%s: can't find fsdb: rc = %d\n", fsname, rc);
1365 /* Process client llogs */
1366 name_create(&logname, fsname, "-client");
1367 rc = mgs_replace_nids_log(env, mgs_obd, fsdb, logname, devname, nids);
1368 name_destroy(&logname);
1370 CERROR("%s: error while replacing NIDs for %s: rc = %d\n",
1371 fsname, devname, rc);
1375 /* Process MDT llogs */
1376 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
1377 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
1379 name_create_mdt(&logname, fsname, i);
1380 rc = mgs_replace_nids_log(env, mgs_obd, fsdb, logname, devname, nids);
1381 name_destroy(&logname);
1387 spin_lock(&mgs_obd->obd_dev_lock);
1388 mgs_obd->obd_no_conn = conn_state;
1389 spin_unlock(&mgs_obd->obd_dev_lock);
1394 static int record_lov_setup(const struct lu_env *env, struct llog_handle *llh,
1395 char *devname, struct lov_desc *desc)
1397 struct mgs_thread_info *mgi = mgs_env_info(env);
1398 struct llog_cfg_rec *lcr;
1401 lustre_cfg_bufs_reset(&mgi->mgi_bufs, devname);
1402 lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, desc, sizeof(*desc));
1403 lcr = lustre_cfg_rec_new(LCFG_SETUP, &mgi->mgi_bufs);
1407 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1408 lustre_cfg_rec_free(lcr);
1412 static int record_lmv_setup(const struct lu_env *env, struct llog_handle *llh,
1413 char *devname, struct lmv_desc *desc)
1415 struct mgs_thread_info *mgi = mgs_env_info(env);
1416 struct llog_cfg_rec *lcr;
1419 lustre_cfg_bufs_reset(&mgi->mgi_bufs, devname);
1420 lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, desc, sizeof(*desc));
1421 lcr = lustre_cfg_rec_new(LCFG_SETUP, &mgi->mgi_bufs);
1425 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1426 lustre_cfg_rec_free(lcr);
1430 static inline int record_mdc_add(const struct lu_env *env,
1431 struct llog_handle *llh,
1432 char *logname, char *mdcuuid,
1433 char *mdtuuid, char *index,
1436 return record_base(env,llh,logname,0,LCFG_ADD_MDC,
1437 mdtuuid,index,gen,mdcuuid);
1440 static inline int record_lov_add(const struct lu_env *env,
1441 struct llog_handle *llh,
1442 char *lov_name, char *ost_uuid,
1443 char *index, char *gen)
1445 return record_base(env, llh, lov_name, 0, LCFG_LOV_ADD_OBD,
1446 ost_uuid, index, gen, NULL);
1449 static inline int record_mount_opt(const struct lu_env *env,
1450 struct llog_handle *llh,
1451 char *profile, char *lov_name,
1454 return record_base(env, llh, NULL, 0, LCFG_MOUNTOPT,
1455 profile, lov_name, mdc_name, NULL);
1458 static int record_marker(const struct lu_env *env,
1459 struct llog_handle *llh,
1460 struct fs_db *fsdb, __u32 flags,
1461 char *tgtname, char *comment)
1463 struct mgs_thread_info *mgi = mgs_env_info(env);
1464 struct llog_cfg_rec *lcr;
1468 if (flags & CM_START)
1470 mgi->mgi_marker.cm_step = fsdb->fsdb_gen;
1471 mgi->mgi_marker.cm_flags = flags;
1472 mgi->mgi_marker.cm_vers = LUSTRE_VERSION_CODE;
1473 cplen = strlcpy(mgi->mgi_marker.cm_tgtname, tgtname,
1474 sizeof(mgi->mgi_marker.cm_tgtname));
1475 if (cplen >= sizeof(mgi->mgi_marker.cm_tgtname))
1477 cplen = strlcpy(mgi->mgi_marker.cm_comment, comment,
1478 sizeof(mgi->mgi_marker.cm_comment));
1479 if (cplen >= sizeof(mgi->mgi_marker.cm_comment))
1481 mgi->mgi_marker.cm_createtime = cfs_time_current_sec();
1482 mgi->mgi_marker.cm_canceltime = 0;
1483 lustre_cfg_bufs_reset(&mgi->mgi_bufs, NULL);
1484 lustre_cfg_bufs_set(&mgi->mgi_bufs, 1, &mgi->mgi_marker,
1485 sizeof(mgi->mgi_marker));
1486 lcr = lustre_cfg_rec_new(LCFG_MARKER, &mgi->mgi_bufs);
1490 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1491 lustre_cfg_rec_free(lcr);
1495 static int record_start_log(const struct lu_env *env, struct mgs_device *mgs,
1496 struct llog_handle **llh, char *name)
1498 static struct obd_uuid cfg_uuid = { .uuid = "config_uuid" };
1499 struct llog_ctxt *ctxt;
1504 GOTO(out, rc = -EBUSY);
1506 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
1508 GOTO(out, rc = -ENODEV);
1509 LASSERT(ctxt->loc_obd == mgs->mgs_obd);
1511 rc = llog_open_create(env, ctxt, llh, NULL, name);
1514 rc = llog_init_handle(env, *llh, LLOG_F_IS_PLAIN, &cfg_uuid);
1516 llog_close(env, *llh);
1518 llog_ctxt_put(ctxt);
1521 CERROR("%s: can't start log %s: rc = %d\n",
1522 mgs->mgs_obd->obd_name, name, rc);
1528 static int record_end_log(const struct lu_env *env, struct llog_handle **llh)
1532 rc = llog_close(env, *llh);
1538 /******************** config "macros" *********************/
1540 /* write an lcfg directly into a log (with markers) */
1541 static int mgs_write_log_direct(const struct lu_env *env,
1542 struct mgs_device *mgs, struct fs_db *fsdb,
1543 char *logname, struct llog_cfg_rec *lcr,
1544 char *devname, char *comment)
1546 struct llog_handle *llh = NULL;
1551 rc = record_start_log(env, mgs, &llh, logname);
1555 /* FIXME These should be a single journal transaction */
1556 rc = record_marker(env, llh, fsdb, CM_START, devname, comment);
1559 rc = llog_write(env, llh, &lcr->lcr_hdr, LLOG_NEXT_IDX);
1562 rc = record_marker(env, llh, fsdb, CM_END, devname, comment);
1566 record_end_log(env, &llh);
1570 /* write the lcfg in all logs for the given fs */
1571 static int mgs_write_log_direct_all(const struct lu_env *env,
1572 struct mgs_device *mgs,
1574 struct mgs_target_info *mti,
1575 struct llog_cfg_rec *lcr, char *devname,
1576 char *comment, int server_only)
1578 struct list_head log_list;
1579 struct mgs_direntry *dirent, *n;
1580 char *fsname = mti->mti_fsname;
1581 int rc = 0, len = strlen(fsname);
1584 /* Find all the logs in the CONFIGS directory */
1585 rc = class_dentry_readdir(env, mgs, &log_list);
1589 /* Could use fsdb index maps instead of directory listing */
1590 list_for_each_entry_safe(dirent, n, &log_list, mde_list) {
1591 list_del_init(&dirent->mde_list);
1592 /* don't write to sptlrpc rule log */
1593 if (strstr(dirent->mde_name, "-sptlrpc") != NULL)
1596 /* caller wants write server logs only */
1597 if (server_only && strstr(dirent->mde_name, "-client") != NULL)
1600 if (strlen(dirent->mde_name) <= len ||
1601 strncmp(fsname, dirent->mde_name, len) != 0 ||
1602 dirent->mde_name[len] != '-')
1605 CDEBUG(D_MGS, "Changing log %s\n", dirent->mde_name);
1606 /* Erase any old settings of this same parameter */
1607 rc = mgs_modify(env, mgs, fsdb, mti, dirent->mde_name,
1608 devname, comment, CM_SKIP);
1610 CERROR("%s: Can't modify llog %s: rc = %d\n",
1611 mgs->mgs_obd->obd_name, dirent->mde_name, rc);
1614 /* Write the new one */
1615 rc = mgs_write_log_direct(env, mgs, fsdb, dirent->mde_name,
1616 lcr, devname, comment);
1618 CERROR("%s: writing log %s: rc = %d\n",
1619 mgs->mgs_obd->obd_name, dirent->mde_name, rc);
1621 mgs_direntry_free(dirent);
1627 static int mgs_write_log_osp_to_mdt(const struct lu_env *env,
1628 struct mgs_device *mgs,
1630 struct mgs_target_info *mti,
1631 int index, char *logname);
1632 static int mgs_write_log_osc_to_lov(const struct lu_env *env,
1633 struct mgs_device *mgs,
1635 struct mgs_target_info *mti,
1636 char *logname, char *suffix, char *lovname,
1637 enum lustre_sec_part sec_part, int flags);
1638 static int name_create_mdt_and_lov(char **logname, char **lovname,
1639 struct fs_db *fsdb, int i);
1641 static int add_param(char *params, char *key, char *val)
1643 char *start = params + strlen(params);
1644 char *end = params + sizeof(((struct mgs_target_info *)0)->mti_params);
1648 keylen = strlen(key);
1649 if (start + 1 + keylen + strlen(val) >= end) {
1650 CERROR("params are too long: %s %s%s\n",
1651 params, key != NULL ? key : "", val);
1655 sprintf(start, " %s%s", key != NULL ? key : "", val);
1660 * Walk through client config log record and convert the related records
1663 static int mgs_steal_client_llog_handler(const struct lu_env *env,
1664 struct llog_handle *llh,
1665 struct llog_rec_hdr *rec, void *data)
1667 struct mgs_device *mgs;
1668 struct obd_device *obd;
1669 struct mgs_target_info *mti, *tmti;
1671 int cfg_len = rec->lrh_len;
1672 char *cfg_buf = (char*) (rec + 1);
1673 struct lustre_cfg *lcfg;
1675 struct llog_handle *mdt_llh = NULL;
1676 static int got_an_osc_or_mdc = 0;
1677 /* 0: not found any osc/mdc;
1681 static int last_step = -1;
1686 mti = ((struct temp_comp*)data)->comp_mti;
1687 tmti = ((struct temp_comp*)data)->comp_tmti;
1688 fsdb = ((struct temp_comp*)data)->comp_fsdb;
1689 obd = ((struct temp_comp *)data)->comp_obd;
1690 mgs = lu2mgs_dev(obd->obd_lu_dev);
1693 if (rec->lrh_type != OBD_CFG_REC) {
1694 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
1698 rc = lustre_cfg_sanity_check(cfg_buf, cfg_len);
1700 CERROR("Insane cfg\n");
1704 lcfg = (struct lustre_cfg *)cfg_buf;
1706 if (lcfg->lcfg_command == LCFG_MARKER) {
1707 struct cfg_marker *marker;
1708 marker = lustre_cfg_buf(lcfg, 1);
1709 if (!strncmp(marker->cm_comment, "add osc", 7) &&
1710 (marker->cm_flags & CM_START) &&
1711 !(marker->cm_flags & CM_SKIP)) {
1712 got_an_osc_or_mdc = 1;
1713 cplen = strlcpy(tmti->mti_svname, marker->cm_tgtname,
1714 sizeof(tmti->mti_svname));
1715 if (cplen >= sizeof(tmti->mti_svname))
1717 rc = record_start_log(env, mgs, &mdt_llh,
1721 rc = record_marker(env, mdt_llh, fsdb, CM_START,
1722 mti->mti_svname, "add osc(copied)");
1723 record_end_log(env, &mdt_llh);
1724 last_step = marker->cm_step;
1727 if (!strncmp(marker->cm_comment, "add osc", 7) &&
1728 (marker->cm_flags & CM_END) &&
1729 !(marker->cm_flags & CM_SKIP)) {
1730 LASSERT(last_step == marker->cm_step);
1732 got_an_osc_or_mdc = 0;
1733 memset(tmti, 0, sizeof(*tmti));
1734 rc = record_start_log(env, mgs, &mdt_llh,
1738 rc = record_marker(env, mdt_llh, fsdb, CM_END,
1739 mti->mti_svname, "add osc(copied)");
1740 record_end_log(env, &mdt_llh);
1743 if (!strncmp(marker->cm_comment, "add mdc", 7) &&
1744 (marker->cm_flags & CM_START) &&
1745 !(marker->cm_flags & CM_SKIP)) {
1746 got_an_osc_or_mdc = 2;
1747 last_step = marker->cm_step;
1748 memcpy(tmti->mti_svname, marker->cm_tgtname,
1749 strlen(marker->cm_tgtname));
1753 if (!strncmp(marker->cm_comment, "add mdc", 7) &&
1754 (marker->cm_flags & CM_END) &&
1755 !(marker->cm_flags & CM_SKIP)) {
1756 LASSERT(last_step == marker->cm_step);
1758 got_an_osc_or_mdc = 0;
1759 memset(tmti, 0, sizeof(*tmti));
1764 if (got_an_osc_or_mdc == 0 || last_step < 0)
1767 if (lcfg->lcfg_command == LCFG_ADD_UUID) {
1768 __u64 nodenid = lcfg->lcfg_nid;
1770 if (strlen(tmti->mti_uuid) == 0) {
1771 /* target uuid not set, this config record is before
1772 * LCFG_SETUP, this nid is one of target node nid.
1774 tmti->mti_nids[tmti->mti_nid_count] = nodenid;
1775 tmti->mti_nid_count++;
1777 char nidstr[LNET_NIDSTR_SIZE];
1779 /* failover node nid */
1780 libcfs_nid2str_r(nodenid, nidstr, sizeof(nidstr));
1781 rc = add_param(tmti->mti_params, PARAM_FAILNODE,
1788 if (lcfg->lcfg_command == LCFG_SETUP) {
1791 target = lustre_cfg_string(lcfg, 1);
1792 memcpy(tmti->mti_uuid, target, strlen(target));
1796 /* ignore client side sptlrpc_conf_log */
1797 if (lcfg->lcfg_command == LCFG_SPTLRPC_CONF)
1800 if (lcfg->lcfg_command == LCFG_ADD_MDC) {
1803 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1)
1806 memcpy(tmti->mti_fsname, mti->mti_fsname,
1807 strlen(mti->mti_fsname));
1808 tmti->mti_stripe_index = index;
1810 rc = mgs_write_log_osp_to_mdt(env, mgs, fsdb, tmti,
1811 mti->mti_stripe_index,
1813 memset(tmti, 0, sizeof(*tmti));
1817 if (lcfg->lcfg_command == LCFG_LOV_ADD_OBD) {
1820 char *logname, *lovname;
1822 rc = name_create_mdt_and_lov(&logname, &lovname, fsdb,
1823 mti->mti_stripe_index);
1826 sprintf(mdt_index, "-MDT%04x", mti->mti_stripe_index);
1828 if (sscanf(lustre_cfg_buf(lcfg, 2), "%d", &index) != 1) {
1829 name_destroy(&logname);
1830 name_destroy(&lovname);
1834 tmti->mti_stripe_index = index;
1835 rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, tmti, logname,
1838 name_destroy(&logname);
1839 name_destroy(&lovname);
1845 /* fsdb->fsdb_mutex is already held in mgs_write_log_target*/
1846 /* stealed from mgs_get_fsdb_from_llog*/
1847 static int mgs_steal_llog_for_mdt_from_client(const struct lu_env *env,
1848 struct mgs_device *mgs,
1850 struct temp_comp* comp)
1852 struct llog_handle *loghandle;
1853 struct mgs_target_info *tmti;
1854 struct llog_ctxt *ctxt;
1859 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
1860 LASSERT(ctxt != NULL);
1862 OBD_ALLOC_PTR(tmti);
1864 GOTO(out_ctxt, rc = -ENOMEM);
1866 comp->comp_tmti = tmti;
1867 comp->comp_obd = mgs->mgs_obd;
1869 rc = llog_open(env, ctxt, &loghandle, NULL, client_name,
1877 rc = llog_init_handle(env, loghandle, LLOG_F_IS_PLAIN, NULL);
1879 GOTO(out_close, rc);
1881 rc = llog_process_or_fork(env, loghandle, mgs_steal_client_llog_handler,
1882 (void *)comp, NULL, false);
1883 CDEBUG(D_MGS, "steal llog re = %d\n", rc);
1885 llog_close(env, loghandle);
1889 llog_ctxt_put(ctxt);
1893 /* lmv is the second thing for client logs */
1894 /* copied from mgs_write_log_lov. Please refer to that. */
1895 static int mgs_write_log_lmv(const struct lu_env *env,
1896 struct mgs_device *mgs,
1898 struct mgs_target_info *mti,
1899 char *logname, char *lmvname)
1901 struct llog_handle *llh = NULL;
1902 struct lmv_desc *lmvdesc;
1907 CDEBUG(D_MGS, "Writing lmv(%s) log for %s\n", lmvname,logname);
1909 OBD_ALLOC_PTR(lmvdesc);
1910 if (lmvdesc == NULL)
1912 lmvdesc->ld_active_tgt_count = 0;
1913 lmvdesc->ld_tgt_count = 0;
1914 sprintf((char*)lmvdesc->ld_uuid.uuid, "%s_UUID", lmvname);
1915 uuid = (char *)lmvdesc->ld_uuid.uuid;
1917 rc = record_start_log(env, mgs, &llh, logname);
1920 rc = record_marker(env, llh, fsdb, CM_START, lmvname, "lmv setup");
1923 rc = record_attach(env, llh, lmvname, "lmv", uuid);
1926 rc = record_lmv_setup(env, llh, lmvname, lmvdesc);
1929 rc = record_marker(env, llh, fsdb, CM_END, lmvname, "lmv setup");
1933 record_end_log(env, &llh);
1935 OBD_FREE_PTR(lmvdesc);
1939 /* lov is the first thing in the mdt and client logs */
1940 static int mgs_write_log_lov(const struct lu_env *env, struct mgs_device *mgs,
1941 struct fs_db *fsdb, struct mgs_target_info *mti,
1942 char *logname, char *lovname)
1944 struct llog_handle *llh = NULL;
1945 struct lov_desc *lovdesc;
1950 CDEBUG(D_MGS, "Writing lov(%s) log for %s\n", lovname, logname);
1953 #01 L attach 0:lov_mdsA 1:lov 2:71ccb_lov_mdsA_19f961a9e1
1954 #02 L lov_setup 0:lov_mdsA 1:(struct lov_desc)
1955 uuid=lov1_UUID, stripe count=1, size=1048576, offset=0, pattern=0
1958 /* FIXME just make lov_setup accept empty desc (put uuid in buf 2) */
1959 OBD_ALLOC_PTR(lovdesc);
1960 if (lovdesc == NULL)
1962 lovdesc->ld_magic = LOV_DESC_MAGIC;
1963 lovdesc->ld_tgt_count = 0;
1964 /* Defaults. Can be changed later by lcfg config_param */
1965 lovdesc->ld_default_stripe_count = 1;
1966 lovdesc->ld_pattern = LOV_PATTERN_RAID0;
1967 lovdesc->ld_default_stripe_size = LOV_DESC_STRIPE_SIZE_DEFAULT;
1968 lovdesc->ld_default_stripe_offset = -1;
1969 lovdesc->ld_qos_maxage = LOV_DESC_QOS_MAXAGE_DEFAULT;
1970 sprintf((char*)lovdesc->ld_uuid.uuid, "%s_UUID", lovname);
1971 /* can these be the same? */
1972 uuid = (char *)lovdesc->ld_uuid.uuid;
1974 /* This should always be the first entry in a log.
1975 rc = mgs_clear_log(obd, logname); */
1976 rc = record_start_log(env, mgs, &llh, logname);
1979 /* FIXME these should be a single journal transaction */
1980 rc = record_marker(env, llh, fsdb, CM_START, lovname, "lov setup");
1983 rc = record_attach(env, llh, lovname, "lov", uuid);
1986 rc = record_lov_setup(env, llh, lovname, lovdesc);
1989 rc = record_marker(env, llh, fsdb, CM_END, lovname, "lov setup");
1994 record_end_log(env, &llh);
1996 OBD_FREE_PTR(lovdesc);
2000 /* add failnids to open log */
2001 static int mgs_write_log_failnids(const struct lu_env *env,
2002 struct mgs_target_info *mti,
2003 struct llog_handle *llh,
2006 char *failnodeuuid = NULL;
2007 char *ptr = mti->mti_params;
2012 #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) nal=90 0: 1:uml1_UUID
2013 #04 L add_uuid nid=1@elan(0x1000000000001) nal=90 0: 1:uml1_UUID
2014 #05 L setup 0:OSC_uml1_ost1_mdsA 1:ost1_UUID 2:uml1_UUID
2015 #06 L add_uuid nid=uml2@tcp(0x20000c0a80202) nal=90 0: 1:uml2_UUID
2016 #0x L add_uuid nid=2@elan(0x1000000000002) nal=90 0: 1:uml2_UUID
2017 #07 L add_conn 0:OSC_uml1_ost1_mdsA 1:uml2_UUID
2021 * Pull failnid info out of params string, which may contain something
2022 * like "<nid1>,<nid2>:<nid3>,<nid4>". class_parse_nid() does not
2023 * complain about abnormal inputs like ",:<nid1>", "<nid1>:,<nid2>",
2024 * etc. However, convert_hostnames() should have caught those.
2026 while (class_find_param(ptr, PARAM_FAILNODE, &ptr) == 0) {
2027 while (class_parse_nid(ptr, &nid, &ptr) == 0) {
2028 char nidstr[LNET_NIDSTR_SIZE];
2030 if (failnodeuuid == NULL) {
2031 /* We don't know the failover node name,
2032 * so just use the first nid as the uuid */
2033 libcfs_nid2str_r(nid, nidstr, sizeof(nidstr));
2034 rc = name_create(&failnodeuuid, nidstr, "");
2038 CDEBUG(D_MGS, "add nid %s for failover uuid %s, "
2040 libcfs_nid2str_r(nid, nidstr, sizeof(nidstr)),
2041 failnodeuuid, cliname);
2042 rc = record_add_uuid(env, llh, nid, failnodeuuid);
2044 * If *ptr is ':', we have added all NIDs for
2048 rc = record_add_conn(env, llh, cliname,
2050 name_destroy(&failnodeuuid);
2051 failnodeuuid = NULL;
2055 rc = record_add_conn(env, llh, cliname, failnodeuuid);
2056 name_destroy(&failnodeuuid);
2057 failnodeuuid = NULL;
2064 static int mgs_write_log_mdc_to_lmv(const struct lu_env *env,
2065 struct mgs_device *mgs,
2067 struct mgs_target_info *mti,
2068 char *logname, char *lmvname)
2070 struct llog_handle *llh = NULL;
2071 char *mdcname = NULL;
2072 char *nodeuuid = NULL;
2073 char *mdcuuid = NULL;
2074 char *lmvuuid = NULL;
2076 char nidstr[LNET_NIDSTR_SIZE];
2080 if (mgs_log_is_empty(env, mgs, logname)) {
2081 CERROR("log is empty! Logical error\n");
2085 CDEBUG(D_MGS, "adding mdc for %s to log %s:lmv(%s)\n",
2086 mti->mti_svname, logname, lmvname);
2088 libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2089 rc = name_create(&nodeuuid, nidstr, "");
2092 rc = name_create(&mdcname, mti->mti_svname, "-mdc");
2095 rc = name_create(&mdcuuid, mdcname, "_UUID");
2098 rc = name_create(&lmvuuid, lmvname, "_UUID");
2102 rc = record_start_log(env, mgs, &llh, logname);
2105 rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
2109 for (i = 0; i < mti->mti_nid_count; i++) {
2110 CDEBUG(D_MGS, "add nid %s for mdt\n",
2111 libcfs_nid2str_r(mti->mti_nids[i],
2112 nidstr, sizeof(nidstr)));
2114 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2119 rc = record_attach(env, llh, mdcname, LUSTRE_MDC_NAME, lmvuuid);
2122 rc = record_setup(env, llh, mdcname, mti->mti_uuid, nodeuuid,
2126 rc = mgs_write_log_failnids(env, mti, llh, mdcname);
2129 snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
2130 rc = record_mdc_add(env, llh, lmvname, mdcuuid, mti->mti_uuid,
2134 rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname,
2139 record_end_log(env, &llh);
2141 name_destroy(&lmvuuid);
2142 name_destroy(&mdcuuid);
2143 name_destroy(&mdcname);
2144 name_destroy(&nodeuuid);
2148 static inline int name_create_lov(char **lovname, char *mdtname,
2149 struct fs_db *fsdb, int index)
2152 if (index == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2153 return name_create(lovname, fsdb->fsdb_name, "-mdtlov");
2155 return name_create(lovname, mdtname, "-mdtlov");
2158 static int name_create_mdt_and_lov(char **logname, char **lovname,
2159 struct fs_db *fsdb, int i)
2163 rc = name_create_mdt(logname, fsdb->fsdb_name, i);
2167 if (i == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2168 rc = name_create(lovname, fsdb->fsdb_name, "-mdtlov");
2170 rc = name_create(lovname, *logname, "-mdtlov");
2172 name_destroy(logname);
2178 static inline int name_create_mdt_osc(char **oscname, char *ostname,
2179 struct fs_db *fsdb, int i)
2183 if (i == 0 && test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2184 sprintf(suffix, "-osc");
2186 sprintf(suffix, "-osc-MDT%04x", i);
2187 return name_create(oscname, ostname, suffix);
2190 /* add new mdc to already existent MDS */
2191 static int mgs_write_log_osp_to_mdt(const struct lu_env *env,
2192 struct mgs_device *mgs,
2194 struct mgs_target_info *mti,
2195 int mdt_index, char *logname)
2197 struct llog_handle *llh = NULL;
2198 char *nodeuuid = NULL;
2199 char *ospname = NULL;
2200 char *lovuuid = NULL;
2201 char *mdtuuid = NULL;
2202 char *svname = NULL;
2203 char *mdtname = NULL;
2204 char *lovname = NULL;
2206 char nidstr[LNET_NIDSTR_SIZE];
2210 if (mgs_log_is_empty(env, mgs, mti->mti_svname)) {
2211 CERROR("log is empty! Logical error\n");
2215 CDEBUG(D_MGS, "adding osp index %d to %s\n", mti->mti_stripe_index,
2218 rc = name_create_mdt(&mdtname, fsdb->fsdb_name, mti->mti_stripe_index);
2222 libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2223 rc = name_create(&nodeuuid, nidstr, "");
2225 GOTO(out_destory, rc);
2227 rc = name_create(&svname, mdtname, "-osp");
2229 GOTO(out_destory, rc);
2231 sprintf(index_str, "-MDT%04x", mdt_index);
2232 rc = name_create(&ospname, svname, index_str);
2234 GOTO(out_destory, rc);
2236 rc = name_create_lov(&lovname, logname, fsdb, mdt_index);
2238 GOTO(out_destory, rc);
2240 rc = name_create(&lovuuid, lovname, "_UUID");
2242 GOTO(out_destory, rc);
2244 rc = name_create(&mdtuuid, mdtname, "_UUID");
2246 GOTO(out_destory, rc);
2248 rc = record_start_log(env, mgs, &llh, logname);
2250 GOTO(out_destory, rc);
2252 rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
2255 GOTO(out_destory, rc);
2257 for (i = 0; i < mti->mti_nid_count; i++) {
2258 CDEBUG(D_MGS, "add nid %s for mdt\n",
2259 libcfs_nid2str_r(mti->mti_nids[i],
2260 nidstr, sizeof(nidstr)));
2261 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2266 rc = record_attach(env, llh, ospname, LUSTRE_OSP_NAME, lovuuid);
2270 rc = record_setup(env, llh, ospname, mti->mti_uuid, nodeuuid,
2275 rc = mgs_write_log_failnids(env, mti, llh, ospname);
2279 /* Add mdc(osp) to lod */
2280 snprintf(index_str, sizeof(index_str), "%d", mti->mti_stripe_index);
2281 rc = record_base(env, llh, lovname, 0, LCFG_ADD_MDC, mti->mti_uuid,
2282 index_str, "1", NULL);
2286 rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname, "add osp");
2291 record_end_log(env, &llh);
2294 name_destroy(&mdtuuid);
2295 name_destroy(&lovuuid);
2296 name_destroy(&lovname);
2297 name_destroy(&ospname);
2298 name_destroy(&svname);
2299 name_destroy(&nodeuuid);
2300 name_destroy(&mdtname);
2304 static int mgs_write_log_mdt0(const struct lu_env *env,
2305 struct mgs_device *mgs,
2307 struct mgs_target_info *mti)
2309 char *log = mti->mti_svname;
2310 struct llog_handle *llh = NULL;
2311 char *uuid, *lovname;
2313 char *ptr = mti->mti_params;
2314 int rc = 0, failout = 0;
2317 OBD_ALLOC(uuid, sizeof(struct obd_uuid));
2321 if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
2322 failout = (strncmp(ptr, "failout", 7) == 0);
2324 rc = name_create(&lovname, log, "-mdtlov");
2327 if (mgs_log_is_empty(env, mgs, log)) {
2328 rc = mgs_write_log_lov(env, mgs, fsdb, mti, log, lovname);
2333 sprintf(mdt_index, "%d", mti->mti_stripe_index);
2335 rc = record_start_log(env, mgs, &llh, log);
2339 /* add MDT itself */
2341 /* FIXME this whole fn should be a single journal transaction */
2342 sprintf(uuid, "%s_UUID", log);
2343 rc = record_marker(env, llh, fsdb, CM_START, log, "add mdt");
2346 rc = record_attach(env, llh, log, LUSTRE_MDT_NAME, uuid);
2349 rc = record_mount_opt(env, llh, log, lovname, NULL);
2352 rc = record_setup(env, llh, log, uuid, mdt_index, lovname,
2353 failout ? "n" : "f");
2356 rc = record_marker(env, llh, fsdb, CM_END, log, "add mdt");
2360 record_end_log(env, &llh);
2362 name_destroy(&lovname);
2364 OBD_FREE(uuid, sizeof(struct obd_uuid));
2368 /* envelope method for all layers log */
2369 static int mgs_write_log_mdt(const struct lu_env *env,
2370 struct mgs_device *mgs,
2372 struct mgs_target_info *mti)
2374 struct mgs_thread_info *mgi = mgs_env_info(env);
2375 struct llog_handle *llh = NULL;
2380 CDEBUG(D_MGS, "writing new mdt %s\n", mti->mti_svname);
2382 if (mti->mti_uuid[0] == '\0') {
2383 /* Make up our own uuid */
2384 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
2385 "%s_UUID", mti->mti_svname);
2389 rc = mgs_write_log_mdt0(env, mgs, fsdb, mti);
2392 /* Append the mdt info to the client log */
2393 rc = name_create(&cliname, mti->mti_fsname, "-client");
2397 if (mgs_log_is_empty(env, mgs, cliname)) {
2398 /* Start client log */
2399 rc = mgs_write_log_lov(env, mgs, fsdb, mti, cliname,
2403 rc = mgs_write_log_lmv(env, mgs, fsdb, mti, cliname,
2410 #09 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0: 1:uml1_UUID
2411 #10 L attach 0:MDC_uml1_mdsA_MNT_client 1:mdc 2:1d834_MNT_client_03f
2412 #11 L setup 0:MDC_uml1_mdsA_MNT_client 1:mdsA_UUID 2:uml1_UUID
2413 #12 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0: 1:uml2_UUID
2414 #13 L add_conn 0:MDC_uml1_mdsA_MNT_client 1:uml2_UUID
2415 #14 L mount_option 0: 1:client 2:lov1 3:MDC_uml1_mdsA_MNT_client
2418 /* copy client info about lov/lmv */
2419 mgi->mgi_comp.comp_mti = mti;
2420 mgi->mgi_comp.comp_fsdb = fsdb;
2422 rc = mgs_steal_llog_for_mdt_from_client(env, mgs, cliname,
2426 rc = mgs_write_log_mdc_to_lmv(env, mgs, fsdb, mti, cliname,
2432 rc = record_start_log(env, mgs, &llh, cliname);
2436 rc = record_marker(env, llh, fsdb, CM_START, cliname,
2440 rc = record_mount_opt(env, llh, cliname, fsdb->fsdb_clilov,
2444 rc = record_marker(env, llh, fsdb, CM_END, cliname,
2450 /* for_all_existing_mdt except current one */
2451 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
2452 if (i != mti->mti_stripe_index &&
2453 test_bit(i, fsdb->fsdb_mdt_index_map)) {
2456 rc = name_create_mdt(&logname, fsdb->fsdb_name, i);
2460 /* NB: If the log for the MDT is empty, it means
2461 * the MDT is only added to the index
2462 * map, and not being process yet, i.e. this
2463 * is an unregistered MDT, see mgs_write_log_target().
2464 * so we should skip it. Otherwise
2466 * 1. MGS get register request for MDT1 and MDT2.
2468 * 2. Then both MDT1 and MDT2 are added into
2469 * fsdb_mdt_index_map. (see mgs_set_index()).
2471 * 3. Then MDT1 get the lock of fsdb_mutex, then
2472 * generate the config log, here, it will regard MDT2
2473 * as an existent MDT, and generate "add osp" for
2474 * lustre-MDT0001-osp-MDT0002. Note: at the moment
2475 * MDT0002 config log is still empty, so it will
2476 * add "add osp" even before "lov setup", which
2477 * will definitly cause trouble.
2479 * 4. MDT1 registeration finished, fsdb_mutex is
2480 * released, then MDT2 get in, then in above
2481 * mgs_steal_llog_for_mdt_from_client(), it will
2482 * add another osp log for lustre-MDT0001-osp-MDT0002,
2483 * which will cause another trouble.*/
2484 if (!mgs_log_is_empty(env, mgs, logname))
2485 rc = mgs_write_log_osp_to_mdt(env, mgs, fsdb,
2488 name_destroy(&logname);
2494 record_end_log(env, &llh);
2496 name_destroy(&cliname);
2500 /* Add the ost info to the client/mdt lov */
2501 static int mgs_write_log_osc_to_lov(const struct lu_env *env,
2502 struct mgs_device *mgs, struct fs_db *fsdb,
2503 struct mgs_target_info *mti,
2504 char *logname, char *suffix, char *lovname,
2505 enum lustre_sec_part sec_part, int flags)
2507 struct llog_handle *llh = NULL;
2508 char *nodeuuid = NULL;
2509 char *oscname = NULL;
2510 char *oscuuid = NULL;
2511 char *lovuuid = NULL;
2512 char *svname = NULL;
2514 char nidstr[LNET_NIDSTR_SIZE];
2518 CDEBUG(D_INFO, "adding osc for %s to log %s\n",
2519 mti->mti_svname, logname);
2521 if (mgs_log_is_empty(env, mgs, logname)) {
2522 CERROR("log is empty! Logical error\n");
2526 libcfs_nid2str_r(mti->mti_nids[0], nidstr, sizeof(nidstr));
2527 rc = name_create(&nodeuuid, nidstr, "");
2530 rc = name_create(&svname, mti->mti_svname, "-osc");
2534 /* for the system upgraded from old 1.8, keep using the old osc naming
2535 * style for mdt, see name_create_mdt_osc(). LU-1257 */
2536 if (test_bit(FSDB_OSCNAME18, &fsdb->fsdb_flags))
2537 rc = name_create(&oscname, svname, "");
2539 rc = name_create(&oscname, svname, suffix);
2543 rc = name_create(&oscuuid, oscname, "_UUID");
2546 rc = name_create(&lovuuid, lovname, "_UUID");
2552 #03 L add_uuid nid=uml1@tcp(0x20000c0a80201) 0: 1:uml1_UUID
2554 #04 L add_uuid nid=1@elan(0x1000000000001) nal=90 0: 1:uml1_UUID
2555 #04 L attach 0:OSC_uml1_ost1_MNT_client 1:osc 2:89070_lov1_a41dff51a
2556 #05 L setup 0:OSC_uml1_ost1_MNT_client 1:ost1_UUID 2:uml1_UUID
2558 #06 L add_uuid nid=uml2@tcp(0x20000c0a80202) 0: 1:uml2_UUID
2559 #07 L add_conn 0:OSC_uml1_ost1_MNT_client 1:uml2_UUID
2560 #08 L lov_modify_tgts add 0:lov1 1:ost1_UUID 2(index):0 3(gen):1
2563 rc = record_start_log(env, mgs, &llh, logname);
2567 /* FIXME these should be a single journal transaction */
2568 rc = record_marker(env, llh, fsdb, CM_START | flags, mti->mti_svname,
2573 /* NB: don't change record order, because upon MDT steal OSC config
2574 * from client, it treats all nids before LCFG_SETUP as target nids
2575 * (multiple interfaces), while nids after as failover node nids.
2576 * See mgs_steal_client_llog_handler() LCFG_ADD_UUID.
2578 for (i = 0; i < mti->mti_nid_count; i++) {
2579 CDEBUG(D_MGS, "add nid %s\n",
2580 libcfs_nid2str_r(mti->mti_nids[i],
2581 nidstr, sizeof(nidstr)));
2582 rc = record_add_uuid(env, llh, mti->mti_nids[i], nodeuuid);
2586 rc = record_attach(env, llh, oscname, LUSTRE_OSC_NAME, lovuuid);
2589 rc = record_setup(env, llh, oscname, mti->mti_uuid, nodeuuid,
2593 rc = mgs_write_log_failnids(env, mti, llh, oscname);
2597 snprintf(index, sizeof(index), "%d", mti->mti_stripe_index);
2599 rc = record_lov_add(env, llh, lovname, mti->mti_uuid, index, "1");
2602 rc = record_marker(env, llh, fsdb, CM_END | flags, mti->mti_svname,
2607 record_end_log(env, &llh);
2609 name_destroy(&lovuuid);
2610 name_destroy(&oscuuid);
2611 name_destroy(&oscname);
2612 name_destroy(&svname);
2613 name_destroy(&nodeuuid);
2617 static int mgs_write_log_ost(const struct lu_env *env,
2618 struct mgs_device *mgs, struct fs_db *fsdb,
2619 struct mgs_target_info *mti)
2621 struct llog_handle *llh = NULL;
2622 char *logname, *lovname;
2623 char *ptr = mti->mti_params;
2624 int rc, flags = 0, failout = 0, i;
2627 CDEBUG(D_MGS, "writing new ost %s\n", mti->mti_svname);
2629 /* The ost startup log */
2631 /* If the ost log already exists, that means that someone reformatted
2632 the ost and it called target_add again. */
2633 if (!mgs_log_is_empty(env, mgs, mti->mti_svname)) {
2634 LCONSOLE_ERROR_MSG(0x141, "The config log for %s already "
2635 "exists, yet the server claims it never "
2636 "registered. It may have been reformatted, "
2637 "or the index changed. writeconf the MDT to "
2638 "regenerate all logs.\n", mti->mti_svname);
2643 attach obdfilter ost1 ost1_UUID
2644 setup /dev/loop2 ldiskfs f|n errors=remount-ro,user_xattr
2646 if (class_find_param(ptr, PARAM_FAILMODE, &ptr) == 0)
2647 failout = (strncmp(ptr, "failout", 7) == 0);
2648 rc = record_start_log(env, mgs, &llh, mti->mti_svname);
2651 /* FIXME these should be a single journal transaction */
2652 rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,"add ost");
2655 if (*mti->mti_uuid == '\0')
2656 snprintf(mti->mti_uuid, sizeof(mti->mti_uuid),
2657 "%s_UUID", mti->mti_svname);
2658 rc = record_attach(env, llh, mti->mti_svname,
2659 "obdfilter"/*LUSTRE_OST_NAME*/, mti->mti_uuid);
2662 rc = record_setup(env, llh, mti->mti_svname,
2663 "dev"/*ignored*/, "type"/*ignored*/,
2664 failout ? "n" : "f", NULL/*options*/);
2667 rc = record_marker(env, llh, fsdb, CM_END, mti->mti_svname, "add ost");
2671 record_end_log(env, &llh);
2674 /* We also have to update the other logs where this osc is part of
2677 if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
2678 /* If we're upgrading, the old mdt log already has our
2679 entry. Let's do a fake one for fun. */
2680 /* Note that we can't add any new failnids, since we don't
2681 know the old osc names. */
2682 flags = CM_SKIP | CM_UPGRADE146;
2684 } else if ((mti->mti_flags & LDD_F_UPDATE) != LDD_F_UPDATE) {
2685 /* If the update flag isn't set, don't update client/mdt
2688 LCONSOLE_WARN("Client log for %s was not updated; writeconf "
2689 "the MDT first to regenerate it.\n",
2693 /* Add ost to all MDT lov defs */
2694 for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
2695 if (test_bit(i, fsdb->fsdb_mdt_index_map)) {
2698 rc = name_create_mdt_and_lov(&logname, &lovname, fsdb,
2702 sprintf(mdt_index, "-MDT%04x", i);
2703 rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, mti,
2705 lovname, LUSTRE_SP_MDT,
2707 name_destroy(&logname);
2708 name_destroy(&lovname);
2714 /* Append ost info to the client log */
2715 rc = name_create(&logname, mti->mti_fsname, "-client");
2718 if (mgs_log_is_empty(env, mgs, logname)) {
2719 /* Start client log */
2720 rc = mgs_write_log_lov(env, mgs, fsdb, mti, logname,
2724 rc = mgs_write_log_lmv(env, mgs, fsdb, mti, logname,
2729 rc = mgs_write_log_osc_to_lov(env, mgs, fsdb, mti, logname, "",
2730 fsdb->fsdb_clilov, LUSTRE_SP_CLI, flags);
2732 name_destroy(&logname);
2736 static __inline__ int mgs_param_empty(char *ptr)
2740 if ((tmp = strchr(ptr, '=')) && (*(++tmp) == '\0'))
2745 static int mgs_write_log_failnid_internal(const struct lu_env *env,
2746 struct mgs_device *mgs,
2748 struct mgs_target_info *mti,
2749 char *logname, char *cliname)
2752 struct llog_handle *llh = NULL;
2754 if (mgs_param_empty(mti->mti_params)) {
2755 /* Remove _all_ failnids */
2756 rc = mgs_modify(env, mgs, fsdb, mti, logname,
2757 mti->mti_svname, "add failnid", CM_SKIP);
2758 return rc < 0 ? rc : 0;
2761 /* Otherwise failover nids are additive */
2762 rc = record_start_log(env, mgs, &llh, logname);
2765 /* FIXME this should be a single journal transaction */
2766 rc = record_marker(env, llh, fsdb, CM_START, mti->mti_svname,
2770 rc = mgs_write_log_failnids(env, mti, llh, cliname);
2773 rc = record_marker(env, llh, fsdb, CM_END,
2774 mti->mti_svname, "add failnid");
2776 record_end_log(env, &llh);
2781 /* Add additional failnids to an existing log.
2782 The mdc/osc must have been added to logs first */
2783 /* tcp nids must be in dotted-quad ascii -
2784 we can't resolve hostnames from the kernel. */
2785 static int mgs_write_log_add_failnid(const struct lu_env *env,
2786 struct mgs_device *mgs,
2788 struct mgs_target_info *mti)
2790 char *logname, *cliname;
2794 /* FIXME we currently can't erase the failnids
2795 * given when a target first registers, since they aren't part of
2796 * an "add uuid" stanza */
2798 /* Verify that we know about this target */
2799 if (mgs_log_is_empty(env, mgs, mti->mti_svname)) {
2800 LCONSOLE_ERROR_MSG(0x142, "The target %s has not registered "
2801 "yet. It must be started before failnids "
2802 "can be added.\n", mti->mti_svname);
2806 /* Create mdc/osc client name (e.g. lustre-OST0001-osc) */
2807 if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
2808 rc = name_create(&cliname, mti->mti_svname, "-mdc");
2809 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
2810 rc = name_create(&cliname, mti->mti_svname, "-osc");
2816 /* Add failover nids to the client log */
2817 rc = name_create(&logname, mti->mti_fsname, "-client");
2819 name_destroy(&cliname);
2822 rc = mgs_write_log_failnid_internal(env, mgs, fsdb,mti,logname,cliname);
2823 name_destroy(&logname);
2824 name_destroy(&cliname);
2828 if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
2829 /* Add OST failover nids to the MDT logs as well */
2832 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
2833 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
2835 rc = name_create_mdt(&logname, mti->mti_fsname, i);
2838 rc = name_create_mdt_osc(&cliname, mti->mti_svname,
2841 name_destroy(&logname);
2844 rc = mgs_write_log_failnid_internal(env, mgs, fsdb,
2847 name_destroy(&cliname);
2848 name_destroy(&logname);
2857 static int mgs_wlp_lcfg(const struct lu_env *env,
2858 struct mgs_device *mgs, struct fs_db *fsdb,
2859 struct mgs_target_info *mti,
2860 char *logname, struct lustre_cfg_bufs *bufs,
2861 char *tgtname, char *ptr)
2863 char comment[MTI_NAME_MAXLEN];
2865 struct llog_cfg_rec *lcr;
2868 /* Erase any old settings of this same parameter */
2869 memcpy(comment, ptr, MTI_NAME_MAXLEN);
2870 comment[MTI_NAME_MAXLEN - 1] = 0;
2871 /* But don't try to match the value. */
2872 tmp = strchr(comment, '=');
2875 /* FIXME we should skip settings that are the same as old values */
2876 rc = mgs_modify(env, mgs, fsdb, mti, logname, tgtname, comment,CM_SKIP);
2879 del = mgs_param_empty(ptr);
2881 LCONSOLE_INFO("%s parameter %s.%s in log %s\n", del ? "Disabling" : rc ?
2882 "Setting" : "Modifying", tgtname, comment, logname);
2884 /* mgs_modify() will return 1 if nothing had to be done */
2890 lustre_cfg_bufs_reset(bufs, tgtname);
2891 lustre_cfg_bufs_set_string(bufs, 1, ptr);
2892 if (mti->mti_flags & LDD_F_PARAM2)
2893 lustre_cfg_bufs_set_string(bufs, 2, LCTL_UPCALL);
2895 lcr = lustre_cfg_rec_new((mti->mti_flags & LDD_F_PARAM2) ?
2896 LCFG_SET_PARAM : LCFG_PARAM, bufs);
2900 rc = mgs_write_log_direct(env, mgs, fsdb, logname, lcr, tgtname,
2902 lustre_cfg_rec_free(lcr);
2906 static int mgs_write_log_param2(const struct lu_env *env,
2907 struct mgs_device *mgs,
2909 struct mgs_target_info *mti, char *ptr)
2911 struct lustre_cfg_bufs bufs;
2915 CDEBUG(D_MGS, "next param '%s'\n", ptr);
2916 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, PARAMS_FILENAME, &bufs,
2917 mti->mti_svname, ptr);
2922 /* write global variable settings into log */
2923 static int mgs_write_log_sys(const struct lu_env *env,
2924 struct mgs_device *mgs, struct fs_db *fsdb,
2925 struct mgs_target_info *mti, char *sys, char *ptr)
2927 struct mgs_thread_info *mgi = mgs_env_info(env);
2928 struct lustre_cfg *lcfg;
2929 struct llog_cfg_rec *lcr;
2931 int rc, cmd, convert = 1;
2933 if (class_match_param(ptr, PARAM_TIMEOUT, &tmp) == 0) {
2934 cmd = LCFG_SET_TIMEOUT;
2935 } else if (class_match_param(ptr, PARAM_LDLM_TIMEOUT, &tmp) == 0) {
2936 cmd = LCFG_SET_LDLM_TIMEOUT;
2937 /* Check for known params here so we can return error to lctl */
2938 } else if ((class_match_param(ptr, PARAM_AT_MIN, &tmp) == 0) ||
2939 (class_match_param(ptr, PARAM_AT_MAX, &tmp) == 0) ||
2940 (class_match_param(ptr, PARAM_AT_EXTRA, &tmp) == 0) ||
2941 (class_match_param(ptr, PARAM_AT_EARLY_MARGIN, &tmp) == 0) ||
2942 (class_match_param(ptr, PARAM_AT_HISTORY, &tmp) == 0)) {
2944 } else if (class_match_param(ptr, PARAM_JOBID_VAR, &tmp) == 0) {
2945 convert = 0; /* Don't convert string value to integer */
2951 if (mgs_param_empty(ptr))
2952 CDEBUG(D_MGS, "global '%s' removed\n", sys);
2954 CDEBUG(D_MGS, "global '%s' val=%s\n", sys, tmp);
2956 lustre_cfg_bufs_reset(&mgi->mgi_bufs, NULL);
2957 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, sys);
2958 if (!convert && *tmp != '\0')
2959 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 2, tmp);
2960 lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
2964 lcfg = &lcr->lcr_cfg;
2965 lcfg->lcfg_num = convert ? simple_strtoul(tmp, NULL, 0) : 0;
2966 /* truncate the comment to the parameter name */
2970 /* modify all servers and clients */
2971 rc = mgs_write_log_direct_all(env, mgs, fsdb, mti,
2972 *tmp == '\0' ? NULL : lcr,
2973 mti->mti_fsname, sys, 0);
2974 if (rc == 0 && *tmp != '\0') {
2976 case LCFG_SET_TIMEOUT:
2977 if (!obd_timeout_set || lcfg->lcfg_num > obd_timeout)
2978 class_process_config(lcfg);
2980 case LCFG_SET_LDLM_TIMEOUT:
2981 if (!ldlm_timeout_set || lcfg->lcfg_num > ldlm_timeout)
2982 class_process_config(lcfg);
2989 lustre_cfg_rec_free(lcr);
2993 /* write quota settings into log */
2994 static int mgs_write_log_quota(const struct lu_env *env, struct mgs_device *mgs,
2995 struct fs_db *fsdb, struct mgs_target_info *mti,
2996 char *quota, char *ptr)
2998 struct mgs_thread_info *mgi = mgs_env_info(env);
2999 struct llog_cfg_rec *lcr;
3002 int rc, cmd = LCFG_PARAM;
3004 /* support only 'meta' and 'data' pools so far */
3005 if (class_match_param(ptr, QUOTA_METAPOOL_NAME, &tmp) != 0 &&
3006 class_match_param(ptr, QUOTA_DATAPOOL_NAME, &tmp) != 0) {
3007 CERROR("parameter quota.%s isn't supported (only quota.mdt "
3008 "& quota.ost are)\n", ptr);
3013 CDEBUG(D_MGS, "global '%s' removed\n", quota);
3015 CDEBUG(D_MGS, "global '%s'\n", quota);
3017 if (strchr(tmp, 'u') == NULL && strchr(tmp, 'g') == NULL &&
3018 strcmp(tmp, "none") != 0) {
3019 CERROR("enable option(%s) isn't supported\n", tmp);
3024 lustre_cfg_bufs_reset(&mgi->mgi_bufs, mti->mti_fsname);
3025 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, quota);
3026 lcr = lustre_cfg_rec_new(cmd, &mgi->mgi_bufs);
3030 /* truncate the comment to the parameter name */
3035 /* XXX we duplicated quota enable information in all server
3036 * config logs, it should be moved to a separate config
3037 * log once we cleanup the config log for global param. */
3038 /* modify all servers */
3039 rc = mgs_write_log_direct_all(env, mgs, fsdb, mti,
3040 *tmp == '\0' ? NULL : lcr,
3041 mti->mti_fsname, quota, 1);
3043 lustre_cfg_rec_free(lcr);
3044 return rc < 0 ? rc : 0;
3047 static int mgs_srpc_set_param_disk(const struct lu_env *env,
3048 struct mgs_device *mgs,
3050 struct mgs_target_info *mti,
3053 struct mgs_thread_info *mgi = mgs_env_info(env);
3054 struct llog_cfg_rec *lcr;
3055 struct llog_handle *llh = NULL;
3057 char *comment, *ptr;
3063 ptr = strchr(param, '=');
3064 LASSERT(ptr != NULL);
3067 OBD_ALLOC(comment, len + 1);
3068 if (comment == NULL)
3070 strncpy(comment, param, len);
3071 comment[len] = '\0';
3074 lustre_cfg_bufs_reset(&mgi->mgi_bufs, mti->mti_svname);
3075 lustre_cfg_bufs_set_string(&mgi->mgi_bufs, 1, param);
3076 lcr = lustre_cfg_rec_new(LCFG_SPTLRPC_CONF, &mgi->mgi_bufs);
3078 GOTO(out_comment, rc = -ENOMEM);
3080 /* construct log name */
3081 rc = name_create(&logname, mti->mti_fsname, "-sptlrpc");
3085 if (mgs_log_is_empty(env, mgs, logname)) {
3086 rc = record_start_log(env, mgs, &llh, logname);
3089 record_end_log(env, &llh);
3092 /* obsolete old one */
3093 rc = mgs_modify(env, mgs, fsdb, mti, logname, mti->mti_svname,
3097 /* write the new one */
3098 rc = mgs_write_log_direct(env, mgs, fsdb, logname, lcr,
3099 mti->mti_svname, comment);
3101 CERROR("%s: error writing log %s: rc = %d\n",
3102 mgs->mgs_obd->obd_name, logname, rc);
3104 name_destroy(&logname);
3106 lustre_cfg_rec_free(lcr);
3108 OBD_FREE(comment, len + 1);
3112 static int mgs_srpc_set_param_udesc_mem(struct fs_db *fsdb,
3117 /* disable the adjustable udesc parameter for now, i.e. use default
3118 * setting that client always ship udesc to MDT if possible. to enable
3119 * it simply remove the following line */
3122 ptr = strchr(param, '=');
3127 if (strcmp(param, PARAM_SRPC_UDESC))
3130 if (strcmp(ptr, "yes") == 0) {
3131 set_bit(FSDB_UDESC, &fsdb->fsdb_flags);
3132 CWARN("Enable user descriptor shipping from client to MDT\n");
3133 } else if (strcmp(ptr, "no") == 0) {
3134 clear_bit(FSDB_UDESC, &fsdb->fsdb_flags);
3135 CWARN("Disable user descriptor shipping from client to MDT\n");
3143 CERROR("Invalid param: %s\n", param);
3147 static int mgs_srpc_set_param_mem(struct fs_db *fsdb,
3151 struct sptlrpc_rule rule;
3152 struct sptlrpc_rule_set *rset;
3156 if (strncmp(param, PARAM_SRPC, sizeof(PARAM_SRPC) - 1) != 0) {
3157 CERROR("Invalid sptlrpc parameter: %s\n", param);
3161 if (strncmp(param, PARAM_SRPC_UDESC,
3162 sizeof(PARAM_SRPC_UDESC) - 1) == 0) {
3163 RETURN(mgs_srpc_set_param_udesc_mem(fsdb, param));
3166 if (strncmp(param, PARAM_SRPC_FLVR, sizeof(PARAM_SRPC_FLVR) - 1) != 0) {
3167 CERROR("Invalid sptlrpc flavor parameter: %s\n", param);
3171 param += sizeof(PARAM_SRPC_FLVR) - 1;
3173 rc = sptlrpc_parse_rule(param, &rule);
3177 /* mgs rules implies must be mgc->mgs */
3178 if (test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
3179 if ((rule.sr_from != LUSTRE_SP_MGC &&
3180 rule.sr_from != LUSTRE_SP_ANY) ||
3181 (rule.sr_to != LUSTRE_SP_MGS &&
3182 rule.sr_to != LUSTRE_SP_ANY))
3186 /* preapre room for this coming rule. svcname format should be:
3187 * - fsname: general rule
3188 * - fsname-tgtname: target-specific rule
3190 if (strchr(svname, '-')) {
3191 struct mgs_tgt_srpc_conf *tgtconf;
3194 for (tgtconf = fsdb->fsdb_srpc_tgt; tgtconf != NULL;
3195 tgtconf = tgtconf->mtsc_next) {
3196 if (!strcmp(tgtconf->mtsc_tgt, svname)) {
3205 OBD_ALLOC_PTR(tgtconf);
3206 if (tgtconf == NULL)
3209 name_len = strlen(svname);
3211 OBD_ALLOC(tgtconf->mtsc_tgt, name_len + 1);
3212 if (tgtconf->mtsc_tgt == NULL) {
3213 OBD_FREE_PTR(tgtconf);
3216 memcpy(tgtconf->mtsc_tgt, svname, name_len);
3218 tgtconf->mtsc_next = fsdb->fsdb_srpc_tgt;
3219 fsdb->fsdb_srpc_tgt = tgtconf;
3222 rset = &tgtconf->mtsc_rset;
3223 } else if (strcmp(svname, MGSSELF_NAME) == 0) {
3224 /* put _mgs related srpc rule directly in mgs ruleset */
3225 rset = &fsdb->fsdb_mgs->mgs_lut.lut_sptlrpc_rset;
3227 rset = &fsdb->fsdb_srpc_gen;
3230 rc = sptlrpc_rule_set_merge(rset, &rule);
3235 static int mgs_srpc_set_param(const struct lu_env *env,
3236 struct mgs_device *mgs,
3238 struct mgs_target_info *mti,
3248 /* keep a copy of original param, which could be destroied
3250 copy_size = strlen(param) + 1;
3251 OBD_ALLOC(copy, copy_size);
3254 memcpy(copy, param, copy_size);
3256 rc = mgs_srpc_set_param_mem(fsdb, mti->mti_svname, param);
3260 /* previous steps guaranteed the syntax is correct */
3261 rc = mgs_srpc_set_param_disk(env, mgs, fsdb, mti, copy);
3265 if (test_bit(FSDB_MGS_SELF, &fsdb->fsdb_flags)) {
3267 * for mgs rules, make them effective immediately.
3269 LASSERT(fsdb->fsdb_srpc_tgt == NULL);
3270 sptlrpc_target_update_exp_flavor(mgs->mgs_obd,
3271 &fsdb->fsdb_srpc_gen);
3275 OBD_FREE(copy, copy_size);
3279 struct mgs_srpc_read_data {
3280 struct fs_db *msrd_fsdb;
3284 static int mgs_srpc_read_handler(const struct lu_env *env,
3285 struct llog_handle *llh,
3286 struct llog_rec_hdr *rec, void *data)
3288 struct mgs_srpc_read_data *msrd = data;
3289 struct cfg_marker *marker;
3290 struct lustre_cfg *lcfg = REC_DATA(rec);
3291 char *svname, *param;
3295 if (rec->lrh_type != OBD_CFG_REC) {
3296 CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
3300 cfg_len = REC_DATA_LEN(rec);
3302 rc = lustre_cfg_sanity_check(lcfg, cfg_len);
3304 CERROR("Insane cfg\n");
3308 if (lcfg->lcfg_command == LCFG_MARKER) {
3309 marker = lustre_cfg_buf(lcfg, 1);
3311 if (marker->cm_flags & CM_START &&
3312 marker->cm_flags & CM_SKIP)
3313 msrd->msrd_skip = 1;
3314 if (marker->cm_flags & CM_END)
3315 msrd->msrd_skip = 0;
3320 if (msrd->msrd_skip)
3323 if (lcfg->lcfg_command != LCFG_SPTLRPC_CONF) {
3324 CERROR("invalid command (%x)\n", lcfg->lcfg_command);
3328 svname = lustre_cfg_string(lcfg, 0);
3329 if (svname == NULL) {
3330 CERROR("svname is empty\n");
3334 param = lustre_cfg_string(lcfg, 1);
3335 if (param == NULL) {
3336 CERROR("param is empty\n");
3340 rc = mgs_srpc_set_param_mem(msrd->msrd_fsdb, svname, param);
3342 CERROR("read sptlrpc record error (%d): %s\n", rc, param);
3347 int mgs_get_fsdb_srpc_from_llog(const struct lu_env *env,
3348 struct mgs_device *mgs,
3351 struct llog_handle *llh = NULL;
3352 struct llog_ctxt *ctxt;
3354 struct mgs_srpc_read_data msrd;
3358 /* construct log name */
3359 rc = name_create(&logname, fsdb->fsdb_name, "-sptlrpc");
3363 ctxt = llog_get_context(mgs->mgs_obd, LLOG_CONFIG_ORIG_CTXT);
3364 LASSERT(ctxt != NULL);
3366 if (mgs_log_is_empty(env, mgs, logname))
3369 rc = llog_open(env, ctxt, &llh, NULL, logname,
3377 rc = llog_init_handle(env, llh, LLOG_F_IS_PLAIN, NULL);
3379 GOTO(out_close, rc);
3381 if (llog_get_size(llh) <= 1)
3382 GOTO(out_close, rc = 0);
3384 msrd.msrd_fsdb = fsdb;
3387 rc = llog_process(env, llh, mgs_srpc_read_handler, (void *)&msrd,
3391 llog_close(env, llh);
3393 llog_ctxt_put(ctxt);
3394 name_destroy(&logname);
3397 CERROR("failed to read sptlrpc config database: %d\n", rc);
3401 /* Permanent settings of all parameters by writing into the appropriate
3402 * configuration logs.
3403 * A parameter with null value ("<param>='\0'") means to erase it out of
3406 static int mgs_write_log_param(const struct lu_env *env,
3407 struct mgs_device *mgs, struct fs_db *fsdb,
3408 struct mgs_target_info *mti, char *ptr)
3410 struct mgs_thread_info *mgi = mgs_env_info(env);
3416 /* For various parameter settings, we have to figure out which logs
3417 care about them (e.g. both mdt and client for lov settings) */
3418 CDEBUG(D_MGS, "next param '%s'\n", ptr);
3420 /* The params are stored in MOUNT_DATA_FILE and modified via
3421 tunefs.lustre, or set using lctl conf_param */
3423 /* Processed in lustre_start_mgc */
3424 if (class_match_param(ptr, PARAM_MGSNODE, NULL) == 0)
3427 /* Processed in ost/mdt */
3428 if (class_match_param(ptr, PARAM_NETWORK, NULL) == 0)
3431 /* Processed in mgs_write_log_ost */
3432 if (class_match_param(ptr, PARAM_FAILMODE, NULL) == 0) {
3433 if (mti->mti_flags & LDD_F_PARAM) {
3434 LCONSOLE_ERROR_MSG(0x169, "%s can only be "
3435 "changed with tunefs.lustre"
3436 "and --writeconf\n", ptr);
3442 if (class_match_param(ptr, PARAM_SRPC, NULL) == 0) {
3443 rc = mgs_srpc_set_param(env, mgs, fsdb, mti, ptr);
3447 if (class_match_param(ptr, PARAM_FAILNODE, NULL) == 0) {
3448 /* Add a failover nidlist */
3450 /* We already processed failovers params for new
3451 targets in mgs_write_log_target */
3452 if (mti->mti_flags & LDD_F_PARAM) {
3453 CDEBUG(D_MGS, "Adding failnode\n");
3454 rc = mgs_write_log_add_failnid(env, mgs, fsdb, mti);
3459 if (class_match_param(ptr, PARAM_SYS, &tmp) == 0) {
3460 rc = mgs_write_log_sys(env, mgs, fsdb, mti, ptr, tmp);
3464 if (class_match_param(ptr, PARAM_QUOTA, &tmp) == 0) {
3465 rc = mgs_write_log_quota(env, mgs, fsdb, mti, ptr, tmp);
3469 if (class_match_param(ptr, PARAM_OSC PARAM_ACTIVE, &tmp) == 0 ||
3470 class_match_param(ptr, PARAM_MDC PARAM_ACTIVE, &tmp) == 0) {
3471 /* active=0 means off, anything else means on */
3472 int flag = (*tmp == '0') ? CM_EXCLUDE : 0;
3473 bool deactive_osc = memcmp(ptr, PARAM_OSC PARAM_ACTIVE,
3474 strlen(PARAM_OSC PARAM_ACTIVE)) == 0;
3477 if (!deactive_osc) {
3480 rc = server_name2index(mti->mti_svname, &index, NULL);
3485 LCONSOLE_ERROR_MSG(0x144, "%s: MDC0 can not be"
3486 " (de)activated.\n",
3488 GOTO(end, rc = -EPERM);
3492 LCONSOLE_WARN("Permanently %sactivating %s\n",
3493 flag ? "de" : "re", mti->mti_svname);
3495 rc = name_create(&logname, mti->mti_fsname, "-client");
3498 rc = mgs_modify(env, mgs, fsdb, mti, logname,
3500 deactive_osc ? "add osc" : "add mdc", flag);
3501 name_destroy(&logname);
3506 /* Add to all MDT logs for DNE */
3507 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
3508 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
3510 rc = name_create_mdt(&logname, mti->mti_fsname, i);
3513 rc = mgs_modify(env, mgs, fsdb, mti, logname,
3515 deactive_osc ? "add osc" : "add osp",
3517 name_destroy(&logname);
3523 LCONSOLE_ERROR_MSG(0x145, "Couldn't find %s in"
3524 "log (%d). No permanent "
3525 "changes were made to the "
3527 mti->mti_svname, rc);
3528 if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags))
3529 LCONSOLE_ERROR_MSG(0x146, "This may be"
3534 "update the logs.\n");
3537 /* Fall through to osc/mdc proc for deactivating live
3538 OSC/OSP on running MDT / clients. */
3540 /* Below here, let obd's XXX_process_config methods handle it */
3542 /* All lov. in proc */
3543 if (class_match_param(ptr, PARAM_LOV, NULL) == 0) {
3546 CDEBUG(D_MGS, "lov param %s\n", ptr);
3547 if (!(mti->mti_flags & LDD_F_SV_TYPE_MDT)) {
3548 LCONSOLE_ERROR_MSG(0x147, "LOV params must be "
3549 "set on the MDT, not %s. "
3556 if (mgs_log_is_empty(env, mgs, mti->mti_svname))
3557 GOTO(end, rc = -ENODEV);
3559 rc = name_create_mdt_and_lov(&logname, &mdtlovname, fsdb,
3560 mti->mti_stripe_index);
3563 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, mti->mti_svname,
3564 &mgi->mgi_bufs, mdtlovname, ptr);
3565 name_destroy(&logname);
3566 name_destroy(&mdtlovname);
3571 rc = name_create(&logname, mti->mti_fsname, "-client");
3574 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname, &mgi->mgi_bufs,
3575 fsdb->fsdb_clilov, ptr);
3576 name_destroy(&logname);
3580 /* All osc., mdc., llite. params in proc */
3581 if ((class_match_param(ptr, PARAM_OSC, NULL) == 0) ||
3582 (class_match_param(ptr, PARAM_MDC, NULL) == 0) ||
3583 (class_match_param(ptr, PARAM_LLITE, NULL) == 0)) {
3586 if (test_bit(FSDB_OLDLOG14, &fsdb->fsdb_flags)) {
3587 LCONSOLE_ERROR_MSG(0x148, "Upgraded client logs for %s"
3588 " cannot be modified. Consider"
3589 " updating the configuration with"
3592 GOTO(end, rc = -EINVAL);
3594 if (memcmp(ptr, PARAM_LLITE, strlen(PARAM_LLITE)) == 0) {
3595 rc = name_create(&cname, mti->mti_fsname, "-client");
3596 /* Add the client type to match the obdname in
3597 class_config_llog_handler */
3598 } else if (mti->mti_flags & LDD_F_SV_TYPE_MDT) {
3599 rc = name_create(&cname, mti->mti_svname, "-mdc");
3600 } else if (mti->mti_flags & LDD_F_SV_TYPE_OST) {
3601 rc = name_create(&cname, mti->mti_svname, "-osc");
3603 GOTO(end, rc = -EINVAL);
3608 /* Forbid direct update of llite root squash parameters.
3609 * These parameters are indirectly set via the MDT settings.
3611 if ((class_match_param(ptr, PARAM_LLITE, &tmp) == 0) &&
3612 ((memcmp(tmp, "root_squash=", 12) == 0) ||
3613 (memcmp(tmp, "nosquash_nids=", 14) == 0))) {
3614 LCONSOLE_ERROR("%s: root squash parameters can only "
3615 "be updated through MDT component\n",
3617 name_destroy(&cname);
3618 GOTO(end, rc = -EINVAL);
3621 CDEBUG(D_MGS, "%.3s param %s\n", ptr, ptr + 4);
3624 rc = name_create(&logname, mti->mti_fsname, "-client");
3626 name_destroy(&cname);
3629 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname, &mgi->mgi_bufs,
3632 /* osc params affect the MDT as well */
3633 if (!rc && (mti->mti_flags & LDD_F_SV_TYPE_OST)) {
3636 for (i = 0; i < INDEX_MAP_SIZE * 8; i++){
3637 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
3639 name_destroy(&cname);
3640 rc = name_create_mdt_osc(&cname, mti->mti_svname,
3642 name_destroy(&logname);
3645 rc = name_create_mdt(&logname,
3646 mti->mti_fsname, i);
3649 if (!mgs_log_is_empty(env, mgs, logname)) {
3650 rc = mgs_wlp_lcfg(env, mgs, fsdb,
3660 /* For mdc activate/deactivate, it affects OSP on MDT as well */
3661 if (class_match_param(ptr, PARAM_MDC PARAM_ACTIVE, &tmp) == 0 &&
3664 char *lodname = NULL;
3665 char *param_str = NULL;
3669 /* replace mdc with osp */
3670 memcpy(ptr, PARAM_OSP, strlen(PARAM_OSP));
3671 rc = server_name2index(mti->mti_svname, &index, NULL);
3673 memcpy(ptr, PARAM_MDC, strlen(PARAM_MDC));
3677 for (i = 0; i < INDEX_MAP_SIZE * 8; i++) {
3678 if (!test_bit(i, fsdb->fsdb_mdt_index_map))
3684 name_destroy(&logname);
3685 rc = name_create_mdt(&logname, mti->mti_fsname,
3690 if (mgs_log_is_empty(env, mgs, logname))
3693 snprintf(suffix, sizeof(suffix), "-osp-MDT%04x",
3695 name_destroy(&cname);
3696 rc = name_create(&cname, mti->mti_svname,
3701 rc = mgs_wlp_lcfg(env, mgs, fsdb, mti, logname,